Dependent field

Dependent field modifies a field on a form depending on the value of one or more other fields.

Note that only value and dropdown modes are currently implemented.

Dependent field has three modes:

  • value – set the value of the field
  • dropdown – set the items in the dropdown
  • show – show or hide the field

The modification is controlled by server-side processing, which can either be run or executed.

Value mode

In value mode the dependent field is only set if it was initially blank and if the user has not modified it. Once the user has modified the field, it is not changed.

Dropdown mode

Dropdown mode runs initially and every time any of the depends on field changes.

Show mode

show mode runs initially and every time any of the depends on field changes.

Options

Each of these is specified in the same way, using a class of "dependent-field" and a data-options attribute. The data options may contain the following.

mode The mode. Must be one of "value", "dropdown" or "show".
dependsOn The name of the field on which this depends, or an array of field names.
method Whether to "execute" or "run" a script.
script When method is run, the node version reference of the script to run.
context

When method is run, value to be passed as the context parameter.

When method is execute, node to be executed.

Defaults to the nodeVersionReference of the page.

params

Additional parameters to be passed to the script or the execute.

For execute, this would typically include an action parameter.

lookup

As an alternative to setting a script, provide a lookup object which provides values for the data for the first or only depends on field. For example, 

{
"lookup": {
"yes":"You have responded in the affirmative",
"no":"You say no"
}
}

This is most useful for dropdowns, where each value in the lookup object would be an items array.

Use a "default" lookup property for unknown values.

If you want to share lookups between fields, you can write the lookup to a hidden field or a hidden div, and provide jQuery selector for it in lookup.

For example

{
"lookup": "input[name=\"lookup-values\"]"
}

Means "read lookup value from the value of the lookup-values input.

Alternatively, you could use a div, something like.

<div class="d-none" id="lookup-values">
{
"animals":[{"value":"horse","name":"Horse"},{"value":"dog","name":"Dog"}],
"fruit":[{"value":"apple","name":"Apple"},{"value":"banana","name":"Banana"}],
"default":[{"value":"","name":"Please select"}]
}
</div>

 And then use this

{
"lookup": "#lookup-values"
}

Script conventions

The executed or run script will be passed the following parameters.

context In run mode, the calling context. In execute mode, this can be found using application.getContext().
data

A JSON object which contains the values of each of the fields on which this field depends, plus the original dependsOn as an array (a single field is converted to a 1-item array).

For example, if "dependsOn" was set to ["name","email"], then data might be

{
"dependsOn": ["name","email"],
"name": "John smith",
"email": "john.smith@somewhere.com"
}
... Additional parameters, as specified in the params option.

The script should return in the <return> element a JSON object the data property of which contains the required value, depending on the mode.

value A text string for the suggested value.
dropdown A JSON array with objects with name and value, as used by the dropdown field "items" property.
show true to show the field, false to not show the field.

Example field

This example shows how to use script mode to set the suggested value of a user id field based on an email address.

The options for this might be:

{
"mode": "value",
"dependsOn": "email",
"method": "run",
"script": "library.user.EmailToUserIdDependentFieldScript"
}

The form has two fields

<input name="email" type="text"/>
<input name="userId" type="text" class="dependent-field" data-options=".. options .."/>

Example script

The server-based script in library.user.EmailToUserIdDependentFieldScript would be something like this.

It suggest a user id based on the first bit of the email address, incrementing this as necessary if the id is already used.

var request = application.get('request');
var data = application.parseJSON(request.getString('data'),{});

function main(){
  var userId = '';
  // We only expect one field value, so extract it from the data
var fieldName = data.dependsOn[0];
  if ( fieldName ) {
    var emailAddress = data[fieldName];
    var atPos = emailAddress.indexOf('@');
    var nameRoot = atPos == -1 ? emailAddress : emailAddress.substr(0,atPos);
    if ( nameRoot ) {
      var userId = nameRoot
      var nextSuffix = 2;
      while(application.service(
        '<UserExists><reference>' + application.escape(userId) + '</reference></UserExists>'
      ).getString('referenceExists') == 'true' ) {
        userId = nameRoot + nextSuffix++;
      } 
    }  
  }
application.put('return',application.stringify({data:userId}));
}

if (!application.errorFound()) {
  main();
}

Lookups

For simple dropdown dependencies, you can use an additional parameter that contains the lookup values from the values of the depends-on field to the items that should be shown in the dependent field. If you have many dropdowns with the same dependencies, you can create a hidden lookup field that contains a lookup field.

Pass the depends-on field and the lookup as the dependsOn property.

Use a simple script to return the correct items from the lookup.

var params = JSON.parse(application.get('request').getString('data'));
var field = params[String(params.dependsOn[0])];
// Use this if passed in params
var lookup = params.lookup;
// Use this if a dependends-on hidden field
var lookup = application.parseJSON(params[String(params.dependsOn[1])],{});
var items = lookup[field];
if ( !items ) {
  items = [
    { value: '', name: 'Select an option' }
  ];
}
application.put('return', application.stringify({data:items}));