---
keyword: [Extend, PMD Scripting, Scripts]
nav: wcp_docs
parent_url: /wcp_docs/
title: >- 
  Reference: PMD Scripting Examples
layout: subsection
---

## <a id="section_checkBoxOnChange"></a>Setting a Dependent Widget Value Using the onChange Event

This example demonstrates how to set a widget value based on another widget value using the `onChange` event. When the user changes the value on the `checkBox`, the script sets the value of the `instanceList`.

This sample edit PMD uses:

-   PMD Scripting, which uses the `<% %>` notation.
-   A `script` block that declares a function, `getSelectedValues`. This function returns a list whose value depends on the selected value of the input `checkBox` widget.
-   The `onChange` attribute of the sample `checkBoxId` tag. The sample `onChange` event handler:

    -   Calls the sample `getSelectedValues` function to set the value of `dependentInstanceList`.
    -   Uses the `selectedEntries[0].descriptor` property of an instanceList to display the selected list entry on a text widget.

-   The `selectedValues` attribute of the sample `dependentInstanceList` tag. The embedded script calls the `getSelectedValues` function to display the default list value when the page loads.


```
{
  "id": "dependentList",
  "script" : "<%
    // This function returns a list containing either 'yes' or 'no'.
    var getSelectedValues = function(thisCheckBox) {
        !(empty thisCheckBox.value) ? (thisCheckBox.value == 'true' ? ['yes'] : ['no']) : ['no'];
    }
  %>",
  "presentation": {
    "pageType": "edit",
    "body": {
      "type": "section",
      "horizontal": false,
      "children": [
        {
          "type": "checkBox",
          "label": "Check this box to cast your vote:",
          "id": "checkBoxId",
          "onChange": "<%
             dependentInstanceList.value = getSelectedValues(self);
             selectedValueOnList.value = dependentInstanceList.selectedEntries[0].descriptor
          %>"
        },
        {
          "type": "instanceList",
          "id": "dependentInstanceList",
          "label": "This instanceList depends on your checkBox vote:",
          "selectedValues": "<% getSelectedValues(checkBoxId) %>",
          "instanceList": [
            {
              "id": "yes",
              "descriptor": "Yes"
            },
            {
              "id": "no",
              "descriptor": "No"
            }
          ]
        },
        {
          "type": "text",
          "id": "selectedValueOnList",
          "label": "Selected value on instanceList"
        }
      ]
    }
  }
}
```

## <a id="section_grid"></a>Displaying Data in a Grid and Auto-Populating a FieldSet

This example demonstrates a `grid` and an automatically populated `fieldSet`. In this scenario, an edit PMD contains these tags:

-   `expenseGrid` - A selection-enabled `grid` that displays expense entries from the `expenses` endpoint.
-   `summary` - A `fieldSet` that displays a `text` widget with the selected expense entries and another `text` widget with the total expense amount. The summary automatically updates the values when the user changes the grid selection.


This sample PMD uses:

-   PMD Scripting, which uses the `<% %>` notation.
-   A `script` block that declares a function, `selectRow`. This function updates the widgets in the `summary` fieldSet.
-   Scripted `rows` and `value` attributes of the `expenseGrid`.
-   The `onRowSelect` attribute on the `expenseGrid` tag. `onRowSelect` is the event that calls the `selectRow` function.


