Adding Dynamic Lists to Forms

The Dynamic List form element runs a script to retrieve items from an external source to populate the form list at request time. The scripts, which can be written in the language of your choice, can use values of other form elements to build dynamic lists of values with relevant content. Using variables, the scripts can access additional information such as the requester's user name or email address. They can be added to a change request form, service form, or service component form.

Dynamic drop-down lists allow you to maintain real-time values for any frequently changing form options. Using any external system’s API, dynamic lists can retrieve lists such as:

  • available organizations to join
  • cost centers that are accessible to a user
  • database types and the appropriate versions for each database type
  • all subnets in the destination selected on the form

Using Commander variables in dynamic list scripts

Some Commander variables can reference other form elements and some Commander variables can reference other information. See Script examples for the Dynamic List form element.

  • The maximum length of variable values is 1000 characters.
  • Dynamic list variables can't have costs associated with them.

Note: The script won't execute until all variables have a value. If the form contains a blank list, the issue might be that one or more variables aren't resolving. To fix this issue, check the Commander log file for the following message: Dynamic list [name] can't resolve variables: [variable names], and provide access to the missing variables.

Access through:

Configuration > Self-Service > Forms

Available to:

Commander Roles of Superuser and Enterprise Admin

Tip: In any text field that supports variables, you can click to open the script editor and select variables for the current context.

To configure a script for the Dynamic List form element:

  1. In the Toolbox section on the right, click Dynamic List.
  2. In the Dynamic List form element, click the Configure link to edit and test the script before publishing it.
  3. In the Edit Script dialog, optionally enter any arguments that you want to pass to the script executable in the Script Arguments field.

    The maximum length is 2048 characters.

  4. In the Script field, enter the script to be executed.

    The result must be a JSON string array.

  5. In the Executable field, enter the executable that will be used run the script.

    If your system environment doesn't have the script executable on its path, you must provide the fully qualified path to it (for example, C:\python37\python.exe). To use PowerShell, you only need to enter powershell.exe.

    Note: Some scripting executables require files to have a particular extension (for example, powershell.exe requires a .ps1 extension for scripts). For an executable that requires a file extension, you must map the executable and file extension in the advanced system property embotics.workflow.embedded.script.extensions. By default, mappings already exist for the following executables: powershell.exe=.ps1, python.exe=.py, cmd.exe=.bat. See Setting system properties in Commander for details on how to modify system properties through Commander.

  6. In the optional Credentials field, select or add guest OS credentials that are required to run the script. See Managing Credentials.

    The credential contents are populated into environment variables that the script can access.

  7. In the Timeout field, adjust the default timeout, if required. The script will fail if it can't be completed within the given time. Maximum timeout is 99 seconds.
  8. In the optional Fallback Value field, enter a value that will be used if the script fails or times out.
  9. Optional: Test your script. See Testing dynamic list scripts.

    The script output has a maximum limit as defined in the advanced system property embotics.execute.command.task.capture.length, which is 512 KB by default.

  10. Click OK.

Notes:  

  • If some lists contain content that's dependent on the selections made in other form elements, arrange the lists so they appear in the form in the order of their dependence, top to bottom. When requesters work from top to bottom on the form, their choices may affect the contents of subsequent lists. If requesters go back and make changes, they may lose some of their selections.
  • You can't create two lists that reference each other.

Testing dynamic list scripts

Use the Test tab of the Edit Script dialog to see the output of your script. If your script contains Commander variables, you can specify the values of each variable in the script and view the results. If there are no variables in your script, the Variable/Value section won't appear in the Test tab of the Edit Script dialog. See Script examples for the Dynamic List form element.

Script status is recorded in the Commander log file. A successful script exit code is 0. Any other exit code means that the script has failed. Details of script failures are displayed in the Test tab result field.

If the script fails during deployment, users will see a generic failure alert, but details of the failure won't be exposed to users. Users will be directed to contact their administrator.

Script examples for the Dynamic List form element

Here are two examples that illustrate how to use dynamic lists.

Example 1: List that depends on another list

The following script retrieves a list of Canadian provinces. The results will be used in the second list. Both dynamic list elements are added in sequence to the form.

$headers = @{Accept = "application/json" }
  $Data = Invoke-RestMethod -Method Get -Uri "http://geogratis.gc.ca/services/geoname/en/codes/province" -Headers $headers
  ($Data.definitions)|Select -ExpandProperty description | ConvertTo-Json

Dynamic List Edit Script Provinces

Running this script in the Test tab shows the list of provinces that will be visible to users.

Dynamic List Test Script Provinces

This script below retrieves the selected province from the list above and inserts it into the variable service.settings.dynamicList['Province']. This script is added to a new Dynamic List form element. From this information, the script produces a list of cities that are relevant to that province.

$headers = @{Accept = "application/json" }	
$Data = Invoke-RestMethod -Method Get -Uri "http://geogratis.gc.ca/services/geoname/en/codes/province" -Headers $headers
$Provinceid = $Data.definitions | Where-Object {$_.description -eq "#{service.settings.dynamicList['Province']}"} | Select-object code -ExpandProperty code
$CityData = Invoke-RestMethod -Method Get -Uri "http://geogratis.gc.ca/services/geoname/en/geonames?province=$Provinceid&concise=CITY" -Headers $headers

$result = @()

if ($CityData.items.Length > 1) {
   $result += $CityData.items |Select -ExpandProperty name 
} else {
   $result = $CityData.items |Select -ExpandProperty name
}

ConvertTo-Json @($result)

Dynamic List Edit Script Cities

Running this script in the Test tab shows the list of cities that will be visible to users after they have selected the province Ontario. Using this Test tab, you can change the value of the variables in the script, run the script, and see the appropriate output.

Dynamic List Test Script Cities

In the Service Catalog, the two lists will be available for selection; a list of provinces and a list of cities for the province that was selected in the first list.

Example 2: List that includes credentials to an API request using environment variables

This is an example of how a script that can be used for a dynamic list form element can retrieve the username and password from the credentials. The credentials selected in the Edit Script dialog are injected into the script's environment variables. This sample script accesses Commander metadata to get a list of services.

$user = (Get-Item Env:SELECTED_CREDENTIALS_USERNAME).value;
$pass= (Get-Item Env:SELECTED_CREDENTIALS_PASSWORD).value;
$secpasswd = ConvertTo-SecureString $pass -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($user, $secpasswd)
$headers = @{Accept = "application/json" }
$Data = Invoke-RestMethod -Method Get -cred $cred -Uri "https://#{system.address}:#{system.port}/rest/v3/services" -Headers $headers
$Data.items |Select -ExpandProperty name | ConvertTo-Json