Page History
Related issue Jira server Magnolia - Issue tracker columns key,summary,type,created,updated,due,assignee,reporter,priority,status,resolution serverId 500b06a6-e204-3125-b989-2d75b973d05f key DEV-883
Table of Contents
Introduction
Problem
...
Goal
We want to provide users with a simple, modern API to build arbitrarily complex fields.
Problem
All is good, as long as a simple value is bound to a simple field, e.g. TextField → String.
But what if I need a field manage a complex nested value, i.e. if I have to manage hierarchical data?
Currently Magnolia does provide such ability through custom multi fields (see AbstractCustomMultiField) but they have several shortcomings, both in terms of internal implementation and from a client developer's perspective (see for instance
Jira | ||||||
---|---|---|---|---|---|---|
|
Proposal
Assume the field is simple and atomic
When you need to manage many related values - it is another form within a form
Complex fields are like forms but with striped layout.
Layouting
Form (or editor) layout should be separated from the binding mechanism and should be flexible:
first, we produce the field/sub-form components and bind them to the binder
then we pass the mapping of e.g. the property names and the resulting components (fields/sub-forms) to a layout producer
LayoutProducer could yield a tabbed layout that we have currently or any other type of layout based on the configured definition
Form
- is a component, same as a field
- during its building process it stores
-- a mapping of field names and resulting field components
-- a LayoutDefinition
- exposes mappings + LayoutDefinition via functional interface
e.g. form.attachToLayout((layout, mappings) -> doLayout(layout, mapping))
- attachToLayout internally takes care of creating the main form layout
and all subforms' layouts (if any)
FormViewFactory
- creates a FormView (a Vaadin Layout)
-- instantiates a Form from a FormDefinition
-- instantiates a LayoutProducer
-- calls form.attachToLayout(..) and passes mappings + LayoutDefinition to the LayoutProducer
Code Pro | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
# this is the 'main' form configuration form: fields: title: class: info.magnolia.ui.form.poc.definition.TextFieldDefinition name: class: info.magnolia.ui.form.poc.definition.TextFieldDefinition # address is a form component (a subform of the main form) and specifies its own layout. # It is declared under fields and we can refer to it as a field # see below form/layout/tabs/more/fields/address address: class: info.magnolia.ui.form.poc.definition.FormDefinition fields: city: class: info.magnolia.ui.form.poc.definition.TextFieldDefinition country: class: info.magnolia.ui.form.poc.definition.TextFieldDefinition nested: # a form component can have sub-form components with their own layout class: info.magnolia.ui.form.poc.definition.FormDefinition fields: qux: class: info.magnolia.ui.form.poc.definition.TextFieldDefinition layout: class: info.magnolia.ui.form.poc.layout.MyLayout fields: qux: layout: # this is the layout for address class: info.magnolia.ui.form.poc.layout.DefaultLayoutDefinition fields: city: country: nested: # this is the main form's layout configuration # layout configurations could probably be omitted altogether and rely on a reasonable default layout: class: info.magnolia.ui.form.poc.layout.TabbedLayoutDefinition tabs: personal: fields: title: name: more: fields: # address is a form component (a subform of the main form) # here it is referred to as if it were a plain Field address: |
...