I want the sort indicators (up/down arrowheads) in table visualization column headings to reflect the default sort order of the data supplied by the underlying search.
I'm using the sort
command in Splunk 7.3.0 to sort the search results for a table by one of the fields in descending order. So the rows of the table are already sorted. However, the sort indicators in the visualization don't reflect that default sort order.
Instead of this:
I want the table to show this, by default:
(How) can I do this? There doesn't appear to be a corresponding formatting option to set the table visualization sort indicators.
[UPDATED ANSWER]
Updated the answer to render the table only after search completes using <done>
and added a token dependency to apply desc
class to the icon for count
so that it shows down arrow only when dashboard loads. After which it should respond to click on the table header.
@Graham_Hannington this would be possible through Simple XML JS Extension where on load of the table you can override the icon of table header using SplunkJS.
In the following run anywhere example I have a table with id="my_table_with_default_sort"
which I am accessing via JS to override icon class as desc
to apply icon.
<dashboard script="table_default_sort.js">
<label>Table with Sort</label>
<init>
<set token="tokTableOnLoad">true</set>
</init>
<row>
<panel>
<table id="my_table_with_default_sort" depends="$tokRenderTableOnSearchCompletion$">
<search>
<query>index=_internal sourcetype=splunkd log_level!=INFO
| stats count by component
| sort 0 -count</query>
<done>
<set token="tokRenderTableOnSearchCompletion">true</set>
</done>
<earliest>-24h@h</earliest>
<latest>now</latest>
<sampleRatio>1</sampleRatio>
</search>
<option name="count">20</option>
<option name="dataOverlayMode">none</option>
<option name="drilldown">none</option>
<option name="percentagesRow">false</option>
<option name="rowNumbers">false</option>
<option name="totalsRow">false</option>
<option name="wrap">true</option>
</table>
</panel>
</row>
</dashboard>
Following is the required JS table_default_sort.js
require(["jquery",
"splunkjs/mvc",
"splunkjs/mvc/tableview",
"splunkjs/mvc/simplexml/ready!"],
function ($,
mvc,
TableView) {
var defaultTokenModel=mvc.Components.get("default");
mvc.Components.get('my_table_with_default_sort').getVisualization(function (tableView) {
tableView.on('rendered', function () {
setTimeout(function(){
var strTokTableOnLoad=defaultTokenModel.get("tokTableOnLoad");
// Get the Token tokTableOnLoad which is set in the <init> section for the first time override of table sort icon for count column
if(strTokTableOnLoad!==undefined){
$('#my_table_with_default_sort table th[data-sort-key="count"] a i').addClass("desc");
// Unset the token tokTableOnLoad so that Table icon override never happens for the second time.
defaultTokenModel.unset("tokTableOnLoad");
}
},100);
});
});
});
Please try out and confirm!
I am surprised that this behavior is not already baked in to Splunk, at 7.3.x. Having tables reflect the default sort order of their data seems such an obvious thing to do. Is my use case so atypical? I understand that this might be a low priority, but still, isn't it "low-hanging fruit": relatively easy for the Splunk developers to add options to the table viz to support this behavior (say, sortColumn
, sortOrder
)?
[UPDATED ANSWER]
Updated the answer to render the table only after search completes using <done>
and added a token dependency to apply desc
class to the icon for count
so that it shows down arrow only when dashboard loads. After which it should respond to click on the table header.
@Graham_Hannington this would be possible through Simple XML JS Extension where on load of the table you can override the icon of table header using SplunkJS.
In the following run anywhere example I have a table with id="my_table_with_default_sort"
which I am accessing via JS to override icon class as desc
to apply icon.
<dashboard script="table_default_sort.js">
<label>Table with Sort</label>
<init>
<set token="tokTableOnLoad">true</set>
</init>
<row>
<panel>
<table id="my_table_with_default_sort" depends="$tokRenderTableOnSearchCompletion$">
<search>
<query>index=_internal sourcetype=splunkd log_level!=INFO
| stats count by component
| sort 0 -count</query>
<done>
<set token="tokRenderTableOnSearchCompletion">true</set>
</done>
<earliest>-24h@h</earliest>
<latest>now</latest>
<sampleRatio>1</sampleRatio>
</search>
<option name="count">20</option>
<option name="dataOverlayMode">none</option>
<option name="drilldown">none</option>
<option name="percentagesRow">false</option>
<option name="rowNumbers">false</option>
<option name="totalsRow">false</option>
<option name="wrap">true</option>
</table>
</panel>
</row>
</dashboard>
Following is the required JS table_default_sort.js
require(["jquery",
"splunkjs/mvc",
"splunkjs/mvc/tableview",
"splunkjs/mvc/simplexml/ready!"],
function ($,
mvc,
TableView) {
var defaultTokenModel=mvc.Components.get("default");
mvc.Components.get('my_table_with_default_sort').getVisualization(function (tableView) {
tableView.on('rendered', function () {
setTimeout(function(){
var strTokTableOnLoad=defaultTokenModel.get("tokTableOnLoad");
// Get the Token tokTableOnLoad which is set in the <init> section for the first time override of table sort icon for count column
if(strTokTableOnLoad!==undefined){
$('#my_table_with_default_sort table th[data-sort-key="count"] a i').addClass("desc");
// Unset the token tokTableOnLoad so that Table icon override never happens for the second time.
defaultTokenModel.unset("tokTableOnLoad");
}
},100);
});
});
});
Please try out and confirm!
I've accepted this answer because it works for the question I asked. @niketnilay deserves credit for that.
However, there's a caveat: I can't—or rather, won't—be using this answer in practice, because, in my opinion, it's too onerous to implement. The code presented in this answer is specific to a particular table visualization. I'm considering asking a new, follow-on, more carefully worded question to address this.
@Graham_Hannington thanks for accepting the answer. And trust me I have got your followup question for making this generic for all tableViews in the dashboard. Which is doable, but I would be able to spend time for creating an example only o we the weekend. So hang tight (hopefully I get to spend time as I have pipelinedquite many such challenges for the weekend).
Hi @niketnilay,
With apologies for the belated reply (I was on leave for a couple of days): thanks very much! Yes, that worked!
Nit: to get your code to work, I had to change tokRenderTableOnSearchCompletion
in the dashboard source to match the corresponding token name tokTableOnLoad
in the JavaScript. At least—I write this in case I'm completely misunderstanding something here—it didn't work at first, and then I made that change, and then it worked.
So... I suppose I should accept your answer immediately. And, if that's what you'd prefer, after reading the rest of this comment, I'll do just that.
Your current answer works for a specific table: with hardcoded table ID, sorted column name, and sort order.
I want to apply this behavior to multiple tables on a dashboard. I don't want to create a separate .js
file for each table. I can't bring myself to implement this answer in code that I'm going to deliver to customers. (My problem? Sure.)
I've started experimenting with JavaScript that will iterate over all table views in a dashboard:
$.each(mvc.Components.getInstances(), function (i, view) {
if (view instanceof TableView) {
view.on('rendered', function(view) {setDefaultSort(view)});
}
});
but tokens are—unless I'm mistaken; I might be—by definition dashboard-wide, not view-specific, so this token-based approach does not work for multiple views in a dashboard.
I've started to look into other ways to pass a sort column name and sort order through to the JavaScript, and to have the rendering occur only on page load, but I feel like I'm heading down a developmental rabbit hole (custom visualization?) that I don't have time to explore.
Your thoughts?
Extending the table cell renderer initially occurred to me as a possibility, but it seems that the cell renderer is limited to the table body cells (td); I can't find a way to extend the rendering of the table header cells (th).