Example: Tables with custom renderers using a Simple XML extension

This example uses a Simple XML extension to display a table that includes a sparkline in the search results, a second version of the table shows how to format the sparkline and create a custom cell renderer, and a third table that uses a custom row expansion renderer.

To use this code:

  1. Save the XML file under an existing app in $SPLUNK_HOME/etc/apps/app_name/local/data/ui/views/.
  2. Save the JS file under $SPLUNK_HOME/etc/apps/app_name/appserver/static/.
  3. Save the CSS file under $SPLUNK_HOME/etc/apps/app_name/appserver/static/.
  4. Restart Splunk.
  5. Open Splunk Web and view the dashboard in your app. For example, to view myexample in mysplunkapp, go to http://<localhost:port>/app/mysplunkapp/myexample.

example_customtables.xml

<dashboard script="example_customtables.js" stylesheet="custom.css">
    <label>Custom table cell and row rendering</label>
    <row>
        <panel>
            <html>
                <table>
                    <tr>
                        <td style="width: 100%;">
                            <h3>Standard table cells</h3>
                            <div id="table-plain"></div>
                        </td>
                    </tr>

                    <tr>
                        <td style="width: 100%;">
                            <h3>Custom table cells</h3>
                            <div id="table-customcell"></div>
                        </td>
                    </tr>

                    <tr>
                        <td style="width: 100%;">
                            <h3>Custom expanding table rows</h3>
                            <div id="table-customrow"></div>
                        </td>
                    </tr>

                </table>
            </html>
        </panel>
    </row>
</dashboard>

example_customtables.js

require([
    "underscore",
    "splunkjs/mvc/searchmanager",
    "splunkjs/mvc/tableview",
    "splunkjs/mvc/simplexml/ready!"
], function(
   _,
   SearchManager,
   TableView
) {

    // Set up search managers
    var search1 = new SearchManager({
        id: "search1",
        search: "index=_internal | head 10000 | stats sparkline count by sourcetype | rangemap field=count low=0-100 elevated=101-1000 default=severe",
        earliest_time: "-1h@h",
        latest_time: "now",
        preview: true,
        cache: true
    });

    var search2 = new SearchManager({
        id: "search2",
        preview: true,
        cache: true,
        search: "index=_internal | stats count by sourcetype, source, host"
    });

    // Create a table
    var myplaintable = new TableView({
        id: "table-plain",
        managerid: "search1",
        el: $("#table-plain")
    }).render();

    // Create a custom table and set sparkline properties
    var mycustomcelltable = new TableView({
        id: "table-customcell",
        managerid: "search1",
        el: $("#table-customcell"),
        // Format the sparkline cell
        format: {
            "sparkline": [ // This field name is required
                {
                    "type": "sparkline", // This property must be "sparkline"

                    // Sparkline options
                    "options":
                    {
                        "type": "bar",
                        "height": "40px",
                        "barWidth": "5px",
                        "colorMap":
                        {
                            "100:": "#0033CC",
                            ":99": "#00FF00"
                        }
                    }
                }
            ]
        }
    });

    // Create a table for a custom row expander
    var mycustomrowtable = new TableView({
        id: "table-customrow",
        managerid: "search2",
        drilldown: "none",
        el: $("#table-customrow")
    });

    // Define icons for the custom table cell
    var ICONS = {
        severe: "alert-circle",
        elevated: "alert",
        low: "check-circle"
    };

    // Use the BaseCellRenderer class to create a custom table cell renderer
    var CustomCellRenderer = TableView.BaseCellRenderer.extend({
        canRender: function(cellData) {
            // This method returns "true" for the "range" field
            return cellData.field === "range";
        },

        // This render function only works when canRender returns "true"
        render: function($td, cellData) {
            console.log("cellData: ", cellData);

            var icon = "question";
            if(ICONS.hasOwnProperty(cellData.value)) {
                icon = ICONS[cellData.value];
            }
            $td.addClass("icon").html(_.template('<i class="icon-<%-icon%> <%- range %>" title="<%- range %>"></i>', {
                icon: icon,
                range: cellData.value
            }));
        }
    });

    // Use the BasicRowRenderer class to create a custom table row renderer
    var CustomRowRenderer = TableView.BaseRowExpansionRenderer.extend({
        canRender: function(rowData) {
            console.log("RowData: ", rowData);
            return true;
        },

        render: function($container, rowData) {
        // Print the rowData object to the console
        console.log("RowData: ", rowData);

        // Display some of the rowData in the expanded row
        $container.append("<div>"
            + "<b>rowIndex</b>: " + rowData.rowIndex + "<br>"
            + "<b>colspan</b>: " + rowData.colspan + "<br>"
            + "<b>fields</b>: " + rowData.fields + "<br>"
            + "<b>values</b>: " + rowData.values
            + "</div>");
        }
    });

    // Create an instance of the custom cell renderer,
    // add it to the table, and render the table
    var myCellRenderer = new CustomCellRenderer();
    mycustomcelltable.addCellRenderer(myCellRenderer);
    mycustomcelltable.render();

    // Create an instance of the custom row renderer,
    // add it to the table, and render the table
    var myRowRenderer = new CustomRowRenderer();
    mycustomrowtable.addRowExpansionRenderer(myRowRenderer);
    mycustomrowtable.render();
});

custom.css

/* custom.css */

/* Define icon styles */

td.icon {
    text-align: center;
}

td.icon i {
    font-size: 15px;
    text-shadow: 1px 1px #aaa;
}

td.icon .severe {
    color: red;
}

td.icon .elevated {
    color: orangered;
}

td.icon .low {
    color: #006400;
}