---
category: [Administration & Integrations, Platform and Product Extensions, Platform and Product Extensions/Integration, Administration & Integrations/Custom Integrations & Apps, Platform and Product Extensions/Workday Extend]
keyword: [Extend, PMD Scripting, Scripts]
nav: wcp_docs
parent_url: /wcp_docs/
title: >- 
  Concept: PMD Scripting
layout: subsection
---

## <a id="section_overview"></a>Overview

PMD Scripting is a server-side scripting language that enables you to author and embed multiline scripts in the PMD. Use PMD Scripting to:

-   Call PMD functions that manipulate data upon displaying it on the page or submitting it to outbound endpoints.
-   Call widget methods that get or set widget properties. A widget is the runtime instance of the PMD tag. The ability to code business logic and dynamically set widget properties replaces the need to use dynamic bindings on tag attributes.
-   Invoke an endpoint to fetch data only when needed. 
-   Use an object-oriented approach to implementing custom logic in a PMD.


## <a id="section_syntax"></a>PMD Scripting Syntax and Notation

PMD Scripting uses a Java-based expression language and syntax that provide the ability to code multiline statements and API calls on widget objects. A PMD script uses this notation:

```
<% insert-your-script-here %>
```

Although there is similarity between PMD Scripting and JavaScript syntax, PMD Scripting is not based on JavaScript. JavaScript is a client-side scripting language that enables the manipulation of data within the user's browser. You can't use JavaScript in Extend apps. For details of the PMD Scripting syntax, see [Reference: PMD Scripting Syntax](/wcp_docs/snh1581402351791.html).

PMD scripts are enclosed with the `<% %>` notation. Enclose PMD scripts within the `<% %>` notation when you:

-   Bind a variable or data to a tag attribute.

    This example binds endpoint data to the `values` attribute of an `instanceList`:

    ```
    {
      "type": "instanceList",
      "label": "A simple instanceList",
      "id": "instanceListSimple",
      "values": "<% workersEndpoint.data %>"
    },
    ```

-   Define a script block in the `script` section of the PMD.

    A script block contains custom function declarations. Define each script using the `var` keyword:

    ```
    "script": "<%
       var  yourFunctionName = function() {
            /* 
              Insert your function variables and statements.
            */
       }
    %>",
    ```

    The functions you declare in the `script` block are available to all widgets within the same PMD. Although not required, we recommend that you code the `script` block at the top of a PMD.

    This script block declares a function:

    ```
    "script": "<%
       var getRegistrationFee = function() {
         return 75;
       };
    %>",
    ```

-   Embed a script that calls custom functions and the PMD Scripting APIs.

    The `value` attribute of this sample `number` tag calls a custom function and references a flow variable to perform a calculation:

    Example:

    ```
    {
     "type": "number",
     "id": "freq",
     "label": "Total amount due today : ",
     "value": "<% getRegistrationFee() + (12 * flowVariables.monthlyRateFlowValue) %>"
    }
    
     
    ```

    Within an embedded script containing function declarations, if a function calls another function, declare the called function before the calling function. Example:

    ```
    "onChange": "<%
      var firstFunction = function() {
        return X;
      }
      var secondFunction = function() {
        firstFunction();
      }
      secondFunction();
    %>"
    ```



<b>Note:</b> Unless you have an explicit `return` statement, the last line of the script is the script return value. If you want to log the return value of the script on the console, ensure that the last line returns the value after the `console` method call. Example:

```
"value": "<% var result = getStaticText();
  console.info(result);
  result;
%>"
```

## <a id="section_callingWidgetMethods"></a>Calling Widget Methods

PMD Scripting provides widget APIs that enable you to code your scripts using object-oriented method calls on widget instances. The widget APIs provide the ability to execute methods on widget instances to get or set their runtime properties. You can call the widget APIs to apply business logic when a user interacts with the widgets on the page. Call the widget methods on pages that enable user interaction. Example: When a user enters a value on the widget, you can call its methods to display or hide other widgets using the `onChange` event.

