Versions Compared

Key

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

Table of Contents

 

Info
This concept captures improvements to the Magnolia forms/dialogs. They address various sides and pain points with the current UI framework, in order to gain flexibility, sanitize our own customizations and expose more easily the key benefits of Vaadin (ease and speed of such developments).

Most work is expected to be carried out through the following ticket/epic. This ticket, as well as linked support tickets hold several concrete scenarios.

Jira
serverMagnolia - Issue tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId500b06a6-e204-3125-b989-2d75b973d05f
keyMGNLUI-2542

 

1. Use cases

We need to support such dynamic forms in a much easier way. Collecting some commons requirements:

  • populating select options based on the value of another field
  • validating a field depending on the value of another field (including within a composite field itself)
  • enabling/disabling fields conditionally
  • potentially custom handling of any field, via plain Vaadin code
  • updating form buttons (enabling/disabling/relabeling)

 

2. General directions & goals

  • Exposing hooks on form-level
    • currently only possible on field-level via FieldFactories
    • fields & factories are only aware about themselves, in isolation. They're not aware about other fields and this is harder to do than it should.
  • Use more of Vaadin out of the box
    • less customizations
    • get rid of legacy Vaadin 6.x or client-side code
  • Open up APIs to offer more possibilities (data-binding, or dynamic/ cross-field behaviors)
  • Reduce technical debt

...

3.

...

Key Concepts

  • Goals

    • Validate several assumptions from Mika

    • If all goes well, put it all together at the end, through an Integration phase
  • Process

    • To be carried out by the VN Core Team
    • Try to work in pairs (can still switch afterwards), or alternate between group phases and individual work/thinking
    • Keep each PoC standalone until the end of the PoC phase
  • Target date:
    •  

PoC #1: New FormPresenter

