Splunk Search

multiselect table rows

493669
Super Champion

Hi,
I am currently trying to multi-select table rows. So basically I want to select multiple rows and on selction ,selected rows fields values get store(like in SQL using select query) and below table one button will be present .On clicking that button, the selected rows (field values) get stored in lookup (using outputlookup query).
Is it Possible in Splunk.
Any pointers to this will really help.

Thanks,

1 Solution

kamlesh_vaghela
SplunkTrust
SplunkTrust

HI,

To select row is not direclty possible but yes you can achieve this.

1) In the table view, add one more column which will display the checkbox for each row. (using javascript)
2) Declare a javascript variable, like array type, which store table row value on tick and remove on untick of checkbox.
3) Add a button below table view and define a onclick function, which executes outputlookup search for selected table rows( which is stored into javascript vaiable) and stores it into lookup.

Is this approach ok for you?

Thanks

View solution in original post

niketn
Legend

@493669 while ideally it should be done via JavaScript so that you have better control of data, validations and event actions.
However, I am giving a run anywhere dashboard examples purely in Simple XML just for the heck of it just because @kamlesh_vaghela's comment not directly possible got me thinking 🙂

alt text

Following is the run anywhere Dashboard Example (PS: I have purposely not used depends attribute for various panels to ensure that demo shows how temporary csv and final csv gets modified with various events).

<form>
  <label>Move Selected row/s from one table to another</label>
  <!-- Query to run in background to clear temporary cvs on selecting discard option -->
  <search>
    <query>$tokQueryClearTempLookup$
    </query>
    <done>
      <!-- Unsets clear temp table query once search completes -->
      <unset token="tokQueryClearTempLookup"></unset>
      <!-- Once Temporary CSV is cleaned up the same should be updated in the table view (for No Rsults found) -->
      <set token="tokRowData">| inputlookup tempRowData.csv | table component ERROR WARN | dedup component ERROR WARN | outputlookup tempRowData.csv</set>
    </done>
  </search>
  <fieldset submitButton="false"></fieldset>
  <row>
    <panel>
      <!-- Table with Sample data. Following is run anywhere search of Splunk Errors with first 10 rows by component name -->
      <table>
        <title>Source Table (Splunk Component Errors head 10)</title>
        <search>
          <query>index=_internal sourcetype=splunkd log_level!="INFO"
|  chart count over component by log_level
|  head 10</query>
          <earliest>-24h@h</earliest>
          <latest>now</latest>
          <sampleRatio>1</sampleRatio>
        </search>
        <option name="count">20</option>
        <option name="dataOverlayMode">none</option>
        <option name="drilldown">cell</option>
        <option name="percentagesRow">false</option>
        <option name="rowNumbers">false</option>
        <option name="totalsRow">false</option>
        <option name="wrap">true</option>
        <drilldown>
          <!-- Set the query for updating the temporary CSV when a row is selected in the Table. All table columns are accessed with $row.<fieldname>$ predefined table drilldown token -->
          <set token="tokRowData">| inputlookup tempRowData.csv | append [| makeresults | eval component="$row.component$",ERROR="$row.ERROR$",WARN="$row.WARN$"] | table component ERROR WARN | dedup component ERROR WARN | outputlookup tempRowData.csv</set>
        </drilldown>
      </table>
    </panel>
    <panel>
      <input type="radio" token="chkSaveResult" searchWhenChanged="true">
        <label>(Clicking save with empty temporary csv will clear Final Table as well)</label>
        <choice value="save">Save</choice>
        <choice value="discard">Discard</choice>
        <change>
          <!-- On click of Save radio button, set the query for saving data from Temporary CSV to Final CSV -->
          <!-- Clean Radio Button token after click to give button like behavior i.e. Event on every click -->
          <condition value="save">
            <set token="tokQuerySaveFinalLookup">| inputlookup tempRowData.csv | outputlookup finalLookup.csv</set>
            <unset token="chkSaveResult"></unset>
            <unset token="form.chkSaveResult"></unset>
          </condition>
          <!-- On click of Discard radio button, set the query for clearing Temporary CSV and unset the final save query token-->
          <!-- Clean Radio Button token after click to give button like behavior i.e. Event on every click -->
          <condition value="discard">
            <set token="tokQueryClearTempLookup">|  makeresults |  fields - _time | outputlookup tempRowData.csv</set>
            <unset token="chkSaveResult"></unset>
            <unset token="form.chkSaveResult"></unset>
            <unset token="tokQuerySaveFinalLookup"></unset>
          </condition>
        </change>
      </input>
      <!-- Text box to provide Lookup File to save the final Output. temp.csv is default final file-->
      <input type="text" token="tokFileName" searchWhenChanged="true">
        <label>Final Lookup File Name</label>
        <initialValue>temp.csv</initialValue>
      </input>
      <!-- Table to Show Temporary CSV -->
      <table>
        <title>Temporary Table Based on Selected Values (tempRowData.csv)</title>
        <search>
          <query>$tokRowData$
          </query>
        </search>
      </table>
    </panel>
    <panel>
      <!-- Table to show content of Final Output csv file-->
      <table>
        <title>Final Table ($tokFileName$)</title>
        <search>
          <query>$tokQuerySaveFinalLookup$
          </query>
          <done>
            <!-- After saving to Final Output File Clear out content of Temporary CSV, reset the Final CSV name to temp.csv and clear the Save Query-->
            <!-- Since Saving results to final CSV clears the Temporary table. Clicking again on Save radio option will set the Final csv with empty values. So it is better to provide custom file name rather that temp.csv before saving. -->   
            <set token="tokQueryClearTempLookup">| makeresults |  fields - _time | outputlookup tempRowData.csv</set>
            <set token="form.tokFileName">temp.csv</set>
            <unset token="tokQuerySaveFinalLookup"></unset>
          </done>
        </search>
      </table>
    </panel>
  </row>
