All Apps and Add-ons

Sideview Utils: How to get Sideview Table Module to render in dynamic column names based on its value?

Path Finder

Hello all!

I'm working with dynamic field names, i.e

eval {data_name} = data_value

will generate, for N different data_name entries, N fields with data_name value. Very useful when data fields are not static.

But now I would like to work with custom css rendering for each column based on its value. I normally use Sideview Table module with the "columns.<fieldname>.style" param, but my fieldnames are dynamic.

Any way to accomplish this? I was thinking about some king of wildcard approach like:

columns.dynamicfieldexample*.style

that would match all columns of fields starting with dynamicfieldexample

Thanks!!

1 Solution

SplunkTrust
SplunkTrust

This is a fun question - thanks for asking it.

The custom column-rendering features in the Table module indeed are strictly static. (For readers who aren't familiar with this, within the Sideview Utils app you can read about them by going to "Module Documentation > The Table module > Custom rendering") .

Specifically, by static here I mean that you can't do $foo$ substitution or wildcards or anything in the columnName. Adding $foo$ substitution in a future release would be pretty easy although it doesn't sound like that improvement by itself would help you much. Adding wildcard support (ie for columns.somePrefix*.class)... that's getting a bit further out on a limb than is probably wise. (Not because it's hard but just because it's probably better to explore this sort of requirements with some JS customBehavior a bit more before baking in new features)

Before resorting to custom JS though, the other way you might attack this problem is with pure CSS. The problem I think with using CSS for this, is that between the need to style the cells based on the mere contents of the column header node, and the need to wildcard in our match... pure CSS table styles just don't really have this kind of power yet. Getting there. And the Table module doesn't help because there's no secret class or attribute on the td elements that could help you customize them based on column names.

Which leaves JS.

Splunk UI modules have kind of a lot of moving parts and event-driven behaviors and as a rule if you try and just start writing your own JS independently based on someones generic jquery sample code.... it wont work. This is certainly the case with the table module. Between re-rendering when the job is running/finished and re-rendering when someone changes the page and when someone clicks a sort arrow, your clever generic jquery code is kinda doomed.

So if you work with the system rather than against it, and assuming you're OK with writing, tinkering, cursing at, and maintaining custom Javascript (hey where'd everybody go??)

....here's an example of the sort of thing you need.

1) read the somewhat hidden docs page about Sideview "customBehavior" mechanisms. (Tools > Other Tools > and then scroll down to the last panel)

2) In the XML, give a Table module this param:

<param name="customBehavior">customColumnRendering</param>

3) and then add this to your application.js

if (typeof(Sideview)!="undefined") {
    Sideview.utils.declareCustomBehavior("customColumnRendering", function(tableModule) {
        var methodReference = tableModule.renderResults.bind(tableModule);
        tableModule.renderResults = function(xmlStr) {
            // save a copy of the property before we muck with it.
            var pristineCopy = $.extend(true,{},this.columnRenderingRules);
            // add in some new rules
            for (var i=0,len=this.fieldOrder.length;i<len;i++ ) {
                var field = this.fieldOrder[i];
                if (field.substr(0,10)=="somePrefix") {
                    this.columnRenderingRules[field] = {"class":"myClassName"};
                }
            }
            // done adding in new rules

            // don't forget to call the base implementation of renderResults()
            var retVal = methodReference(xmlStr);
            // put the clean copy back.
            this.columnRenderingRules = pristineCopy;
            return retVal;
        }
    })
}

What you'll get afterwards is a Table where any column whose header label begins with "somePrefix", gets a CSS classname slapped on it's th and td elements, of "myClassName".

View solution in original post

SplunkTrust
SplunkTrust

This is a fun question - thanks for asking it.

