Dashboards & Visualizations

Javascript select table row values

mwdbhyat
Builder

Hi there,

How would I select an entire row in a table from a dashboard and use each field/cell from that table to populate another panel/table when selected? Essentially just cloning whatever rows i select from one panel -> hit submit -> selected rows go to another panel.

Any thoughts on how to achieve this?

Thanks!

1 Solution

kamlesh_vaghela
SplunkTrust
SplunkTrust

@mwdbhyat

You are lucky. I'm working on the same for another purpose but I'm sure you will achieve the same by using the below code.

Note: This code is now Specific to index=_internal | stats count by sourcetype | eval recNumber=1 | accum recNumber | table recNumber sourcetype count - this - search. So you have to manual change for your search. In your search you have to add | eval recNumber=1 | accum recNumber and put this as checkbox column. find recNumber in javascript which will let you know at how many places you have to make changes. Another field is sourcetype, this will also help you.

XML

<dashboard script="multiselect_table_data.js" stylesheet="multiselect_table_data.css">
  <label>Multi-Select Table Rows Example</label>
  <row>
    <panel>
      <table id="myTable">
        <title>Panel A</title>
        <search id="myPrimarySearch">
          <query>index=_internal | stats count by sourcetype | eval recNumber=1 | accum recNumber | table recNumber sourcetype count</query>
          <earliest>-15m</earliest>
          <latest>now</latest>
        </search>
        <option name="count">10</option>
        <option name="drilldown">row</option>
        <option name="refresh.display">progressbar</option>
        <drilldown>
          <condition field="*"></condition>
        </drilldown>
      </table>
    </panel>
     <panel>
      <html>
       <div>
         <input type="button" id="mybutton" value="Submit"/>
       </div>
     </html>
    </panel>
    <panel>
      <table id="secondTable">
        <title>Panel B</title>
        <search id="mysearch">
          <query> $searchQuery$ </query>
          <earliest>-15m</earliest>
          <latest>now</latest>
        </search>
        <option name="count">10</option>
        <option name="drilldown">none</option>
      </table>
    </panel>
  </row>
</dashboard>

multiselect_table_data.js

require([
        'underscore',
        'jquery',
        'splunkjs/mvc',
        'splunkjs/mvc/tableview',
        'splunkjs/mvc/simplexml/ready!'
    ], function (_, $, mvc, TableView) {
    // Access the "default" token model

    var defaultTokenModel = mvc.Components.get("default");
    var selected_values_array = [];
    var submittedTokens = mvc.Components.get('submitted');

    var myPrimarySearchData;

    var myPrimarySearch = mvc.Components.get('myPrimarySearch');
    var myPrimarySearch_results = myPrimarySearch.data("preview");
    //console.log("myPrimarySearch_results",myPrimarySearch_results);


    var myPrimarySearchArray = [];
    myPrimarySearch_results.on("data", function() {
        myPrimarySearchData = myPrimarySearch_results.data();

    });


    console.log("This is Multi-select table JS");
    // Custom renderer for applying checkbox.
    var FirstTableRenderer = TableView.BaseCellRenderer.extend({
        canRender: function (cell) {
            return _(['recNumber']).contains(cell.field);
        },
        render: function ($td, cell) {
            var a = $('<div>').attr({
                    "id": "chk-sourcetype" + cell.value,
                    "value": cell.value
                }).addClass('checkbox').click(function () {
                    if ($(this).attr('class') === "checkbox") {
                        selected_values_array.push($(this).attr('value'));
                        $(this).removeClass();
                        $(this).addClass("checkbox checked");
                    } else {
                        $(this).removeClass();
                        $(this).addClass("checkbox");
                        var i = selected_values_array.indexOf($(this).attr('value'));
                        if (i != -1) {
                            selected_values_array.splice(i, 1);
                        }
                    }
                });
                if(selected_values_array.indexOf(cell.value) > -1) {
                    a = a.addClass("checked");
                }
                a.appendTo($td);
        }
    });

    var sh = mvc.Components.get("myTable");
    if (typeof(sh) != "undefined") {
        sh.getVisualization(function (tableView) {
            // Add custom cell renderer and force re-render
            tableView.table.addCellRenderer(new FirstTableRenderer());
            tableView.table.render();
        });
    }

    // Disabling button while search is running 
    var mysearch = mvc.Components.get('mysearch');
    mysearch.on('search:start', function (properties) {
        $("#mybutton").attr('disabled', true);
    });

    mysearch.on('search:done', function (properties) {
        $("#mybutton").attr('disabled', false);
    });

    $(document).ready(function () {
        //setting up tokens with selected value.
        $("#mybutton").on("click", function (e) {
            e.preventDefault();
            setArrayInToken();
        });
    });

    function setArrayInToken(){
        defaultTokenModel.set("mytoken", selected_values_array.join());
        submittedTokens.set(defaultTokenModel.toJSON());
    }

    defaultTokenModel.on("change:mytoken", function(formQuery, indexName) {
        var newQuery = ' | makeresults | eval recNumber="'+indexName+'" | makemv delim="," recNumber | stats count by recNumber  | eval sourcetype=recNumber,count=recNumber | table  sourcetype count';
        console.log(newQuery);
        defaultTokenModel.set('searchQuery', newQuery);
    });

    var SecondTableRenderer = TableView.BaseCellRenderer.extend({
        canRender: function (cell) {
            return _(['recNumber','sourcetype','count']).contains(cell.field);
        },
        render: function ($td, cell) {
            var rows = myPrimarySearchData.rows;
            var fields = myPrimarySearchData.fields;
            var dataIndex = fields.indexOf(cell.field);
            var cellValue=rows[cell.value - 1][dataIndex];
            $td.addClass("string");
            var a = $('<div>'+cellValue+'</div>').appendTo($td);            
        }
    });

    var sh = mvc.Components.get("secondTable");
    if (typeof(sh) != "undefined") {
        sh.getVisualization(function (tableView) {
            // Add custom cell renderer and force re-render
            tableView.table.addCellRenderer(new SecondTableRenderer());
            tableView.table.render();
        });
    }   
});

