Changing the Options list

From pmusers
Jump to: navigation, search

This documentation provides three ways to dynamically change the list of available options in a Dynaform field (dropdown box, suggest box, radio button or checkgroup).

1. Use an SQL query with a dependent field

The recommended way to dynamically add or remove options from dropdown boxes, suggest boxes, radio buttons and checkgroups is to create an dependent field query, which will add or remove options from the list, depending on the value entered in other fields.

For example, a company wants to offer services to its clients, but those services depend on the type of client. A Dynaform contains a dropdown box with the ID "clientType", which has the following list of options:

KEY              |  LABEL
large_business   |  Large business 
single_person    |  Single person
contractor       |  Contractor

Depending on which type of client is selected, the list of options will change in a radio button below with the ID "selectService".

A PM Table is constructed which holds the available options which will be listed in the "selectService" radio button. For example, the following PM_TABLE named PMT_CLIENT_SERVICES holds the list of available options for the radio button:

1    | accounting     | Accounting        | large_business
2    | planning       | Business planning | large_business,single_person
3    | legal          | Legal services    | large_business,single_person
4    | catering       | Catering          | large_business,single_person,contractor

If the client is a large business then all the services are offered. If the client is a single person, then legal services, business planning and catering are offered. If a contractor, then only catering is offered.

Then, use the following SQL query in the "selectService" radio button, to limit which options are displayed:


2. Use an SQL query and JavaScript to filter the list

The first method list above is the easiest way to filter the list of available services, but the information to filter the list has to be included in the database table. If wishing to use JavaScript to determine the options for each type of client, then add a text field with the ID "servicesList". Then, use the following SQL query in the "selectService" radio button:


Finally, add the following JavaScript code to the Dynaform to populate the list in the "servicesList" field:

//hide the "servicesList" field when the Dynaform loads so the user won't see it:

function setServicesList(clientType) {
   var list = '';
   if (clientType == "large_business") {
      list = "'accounting','planning','legal','catering'";
   else if (clientType == "single_person") {
      list = "'planning','legal','catering'";
   else if (clientType == "contractor") {
      list = "'catering'";
//execute when user changes a client type:   
$("#clientType").setOnchange(function(newVal, oldVal) {

//execute when the Dynaform loads:
setServicesList( $("#clientType").getValue() );

Note: The "servicesList" field must be a text field, because hidden fields can't be used in dependent field queries.

3. Use JavaScript to modify the model information for the field

It is recommended that either a source variable or an SQL query be used to modify the list of options in a dropdown, suggest, checkgroup or radio, as shown in the above examples. However, if the list of options cannot be known beforehand, such as allowing a user to dynamically add options to the list while filling out the form, then JavaScript needs to be used to modify the list of options in the field's model.

The mergeRemoteOptions() function is used by ProcessMaker to add an array of options which were returned by an SQL query to the end of the list of fixed options which were set in the options property of a dropdown, suggest, checkgroup or radio:

      value: "value1", 
      label: "label1"
      value: "value2", 
      label: "label2"

For example, to add two options to the "selectService" radio button:

getFieldById("selectService").model.mergeRemoteOptions([{value:"cleaning", label:"Cleaning Service"}, {value:"lawn", label:"Lawn Service"}])

The problem is that mergeRemoteOptions() will overwrite all the existing options which were added by an SQL query. If needing to preserve the list of existing options, then add the new option to the end of the model.attributes.remoteOptions array where the existing options from the last SQL query are stored and then call mergeRemoteOptions().

For example, the following code adds a new option to the "selectService" radio button while preserving the list of options set by the last SQL Query:

getFieldById("selectService").model.attributes.remoteOptions.push( {value: "redecorating", label: "Redecorating"} );
var aOptions = getFieldById("selectService").model.attributes.remoteOptions;

If the SQL query for the field is reexecuted because it contains a dependent field whose value has been changed by the user, then it will overwrite the list of options in the model.attributes.remoteOptions array. The way to get around this problem is to add the new option to model.attributes.localOptions, which is an array of the fixed options that were set by the options property of the dropdown, suggest, checkgroup or radio. Changing the localOptions array will not cause the list of options to be updated on the screen, so mergeRemoteOptions() needs to be called afterwards to display the changed list of options to the user.

For example:

getFieldById("selectService").model.attributes.localOptions.push( {value: "lawn", label: "Lawn Service"} );
var aOptions = getFieldById("selectService").model.attributes.remoteOptions;

Deleting an option from the localOptions or remoteOptions array is a bit more difficult. If the order of the options is known, then the Array.splice() method can be used to remove an option.

For example, the following code removes the third option in the "selectService" field and then displays the changed list of options:

getFieldById("selectService").model.attributes.localOptions.splice(2, 1);

Note that arrays start counting from 0, so 2 is the third option in the array.

If the order of the options is not known, then the code will have to search through the array for the option to remove and then call .splice(). For example, the following code deletes an option whose value is "lawn":

var opts = getFieldById("selectService").model.attributes.localOptions;
for (var i = 0; i < opts.length; i++) {
   if (opts[i].value == "lawn") {
       getFieldById("selectService").model.attributes.localOptions.splice(i, 1);

The problem with using JavaScript to add and remove options from a list is that if the Dynaform is redisplayed, the original list of options will be used. If the field is set to an option which is isn't in the original list of options, then field will be displayed as blank. JavaScript needs to be added that will recreate the list of options as it existed the last time the Dynaform was displayed. For this reason, it is recommended to use SQL queries with dependent fields to create the list of available options, because it is reproducible if the Dynaform is opened a second time.

Understanding how mergeRemoteOptions() works

When the getFieldById("field-id").model.mergeRemoteOptions() function is executed, it first overwrites the list of options from the last SQL query, stored in getFieldById("field-id").model.attributes.remoteOptions.

Then, it concatenates the .remoteOptions array to the end of the .localOptions array and writes that to:

Finally, it takes the complete list in the .options array and displays that in the list of options for the field, so that it is visible to the user.

Changing options in grid fields

To add a new options to a dropdown field inside a grid, the options list in each dropdown in the grid rows can be modified with the following function:

getFieldById("grid-id").gridtable[row][column].model.mergeRemoteOptions([{[value:"value1", label:"label1"}, ...})

Where row and column are integers that count the grid rows and fields in each row starting from the number 0, so gridtable[1][3] is the fourth field in the second row of the grid.

The following JavaScript code example adds two options to a dropdown in all rows of a grid whose ID is "clientsList". The dropdown is the fourth field in the grid.

var gridId = 'clientsList'; //set to grid ID
var dropdownColNo = 3; //set to the column number of the dropdown in grid. Count columns from 0.
var aNewOptions = [{value:"cleaning", label:"Cleaning Service"}, {value:"lawn", label:"Lawn Service"}];

//add new options to dropdown in all existing rows in grid when the dynaform loads:
var rowCount = $("#"+gridId).getNumberRows();

for (i = 0; i < rowCount; i++) {

//add new options to dropdown when a new row is added to the grid 
$("#"+gridId).onAddRow( function(aNewRow, oGrid, newRowNo) {
  //newRowNo counts row numbers starting from 1, so subtract 1 for gridtable which counts from 0: