Edit online

Dynamically Add Form Controls Using a Styles Filter

Use Case

You want to add form controls using an API.

Solution

Usually, a form control is added from the CSS using one of the built-in form controls. However, in some cases you do not have all the information you need to properly initialize the form control at CSS level. In these cases you can add the form controls by using the API, more specifically ro.sync.ecss.extensions.api.StylesFilter.

For instance, if you want a combo box form control and the values to populate the combo are specified inside a file (or they come from a database). Here is how to add the form control from the API:

public class SDFStylesFilter implements StylesFilter {

 public Styles filter(Styles styles, AuthorNode authorNode) {
  if(authorNode.getType() == AuthorNode.NODE_TYPE_PSEUDO_ELEMENT 
      && "before".equals(authorNode.getName())) {
    authorNode = authorNode.getParent();
   if ("country".equals(authorNode.getName())) {
    // This is the BEFORE pseudo element of the "country" element.
    // Read the supported countries from the configuration file.
    Map<String, Object> formControlArgs = new HashMap<String, Object>();
    formControlArgs.put(InplaceEditorArgumentKeys.PROPERTY_EDIT, "#text");
    formControlArgs.put(InplaceEditorArgumentKeys.PROPERTY_TYPE, 
          InplaceEditorArgumentKeys.TYPE_COMBOBOX);
    // This will be a comma separated enumeration: France, Spain, Great Britain
    String countries = readCountriesFromFile();
    formControlArgs.put(InplaceEditorArgumentKeys.PROPERTY_VALUES, countries);
    formControlArgs.put(InplaceEditorArgumentKeys.PROPERTY_EDITABLE, "false");

    // We also add a label in form of the form control.
    Map<String, Object> labelProps = new HashMap<String, Object>();
    labelProps.put("text", "Country: ");
    labelProps.put("styles", "* {width: 100px; color: gray;}");
    StaticContent[] mixedContent = new StaticContent[] 
           {new LabelContent(labelProps),new EditorContent(formControlArgs)};
    styles.setProperty(Styles.KEY_MIXED_CONTENT, mixedContent);
      }
    }
    
    // The added form control is the only way the element can be edited.
    if ("country".equals(authorNode.getName())) {
      styles.setProperty(Styles.KEY_VISIBITY, "-oxy-collapse-text");
    }

    return styles;
  }
}
If the execution of the formControlArgs.put(InplaceEditorArgumentKeys.PROPERTY_VALUES, countries); line consumes too much execution time (for example, if it connects to a database or if it needs to extract data from a very large file), you can choose to delay it until the values are actually needed by the form control. This approach is called lazy evaluation and can be implemented as follows:
formControlArgs.put(InplaceEditorArgumentKeys.PROPERTY_VALUES, 
           new LazyValue<List<CIValue>>() {
  public java.util.List<CIValue> get() {
    // We avoid reading the possible values until they are actually requested.
    // This will be a List with CIValues created over countries:
           France, Spain, Great Britain
    return readCountriesFromFile();
  }
});
The lazy evaluation approach can be used for the following form controls properties:
  • InplaceEditorArgumentKeys.PROPERTY_VALUES
  • InplaceEditorArgumentKeys.PROPERTY_LABELS
  • InplaceEditorArgumentKeys.PROPERTY_TOOLTIPS

The full source code for this example is available inside the Oxygen SDK.