Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • 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

    • the layout producer could yield a tabbed layout that we have currently or any other type of layout based on the configured definition


PoC https://git.magnolia-cms.com/users/jsimak/repos/ui/pull-requests/1/commits/91980c4dbd0803b429e50f037f4b70a638cce0dd

A class diagram from the current PoC and a description of their main responsibilities

Image Modified


FormDefinition

  • is a ComponentDefinition
  • is registered and mapped to a factory class like any other form field
  • has FieldDefinition(s)
  • has a LayoutDefinition



Code Pro
collapseTypeClassic
languageyaml
themeEmacs
titleForm configuration example (YAML)
# this is the 'main' form configuration
form:
  fields:
    title:
      class: info.magnolia.ui.form.poc.definition.TextFieldDefinition
    firstName:
      class: info.magnolia.ui.form.poc.definition.TextFieldDefinition
	lastName:
      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:
          firstName:
		  lastName:	
      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:


LayoutDefinition

  • has a list of field names composing the layout. Their names match those of the FieldDefinition(s)
  • specifies LayoutProducer implementation class


LayoutProducer

  • is instantiated from a LayoutDefinition
  • createLayout(LayoutDefinition, Map<String, Component>) creates the actual layout (a Vaadin Component) from
    • LayoutDefinition
    • a mapping of field names and actual field components

Form

  • is a component, same as a fieldplain Java class

  • during its building process it stores
    • a mapping of field names and resulting field components
    • its own 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)
    • its Binder
    • its own Layout (including sub-form layouts)
    • its sub-forms
  • can save and validate self and its sub-forms recursively (should this functionality move away from Form?) 

FormPresenterFormViewFactory

  • is currently the orchestrator of the whole form building process
  • creates the final form view (a Vaadin Layout)
    • instantiates a Form from a FormDefinition
    • returns the form view to the caller
    • TODO 

      • set labels, help messages and descriptions: use something like info.magnolia.ui.dialog.formdialog.FormView?

      • update forms/fields based on Locale? See info.magnolia.ui.dialog.formdialog.FormPresenterImpl.updateForm()

  • it gets passed to DetailPresenter

  • instantiates a LayoutProducer
  • calls form.attachToLayout

    (..)

    and passes a lambda function which eventually delegates to the LayoutProducer

    which takes care of initializing actions and other stuff before calling and setting the form view produced by FormPresenter



Code Pro
languagejava
themeEmacs
titleSnippet from FormViewFactory
collapsetrue
...
  /***
   * @return a {@link View} as described by this {@link FormDefinition} including nested forms, if any.
   */
   public View createFormView(D formDefinition) {
       CssLayoutFormView view = new CssLayoutFormView();
       Form<T> form = formFactory.createForm(formDefinition);
       Layout rootLayout = form.attachToLayout((layout, mappings) -> createLayout(layout, mappings));
       view.addComponent(rootLayout);

       return view;
   }

   protected Form<T> createForm(D formDefinition) {
       //TODO how to instantiate the correct PropertySet?
       FormFactory<D, T> formFactory = componentProvider.newInstance(FormFactory.class, formDefinition, subAppContext,
               new JcrNodePropertySet(collectFormFieldDefinitions(formDefinition), null, null), componentFactoryFactory);
       return (Form<T>) formFactory.createComponent();
   }

   protected Layout createLayout(LayoutDefinition definition, Map<String, Component> mappings) {
       LayoutProducer producer = componentProvider.newInstance(definition.getImplementationClass());view.addComponent(form.getLayout());

       return producer.createLayout(definition, mappings)view;
   }