</form>
____________________________________________
| makeresults | eval message= "Happy Splunking!!!"
0 Karma

493669
Super Champion

Thanks @niketnilay .
It will select one row at a time but I want to select multiple rows simultaneously and after that clicking on button will |outputlookup all select rows (field values)

Thats why I might need to use javascript

0 Karma

niketn
Legend

Sure. Although for selecting one row you need to click each time. However, temporary table which builds up with individual rows get saved only if you click on Save radio button option. For Simultaneous selection if you are planning on coding drag event then you can do the same only through JavaScript. Even check box option will work based on clicking one row at a time.

____________________________________________
| makeresults | eval message= "Happy Splunking!!!"
0 Karma

kamlesh_vaghela
SplunkTrust
SplunkTrust

HI,

To select row is not direclty possible but yes you can achieve this.

1) In the table view, add one more column which will display the checkbox for each row. (using javascript)
2) Declare a javascript variable, like array type, which store table row value on tick and remove on untick of checkbox.
3) Add a button below table view and define a onclick function, which executes outputlookup search for selected table rows( which is stored into javascript vaiable) and stores it into lookup.

Is this approach ok for you?

Thanks

Sankavi
Engager

This is awesome and works like a pro!! @kamlesh_vaghela

0 Karma

493669
Super Champion

Thanks @kamlesh_vaghela
I am not familiar with javascript. Could you please explain in details to store row value on click of multiselect checkbox.

0 Karma

kamlesh_vaghela
SplunkTrust
SplunkTrust

Hi
I have created sample dashboard for you.

Can you please try below code?

mydashboard.xml

<form script="my.js" stylesheet="my.css">
  <row>
    <panel>
      <table id="myTable">
        <title>My Table</title>
        <search>
          <query>index=_internal | stats count by sourcetype | eval checkbox=sourcetype</query>
          <earliest>-15m</earliest>
          <latest>now</latest>
        </search>
        <option name="count">10</option>
        <option name="drilldown">row</option>
        <drilldown>
          <condition field="*">

          </condition>
          </drilldown>
      </table>
    </panel>
  </row>
  <row>
    <html>
      <div>
        <input type="button" id="mybutton" value="My Button" />
      </div>
    </html>
  </row>
  <row>
     <panel>
      <table>
        <title>My Selected Value</title>
        <search>
          <query>| makeresults | eval myvalue="$mytoken$" | makemv delim="," myvalue | stats count by myvalue | table myvalue</query>
          <earliest>-15m</earliest>
          <latest>now</latest>
        </search>
        <option name="count">10</option>
        <option name="drilldown">none</option>
      </table>
    </panel>
  </row>
</form>

my.js

