Multi-response output controls

  • Release version: Yokohama
  • Updated January 30, 2025
  • 2 minutes to read
  • Summarize
    Summarized using AI
    This content was generated using new OpenAI-powered functionality. Results are provided on an as is basis and are not guaranteed to be accurate or complete.

    Summary of Multi-response output controls

    This feature enables ServiceNow customers to implement multi-step user input controls, such as paginated pickers or sequential date pickers. It uses specific APIs within inbound and outbound transformers to manage user context data across multiple interaction steps, allowing for enhanced control flows and user experiences.

    Show full answer Show less

    Key Features

    • Context Data Management APIs: Use setProviderUserContext, getProviderUserContext, removeProviderUserContext, and removeAllProviderUserContext to store, retrieve, and manage multi-step interaction state per user and application.
    • Pagination Handling: Maintain current page index and pagination length in user context to enable next/previous navigation in picker controls.
    • Step-by-Step Input: Supports sequential interactions such as selecting year, then month, then date, by preserving intermediate states.
    • Example Implementations: Provides example code for outbound transformers to display paginated options and inbound transformers to process user selections and update pagination states accordingly.

    Practical Usage

    ServiceNow customers can apply these controls to build conversational interfaces or rich controls that require multiple user inputs over several steps without losing context. This is useful for complex pickers or date selections where users navigate through options page by page.

    The outbound transformer prepares and presents options for the current page, including "next" and "prev" commands for navigation. The inbound transformer processes user responses, updates pagination state, and selects the appropriate value based on user input.

    Expected Outcomes

    • Improved user experience with multi-step input flows that maintain state seamlessly.
    • Ability to paginate large option sets within a picker control, reducing user overwhelm.
    • Customizable navigation through user responses, enabling dynamic and interactive controls.
    • Consistent context management ensuring state persistence across turns in the interaction.

    Implement controls that involve multiple steps to get user input.

    Use the following API to configure context data for multi-output controls.

    Common use cases

    1. To achieve pagination of pickers: page_no, pagination_length updated in inbound based on next/previous button is read in outbound.
    2. Step by step response of date picker like first year, then month, and then date selection.
    The following APIs are only available in inbound and outbound transformers.
    sn_cs.VASystemObject.setProviderUserContext( key, contextData, providerAppId, providerUserId);
    sn_cs.VASystemObject.getProviderUserContext(key, providerAppId, providerUserId);
    sn_cs.VASystemObject.removeProviderUserContext(key, providerAppId, providerUserId);
    sn_cs.VASystemObject.removeAllProviderUserContext(providerAppId, providerUserId)
    The outbound transformer of the picker control can store current page details in user contextData.
     var paginationData = {
              "page_index": 1,
              "pagination_length": 2
        }
    };
    sn_cs.VASystemObject.setProviderUserContext("picker_pagination", paginationData, providerAppId, providerUserId, );
    The inbound transformer of picker control can get current page details from user contextData.
    var paginationData = sn_cs.VASystemObject.getProviderUserContext("picker_pagination", providerAppId, providerUserId);

    Example code for picker control outbound transformer

    (function execute(inputs, outputs) {
        var control = inputs.rich_control;
        var payload = inputs.payload;
        var appId = payload.appId;
        var userId = payload.userId;
    
        var paginationData = sn_cs.VASystemObject.getProviderUserContext('picker_control', appId, userId);
        paginationData = JSON.parse(paginationData);
        //First time when the outbound picker is called when selecting the topic.
        if (paginationData == null) {
            paginationData = {
                'page_index': 1,
                'pagination_length': 5
            };
            sn_cs.VASystemObject.setProviderUserContext('picker_control', paginationData, appId, userId);
        }
    
        var page_index = paginationData['page_index'];
        var pagination_length = paginationData['pagination_length'];
        var start = (page_index - 1) * pagination_length;
        var end = page_index * pagination_length;
    
        if (control['options']) {
            var options = control['options'];
            var optionsLength = options.length;
            if (end > optionsLength)
                end = optionsLength;
            var picker = control["label"] + ":";
            if (start > 0)
                picker += "\n" + "*" + ": " + "prev";
            for (var x = start; x < end; x++) {
                gs.log("here " + x + " : " + options[x]);
                picker += "\n" + (x + 1) + ": " + options[x].label;
            }
            if (end < optionsLength)
                picker += "\n" + "#" + ": " + "next";
        }
        outputs.text_message = picker;
    })(inputs, outputs);
    Example Picker Control Inbound Tranformer
    (function execute(inputs, outputs) {
    
        var request_context = inputs.request_context;
        var rich_control = inputs.rich_control;
        var appId = request_context.appId;
        var userId = request_context.userId;
    
        var selectedValue = request_context["typed_value"];
        var result = {};
        result["value"] = "";
        result["search_text"] = selectedValue;
    
        var options = rich_control['options'];
    
        var paginationData = sn_cs.VASystemObject.getProviderUserContext('picker_control', appId, userId);
        paginationData = JSON.parse(paginationData);
    
        switch (selectedValue) {
            case 'prev': {
                --paginationData["page_index"];
                result["send_prev_control"] = true;
            }
            break;
        case 'next': {
            ++paginationData["page_index"];
            result["send_prev_control"] = true;
        }
        break;
        default: {
            var selectedIndex = Number(selectedValue) - 1;
            if (paginationData["page_index"] != undefined && paginationData["pagination_length"] != undefined) {
                var highestOptionInPage = paginationData["page_index"] * paginationData["pagination_length"];
                if (selectedIndex >= 0 && selectedIndex < highestOptionInPage) {
                    var selectedOption = options[selectedIndex];
                    result["value"] = selectedOption.value;
                    result["search_text"] = "";
                }
            } else {
                var selectedOption = options[selectedIndex];
                result["value"] = selectedOption.value;
                result["search_text"] = "";
            }
        }
        }
        sn_cs.VASystemObject.setProviderUserContext('picker_control', paginationData, appId, userId);
        outputs.result = result;
    })(inputs, outputs);