All Apps and Add-ons

Sideview Utils: customBehavior to show/hide checkbox not working

Contributor

I wrote the code below after looking at many examples, and reviewing the modules documentation.
And yet, I can't get it to work. The checkbox remains visible regardless of the time range I select. It should only be visible when the user selects "Last 60 minutes" in the TimeRangePicker.

<view isVisible="true" objectMode="SimpleDashboard" onunloadCancelJobs="true" template="dashboard.html">





False


splunk.search.job
True
1
warn


Last 4 hours
True

<module name="Checkbox" layoutPanel="viewHeader">
  <param name="label">"5m auto-refresh"</param>
  <param name="customBehavior">LRO_ShowAutoRefreshCheckBox</param>
  <param name="float">left</param>
</module>

<module name="HTML">
    <param name="html">For 5 mins auto-refresh select the "Last 60 minutes" time range.</param>
</module>  

<module name="Search" layoutPanel="panel_row1_col1" autoRun="True">
    <param name="search">
  index=os * | rex &quot;lvn-(?&lt;Line&gt;[a-z][0-9])-&quot; | dedup Line | table Line | sort Line</param>
    <module name="JobProgressIndicator"/>
    <module name="SimpleResultsTable"/>
</module>

</module><!-- TimeRangePicker -->

OK the code looks partly marked as code partly as regular comments. But it's all there.

And here is the code I added in application.js:

Sideview.utils.declareCustomBehavior("LRO_ShowAutoRefreshCheckBox", function(checkBoxModule)
{
var methodReference = checkBoxModule.onContextChange.bind(checkBoxModule);
checkBoxModule.onContextChange = function()
{
var retVal = methodReference();
if (this.getContext().get("search").getTimeRange().getEarliestTimeTerms()=="-60m@m" && this.getContext().get("search").getTimeRange().getEarliestTimeTerms()=="now")
{
this.show();
} else
{
this.hide();
}
return retVal;
}
});

And yes, I rebooted splunkweb to make sure application.js has been read by splunk after my change.

EDIT: I just found 2 errors, thanks to google developper tools.
1- there was a brace missing in my javascript.
2- I needed to get the context from "this".

The js code above reflects those fixes. But it still doesn't work right. Now the checkbox goes away as soon as I change the time range and never comes back regardless of the setting.

1 Solution

SplunkTrust
SplunkTrust

1) The main problem is that your if statement is only firing if the earliest time term is "-60m@m" and also the earliest time term is "now". For the second you meant to check the getLatestTimeTerms not getEarliestTimeTerms.

Changing that alone gets it to mostly work.

2) There is also a second lesser problem though. You have an autoRun="True" but you've made a common mistake which is to put it on the Search module thinking it tells the Search module to run it's search. It actually tells any module "when the page loads, start pushing data to all downstream from this point", and as such it should always be up at the top of the hierarchy. IN this case you should move it up to the TimeRangePicker and not have any autoRun on the Search module. With the autoRun="true" on the Search module, the very first push on page load doesn't hide the checkbox because nobody has pushed the TimeRangePicker's data downstream yet. =/ (Yes autoRun is very strange but if you follow the rule of only ever having one, and always having it at the top, almost all of the strangeness goes away)

3) and thirdly, here's a slightly cleaner version of your JS function that you may find useful.

Sideview.utils.declareCustomBehavior("LRO_ShowAutoRefreshCheckBox", function(checkBoxModule) {
    var methodReference = checkBoxModule.onContextChange.bind(checkBoxModule);
    checkBoxModule.onContextChange = function() {
        var range = this.getContext().get("search").getTimeRange();
        var REASON = "only show for last 60 minutes";
        if (range.getEarliestTimeTerms()=="-60m@m" && range.getLatestTimeTerms()=="now") {
            this.show(REASON);
        } else {
            this.hide(REASON);
        }
        return methodReference();
    }
});

The reasons to pass a "reason" string to the show/hide methods is a little advanced, but it's important for more complicated pages where there are lots of reasons that might or might not dictate when a module should be shown or hidden. Technically show/hide should always be given a reason so that the system can differentiate properly which show requests are coming from which parts of the client code. However it was such a common implementation mistake that the framework allows one piece of the client code to be sloppy and provide no reason and it just remembers that one has having a reason of null. You can get away with this exactly once but not twice. 😃 So if you had a second custom behavior calling show/hide with no reasons, the behavior would be very confusing! Short version - always pass reason strings to show()/hide() and it will work even in arbitrarily complicated views.

View solution in original post

SplunkTrust
SplunkTrust

1) The main problem is that your if statement is only firing if the earliest time term is "-60m@m" and also the earliest time term is "now". For the second you meant to check the getLatestTimeTerms not getEarliestTimeTerms.

Changing that alone gets it to mostly work.

2) There is also a second lesser problem though. You have an autoRun="True" but you've made a common mistake which is to put it on the Search module thinking it tells the Search module to run it's search. It actually tells any module "when the page loads, start pushing data to all downstream from this point", and as such it should always be up at the top of the hierarchy. IN this case you should move it up to the TimeRangePicker and not have any autoRun on the Search module. With the autoRun="true" on the Search module, the very first push on page load doesn't hide the checkbox because nobody has pushed the TimeRangePicker's data downstream yet. =/ (Yes autoRun is very strange but if you follow the rule of only ever having one, and always having it at the top, almost all of the strangeness goes away)

3) and thirdly, here's a slightly cleaner version of your JS function that you may find useful.

Sideview.utils.declareCustomBehavior("LRO_ShowAutoRefreshCheckBox", function(checkBoxModule) {
    var methodReference = checkBoxModule.onContextChange.bind(checkBoxModule);
    checkBoxModule.onContextChange = function() {
        var range = this.getContext().get("search").getTimeRange();
        var REASON = "only show for last 60 minutes";
        if (range.getEarliestTimeTerms()=="-60m@m" && range.getLatestTimeTerms()=="now") {
            this.show(REASON);
        } else {
            this.hide(REASON);
        }
        return methodReference();
    }
});

The reasons to pass a "reason" string to the show/hide methods is a little advanced, but it's important for more complicated pages where there are lots of reasons that might or might not dictate when a module should be shown or hidden. Technically show/hide should always be given a reason so that the system can differentiate properly which show requests are coming from which parts of the client code. However it was such a common implementation mistake that the framework allows one piece of the client code to be sloppy and provide no reason and it just remembers that one has having a reason of null. You can get away with this exactly once but not twice. 😃 So if you had a second custom behavior calling show/hide with no reasons, the behavior would be very confusing! Short version - always pass reason strings to show()/hide() and it will work even in arbitrarily complicated views.

View solution in original post

Contributor

Excellent! I feel a bit stupid for the dumb copy/paste mistake. At the same time I learn a lot from you.
I may be the sansay, but you sure are the sensei.
Thank you so much!!