require([
    'underscore',
    'jquery',
    'splunkjs/mvc',
    'splunkjs/mvc/tableview',
    'splunkjs/mvc/simplexml/ready!'
], function(_, $, mvc, TableView) {
    // Access the "default" token model
    var tokens = mvc.Components.get("default");
    var selected_values_array = [];
    var submittedTokens = mvc.Components.get('submitted');

    var CustomRangeRenderer = TableView.BaseCellRenderer.extend({
        canRender: function(cell) {
            return _(['checkbox']).contains(cell.field);
        },
        render: function($td, cell) {
            var a = $('<div>').attr({"id":"chk-sourcetype"+cell.value,"value":cell.value}).addClass('checkbox').click(function() {
                // console.log("checked",$(this).attr('class'));
                // console.log("checked",$(this).attr('value'));
                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);
                    }
                    // Change the value of a token $mytoken$
                }
                console.log(selected_values_array);
            }).appendTo($td);
        }
    });

    //List of table IDs
    var tableIDs = ["myTable"];
    for (i=0;i<tableIDs.length;i++) {
        var sh = mvc.Components.get(tableIDs[i]);
        if(typeof(sh)!="undefined") {
            sh.getVisualization(function(tableView) {
                // Add custom cell renderer and force re-render
                tableView.table.addCellRenderer(new CustomRangeRenderer());
                tableView.table.render();
            });
        }
    }
    $(document).ready(function () {
        $("#mybutton").on("click", function (e) {
            e.preventDefault();
            console.log("in");
            tokens.set("mytoken", selected_values_array.join());
            submittedTokens.set(tokens.toJSON());
        });
    });
});

my.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);
}

Here I have created javascript and Css (my.js and my.css).
Keep both file in SPLUNK_HOME/etc/apps/MYAPP/appserver/static/ path.

There are two tables in dashboard. First for selection and seconf for selected value.
I have stored value in javascript variable selected_values_array and splunk token mytoken.
You can use splunk token mytoken in any search.
2nd table is an example of using splunk token mytoken. You can use this token for store in lookup.

Thanks

cmerriman
Super Champion

i seriously could not upvote this enough. you should package this up and put it out on splunkbase as a custom viz. saved me so much time. you are amazing.

0 Karma

kamlesh_vaghela
SplunkTrust
SplunkTrust
0 Karma

mwdbhyat
Builder

@kamlesh_vaghela this is awesome!..Is there a way to create a "select all" checkbox that would select everything and dump to another table ?

0 Karma

kamlesh_vaghela
SplunkTrust
SplunkTrust

@mwdbhyat

Yes, you can do that. In this case, you have to use the first table's search in the second table with the filter with mytoken.

Can you please try?

0 Karma

mwdbhyat
Builder

@kamlesh_vaghela im more after an actual checkbox above the first table(or at the top) so if I tick it, it selects all the boxes below it and then adds to the second table?

0 Karma

vasanthi77
Explorer

@mwdbhyat did u get the solution to have check box which will select all.?
Please help me , even i m looking for such kind of requirement

0 Karma

vasanthi77
Explorer

@kamlesh_vaghela can u please help here out

0 Karma

kamlesh_vaghela
SplunkTrust
SplunkTrust

@vasanthi77

This feature will be added in a future release but you try below workaround.

Note: Here, we have changed the logic and instead of making results we are executing Search for getting the events. Second, this will not take the effect of a selected row, it will directly reflect into the 2nd table.

I've made some changes in XML.

multiselect_table.xml

<dashboard script="multiselect_table.js" stylesheet="multiselect_table.css">
  <label>Multi-Select Table Rows Example</label>
  <row>
    <panel>
    <!-- This Panel is for instruction purpose only-->
      <html>
    <h1>This is an example for multi select table rows.</h1>
    <h2>Steps:</h2>
    <ui>
    <li>Select rows from Panel A by clicking on checkboxes.</li>
    <li>Click on "Submit" button</li>
    <li>You will get selected values in Panel B.</li>
    </ui>
    &lt;br/&gt;
    <h3>This is how you can achieve your requirements. See below files for implementation code.</h3>
    <code>multiselect_table.js</code>&lt;br/&gt;
    <code>multiselect_table.css</code>&lt;br/&gt;
    <code>multiselect_table.xml</code>&lt;br/&gt;
    </html>
    </panel>
  </row>
  <row>
    <panel>
      <table id="myTable">
        <title>Panel A</title>
        <search>
          <query>index=_internal | stats count by sourcetype | eval CheckBox=sourcetype | table CheckBox sourcetype count</query>
          <earliest>-15m</earliest>
          <latest>now</latest>
        </search>
        <option name="count">10</option>
        <option name="drilldown">row</option>
        <drilldown>
          <condition field="*"></condition>
        </drilldown>
      </table>
    </panel>
    <panel>
      <html>
       <div>
         <input type="button" id="mybutton" value="Submit"/>
         <input type="button" id="btnSelectAll" value="Select All"/>
       </div>
     </html>
    </panel>
    <panel>
      <table>
        <title>Panel B</title>
        <search id="mysearch">
          <query>
          index=_internal [| makeresults | eval sourcetype="$mytoken$" | makemv delim="," sourcetype | stats count by sourcetype | fields sourcetype | format " " " " " " " " "OR" " " ] | stats count by sourcetype | eval CheckBox=sourcetype | table CheckBox sourcetype count
          </query>
          <earliest>-15m</earliest>
          <latest>now</latest>
        </search>
        <option name="count">10</option>
        <option name="drilldown">none</option>
      </table>
    </panel>
  </row>