This sample `radioGroup` uses an `onChange` event handler that calls methods on other widgets: `billingRate` and `billingFrequencyList`. (For brevity, this example doesn't include the `billingRate` and `billingFrequencyList` widgets. )

```
{
   "type": "radioGroup",
   "label": "Select a billing cycle:",
   "id": "billType",
   "instanceList": [
     {
       "id": "annual",
       "descriptor": "Annual"
     },
     {
       "id": "other",
       "descriptor": "Other options"
     }
   ],
   "required": "true",
   "onChange": "<%
     var myVal = self.value.get(0);
     if (myVal == 'annual') { // Set the monthly term billingRate and value if annual billing.
       billingRate.setValue(string:toString(40));
       billingFrequencyList.setVisible(false);
     } else { // Let the user select the billing frequency.       
       billingFrequencyList.setVisible(true);
       billingFrequencyList.setEnabled(true);
       billingFrequencyList.setRequired(true);
     }
   %>"
}
```

Some of the `get` and `set` methods of a widget provide access to widget properties. Instead of calling the `getPropertyName` or `setPropertyName` method, PMD Scripting provides a shortcut way to access the property name on the widget instance. You can replace the method name with the name of the property, which starts with a lowercase letter. Examples:

<table><thead><tr><th>Sample Widget Method Call</th><th>Shortcut</th></tr></thead><tbody><tr><td><code>var someValue = someText.getValue();</code></td><td><code>var someValue = someText.value;</code></td></tr><tr><td><code>someGrid.setVisible(false);</code></td><td><code>someGrid.visible = true;</code></td></tr></tbody></table><br/>

For a list of the available PMD Scripting widget methods, see [Reference: PMD Scripting Widget Methods](/wcp_docs/hno1582318947208.html).

## <a id="section_callingNamespaceFunctions"></a>Calling PMD Functions and Instance Methods

With PMD Scripting, you can call any of the PMD functions in your script. The PMD functions enable you to perform data manipulations, calculations, comparisons, and validations. You can call a script containing a series of functions that format the data before displaying it on the widget.

The PMD functions are namespace functions, most of which provide equivalent instance methods. An instance method enables you to call a function as a method on an object instance. It's generally more convenient and concise to call instance methods. However, you can call a PMD function either as an instance method or namespace function depending on your programming style. If a PMD function doesn't have an instance method equivalent, you can only call it as a namespace function.

To call a PMD function as an instance method on an object instance:

```
objectInstance.functionName(functionParam1, functionParamN)
```

This sample `text` value calls the string function `defaultIfBlank` on <i>getAlias.name</i>, which is a sample string from an endpoint.

```
{
  "type": "text",
  "id": "alias",
  "label": "Alternate name:",
  "value": "<% getAlias.name.defaultIfBlank('None') %>"
}
```

To call a PMD function as a namespace function, specify the namespace prefix followed by `:` and the function name. Include the object instance as the first parameter:

```
namespace:functionName(objectInstance, functionParam1, functionParamN)
```

This sample `text` calls the same string function `defaultIfBlank` using the namespace function syntax:

```
{
  "type": "text",
  "id": "alias",
  "label": "Alternate name:",
  "value": "<% string:defaultIfBlank(getAlias.name, 'None') %>"
}
```

For a list of the available PMD functions, see [Reference: PMD Functions](/wcp_docs/xlc1526013916076.html).

## <a id="section_eventHandling"></a>Event Handling

See [Concept: Event Handling with PMD Scripting](/wcp_docs/GUID-d643a5ea-c540-466d-9db7-2541753fce7c-enHYPHENus.html).

## <a id="section_invokingEndpoints"></a>Invoking Deferred Endpoints

With PMD Scripting, you can call the `invoke` method on a deferred endpoint only when your business logic requires data from that endpoint.

This sample `text` invokes the `workerData` endpoint only on the `onChange` event.

```
{
   "type": "text",
   "id": "searchName",
   "label": "Please enter a name to search",
   "onChange": "<%
     // Call the workerData endpoint with the user-entered name as a parameter.
     var test = workerData.invoke({'name': self.value});
     // Make the grid visible and set its row data.
     workersGrid.setVisible(true);
     workersGrid.setRows(test.data);
   %>"
}
```

This snippet displays the `workerData` deferred endpoint:

```
{
  "name": "workerData",
  "baseUrlType": "worker",
  "url": "<% 'workers?limit=10&search=' + name %>",
  "authType": "SSO",
  "deferred": "true"
}
```

## <a id="section_variables"></a>Using Variables

You can use these variables in a script:

-   Local script variables.
-   Predefined app variables such as `pageVariables`, `flowVariables`, `queryParams`, `site` attributes, and others.


To define a local variable within a script, specify the `var` keyword. This example illustrates local variables within a script block:

```
"script": "<%
   var selectRow = function(grid) {
      var nameList = [];
      var expenses = 0;
      for (var row : grid.selectedRows) {
        //childrenMap is a property of the grid row.
        nameList.add(row.childrenMap.fname.value + ' ' + row.childrenMap.lname.value);
        expenses += row.childrenMap.expense.value;
      }
    };
%>"
```

This example illustrates variables within an `onChange` script:

```
"onChange": "<%
  if (! (empty self.value)) {
    var id = self.value.get(0);
    var childrenMap; 
    for (var team : teamContainer.children) {  //teamContainer is a fieldSet tag id.
      if (team.childrenMap.id.value == id) {
        childrenMap = team.childrenMap;
        break;
      }
    }
    //total is a currency tag id.
    total.value = childrenMap.parking.value + childrenMap.food.value + childrenMap.drink.value;
  }
  else {
    total.value = 0;
  }
%>"
```

Consider these guidelines:

-   If you reference a variable that might contain a null value, check for the null value before you reference it.

    Example: To check whether the list `myEndPoint.data.customers` is empty or null before accessing its items:

    ```
    var customers = myEndPoint.data.customers;
    empty customers ? '' : customers[0].name;
    ```

    If you use any of the predefined variables containing a map of custom properties, ensure that the property already exists before you reference it.

    Example: To check the empty state of a `flowVariables` property, you can use either the ternary operator `?:` or the null-coalescing operator `??`.

    ```
    "value": "<% flowVariables.aFlowVariable ?: 'falseValue' %>"
    ```

    For a list of the predefined app variables, see [Reference: Predefined App Variables](/wcp_docs/urd1528494500512.html).

-   You can't define a variable outside a function declaration, such as this declaration:

    ```
    "script": "<%
       var someInvalidVariable;
       var someFunction = function() {
           . . .
       };
    %>",
    ```



## <a id="section_reusingScripts"></a>Reusing Scripts

The PMD can reuse scripts in these ways:

-   `script` tag - A page-level script block, denoted by `<% %>`, which contains functions that the widgets and events on the same page can invoke. Pods used by the PMD can also invoke the functions in the `script` tag.
-   Script module - A `.script` file containing scripts that multiple PMDs in the custom app can invoke. Add script modules to the `presentation/scripts` folder of your custom app. Only PMDs that include and load the script module can use its exported static variables and functions. Don't use `<% %>` in script modules; use `<% %>` only with scripts inside PMDs or pods.
-   Nested script module - A script module containing shared variables and functions that other script modules in the custom app can use. Only script modules that include the nested script module can use its exported scripts. You can include a maximum of 2 dependency levels. Example of 2 dependency levels: `a.script` includes `b.script` includes `c.script`. The PMD validation fails if `c.script` includes another script module.


For details and guidance about using script modules and script module dependency, see [Concept: Script Modules](/wcp_docs/vvg1604530023020.html).

## <a id="section_stringInterpolation"></a>String Interpolation

Use the `<% %>` notation for string interpolations. When a string value includes both static text and variable substitutions, enclose both static and variable strings inside the `<% %>` notation. Example:

```
"value": "<% 'static text ' + variable %>"
```

The value on this sample `text` includes both static text and variables inside the `<% %>` notation:

```
{
  "type": "text",
  "label": "Team Scorecard and Goal",
  "enabled": "false",
  "value": "<% 'Team\\'s ' + aScorecard.scorecardName + ':  ' + pageVariables.primaryGoal  %>"
}
```

The PMD validation returns a warning if you separate static text from an interpolated expression. Example: `"value": " 'static text' + <%variable%> "` returns a warning.

## <a id="section_limits"></a>Limits on PMD Scripting

<table><thead><tr><th>Limit</th><th>Maximum Value or Recommendation</th></tr></thead><tbody><tr><td>Call frames.</td><td>The number of levels in a program stack execution, such as recursive function calls, has a maximum of 25.</td></tr><tr><td>CPU time.</td><td>The CPU time consumed for each script execution has a maximum of 5 seconds. This limit doesn't include endpoint invocation and widget API calls because these calls are executed in separate threads.</td></tr><tr><td>Levels of nested script modules.</td><td>The maximum number of levels of nested script modules is 2. Example of 2 levels of nested scripts: script1 that includes script 2 that includes script 3. If script 3 includes another script, it exceeds the limit, and receives a validation error.</td></tr><tr><td>Memory usage.</td><td>We allocate memory to accommodate each script execution while we protect our service regarding memory usage. If your script exceeds the allocated memory threshold, the script will throw an error. <p><b>Note:</b> We highly recommend that you follow best practices for proper memory management in your PMD scripts. See PMD Scripting Memory Management in <a href="/wcp_docs/asx1597867253394.html">Concept: PMD Best Practices</a>.</p></td></tr><tr><td>Script size.</td><td>The script size limit within the maximum PMD file size, which is 100 KB.</td></tr></tbody></table><br/>

## <a id="section_pgj_kzg_r4b"></a>Sample App

The PMD Scripting sample app in the App Catalog demonstrates various examples of PMD Scripting usage.

### Related Information

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

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

[Reference: PMD Scripting Examples](/wcp_docs/mdp1582058758619.html)

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

