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
Get Updates on the Splunk Community!

Introduction to Splunk Observability Cloud - Building a Resilient Hybrid Cloud

Introduction to Splunk Observability Cloud - Building a Resilient Hybrid Cloud  In today’s fast-paced digital ...

Observability protocols to know about

Observability protocols define the specifications or formats for collecting, encoding, transporting, and ...

Take Your Breath Away with Splunk Risk-Based Alerting (RBA)

WATCH NOW!The Splunk Guide to Risk-Based Alerting is here to empower your SOC like never before. Join Haylee ...