logo

NJP

UI Builder Component: Content Tree

Import · Aug 21, 2022 · article

ServiceNow documentation: https://developer.servicenow.com/dev.do#!/reference/now-experience/sandiego/now-components/now-content-tree/overview

Use Cases

The Content Tree is a powerful widget to make complex data structures transparent.

Examples of use cases:

  • SAFe: Structure of Epics/Stories/Tasks
  • PPM: Structure of Programs/Projects/Subprojects/Project Tasks
  • TSM/OMT:
    • Structure of Product Model (Specifications)
    • Customer Order/Order Line Items/Domain Orders/Tasks
    • Structure of Product Inventory (Parent/Child/Child of Child/…)

The main properties of tree items are the internal id and the visible label. Both are simple strings!

Scrolling is supported when the tree component has a fixed height otherwise it will be always longer.

Based on the selected item different components can be displayed on the same page.

Example script to identify and manage different types of items:

/**
 * @param {params} params
 * @param {api} params.api
 * @param {any} params.event
 * @param {any} params.imports
 * @param {ApiHelpers} params.helpers
 */
function handler({
    api,
    event,
    helpers,
    imports
}) {
    var treeID = api.state.selectedTreeItem;
    var ids = treeID.split('#');
    api.setState('selectedID', ids[0]);
    api.setState('selectedType', ids[1]);
    api.setState('detailsURL', "/nav_to.do?uri=" + ids[1] + ".do?sys_id=" + ids[0]);
    if (ids[1] == 'sn_ind_tmt_orm_order_task') {
        api.setState('isTask', true);
        api.setState('isOLI', false);
        api.setState('isSpec', false);
        api.setState('isProductOrder', false);
    } else if (ids[1] == 'sn_ind_tmt_orm_order_line_item') {
        api.setState('isTask', false);
        api.setState('isOLI', true);
        api.setState('isSpec', false);
        api.setState('isProductOrder', false);
    } else if (ids[1] == 'sn_prd_pm_product_specification') {
        api.setState('isTask', false);
        api.setState('isOLI', false);
        api.setState('isSpec', true);
        api.setState('isProductOrder', false);
    } else if (ids[1] == 'sn_ind_tmt_orm_product_order' || ids[1] == 'sn_ind_tmt_orm_service_order') {
        api.setState('isTask', false);
        api.setState('isOLI', false);
        api.setState('isSpec', false);
        api.setState('isProductOrder', true);
    }
}

Controlling of expanded/collapsed areas

You must specify the item path as an array to define expanded items.

Path means an array of parent id’s starting from the top-most one.

Example:

[
    [
      "3ee1fdb1c3331010d216b5183c40dd81"
    ],
    [
      "3ee1fdb1c3331010d216b5183c40dd81", "af66e551c32f10105252716b7d40dd52"
    ],
    [
      "3ee1fdb1c3331010d216b5183c40dd81", "fbd9e5a7c32310105252716b7d40ddb7"
    ]
  ]

Access an item after selection

Grab a single item selection by event “Content tree item clicked”. The id is available by @payload.item.id

Expand and collapse all items

It’s often very helpful to have some buttons to expand and collapse all items.

To change the expanded items by a script and manually in the content tree you must bind the “Expanded Items” property to a client state parameter.

image

Expand all items

To expand all items, walk through the complete item tree and fill the array with the path of ids of each item.

Example script to walk through all items delivered by the data broker for the content tree:

/**
* @param {params} params
* @param {api} params.api
* @param {any} params.event
* @param {any} params.imports
* @param {ApiHelpers} params.helpers
*/
function handler({api, event, helpers, imports}) {
       var titems = api.data.order_tree_data.output.items;
    var sel = [];

    for (var ind = 0; ind < titems.length; ind++) {
        var spath = [];
        var titem = titems[ind];
        processID(titem);
    }
    api.setState('expandedItems', sel);

    function processID(titem) {
        spath.push(titem.id);
        var mspath = Array.from(spath);
        sel.push(mspath);
        if (titem.children != null && titem.children.length > 0) {
            for (var ind2 = 0; ind2 < titem.children.length; ind2++) {
                var ctitem = titem.children[ind2];
                processID(ctitem); // Recursion!!
            }
        }
        spath.pop();
    }
}

Assign the client script to a button:

image

Collapse all items

This is very easy. Set the “Expanded Items” property or the bound client state parameter to an empty array.

/**
* @param {params} params
* @param {api} params.api
* @param {any} params.event
* @param {any} params.imports
* @param {ApiHelpers} params.helpers
*/
function handler({api, event, helpers, imports}) {
    api.setState('expandedItems', []);
}

Select multiple items

The content tree is also supporting multiple selection.

image

You must set the property “Selected Items” in the same format as for expanded items to select multiple items by a script. Means as an array of item paths. See above for an example.

View original source

https://www.servicenow.com/community/developer-articles/ui-builder-component-content-tree/ta-p/2305852