```
{
  "id": "gridAutoFieldSet",
  "endPoints": [
    {
      "name": "expenses",
      "baseUrlType": "workday-expense",
      "url": "/entries",
      "authType": "sso"
    }
  ],
  "script": "<%
    var selectRow = function(grid) {
      var nameList = [];
      var expenses = 0;
      for (var row : grid.selectedRows) {
        nameList.add(
          row.childrenMap.dateColumnId.value + ' ' +
          row.childrenMap.merchantColumnId.value
        );
        expenses += number:convertStringToInt(row.childrenMap.expenseColumnId.value);
      }
      /* Update Summary */
      if (!(empty(nameList))) {
        names.value = nameList.join(', ');
        names.visible = true;
        total.value = expenses;
        total.visible = true;
      }
      else {
        names.value = '';
        names.visible = false;
        total.value = 0;
        total.visible = false;
      }
    };
   %>",
  "presentation": {
    "pageType": "EDIT",
    "body": {
      "type": "fieldSet",
      "children": [
        {
          "type": "grid",
          "id": "expenseGrid",
          "label": "Employee Expenses",
          "doNotAdd": true,
          "doNotRemove": true,
          "selectionEnabled": true,
          "maxRowSelection": 10,
          "rows": "<% expenses.data %>",
          "rowVariableName": "row",
          "onRowSelect": "<% selectRow(self); %>",
          "columns": [
            {
              "type": "column",
              "columnId": "dateColumnId",
              "label": "Date",
              "cellTemplate": {
                "type": "text",
                "id": "expDate",
                "value": "<% row.date %>",
                "enabled": false
              }
            },
            {
              "type": "column",
              "columnId": "merchantColumnId",
              "label": "Expense",
              "cellTemplate": {
                "type": "text",
                "id": "expMerchant",
                "value": "<% row.merchant %>",
                "enabled": false
              }
            },
            {
              "type": "column",
              "columnId": "expenseColumnId",
              "label": "Amount",
              "cellTemplate": {
                "type": "text",
                "id": "expAmount",
                "currencyCode": "USD",
                "value": "<% row.amount.value %>",
                "enabled": false
              }
            }
          ]
        },
        {
          "type": "fieldSet",
          "title": "Summary of Selected Expenses",
          "id": "summary",
          "children": [{
             "type": "text",
             "label": "Selected Expense",
             "id": "names",
              "visible": "false",
              "enabled": false
           }, {
              "type": "currency",
              "label": "Total Expense",
              "id": "total",
              "currencyCode": "USD",
              "visible": "false",
              "enabled": false
           }
          ]
        }
      ]
    }
  }
}
```

## <a id="section_container"></a>Displaying Data in Container Widgets and Calculating a Total

This example demonstrates a `loop` that displays a `fieldSet` containing team event expenses. This example also demonstrates a script that calculates the total expense for a selected team and displays the dependent total. In this scenario, an edit PMD contains these tags:

-   `teamContainer` - A `fieldSet` containing a `currency` widget that displays each team expense.
-   `teamLoop` - A loop that displays a `fieldSet` for each team returned by the `teams` endpoint. This snippet displays the data from the sample `teams` endpoint:

    ```
    [
        {
            "id": "1",
            "name": "TeamA",
            "parking": 25,
            "food": 225,
            "drink": 100
        },
        {
            "id": "2",
            "name": "TeamB",
            "parking": 50,
            "food": 125,
            "drink": 200
        }
    ]
    ```



This sample PMD uses:

-   PMD Scripting, which uses the `<% %>` notation.
-   Scripted `on` attribute of the `teamLoop`. The `teamFieldSet` also uses embedded scripts on the `value` attributes of its widgets.
-   The `onChange` attribute on the `teamList` dropdown tag. `onChange` is the event that calls an embedded script, which calculates the total expense of the selected team. The script also sets the `value` of the `total` text widget.


```
{
  "id": "pmdScriptingContainer",
  "endPoints": [
    {
      "name": "teams",
      "baseUrlType": "sampleBaseUrl",
      "url": "/teams"
    }
  ],
  "presentation": {
    "pageType": "EDIT",
    "body": {
      "type": "fieldSet",
      "children": [
        {
          "type": "fieldSet",
          "id": "teamContainer",
          "title": "Team Event Expenses",
          "horizontal": "true",
          "children": [{
            "type": "loop",
            "id": "teamLoop",
            "on": "<% teams %>",
            "as": "team",
            "children": [{
              "type": "fieldSet",
              "id": "teamFieldSet",
              "title": "<% team.name %>",
              "children": [
                {
                  "type": "hidden",
                  "id": "id",
                  "value": "<% team.id %>"
                },
                {
                  "type": "currency",
                  "id": "parking",
                  "label": "Parking Fee ($): ",
                  "value": "<% team.parking %>",
                  "currencyCode": "USD",
                  "enabled": false
                },
                {
                  "type": "currency",
                  "id": "food",
                  "label": "Food ($): ",
                  "value": "<% team.food %>",
                  "currencyCode": "USD",
                  "enabled": false
                },
                {
                  "type": "currency",
                  "id": "drink",
                  "label": "Drink ($): ",
                  "value": "<% team.drink %>",
                  "currencyCode": "USD",
                  "enabled": false
                }
              ]
            }]
          }]
        },
        {
          "type": "dropdown",
          "id": "teamList",
          "label": "Select a team to calculate its total expense:",
          "instanceList": [{
            "id": "1",
            "descriptor": "TeamA"
          }, {
            "id": "2",
            "descriptor": "TeamB"
          }],
          "onChange": "<%
            if (! (empty self.value)) {
              var id = self.value.get(0);
              var childrenMap;
              for (var team : teamContainer.children) {
                if (team.childrenMap.id.value == id) {
                  childrenMap = team.childrenMap;
                  break;
                }
              }
              total.value = childrenMap.parking.value + childrenMap.food.value + childrenMap.drink.value;
            }
            else {
              total.value = 0;
            }
          %>"
        },
        {
          "type": "currency",
          "label": "Total ($):",
          "id": "total",
          "currencyCode": "USD",
          "value": 0,
          "enabled": false
        }
      ]
    }
  }
}
```

