Example: Tables with custom renderers using JavaScript in a template

This example uses JavaScript 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, save it as an HTML file under an existing app in $SPLUNK_HOME/etc/apps/app_name/django/app_name/templates, then view the page in Splunk. For example, to view mypage.html in mysplunkapp, go to http://localhost:8000/dj/mysplunkapp/mypage. For more about creating an app, see How to create a Web Framework app using SplunkJS Stack.

{% extends "splunkdj:base_with_app_bar.html" %}

{% load splunkmvc %}

{% block title %}Custom table cell and row rendering (JavaScript){% endblock title %}

{% block css %}
    <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}splunkjs/css/dashboard.css" />
    <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}{{app_name}}/custom.css" />

    <!-- Define icon styles -->
    <style>
        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;
        }
    </style>
{% endblock css %}

{% block content %}
    <div class="dashboard-body container-fluid main-section-body">

        <div class="row">
            <div class="dashboard-header clearfix">
                <h2>Custom cell and row renderers</h2>
            </div>
        </div>

        <div class="dashboard-row">
            <div class="dashboard-cell" style="width: 100%;">
                <div class="dashboard-panel">
                    <div class="panel-head">
                        <h3>Standard table cells</h3>
                    </div>
                    <div class="panel-body">
                        <div id="table-plain"></div>
                    </div>
                </div>
            </div>
        </div>

        <div class="dashboard-row">
            <div class="dashboard-cell" style="width: 100%;">
                <div class="dashboard-panel">
                    <div class="panel-head">
                        <h3>Custom table cells</h3>
                    </div>
                    <div class="panel-body">
                        <div id="table-customcell"></div>
                    </div>
                </div>
            </div>
        </div>

        <div class="dashboard-row">
            <div class="dashboard-cell" style="width: 100%;">
                <div class="dashboard-panel">
                    <div class="panel-head">
                        <h3>Custom expanding table rows</h3>
                    </div>
                    <div class="panel-body">
                        <div id="table-customrow"></div>
                    </div>
                </div>
            </div>
        </div>

    </div>
{% endblock content%}

{% block js %}
    <script>
        var deps = [
            "splunkjs/ready!",
            "underscore",
            "splunkjs/mvc/searchmanager",
            "splunkjs/mvc/tableview"
        ];
        require(deps, function(mvc,_) {
            // Load individual components
            var SearchManager = require("splunkjs/mvc/searchmanager");
            var TableView = require("splunkjs/mvc/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();
        });
    </script>
{% endblock js %}