Parse values in MRVS

sntech
Tera Contributor

Hi Team,

 

I am creating a catalog item to modify the CI Attributes.

 

Form Design is: 

sntech_0-1769196166575.png

 

 

CI name is 'List Collector' type referencing to CMDB table.

 

Requirement: is Whatever CIs user selects in 'CI Name' field, its corresponding attributes should be shown as a dropdown list on the below field. ('select the field you want to modify). User should be able to select multiple attributes from dropdown list.

But, I did not find the correct field type for this.

 

Hence, I thought of MRVS.

 

But, issue is that, I am not able to apply the script on MRVS variable.

 

Script Include:

 

// Accepts: sysparm_ci_list = comma-separated CI sys_ids (or sysparm_ci for single)
    // Returns: JSON [{label, value, element, table, table_label}]
    getFieldsForCIs: function () {
        var list = (this.getParameter('sysparm_ci_list') || this.getParameter('sysparm_ci') || '').toString().trim();
        if (!list) return '[]';

        var ids = list.split(',').map(function (s) { return s.trim(); }).filter(Boolean);
        if (!ids.length) return '[]';

        // Unique class names for the selected CIs
        var classSet = {};
        var ci = new GlideRecord('cmdb_ci');
        ids.forEach(function (id) {
            if (ci.get(id)) classSet[ci.getValue('sys_class_name') || 'cmdb_ci'] = true;
        });
        var classNames = Object.keys(classSet);
        if (!classNames.length) return '[]';

        // Map table labels
        var tableLabelByName = {};
        var dbo = new GlideRecord('sys_db_object');
        dbo.addQuery('name', 'IN', classNames.join(','));
        dbo.query();
        while (dbo.next())
            tableLabelByName[dbo.getValue('name')] = dbo.getValue('label') || dbo.getValue('name');

        // Collect fields
        var out = [], seen = {}; // key = table::element
        classNames.forEach(function (clsName) {
            var tableLabel = tableLabelByName[clsName] || clsName;

            var dict = new GlideRecord('sys_dictionary');
            dict.addQuery('name', clsName);
            dict.addQuery('internal_type', '!=', 'collection');
            dict.addQuery('active', true);
            dict.orderBy('column_label');
            dict.query();

            while (dict.next()) {
                var element = dict.getValue('element');
                if (!element) continue;

                // Optional blacklist:
                // var blacklist = 'sys_id,sys_created_on,sys_created_by,sys_updated_on,sys_updated_by,sys_mod_count';
                // if ((',' + blacklist + ',').indexOf(',' + element + ',') > -1) continue;

                var key = clsName + '::' + element;
                if (seen[key]) continue;
                seen[key] = true;

                var colLabel = dict.getValue('column_label') || element;
                out.push({
                    label: colLabel + ' [' + tableLabel + ']',
                    value: key,
                    element: element,
                    table: clsName,
                    table_label: tableLabel
                });
            }
        });

        out.sort(function (a, b) { return a.label.localeCompare(b.label); });
        return new global.JSON().encode(out);
    }
 
 
 
 
Catalog Client Script (On Change of CI name):
 
var ciList = g_form.getValue('ci_name'); // List Collector -> comma-separated sys_ids
    var targetVar = 'select_the_field_you_want_to_modify'; // Select Box variable name

    // Reset dropdown to placeholder and keep empty selection
    g_form.clearOptions(targetVar);
    g_form.addOption(targetVar, '', '-- None --', 0);
    g_form.setValue(targetVar, '');

    if (!ciList) return; // nothing selected

    var ga = new GlideAjax('GetCIAttributes');
    ga.addParam('sysparm_name', 'getFieldsForCIs');
    ga.addParam('sysparm_ci_list', ciList);

    ga.getXMLAnswer(function (answer) {
        // Keep placeholder no matter what
        g_form.clearOptions(targetVar);
        g_form.addOption(targetVar, '', '-- None --', 0);
        g_form.setValue(targetVar, '');

        if (!answer) return;

        var arr;
        try {
            arr = JSON.parse(answer); // [{label, value, element, table, table_label}]
        } catch (e) {
          //  console.log('Failed to parse fields JSON: ' + e);
            return;
        }

        arr.forEach(function (f) {
            if (f && f.value) {
                // Show human label including table label, store unique key table::element
                g_form.addOption(targetVar, f.value, f.label);
            }
        });

        // Ensure nothing is pre-selected
        g_form.setValue(targetVar, '');
    });. 
 
 
 
Can anyone please suggest how I can get the script include result in MRVS variable? Or if any other way possible?
 
 
Thank you.
1 REPLY 1

Itallo Brandão
Giga Guru

Hi there,

To achieve this using a Multi-Row Variable Set (MRVS), you need to change your approach slightly. You cannot easily push data into the MRVS dropdown from the main form's script.

Instead, you must pull the data from inside the MRVS when the user clicks "Add".

Here is the technical solution:

  1. The Variable: Inside your MRVS, create a variable (e.g., attribute_to_modify) of type Select Box.

  2. The Script: Create a Catalog Client Script applied specifically to the Variable Set (not the Catalog Item).

Configuration:

  • Applies to: A Variable Set

  • Variable Set: [Your MRVS Name]

  • Type: onLoad

  • UI Type: All

The Code: Use g_service_catalog.parent.getValue() to access the CI field that sits on the main form behind the modal.

function onLoad() {
    // 1. Get the CI list from the PARENT form (outside the MRVS)
    var parentCI = "";
    
    if (typeof g_service_catalog !== 'undefined' && g_service_catalog.parent) {
        // Service Portal / Employee Center method
        parentCI = g_service_catalog.parent.getValue('ci_name');
    } else {
        // Fallback for Native UI (if needed, though rare for Catalog these days)
        try {
            parentCI = parent.g_form.getValue('ci_name');
        } catch (e) {
            console.log("Could not find parent form");
        }
    }

    // 2. Define the variable name INSIDE the MRVS
    var targetVar = 'attribute_to_modify'; // Replace with your actual MRVS variable name

    // If no CIs selected, stop here
    if (!parentCI) return;

    // 3. Call your existing Script Include
    var ga = new GlideAjax('GetCIAttributes');
    ga.addParam('sysparm_name', 'getFieldsForCIs');
    ga.addParam('sysparm_ci_list', parentCI);

    ga.getXMLAnswer(function(answer) {
        g_form.clearOptions(targetVar);
        g_form.addOption(targetVar, '', '-- None --', 0);

        if (!answer) return;

        var arr;
        try {
            arr = JSON.parse(answer);
        } catch (e) {
            return;
        }

        // 4. Populate the dropdown inside the Modal
        arr.forEach(function(f) {
            if (f && f.value) {
                g_form.addOption(targetVar, f.value, f.label);
            }
        });
    });
}

 

How this works for the user:

  1. User selects CIs on the main form.

  2. User clicks "Add" on the MRVS table.

  3. The popup opens.

  4. The script runs immediately (onLoad of the popup), grabs the CIs from the background form, and fills the dropdown.

  5. User picks an attribute and saves the row.

  6. User can repeat this to add multiple attributes.

If this solution helps you achieve the requirement, please mark it as Accepted Solution.

Best regards,

Brandão.