Multi-response output controls

  • Release version: Xanadu
  • Updated August 1, 2024
  • 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

    Multi-response output controls enable the implementation of multi-step user input processes within ServiceNow applications. This functionality is particularly useful for scenarios like paginating picker options or collecting sequential input such as selecting a year, then a month, and finally a date. These controls leverage context data stored per user to maintain state across multiple interaction steps.

    Show full answer Show less

    Key Features

    • Context Data Management APIs: Four key APIs are available exclusively in inbound and outbound transformers to manage user context data:
      • setProviderUserContext(key, contextData, providerAppId, providerUserId) – stores context data keyed by user and application.
      • getProviderUserContext(key, providerAppId, providerUserId) – retrieves stored context data.
      • removeProviderUserContext(key, providerAppId, providerUserId) – deletes specific user context data.
      • removeAllProviderUserContext(providerAppId, providerUserId) – deletes all stored context data for a user and application.
    • User-Specific Pagination State: Outbound transformers can save current pagination details (e.g., page index and length) in the user context. Inbound transformers retrieve and update this information based on user navigation actions.
    • Picker Control Example: Demonstrates how to paginate picker options, presenting "prev" and "next" controls to navigate pages and updating the displayed options accordingly. The outbound transformer constructs the paginated display, while the inbound transformer processes user input, updates pagination state, and resolves selected values.

    How This Enables ServiceNow Customers

    By using multi-response output controls with user context APIs, customers can design conversational or interactive controls that maintain state across multiple user inputs. This is essential for handling large option sets with pagination or sequential input steps without losing context. The provided example code serves as a practical template to implement paginated pickers that respond dynamically to user navigation, improving user experience and input accuracy.

    Practical Application

    • Implement paginated pickers to display manageable subsets of large option lists, enhancing performance and usability.
    • Use multi-step input flows, such as date pickers that prompt for year, month, and day in sequence.
    • Maintain user-specific interaction state securely and efficiently via the provided context APIs within transformers.
    • Customize inbound and outbound transformers to handle user actions like "next" and "prev," updating context and generating appropriate responses.

    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);