multiselect_table_data.css

/* The standalone checkbox square*/
 .checkbox {
   width:20px;
   height:20px;
   border: 1px solid #000;
   display: inline-block;
 }

 /* This is what simulates a checkmark icon */
 .checkbox.checked:after {
   content: '';
   display: block;
   width: 4px;
   height: 7px;

   /* "Center" the checkmark */
   position:relative;
   top:4px;
   left:7px;

   border: solid #000;
   border-width: 0 2px 2px 0;
   transform: rotate(45deg);
 }

View solution in original post

kamlesh_vaghela
SplunkTrust
SplunkTrust

@mwdbhyat

You are lucky. I'm working on the same for another purpose but I'm sure you will achieve the same by using the below code.

Note: This code is now Specific to index=_internal | stats count by sourcetype | eval recNumber=1 | accum recNumber | table recNumber sourcetype count - this - search. So you have to manual change for your search. In your search you have to add | eval recNumber=1 | accum recNumber and put this as checkbox column. find recNumber in javascript which will let you know at how many places you have to make changes. Another field is sourcetype, this will also help you.

XML

<dashboard script="multiselect_table_data.js" stylesheet="multiselect_table_data.css">
  <label>Multi-Select Table Rows Example</label>
  <row>
    <panel>
      <table id="myTable">
        <title>Panel A</title>
        <search id="myPrimarySearch">
          <query>index=_internal | stats count by sourcetype | eval recNumber=1 | accum recNumber | table recNumber sourcetype count</query>
          <earliest>-15m</earliest>
          <latest>now</latest>
        </search>
        <option name="count">10</option>
        <option name="drilldown">row</option>
        <option name="refresh.display">progressbar</option>
        <drilldown>
          <condition field="*"></condition>
        </drilldown>
      </table>
    </panel>
     <panel>
      <html>
       <div>
         <input type="button" id="mybutton" value="Submit"/>
       </div>
     </html>
    </panel>
    <panel>
      <table id="secondTable">
        <title>Panel B</title>
        <search id="mysearch">
          <query> $searchQuery$ </query>
          <earliest>-15m</earliest>
          <latest>now</latest>
        </search>
        <option name="count">10</option>
        <option name="drilldown">none</option>
      </table>
    </panel>
  </row>
</dashboard>

multiselect_table_data.js

