Multi field
info.magnolia.ui.field.MultiFieldDefinition renders a complex field composed of one or more field sets (for example, three sets of two text fields). Magnolia provides four preconfigured multi field definitions:
- 
info.magnolia.ui.field.JcrMultiValueFieldDefinition: allows you to enter multiple values of a single type to be stored as an array in a single JCR property ( jcrMultiValueField).
- 
info.magnolia.ui.field.JcrMultiLinkFieldDefinition: allows you to select multiple values of a single type in a chooser dialog to be stored as an array in a single JCR property ( jcrMultiLinkField).
- 
info.magnolia.ui.field.JcrMultiFieldDefinition: allows you to create multiple JCR fields ( jcrMultiField).
- 
info.magnolia.rest.ui.field.JsonMultiFieldDefinition: allows you to create multiple JSON fields to be used in an app with its own JSON data source ( jsonMultiField).
| These multi field definitions are part of the Magnolia 6 UI framework. Their fully qualified class names are: 
 In the Magnolia 5 UI framework, the field functionally parallel to the JCR fields is Multivalue field. There is no corresponding 5 UI implementation for the JSON multi field. | 
Example definitions
assignedSegments:
  $type: jcrMultiValueField
  label: Multi-value field
  field:
    $type: comboBoxField
    label: Path
    datasource:
      $type: jcrDatasource
      workspace: websitejcrMultiLinkField:
  $type: jcrMultiLinkField
  label: Multi-link field
  field:
    $type: linkField
    label: Page
    datasource:
      $type: jcrDatasource
      workspace: website
damMultiLinkField:
  $type: jcrMultiLinkField
  label: Multi-link field
  chooserId: dam-app-core:multiChooser
  field:
    $type: damLinkField
    label: Assetmulti:
  i18n: true
  $type: jcrMultiField
  label: Address list
  field:
    $type: compositeField
    label: Address
    properties:
      street:
        $type: textField
        label: Street
      city:
        i18n: true
        $type: textField
        label: City
      zip:
        $type: textField
        label: ZIP codestationboard:
  label: Station Board
  $type: jsonMultiField
  itemProvider:
    $type: jsonMultiFieldProvider
  field:
    $type: jsonCompositeField
    idPropertyName: name
    properties:
      name:
        label: Name
        $type: textField
        readOnly: true
      to:
        label: To
        $type: textField
        readOnly: true
      operator:
        label: Operator
        $type: textField
        readOnly: true| JSON data source is read-only.
Therefore, it only supports read-only fields in, typically, the content detail subapp of a read-only REST app.
 The example above is used in the Stations app contained in the field-examples-module. See also Composite field. | 
| You can preview this example using the  | 
Field properties
Common multi field properties
| Property | Description | ||
|---|---|---|---|
| 
 | required Node containing an editor property definition item (typically, a field). All field types are supported. See List of fields for more information. | ||
| 
 | optional (used only in  Unique identifier for the multi-chooser
dialog. If none is specified, the
JCR
 | ||
| 
 | optional, default is 
 Implementation class that defines how the child entries of a multi field should be resolved. 
 | ||
| 
 | optional, default is 
 Implementation class that sorts nodes and ensures that the suffixes in index names correspond to the order in which they are stored. When  | ||
| 
 | optional, default is  When  | ||
| 
 | optional, default is translated  Button label for adding an item. The value is i18n-able. | ||
| 
 | optional, default is translated  Button label for removing an item. The value is i18n-able. | ||
| 
 | optional, default is  Specifies the minimum number of items to be added. | ||
| 
 | optional, default is  Specifies the maximum number of items to be added. 
 | ||
| 
 | optional, default is translated  Error message shown when the number of items is less than
 | ||
| 
 | optional, default is  Makes the field required. An asterisk is displayed next to the field label. | ||
| 
 | optional, default is translated  Error message shown when  | 
Common complex field properties
| Property | Description | ||
|---|---|---|---|
| 
 | required Name of the field definition item. Derived from the configured node name. Use alphanumeric characters without spaces. | ||
| 
 | required (unless  Type of the field definition item. The value must be a fully qualified
class name and a subtype of  | ||
| 
 | You can use this as a shortcut for  Example class annotation See Field types for possible values. | ||
| 
 | required, default is 
 Node with a  For more details, see Item providers. 
 | ||
| 
 | optional Help text displayed when the user clicks the help icon. The value can be literal or a key of a message bundle. | ||
| 
 | optional, default is  Enables i18n authoring support, which allows editors to write foreign-language or regionally targeted content.
A two-letter language identifier ( 
 | ||
| 
 | optional Field label displayed to editors. The value can be literal or a key of a message bundle. If you do not provide the property, Magnolia will fall back to a generated i18n key. If you do not want to have any label, set the property to an empty
string such as  | ||
| 
 | optional Additional style information for an editor property definition item applied to the element when the form is rendered. The value can be a CSS class or a list of CSS classes separated by white spaces. The style name will be rendered as an HTML class name, which can be used in a CSS definition.
The class name is added to the field by calling the Vaadin method  
 | 
Form validation of multiple values
To validate that jcrMultiValueField has only unique values, you can create UniqueValuesMultiFormView
as an implementation class that extends MultiFormView.
public class UniqueValuesMultiFormView<T> extends MultiFormView<T> {
    @Inject
    public UniqueValuesMultiFormView(MultiFormDefinition<T> definition, LocaleContext localeContext, Datasource<T> datasource) {
        super(definition, localeContext, datasource);
    }
    @Override
    public List<BinderValidationStatus<?>> validate() {
        final List<BinderValidationStatus<?>> validate = super.validate();
        if (validate.stream().allMatch(BinderValidationStatus::isOk)) {
            List<String> valuesStringList = validate.stream()
                    .map(v -> v.getBinder().getFields().findFirst().get().getValue()) // could be any data type other than string
                    .map(String::valueOf)
                    .collect(Collectors.toList());
            if (new HashSet<>(valuesStringList).size() != valuesStringList.size()) {
                final Binder.Binding<?, ?> binding = validate.stream()
                        .flatMap(binderValidationStatus -> binderValidationStatus.getFieldValidationStatuses().stream())
                        .map(BindingValidationStatus::getBinding)
                        .findFirst()
                        .orElse(null);
                final BindingValidationStatus<?> validationStatus = new BindingValidationStatus<>(Result.error("All values has to be unique"), binding);
                binding.getValidationStatusHandler().statusChange(validationStatus);
                validate.add(new BinderValidationStatus<>(null, Collections.singletonList(validationStatus), new ArrayList<>()));
            }
        }
        return validate;
    }
}uniqueValues:
  $type: jcrMultiValueField
  implementationClass: info.magnolia.ui.editor.UniqueValuesMultiFormView
  field:
    $type: textField