## <a id="section_validation"></a>Validations

This example demonstrates PMD Scripting with widget-level validation functions. In this scenario, a view page contains 2 pairs of `text` and `dropdown` widgets. Each pair contains a copy of the first widget. Each widget uses the `onChange` event to call a validation function.

```
{
  "id": "validation",
  "script": "<%
    var validateDataFieldCopy = function() {
      if (empty dataFieldCopy.value || dataField.value == dataFieldCopy.value) {
        dataFieldCopy.clearError();
      }
      else {
        dataFieldCopy.setError('Doesn\\'t Match Data Field.');
      }
    };

    var validateDataListCopy = function() {
      if (empty dataList.value || empty dataListCopy.value || dataList.value[0] == dataListCopy.value[0]) {
        dataListCopy.clearWarning();
      }
      else {
        dataListCopy.setWarning('Doesn\\'t Match Data List.');
      }
    };
  %>",
  "presentation": {
    "pageType": "EDIT",
    "body": {
      "type": "fieldSet",
      "children": [
        {
          "type": "text",
          "label": "Data Field",
          "id": "dataField",
          "onChange": "<% validateDataFieldCopy(); %>"
        },
        {
          "type": "text",
          "label": "Data Field Copy",
          "id": "dataFieldCopy",
          "onChange": "<% validateDataFieldCopy(); %>"
        },
        {
          "type": "dropdown",
          "label": "Data List",
          "id": "dataList",
          "instanceList": [
            {
              "id": "Foo",
              "descriptor": "Foo"
            },
            {
              "id": "Bar",
              "descriptor": "Bar"
            }
          ],
          "onChange": "<% validateDataListCopy(); %>"
        },
        {
          "type": "dropdown",
          "label": "Data List Copy",
          "id": "dataListCopy",
          "instanceList": [
            {
              "id": "Foo",
              "descriptor": "Foo"
            },
            {
              "id": "Bar",
              "descriptor": "Bar"
            }
          ],
          "onChange": "<% validateDataListCopy(); %>"
        }
      ]
    }
  }
}
```

This next example validates the widget data by invoking a deferred endpoint:

```
{
    "type": "text",
    "label": "Enter a country: usa or canada",
    "id": "cou",
    "onChange": "<%
        if (['usa', 'canada'].contains(self.value)) {
            var data = countryData.invoke({'country':self.value});
            someWidget.value = data.city;
            self.clearError();
        }
        else {
            self.setError('Country code is not supported!');
        }
    %>"
}
```

This snippet is the sample deferred endpoint:

```
"endPoints": [
  {
    "name": "countryData",
    "baseUrlType": "sampleBaseUrl",
    "url": "<% '/sampleEndpoint/countries/' + country %>",
    "deferred": true
  }
]
```

For page-level validations, use the `onSubmit` event on the edit PMD. For an example, see `onSubmit` on [Reference: PMD Scripting Events](/wcp_docs/tgy1581495452394.html).

## <a id="section_sendingDataFlow"></a>Sending Data in a Page Flow

This example demonstrates an `onSend` event handler that creates JSON data containing selected widget values, and sends the data as a flow variable for the next page. In this scenario, a sample edit PMD (`teamMemberSelection`) uses these widgets:

-   `teamList` - A `dropdown` that uses an `onChange` event handler. It calls the `selectTeam` function to populate `memberGrid` based on the selected team.
-   `memberGrid` - A `grid` that displays the list of names from the `selectTeam` function.


```
{
  "type": "dropdown",
  "id": "teamList",
  "label": "Team",
  "required": true,
  "instanceList": [
    {
      "id": "TeamA",
      "descriptor": "TeamA"
    },
    {
      "id": "TeamB",
      "descriptor": "TeamB"
    }
  ],
  "onChange": "<% selectTeam(empty self.value ? null : self.value[0]); %>"
},
{
  "type": "grid",
  "id": "memberGrid",
  "label": "Members",
  "rows": "<% [] %>",
  "rowVariableName": "member",
  "selectionEnabled": true,
  "maxRowSelection": 10,
  "columns": [
    {
      "type": "column",
      "columnId": "name",
      "label": "Name",
      "cellTemplate": {
        "type": "text",
        "id": "name",
        "enabled": false,
        "value": "<% member.name %>"
      }
    }
  ]
}
```

