-
Notifications
You must be signed in to change notification settings - Fork 949
bean fields core integration
This page is for the discussion of proposed merging of a successor to the bean-fields plugin into Grails core.
- The top-level GSP, e.g. a scaffolded
create.gsp
oredit.gsp
. This is responsible for selecting the fields to be used and laying them out in relation to one another. - The markup surrounding each input. This would include
label
tags, any surroundingdiv
or other container, per-field error messages, etc. This would be the same for the majority of fields in a project but needs to be customisable for special cases. - The input itself. The input rendered should be appropriate to the property type, e.g.
select
for enums,checkbox
for booleans, etc. However, this needs to be customisable on a per-field basis and a per-type basis across the project. i.e. if I want to useradio
inputs for a particular enum instead of aselect
I should be able to configure that once and have it used in any form that renders an input for that enum type.
Grails scaffolding could use a modular, convention-driven way to render a form for a domain instance. The existing create.gsp
and edit.gsp
iterate over the persistent properties and instead of using the monolithic renderEditor.template
can use a tag such as <bean:field bean="${domainInstance}" property="foo"/>
. The exact markup this renders can be customised on a per-property basis falling back to a default with automatic input type selection based on the property type.
A good example is the Joda-Time plugin being able to register default input rendering for the types it supports which gets picked up so that <bean:field bean="${domainInstance}" property="jodaLocalDateProperty"/>
renders the correct input with the same surrounding markup in terms of labels, mandatory indicators, etc. as any other field. Again it should be possible for a user to override how this is done.
Currently these are not handled by scaffolding and it's problematic to do so within the limitations of renderEditor.template
. It would be useful to have recursive rendering so that the properties of embedded types could be grouped inside a fieldset
for example.
The bean-fields plugin currently adds mandatory indicators but with HTML5 we can mark fields up with the required
boolean attribute. Also there are other constraint-type attributes such as pattern
, min
, max
and range
that could be automatically rendered on inputs where appropriate. This implies we probably need access to the ConstrainedProperty
instance inside the templates and a standard way of converting that to HTML attributes.
bean-fields allows for adding a mandatory indicator but it can be a bit inflexible if you want to do something like adding a class to the surrounding div
element and using CSS content generation to apply the indicator. Supporting this kind of flexibility is essential. CSS can also use the :required
and :optional
pseudo-classes in current browsers so hardcoding asterisk characters in the markup is increasingly non-optimal.
- Can we use 2 levels of template, one to render the input itself and one to render the whole field (i.e. including surrounding markup)? The latter would be passed the output of the former much as
g:radioGroup
passes the rendered radio button to the tag body. - Input templates need to be overrideable by class/property or by property type. e.g. if I want the
name
field on myPerson
domain class to use a different type of input to the default for a String I can. Specifying templates by property type would mean plugins can easily extend the rendering, e.g. Joda-time can just register a bunch of templates for theorg.joda.time.*
types and they will just work. Config likegrails.inputs.com.myapp.Book.author = "templatename"
or Config likegrails.inputs.java.lang.String = "templatename"
(might be ambiguity there)? I know Marc isn't keen on using templates here but I'm not sure how else we can allow for extensibility by plugins. Any suggestions welcome. - Field templates need to be overrideable by class/property. I can see edge cases for overriding by property type but I think it would be pretty unusual. Config like
grails.fields.com.myapp.Book.author = "templatename"
? - Preferably the exact same set of attributes should be passed to both 'levels' of template.
I spiked the resolution of templates following discussions with Marc. See code [here]:https://github.com/grails/grails-core/blob/221c15290d845235643d2808e88f28d65693ea2c/grails-plugin-gsp/src/main/groovy/org/codehaus/groovy/grails/plugins/web/taglib/ScaffoldingTagLib.groovy#L25. Code needs refactoring so that some of the internal stuff done by GroovyPagesTemplateEngine
and RenderTagLib
is accessible as right now I'm essentially doing template resolution twice.
- Application and plugins can render fields for bean properties with simple tags that include Label and per-field errors
- The markup surrounding the fields must be configurable by the application and plugin developer, preferably with scope for overriding by the application developer i.e. to make GSPs from plugins visually and markup coherent with their own templates
- The functionality should be based around decorating the "field" markup and providing the smarts for property and constrain-related attributes, error display etc.
- It should be possible to render all the fields for a given bean type using a GSP fragment located explicitly or by convention (depending on user's need)
- All smart property-related behaviour to be overridable by the tag invocation using attributes e.g. override/suppress auto-generated "id", "name", "isRequired", "requiredIndicator", "errorClass", "value", and option lists for selects and so on.
- Mechanism for plugins to provide default field renderings (to be decorated) for specific property types - hooking into the "smart field selection" logic