ddraper

Aikau 1.0.39 - Dynamic Form Field Option Updates

Blog Post created by ddraper on Oct 14, 2015

Amongst all the bug fixes and features added since my last post, in the 1.0.39 release of Aikau we've added a useful addition to our forms capabilities that I thought would be worth calling out. It's actually something that I've been meaning to add for a while but have never had a use-case to drive its inclusion. If you're not familiar with the different ways in which you can provide a from control with options, then you should review the information in this tutorial before reading any further.

 

When using a form control (e.g. Select, ComboBox, MultiSelectInput, RadioButtons), you can provide a “publishTopic” attribute that will be used to request the options for that form control to use, however the published payload didn't provide any data about the the current values of the other fields in the form. We've now updated the Form widget to subscribe to a new topic that can be used to update the options-requesting payload with the current form values and then forward the request onto another topic.

 

In the specific use-case we needed to solve, we needed to get the available sites on the currently selected Cloud network. When the user changed the network we wanted to update a FilteringSelect widget to show the sites for that network.

 

This extract from one of our form models shows how this can be configured

{
  id: 'CLOUD_SYNC_TENANT',
  name: 'alfresco/forms/controls/FilteringSelect',
  config: {
    fieldId: 'CLOUD_SYNC_TENANT',
    name: 'remoteTenantId',
    label: 'cloud-sync.dialog.network.label',
    optionsConfig: {
      queryAttribute: 'value',
      labelAttribute: 'value',
      valueAttribute: 'value',
      publishTopic: topics.GET_CLOUD_TENANTS,
      publishPayload: {
        resultsProperty: 'response'
      }
    }
  }
},
{
  id: 'CLOUD_SYNC_SITE',
  name: 'alfresco/forms/controls/FilteringSelect',
  config: {
    fieldId: 'CLOUD_SYNC_SITE',
    name: 'remoteSiteId',
    label: 'cloud-sync.dialog.site.label',
    optionsConfig: {
      changesTo: [
        {
          targetId: 'CLOUD_SYNC_TENANT'
        }
      ],
      queryAttribute: 'title',
      labelAttribute: 'title',
      valueAttribute: 'shortName',
      publishTopic: topics.GET_FORM_VALUE_DEPENDENT_OPTIONS,
      publishPayload: {
        publishTopic: topics.GET_CLOUD_SITES,
        resultsProperty: 'response'
      },
      publishGlobal: false
    }
  }
},


The key things to notice here are:

    1. We're now using constants for all our topics. As well as reducing the number of string values to maintain, it means that we are able to improve our JSDoc for the topics to include information about the publishers and subscribers of those topics as well as the parameters that should be included in the payloads.
    2. We use topics.GET_FORM_VALUE_DEPENDENT_OPTIONS as the optionsConfig.publishTopic to request that the form (in which the control is placed) should add the current value of all the other fields into the payload provided.
    3. The optionsConfig.publishPayload.publishTopic is assigned the topic that is then published by the form using the updated payload. The subscriber to this topic should provide the options to be displayed.
    4. The optionsConfig.publishGlobal is configured to be false to ensure that the form detects the publication (a Form will generate a unique pubSubScope and pass it on to its child controls in order to scope communication within the form).
    5. It’s also worth noting how the optionsConfig.changesTo configuration is used to trigger a reloading of options as the user switches tenants (networks).

 

In this example the options retrieval is handled by a service subscribing to the topics.GET_CLOUD_SITES. This is able to check the published payload to find the tenant from which to retrieve the sites, e.g:

 

if (payload.username && payload.remoteTenantId)
{
  this.serviceXhr({
    url : AlfConstants.PROXY_URI + 'cloud/people/' + payload.username + '/sites?network=' + payload.remoteTenantId,
    method: 'GET',
    data: payload
  });
}

 

This is obviously just a single example of how this feature could be used. No doubt there will be plenty of other use cases in the future that need to take advantage of this capability.

Outcomes