When the user clicks <b>OK</b> after making selections on the dropdown and the grid, the PMD saves the selections in a flow variable. This sample `outboundVariable` uses an `onSend` event handler that stores `team` and `selectedMembers` in the flow variable. Note that the `teamList` and `memberGrid` tags don't use the `valueOutBinding` attribute, so the `onSend` event handler creates the full JSON data from their selected values.

```
{
  "type": "outboundVariable",
  "name": "selectedTeamMembers",
  "variableScope": "flow",
  "onSend": "<%
    {
      'team': teamList.value[0],
      'selectedMembers': getSelectedMembers()
    }
  %>"
}
```

This `script` block contains the `selectTeam` and `getSelectedMembers` functions:

```
"script": "<%
        var selectTeam = function(team) {
            var members = [];
            if (team == 'TeamA') {
                members = [{'name': 'Logan Mcneil'}, {'name': 'Steve Morgan'}];
            }
            else if (team == 'TeamB') {
                members = [{'name': 'Betty Liu'}, {'name': 'Steve Kerr'}, {'name': 'Tom Taylor'}, {'name': 'John Thomas'}];
            }
            memberGrid.rows = members;
        };

        var getSelectedMembers = function() {
            return memberGrid.selectedRows.map(row => {
                row.childrenMap.name.value
            });
        };
%>",
```

The next page in the sample flow is `teamMemberSummary`, which displays the selected team members and related information. This sample `text` widget on `teamMemberSummary` displays the contents of the `selectedTeamMembers` flow variable:

```
{
  "type": "text",
  "label": "Selected members from the memberGrid",
  "value": "<%
     flowVariables.selectedTeamMembers.toString()
  %>"
}
```

This AMD snippet displays the sample flow definition from the `teamMemberSelection` page to the `teamMemberSummary` page:

```
{
      "id": "onSendFlowDef",
      "name": "onSendFlowDef",
      "flowSteps": [
        {
          "id": "onSend1",
          "taskId": "teamMemberSelection",
          "startsFlow": true,
          "transitions": [
            {
              "order": "a",
              "id": "onSend2",
              "value": "onSend2",
              "condition": "true"
            }
          ]
        },
        {
          "id": "onSend2",
          "taskId": "teamMemberSummary",
          "name": "b",
          "endsFlow": true,
          "transitions": [
            {
              "order": "a",
              "id": "onSendVariableDone",
              "value": "onSendVariableDone",
              "condition": "true"
            }
          ]
        },
        {
          "id": "onSendVariableDone",
          "excludeFromFlow": true,
          "taskId": "root"
        }
      ]
    }
```

## <a id="section_consoleLogging"></a>Console Logging

This outbound endpoint `onSend` event handler uses the `console.debug` method to log the outbound data from a grid row in the console:

```
{
  "name": "updateExpense",
  "authType": "SSO",
  "url": "<% '/entries/' + entryId.value.urlEncode() %>",
  "baseUrlType": "workday-expense",
  "httpMethod": "PATCH",
  "onSend":"<%
    var currRowSelected = false;
    /* Check if the current row is selected. */
    for (var row : theGridId.selectedRows) {
      if (row.childrenMap.column0.value == entryId.value) {
        currRowSelected = true;
        break;
      }
    }
    /* Returning null for unselected row is to prevent current outbound endpoint from invoking. */
    console.debug('Debug: Expense entry id: ', entryId.value, '\\nOutbound data: ', self.data);
    currRowSelected ? self.data : null;
  %>"
}
```

To view the log entries in the Console, select <b>Analytics</b> from the <b>Console</b> section of the Developer Site menu. Navigate to the <b>Logs</b> tab and submit this filter:

```
wd_category is console
```

The `wd_message` log field displays the console messages from the PMD script. Example:

```
Debug: Expense entry id: 12faa9b603900114300f05fd23002c16
Outbound data: {amount={value=300, currency=USD}, memo=Training Project 3, id=12faa9b603900114300f05fd23002c16}"
```

### Related Information

[Concept: PMD Scripting](/wcp_docs/oli1581402304020.html)

[Reference: PMD Scripting Syntax](/wcp_docs/snh1581402351791.html)

[PMD Scripting](/wcp_docs/jab1582081565510.html)

[App Catalog: PMD Scripting](/app-catalog/pmdScripting)