Reading definitions and building tabs and fields

  • 1 Vaadin FieldGroup + FormLayout for each tab (merge bits from FormBuilder)
  • Result: a simple Vaadin application (w/ ui-framework on the classpath)
    • Mika might prepare the skeleton on a branch
  • FormPresenter invoking FieldFactories
    • for the PoC, you can instantiate factories manually
    • either refactor existing ones, or reimplement a simple TextFieldFactory with less Magnolia dependencies
      • maybe API like public Field<T> createField(D definition)
      • so we can reuse a single FieldFactory to produce multiple instances of a field
    • FieldFactories no longer doing property data-binding (#setPropertyDataSource)
      • FormPresenter doing the databinding instead => fieldGroup#setItemDataSource
      • -
  • Not needed for the PoC:
    • locale and i18n handling
    • complex fields (only text fields, selects)
    • visual appearance, no MagnoliaTabSheet needed, just a plain VerticalLayout with one-to-many FormLayouts
    • -

PoC #2: Validation bubbles below field

Validation as a Vaadin JS Extension, see the few links below:

Default Vaadin validation is as follows:

  • warning icon
  • tooltip when hovering the field

Image Removed

Extension should primarily add the bubble below

  • Same styles as now
    • see Image Removed
    • bubble width is the same as field width with border
    • arrow tip should be around 30–40px from the left
  • Result: small Vaadin application
    • Apply to a TextField (e.g. using standard Vaadin email validator)
    • If using the Magnolia theme, then field border should become red too
  • Currently tooltip is hidden via CSS in Magnolia
    • we can still do this the same way, maybe as well for the warning icon

PoC #3: Complex Fields refactoring

Goals:

  • Get rid of Magnolia-specific components within field implementations
  • Get rid of AbstractCustomMultiField abstraction

The following three may be done independently:

—without Magnolia component/definition inside field implementations

Pure Vaadin CompositeField
  • close to AccessControlField
  • Except fields are not hard-coded
    • pass sub-fields into constructor?
      • maybe as map with field-names as keys?
    • would help us keeping FieldFactories outside of field implementations
      • i.e. get rid of infamous AbstractCustomMultiField#createLocalField
  • also bind fields internally via FieldGroup?
  • reuse #setValidationVisible and handling of valueChange on sub-fields
  • Result: simple Vaadin application
    • operating over a PropertysetItem or BeanItem
    • part 1. using a CompositeField for First name and Last name
      • laid out horizontally
      • has an API to set direction (minimum requirement)
    • part2. also API to set an arbitrary layout
      • if feasible, but not a must-have
      • or maybe using a Vaadin declarative layout?
Pure Vaadin MultiValueField
  • close to AccessControlListField
  • reuse some form of EntryFieldFactory (maybe also NewEntryHandler if applicable)
  • Result: simple Vaadin application
    • operating over a PropertysetItem or BeanItem
      • i.e. extends CustomField<I extends Item>
      • (lightbulb)or extends CustomField<C extends Collection> (maybe more in line with Vaadin 8?)
    • with a property of type Collection or List, then one entry per entry in the collection
    • field needs to create Vaadin properties for each entry in the list, and bind it internally to sub-fields
    • also bind fields internally via FieldGroup?
    • reuse validation and valueChange logic from AccessControlListField
    • steps:
      1. a MultiField of TextFields (can be hard-coded)
      2. a MultiField of a CustomField type (First name + Last name)
      3. a MultiField with the pluggable NewEntryHandler (closer to use cases in Magnolia where subfields are configured)
Pure Vaadin LinkField
  • Inspired from AccessControlField$PathChooserHandler
  • Result: small Vaadin application
    • see info.magnolia.dev.acls.AccessControlFieldUI in Mika's sandbox
    • opens a Vaadin Window
      • field inside the window shares property data-source with text field

 

4. Integration phase

- To be determined

...

  • e.g. still as a small Vaadin application, but combining configured forms, complex fields, sub-field validation and a dynamic behavior
Note

Key concepts highlight the main direction. Details and realization are work-in-progress, and are being revised regularly.

A new Form “component”

  • Focus on The Big Role
  • Create a Vaadin form that can be bound to Magnolia content
  • Most often produce fields from config / definitions
  • Most often bound to JCR items, and saving the session

Separation of concerns

  1. Field creation
    • Responsible for producing raw fields with UI presets, unbound
    • New FieldFactory: Creating Field from FieldDefinition => clear and simple
  2. Data-binding
    • New binding ways, using FieldGroup (later V8 Binder) instead of set/get datasource in Factory
    • Responsible for binding, default-values, transforming, converter, validation setup
    • Item variation (i18n, p13n) through re-binding? 
  3. Layout
    • Responsible for laying out fields in order
    • Plain Vaadin form with tabsheets, no need to customize, code is more clear and easy to maintain
  • ~ Action(s)
    • Form actions vs. Dialog actions (surrounding UI context)

Break free from MVP

In our experience, the (M)VP pattern is generally regarded as an obstacle. Creating custom forms, apps can be delicate at times, and almost all the time involves hefty boilerplate.
—Even on our side, dealing with evolution of short-lived APIs in a framework code base is a challenging exercise.

This Vaadin blog post Is MVP a Best Practice highlights common caveats of the pattern. This somewhat prevents Magnolia developers from leveraging Vaadin to its full extent. 

  • The split between view and presenter is rather artificial; in practice, coupling remains high.
  • Presenter is typically not Vaadin-free: it hosts Vaadin data APIs, while View has Vaadin ui APIs
  • Every single Vaadin binding or interaction required additional View +/- Listener API
  • Unit-tests became slightly too atomic, with little value
  • No UI-tests below full-fledged integration

Instead, we embrace a more domain-driven, component approach.

  • Form is a magnolia View itself
    • at this stage, Form may not even need an interface
  • Remove artificial-rigid-public intercom between presenters & views
  • No specific FormView interface + FormViewImpl

The Form componentImage Added

The Form component

Flexibility

  • Primarily through delegation to functional interfaces
  • Ideally also through decoration (TBD)
  • Alternatively through extension (config typically mandates implClass)
  • Less through custom field-factories
  • Less through complex fields

Configuration

  • Support current common cases ootb, without config changes
  • Gained flexibility is not necessarily exposed through config at first
  • Rather whoever opens the form/dialog is responsible for its setup
    • e.g. OpenEditDialogAction
    • entails providing sugar / builders with good defaults
  • Introduce simplified + more advanced config gradually
    • e.g. fields on root level / less nesting, layout config
  • No intent to expose config on technical terms
    • e.g. no defs for bindings, delegates, generics, all sorts of highly technical classes
  • No intent for declarative config of interaction logic between fields


4. PoC phase

The PoC phase was conducted in September–October 2016. Refer to child-page Dynamic forms - PoC phase for details and outcome.

5. Productization phase

Based on the PoC results, we first collected the following tasks, in order to bring new forms on par with the current Magnolia forms.


Jira
showSummarytrue
serverMagnolia - Issue tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId500b06a6-e204-3125-b989-2d75b973d05f
keyDEV-419

  • Validate a high-level architecture with clear component responsibilities
    • expose 1. field creation, 2. data-binding, 3. layouting
    • produce architecture diagrams
  • Assess definition changes to support new ways of configuring forms
    • especially moving towards a separation between bindings and layout
  • Envision repackaging
  • Draft eventual backward compatibility (dedicated ticket for that)
  • Iterate from Sang's PoC
  • Keep in mind / draft check if form is dirty or not
  • Provide validation out of the box (upon #submit)
  • Provide approach for default binding & saving of JCR items (not in the centralized Form, either extended or delegated)


Jira
serverMagnolia - Issue tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId500b06a6-e204-3125-b989-2d75b973d05f
keyDEV-441

  • sort out the problem with marking component visible / invisible in JavaScript extensions
  • Safest bet => Roll back to a GWT-based AbstractExtension where we have more power
    • mostly to listen to the target component state changes
  • use plain Vaadin validation state ( state.errorMessage && state.hideErrors )


Jira
serverMagnolia - Issue tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId500b06a6-e204-3125-b989-2d75b973d05f
keyDEV-442

  • Finalize pure-Vaadin implementation of Oanh's PoC.
  • From the Vaadin data-binding perspective:
    • Refine generic-typing or leave it open: move away from Items, in favor of domain types, e.g. CompositeField<Contact>
    • Challenging with Magnolia "loose types"
    • Challenging with JCR adapters in particular
  • No Magnolia definition into the field instance, use Vaadin Orientation enum for layout direction.


Jira
serverMagnolia - Issue tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId500b06a6-e204-3125-b989-2d75b973d05f
keyDEV-443

  • Finalize pure-Vaadin implementation of Oanh's PoC.
  • From the Vaadin data-binding perspective:
    • Refine generic-typing or leave it open: MultivalueFields would in turn be typed with Collection types (List, Set, ordered/unordered, etc.)
    • Challenging with JCR adapters in particular
    • Should support one level of nesting of arbitrary fields, including CompositeFields
  • No Magnolia definition into the field instance.
  • Externalize new item handlers, in line with AccessControlListField


Jira
serverMagnolia - Issue tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId500b06a6-e204-3125-b989-2d75b973d05f
keyDEV-444

  • Show all tabs as Vaadin Extension
  • Port the styling—quickly estimate effort against restart from Valo
  • Focus first field, via plain Vaadin SelectedTabChangeListener?


Jira
serverMagnolia - Issue tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId500b06a6-e204-3125-b989-2d75b973d05f
keyDEV-445

  • Reuse and style Vaadin Windows instead?
  • How about dynamic resizing of dialog height?
  • How to treat form actions (commit) vs. dialog actions (close/cancel)


Jira
serverMagnolia - Issue tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId500b06a6-e204-3125-b989-2d75b973d05f
keyDEV-446

  • again, maybe as Form component extension?
  • + jump to next error


Jira
serverMagnolia - Issue tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId500b06a6-e204-3125-b989-2d75b973d05f
keyDEV-420
  • Start off a common branch in UI with results from previous PoCs
    • Proposing to start in isolation with new UI submodule, to better control UI inter-dependencies and keep new packages apart
    • Still when it's mature enough, the goal would be to relocate the package/module and relocate the legacy stuff as well.
  • Provide a Vaadin test webapp within the UI, to allow testing the real thing outside a full-fledged Magnolia webapp
  • Eventually consider UI-testability of it
    • Provide test-bed for UI tests early
    • Think page objects


F4. [TOFILE] Reimplement i18n support within new Form

  • Generalize "variation" switching
  • aka item datasource decoration somehow
  • so we can support p13n variant-switching similarly

F5. [TOFILE] Refine support for backward compatibility

  • a. binding strategies would cater to backward compatibility with transformers?
  • b. high-level switch to use fully old dialogs / transformers / FormBuilder.... vs. new APIs

F9. [TOFILE] Reimplement help-text bubbles the same way as validation bubbles

F11. [TOFILE] Write UI tests for our 5 user scenarios

  • Can only be done once the basic stones are in place
  • Prove form-level agility (binding upon field(s) constructed)

F12. [TOFILE] Proof-test new APIs against Vaadin 8

  • Ideally, only the data-binding "part" should be affected, not field creation nor layouting

TODO:

  •  File in JIRA / MGNLUI
  •  Estimate
  •  Flesh out, break out into even smaller tasks
  •  Add relative task dependencies
  •  Set deadline for stabilization

Then reevaluate progress after 2–3w.

Unprocessed ideas

  • (lightbulb) binding strategies: default, transformerDelegate...
  • (lightbulb) expose layouting (default from fieldDef + tabs, declarative, or other new mechanism?, responsive forms?)
  • (lightbulb) save actions bundled in Form itself by default, can be delegated to configured action(s)
    • does validate ootb
  • (lightbulb) extensibility: generate wrapper implementations for component interfaces

Related wishful improvements

—i.e. keep out as long as we can / later scope:

  • Valo-based theme switch
  • Generate concrete FieldDefinitions (& builders) from our interfaces
  • Plain Java Decorators (add/remove field by user-based form decorator)
    • supplanting blossom
  • Documentation generation (via pegdown)

 

...