Skip to main content

NIM

Custom JavaScript columns
Abstract

Guide to creating custom JavaScript columns in NIM for data transformation, including best practices and error handling.

Create a custom JavaScript column to compose a new column based on transformations of other columns. This is possible in both Data tables and Filters.

To get started, Create a JavaScript system column or Create a JavaScript filter column.

Custom JavaScript columns support Vault queries and Variable queries.

Scripted columns can be added as additional columns to a filter's results. They can also be added directly to any system table.

To determine the best place to create a scripted column there are a few things to consider:

  • Will this value be used multiple times or will it impact multiple layers/entities in NIM?

    • E.g. All of the values in the FirstName column have trailing spaces: Trimming this value will need to happen in the filters and also in the name gen.

  • Can the resultant value be determined solely from the data in a single table or do I need data from other joined in tables?

    • E.g. The OU path for a user is based on their grade level and their building name: If Grade Level and Building Name are not available in the same table, this is not a good candidate to be generated in the system table.

There are two situations where fields that you're evaluating in a Scripted Column may throw errors:

  • The value in the table is simply blank

    • Not all user objects in AD will have a description specified

    • See more on Nullish Coalescing

  • The value is coming from an "any-none" join in your filter

A simple way to catch errors in your scripts is to wrap the issue code in a try/catch block

let foo = 'bar'; //default value
try {
	foo = Users['description'].toLowerCase();
}
catch(e) { }

This method can become messy and difficult to understand in more complex scenarios.

The Nullish-Coalescing (see example #1 above) operator can be used to get the variable value or a default value if the variable value is empty:

let foo = (Users['description'] ?? 'bar').toLowerCase();

In the case of example #2 above, we also want to check if the table/collection object is undefined. This is a good method to use regardless of if the table is expected to be null or not.

Snippet 1: Check for undefined via TypeOf

let foo = (typeof Users_01 !== 'undefined') ? Users_01['description'] : 'bar';let foo = (typeof Users_01 !== 'undefined') ? Users_01['description'] : 'bar';

Snippet 2: Check for undefined via direct comparison

let foo = (Users_01 !== undefined) ? Users_01['description'] : 'bar';

The two methods can be combined - the first check to ensure that the table has a record. If the record does exist, then also handle the situation where the field could be empty:

let foo = (typeof Users_01 !== 'undefined') ? (Users_01['description'] ?? 'foobar') : 'bar';

Here is a real world example of this

let result = '';

let LocationAssignment = (typeof AssignConfigEmployeeLocation !== 'undefined') ? (AssignConfigEmployeeLocation['LocationName'] ?? '') : null;
let Location = (typeof ConfigEmployeeLocation !== 'undefined') ? (ConfigEmployeeLocation['LocationName'] ?? '') : null;
let WorkLocationAssignment = (typeof di96_pcassign_export !== 'undefined') ? (di96_pcassign_export['work_location_name'] ?? '') : null
let WorkLocation = (typeof di96_perpay_export !== 'undefined') ? (di96_perpay_export['work_loc1_name'] ?? '') : null


if(LocationAssignment != null) {
  result = LocationAssignment
}
else {
  if(Location != null) {
  	result = Location;
  }
}

if(result === null || result.length < 1)
{
  if(WorkLocationAssignment != null)
     {
       	result = WorkLocationAssignment
     } else {
       if(WorkLocation != null) {
        	result = WorkLocation
       }
     }
}

return result

String interpolation offers a way to define a string structure with variable placeholders and implicitly convert the value of the expression/variable to a string value. This is the recommended method of building strings.

See more on Template Literals

Tip

Template strings are enclosed in the tick character ( ` ).

// String concatenation
return "Student @ " + Students['BldName'] + " | " + Students['Grade'].toString() + ".";

// Templated strings
return `Student @ ${Students['BldName']} | ${Students['Grade']}.`;return `Student @ ${Students['BldName']} | ${Students['Grade']}.`;

The placeholders ("${...}") in the template string can contain full expressions:

return `Grade ${Students['Grade'].slice(-2)}`;