5: Replace radio buttons with checkboxes

When you convert your dashboard to HTML, you can use additional views that are not available in Simple XML, such as custom or third-party views. You can also modify the existing views to change their behavior. So to demonstrate how to add and modify views in a dashboard, in this exercise we'll add the SplunkJS Stack checkbox group to replace the radio buttons. But we'll also need to modify the way the $sourcetype$ token value is passed to the search because we're now allowing multiple values to be selected. We'll do this by adding a custom change event handler.

  1. First, let's add the checkbox view to the dashboard. In the HTML file, find the code library requirements:
  2. require([
        "splunkjs/mvc",
        "splunkjs/mvc/utils",
        "splunkjs/mvc/tokenutils",
        "underscore",
        "jquery",
        "splunkjs/mvc/simplexml",
        "splunkjs/mvc/layoutview",
        "splunkjs/mvc/simplexml/dashboardview",
        "splunkjs/mvc/simplexml/dashboard/panelref",
        "splunkjs/mvc/simplexml/element/chart",
        "splunkjs/mvc/simplexml/element/event",
        "splunkjs/mvc/simplexml/element/html",
        "splunkjs/mvc/simplexml/element/list",
        "splunkjs/mvc/simplexml/element/map",
        "splunkjs/mvc/simplexml/element/single",
        "splunkjs/mvc/simplexml/element/table",
        "splunkjs/mvc/simpleform/formutils",
        "splunkjs/mvc/simplexml/eventhandler",
        "splunkjs/mvc/simplexml/searcheventhandler",
        "splunkjs/mvc/simpleform/input/dropdown",
        "splunkjs/mvc/simpleform/input/radiogroup",
        "splunkjs/mvc/simpleform/input/linklist",
        "splunkjs/mvc/simpleform/input/multiselect",
        "splunkjs/mvc/simpleform/input/checkboxgroup",
        "splunkjs/mvc/simpleform/input/text",
        "splunkjs/mvc/simpleform/input/timerange",
        "splunkjs/mvc/simpleform/input/submit",
        "splunkjs/mvc/searchmanager",
        "splunkjs/mvc/savedsearchmanager",
        "splunkjs/mvc/postprocessmanager",
        "splunkjs/mvc/simplexml/urltokenmodel"
        // Add comma-separated libraries and modules manually here, for example:
        // ..."splunkjs/mvc/simplexml/urltokenmodel",
        // "splunkjs/mvc/checkboxview"
        ],
        function(
            mvc,
            utils,
            TokenUtils,
            _,
            $,
            DashboardController,
            LayoutView,
            Dashboard,
            PanelRef,
            ChartElement,
            EventElement,
            HtmlElement,
            ListElement,
            MapElement,
            SingleElement,
            TableElement,
            FormUtils,
            EventHandler,
            SearchEventHandler,
            DropdownInput,
            RadioGroupInput,
            LinkListInput,
            MultiSelectInput,
            CheckboxGroupInput,
            TextInput,
            TimeRangeInput,
            SubmitButton,
            SearchManager,
            SavedSearchManager,
            PostProcessManager,
            UrlTokenModel
    
            // Add comma-separated parameter names here, for example: 
            // ...UrlTokenModel, 
            // CheckboxView
            ) {
    

    The require function includes all of the Simple XML libraries and others that are required for the dashboard (including search managers). These libraries are mapped to variables that are passed as function parameters (the second list). To use additional SplunkJS Stack views (and third-party or custom views), you'll need to require their libraries and pass in corresponding function parameter variables without stepping on the existing code.

    We'll add the SplunkJS Stack version of the CheckboxGroup view just to show how, even though Simple XML includes a CheckboxGroup input. The reference for the CheckboxGroup view provides the library path we'll need: "splunkjs/mvc/checkboxgroupview". We'll also add a variable called CheckboxGroupView to the parameter list, and remove the comments to tidy up. Update the code above as follows:

    require([
        "splunkjs/mvc",
        "splunkjs/mvc/utils",
        "splunkjs/mvc/tokenutils",
        "underscore",
        "jquery",
        "splunkjs/mvc/simplexml",
        "splunkjs/mvc/layoutview",
        "splunkjs/mvc/simplexml/dashboardview",
        "splunkjs/mvc/simplexml/dashboard/panelref",
        "splunkjs/mvc/simplexml/element/chart",
        "splunkjs/mvc/simplexml/element/event",
        "splunkjs/mvc/simplexml/element/html",
        "splunkjs/mvc/simplexml/element/list",
        "splunkjs/mvc/simplexml/element/map",
        "splunkjs/mvc/simplexml/element/single",
        "splunkjs/mvc/simplexml/element/table",
        "splunkjs/mvc/simpleform/formutils",
        "splunkjs/mvc/simplexml/eventhandler",
        "splunkjs/mvc/simplexml/searcheventhandler",
        "splunkjs/mvc/simpleform/input/dropdown",
        "splunkjs/mvc/simpleform/input/radiogroup",
        "splunkjs/mvc/simpleform/input/linklist",
        "splunkjs/mvc/simpleform/input/multiselect",
        "splunkjs/mvc/simpleform/input/checkboxgroup",
        "splunkjs/mvc/simpleform/input/text",
        "splunkjs/mvc/simpleform/input/timerange",
        "splunkjs/mvc/simpleform/input/submit",
        "splunkjs/mvc/searchmanager",
        "splunkjs/mvc/savedsearchmanager",
        "splunkjs/mvc/postprocessmanager",
        "splunkjs/mvc/simplexml/urltokenmodel",
        "splunkjs/mvc/checkboxgroupview"
        ],
        function(
            mvc,
            utils,
            TokenUtils,
            _,
            $,
            DashboardController,
            LayoutView,
            Dashboard,
            PanelRef,
            ChartElement,
            EventElement,
            HtmlElement,
            ListElement,
            MapElement,
            SingleElement,
            TableElement,
            FormUtils,
            EventHandler,
            SearchEventHandler,
            DropdownInput,
            RadioGroupInput,
            LinkListInput,
            MultiSelectInput,
            CheckboxGroupInput,
            TextInput,
            TimeRangeInput,
            SubmitButton,
            SearchManager,
            SavedSearchManager,
            PostProcessManager,
            UrlTokenModel,
            CheckboxGroupView
            ) {
    

    The code shows the path and variable name for the CheckboxGroup view appended to the previous lists.

      Note  Be careful with trailing commas―all of the items in each list should be comma-separated, but no comma after the last one.
  3. Let's add the checkboxes to the page. We'll need to add JavaScript for the view. The pattern for checkbox groups is as follows:
  4. var uniqueid = new CheckboxGroupView({
        id: "uniqueid",
        "default": "",
        "labelField": "",
        "valueField": "",
        "managerid": "",
        el: $("#uniqueid")
    }).render();
    

    Let's fill in the details:

    • uniqueid: We can use any unique ID string, so let's use "view_checkboxgroup". This value is also used in the layout to indicate where the view is displayed, as indicated by the el property (for more about this property, see the Backbone documentation).
    • For the choices, take a look at the code for the radio buttons we're replacing (find RadioGroupInput). Notice the managerid property, which indicates that the radio button choices are populated by a search ("search3"), so we'll use that for the checkbox choices. The radio button labels and values are set to the "sourcetype" field returned by the search, we'll do the same.
    • For a default value, let's use "splunkd" because the search is on the internal index. (We could even have more than one value because a checkbox group can take an array of choices as a default.)

    Find the section "// VIEWS: FORM INPUTS" and add this code to the end of that section (above the "// SUBMIT FORM DATA" section):

    var view_checkboxgroup = new CheckboxGroupView({
        id: "view_checkboxgroup",
        "default": "splunkd",
        "labelField": "sourcetype",
        "valueField": "sourcetype",
        "managerid": "search3",
        el: $("#view_checkboxgroup")
    }).render();
    

    To display it on the page, in the layout replace the radio button group ID ("input2") with the checkbox group ("view_checkboxgroup")―find this code:

    <div class="panel-body" id="input2">
    

    and change it to:

    <div class="panel-body" id="view_checkboxgroup">
    

    Now that cell will display the checkboxes instead.

    After you save the page, refresh Splunk Web, and reload the dashboard, you'll see that the checkboxes are displayed and the default is selected. But, the checkbox choices don't affect the result table because we haven't connected the checkbox to the $sourcetype$ token yet.

  5. Let's fix the search query. Find the code for the first search:
  6. var search1 = new SearchManager({
        "id": "search1",
        "cancelOnUnload": true,
        "status_buckets": 0,
        "search": "index=_internal sourcetype=$sourcetype$ | head $headcount$",
        "latest_time": "$latest$",
        "earliest_time": "$earliest$",
        "app": utils.getCurrentApp(),
        "auto_cancel": 90,
        "preview": true,
        "runWhenTimeIsUndefined": false
    }, {tokens: true});
    

    This search query is set up to take a single value for source type (sourcetype=$sourcetype$) but the checkbox group displays multiple choices for source types. Rather than using this single value assignment in the search query, we'll create a change event handler (each SplunkJS Stack view fires a "change" event when its value changes) that forms a token value depending on the user's selections. So, remove "sourcetype=" from the search query as follows:

        "search": "index=_internal $sourcetype$ | head $headcount$",
    
  7. Now, let's add a change event handler for the checkbox group so that whenever the value changes (a checkbox is selected or cleared), a new $sourcetype$ token is formed containing the selected values in the format "sourcetype=choice1 OR sourcetype=choice2 ... OR sourcetype=choicen".
  8. To create this value, we'll use the join method to connect the selected source types with a string " OR sourcetype=", then prepend "sourcetype=" to the entire string. Then, we'll set this value into the sourcetype=$sourcetype$ token in the default token model.

    We also need to set the initial value for the $sourcetype$ token to match the default value of the checkbox group ("splunkd").

    Add the following code below the CheckboxGroupView block (above the "// SUBMIT FORM DATA" section):

    // Set the initial value of the sourcetype token to "splunkd"
    defaultTokenModel.set("sourcetype", "splunkd");
    
    // When the checkbox selection changes, reform the sourcetype token
    view_checkboxgroup.on("change", function() {
        // Form the new sourcetype string
        var selectedsourcetypes="sourcetype=" + view_checkboxgroup.val().join(" OR sourcetype=");
        // Set the sourcetype token value
        defaultTokenModel.set("sourcetype", selectedsourcetypes);
    });
    
  9. Finally, one task to tidy up. The radio group code is still affecting the $sourcetype$ token, so comment it out as follows:
  10. // var input2 = new RadioGroupInput({
    //     "id": "input2",
    //     "choices": [
    //     {"value": "*", "label": "All"}
    //     ],
    //     "valueField": "sourcetype",
    //     "labelField": "sourcetype",
    //     "selectFirstChoice": false,
    //     "default": "*",
    //     "value": "$form.sourcetype$",
    //     "managerid": "search3",
    //     "el": $('#input2')
    // }, {tokens: true}).render();
    
    // input2.on("change", function(newValue) {
    //     FormUtils.handleValueChange(input2);
    // });
    

    Update the results table heading—find this code in the layout:

    <h3>index=_internal sourcetype=$sourcetype$ | head $headcount$</h3>

    and change the search string by removing "sourcetype=":

    <h3>index=_internal $sourcetype$ | head $headcount$</h3>
  11. Save the page, refresh Splunk Web, and reload the dashboard to see it:
  12. HTML dashboard

This should give you a small taste of how to go about customizing an HTML dashboard.