require([
        'underscore',
        'jquery',
        'splunkjs/mvc',
        'splunkjs/mvc/tableview',
        'splunkjs/mvc/simplexml/ready!'
    ], function (_, $, mvc, TableView) {
    // Access the "default" token model

    var defaultTokenModel = mvc.Components.get("default");
    var selected_values_array = [];
    var submittedTokens = mvc.Components.get('submitted');

    var myPrimarySearchData;

    var myPrimarySearch = mvc.Components.get('myPrimarySearch');
    var myPrimarySearch_results = myPrimarySearch.data("preview");
    //console.log("myPrimarySearch_results",myPrimarySearch_results);


    var myPrimarySearchArray = [];
    myPrimarySearch_results.on("data", function() {
        myPrimarySearchData = myPrimarySearch_results.data();

    });


    console.log("This is Multi-select table JS");
    // Custom renderer for applying checkbox.
    var FirstTableRenderer = TableView.BaseCellRenderer.extend({
        canRender: function (cell) {
            return _(['recNumber']).contains(cell.field);
        },
        render: function ($td, cell) {
            var a = $('<div>').attr({
                    "id": "chk-sourcetype" + cell.value,
                    "value": cell.value
                }).addClass('checkbox').click(function () {
                    if ($(this).attr('class') === "checkbox") {
                        selected_values_array.push($(this).attr('value'));
                        $(this).removeClass();
                        $(this).addClass("checkbox checked");
                    } else {
                        $(this).removeClass();
                        $(this).addClass("checkbox");
                        var i = selected_values_array.indexOf($(this).attr('value'));
                        if (i != -1) {
                            selected_values_array.splice(i, 1);
                        }
                    }
                });
                if(selected_values_array.indexOf(cell.value) > -1) {
                    a = a.addClass("checked");
                }
                a.appendTo($td);
        }
    });

    var sh = mvc.Components.get("myTable");
    if (typeof(sh) != "undefined") {
        sh.getVisualization(function (tableView) {
            // Add custom cell renderer and force re-render
            tableView.table.addCellRenderer(new FirstTableRenderer());
            tableView.table.render();
        });
    }

    // Disabling button while search is running 
    var mysearch = mvc.Components.get('mysearch');
    mysearch.on('search:start', function (properties) {
        $("#mybutton").attr('disabled', true);
    });

    mysearch.on('search:done', function (properties) {
        $("#mybutton").attr('disabled', false);
    });

    $(document).ready(function () {
        //setting up tokens with selected value.
        $("#mybutton").on("click", function (e) {
            e.preventDefault();
            setArrayInToken();
        });
    });

    function setArrayInToken(){
        defaultTokenModel.set("mytoken", selected_values_array.join());
        submittedTokens.set(defaultTokenModel.toJSON());
    }

    defaultTokenModel.on("change:mytoken", function(formQuery, indexName) {
        var newQuery = ' | makeresults | eval recNumber="'+indexName+'" | makemv delim="," recNumber | stats count by recNumber  | eval sourcetype=recNumber,count=recNumber | table  sourcetype count';
        console.log(newQuery);
        defaultTokenModel.set('searchQuery', newQuery);
    });

    var SecondTableRenderer = TableView.BaseCellRenderer.extend({
        canRender: function (cell) {
            return _(['recNumber','sourcetype','count']).contains(cell.field);
        },
        render: function ($td, cell) {
            var rows = myPrimarySearchData.rows;
            var fields = myPrimarySearchData.fields;
            var dataIndex = fields.indexOf(cell.field);
            var cellValue=rows[cell.value - 1][dataIndex];
            $td.addClass("string");
            var a = $('<div>'+cellValue+'</div>').appendTo($td);            
        }
    });

    var sh = mvc.Components.get("secondTable");
    if (typeof(sh) != "undefined") {
        sh.getVisualization(function (tableView) {
            // Add custom cell renderer and force re-render
            tableView.table.addCellRenderer(new SecondTableRenderer());
            tableView.table.render();
        });
    }   
});

multiselect_table_data.css

/* The standalone checkbox square*/
 .checkbox {
   width:20px;
   height:20px;
   border: 1px solid #000;
   display: inline-block;
 }

 /* This is what simulates a checkmark icon */
 .checkbox.checked:after {
   content: '';
   display: block;
   width: 4px;
   height: 7px;

   /* "Center" the checkmark */
   position:relative;
   top:4px;
   left:7px;

   border: solid #000;
   border-width: 0 2px 2px 0;
   transform: rotate(45deg);
 }

dreadangel
Path Finder

Awesome!!! Thank you a lot!!!

0 Karma

mwdbhyat
Builder

@kamlesh_vaghela awesome stuff this is really cool! Thanks! Do you have any tricks up your sleeve to send a sparkline across from table 1 to table 2 =D ..i have some timechart sparkline graphs in table 1 and in table 2 they are just the numerical values..

0 Karma
Got questions? Get answers!

Join the Splunk Community Slack to learn, troubleshoot, and make connections with fellow Splunk practitioners in real time!

Meet up IRL or virtually!

Join Splunk User Groups to connect and learn in-person by region or remotely by topic or industry.

Get Updates on the Splunk Community!

Index This | What travels the world but is also stuck in place?

April 2026 Edition  Hayyy Splunk Education Enthusiasts and the Eternally Curious!   We’re back with this ...

Discover New Use Cases: Unlock Greater Value from Your Existing Splunk Data

Realizing the full potential of your Splunk investment requires more than just understanding current usage; it ...

Continue Your Journey: Join Session 2 of the Data Management and Federation Bootcamp ...

As data volumes continue to grow and environments become more distributed, managing and optimizing data ...