The custom column-rendering features in the Table module indeed are strictly static. (For readers who aren't familiar with this, within the Sideview Utils app you can read about them by going to "Module Documentation > The Table module > Custom rendering") .

Specifically, by static here I mean that you can't do $foo$ substitution or wildcards or anything in the columnName. Adding $foo$ substitution in a future release would be pretty easy although it doesn't sound like that improvement by itself would help you much. Adding wildcard support (ie for columns.somePrefix*.class)... that's getting a bit further out on a limb than is probably wise. (Not because it's hard but just because it's probably better to explore this sort of requirements with some JS customBehavior a bit more before baking in new features)

Before resorting to custom JS though, the other way you might attack this problem is with pure CSS. The problem I think with using CSS for this, is that between the need to style the cells based on the mere contents of the column header node, and the need to wildcard in our match... pure CSS table styles just don't really have this kind of power yet. Getting there. And the Table module doesn't help because there's no secret class or attribute on the td elements that could help you customize them based on column names.

Which leaves JS.

Splunk UI modules have kind of a lot of moving parts and event-driven behaviors and as a rule if you try and just start writing your own JS independently based on someones generic jquery sample code.... it wont work. This is certainly the case with the table module. Between re-rendering when the job is running/finished and re-rendering when someone changes the page and when someone clicks a sort arrow, your clever generic jquery code is kinda doomed.

So if you work with the system rather than against it, and assuming you're OK with writing, tinkering, cursing at, and maintaining custom Javascript (hey where'd everybody go??)

....here's an example of the sort of thing you need.

1) read the somewhat hidden docs page about Sideview "customBehavior" mechanisms. (Tools > Other Tools > and then scroll down to the last panel)

2) In the XML, give a Table module this param:

<param name="customBehavior">customColumnRendering</param>

3) and then add this to your application.js

if (typeof(Sideview)!="undefined") {
    Sideview.utils.declareCustomBehavior("customColumnRendering", function(tableModule) {
        var methodReference = tableModule.renderResults.bind(tableModule);
        tableModule.renderResults = function(xmlStr) {
            // save a copy of the property before we muck with it.
            var pristineCopy = $.extend(true,{},this.columnRenderingRules);
            // add in some new rules
            for (var i=0,len=this.fieldOrder.length;i<len;i++ ) {
                var field = this.fieldOrder[i];
                if (field.substr(0,10)=="somePrefix") {
                    this.columnRenderingRules[field] = {"class":"myClassName"};
                }
            }
            // done adding in new rules

            // don't forget to call the base implementation of renderResults()
            var retVal = methodReference(xmlStr);
            // put the clean copy back.
            this.columnRenderingRules = pristineCopy;
            return retVal;
        }
    })
}

What you'll get afterwards is a Table where any column whose header label begins with "somePrefix", gets a CSS classname slapped on it's th and td elements, of "myClassName".

View solution in original post

Path Finder

Ey, thanks (with many days of delay) for your detailed and useful answer (as always!). I will stick to custom JS in no new webframework panels, but what I understand here is that dynamic generated fields shall not be a good practice for dashboards and visualizations.

Again, thank you!!

0 Karma

Path Finder

Hi,

I have the same scenario, where I need to update table element dynamically based on search element result. Where I need to map with search id search_id to manager id of the table to display search result in table. problem here is I need to provide every time new id search_id_table to table element which generates new table instead of updating table.
Do u have any idea regarding this?

search_query = new SearchManager({
"id": search_id,
"status_buckets": 0,
"cancelOnUnload": true,
"search": search_cmd,
"latest_time": "$latest$",
"earliest_time": "$earliest$",
"app": utils.getCurrentApp(),
"auto_cancel": 90,
"preview": true,
"runWhenTimeIsUndefined": false,
"timeout": "10"
}, {tokens: true});

     var element1 = new TableElement({
         "id": search_id_table,
         "drilldown": "row",
         "rowNumbers": "undefined",
         "wrap": "undefined",
         "managerid": search_id,
         "el": $('#element1')
     }, {tokens: true}).render();
0 Karma
State of Splunk Careers

Access the Splunk Careers Report to see real data that shows how Splunk mastery increases your value and job satisfaction.

Find out what your skills are worth!