</dashboard>

multiselect_table.js

Add below code in $(document).ready(function () { block.

$("#btnSelectAll").on("click", function (e) {
            e.preventDefault();
            tokens.set("mytoken", "*");
            submittedTokens.set(tokens.toJSON());
            $("#btnSelectAll").attr('disabled', true);
        });

There might be required some specific changes but let's try this and let me know if it is worked or not.

Thanks

0 Karma

vasanthi77
Explorer

@kamlesh_vaghela

Thanks for the reply , It is working. bt i want a checkbox in place of button fr selecting all.
Can u check my question https://answers.splunk.com/answers/767580/how-to-have-a-checkbox-check-all-the-rows-in-the-t.html .
It will be very helpful if u can answer that one please.

Thanks in advance

0 Karma

493669
Super Champion

Thats Great....Thanks @kamlesh_vaghela

I dont understand use of below ... Could you please help to understand

//List of table IDs
     var tableIDs = ["myTable"];
     for (i=0;i<tableIDs.length;i++) {
         var sh = mvc.Components.get(tableIDs[i]);
         if(typeof(sh)!="undefined") {
             sh.getVisualization(function(tableView) {
                 // Add custom cell renderer and force re-render
                 tableView.table.addCellRenderer(new CustomRangeRenderer());
                 tableView.table.render();
             });
         }
     }

I was just thinking if I can disable the "MyButton" after one click to avoid double click...If you could help me...
else I will be accepting your answer

0 Karma

kamlesh_vaghela
SplunkTrust
SplunkTrust

Hi
Above code is for accessing table view using ID and applying custom render for that table view.

Yes, you can disable button.

Just replace onclick with below code.

$(document).ready(function () {
        $("#mybutton").on("click", function (e) {
            e.preventDefault();
            console.log("in");
            tokens.set("mytoken", selected_values_array.join());
            submittedTokens.set(tokens.toJSON());
           $("#mybutton").attr('disabled',true);
        });
    });

I have just added

$("#mybutton").attr('disabled',true);

Please accept this ans to close this question.

0 Karma

493669
Super Champion

correct it will disable it but I want to enable it after table search query runs..

$("#mybutton").attr('disabled',false);

it will enable it but how I can know if table query search is completed.

0 Karma

kamlesh_vaghela
SplunkTrust
SplunkTrust

Hi @493669,
Yes, we can do it.

Can you please add id="mysearch" in second search tag in xml file?? like..

<search id="mysearch">
    <query>| makeresults | eval myvalue="$mytoken$" | makemv delim="," myvalue | stats count by myvalue | table myvalue</query>
    <earliest>-15m</earliest>
    <latest>now</latest>
</search>

Please Remove previously added code $("#mybutton").attr('disabled',true); from javascript & add below code above the $(document).ready(function () { code.

    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 () {
     $("#mybutton").on("click", function (e) {
         e.preventDefault();
         console.log("in");
         tokens.set("mytoken", selected_values_array.join());
         submittedTokens.set(tokens.toJSON());
         // $("#mybutton").attr('disabled',true); // Remove this line.

     });
 });

Thanks
Happy Splunking

0 Karma
Get Updates on the Splunk Community!

Splunk Education - Fast Start Program!

Welcome to Splunk Education! Splunk training programs are designed to enable you to get started quickly and ...

Five Subtly Different Ways of Adding Manual Instrumentation in Java

You can find the code of this example on GitHub here. Please feel free to star the repository to keep in ...

New Splunk APM Enhancements Help Troubleshoot Your MySQL and NoSQL Databases Faster

Splunk Observability has two new enhancements to make it quicker and easier to troubleshoot slow or frequently ...