Dashboards & Visualizations

Comprehensive implementation of a WORKING submit button?

nick405060
Motivator

The Splunk submit button is one of the most unusable things that I have ever seen. Based off two years of Slack usergroups conversations, Splunk Answers, and my own constant struggle with this damn thing, the Splunk community desperately has need for a comprehensive workaround. Is it unreasonable to expect a company valued at a billion dollars to have a working, you know, button?

*Issues, for all released Splunk versions *

Does anyone have a comprehensive submit button replacement that solves all of these issues?

Labels (2)
1 Solution

nick405060
Motivator

Below is a run anywhere example. I asked this question so that I could detail a comprehensive workaround for the Splunk community. This is a list of some of the relevant issues here, many thanks to @niketnilay and @vnravikumar for their help!

https://answers.splunk.com/answers/758332/is-it-impossible-to-resubmit-a-dashboard-search-in.html
https://answers.splunk.com/answers/742451/searchwhenchangedfalse-not-honored-1.html
https://answers.splunk.com/answers/758726/how-can-i-implement-a-pseudo-searchwhenchanged-fun-1.html
https://answers.splunk.com/answers/758977/how-to-adjust-the-click-width-of-a-js-button.html
https://answers.splunk.com/answers/758599/is-it-possible-to-add-a-button-in-line-with-inputs.html

SimpleXML:

<dashboard theme="light" script="button_submit.js">
  <label>Non-Trash Submit Button</label>
  <description></description>

  <row>
    <panel>
      <html depends="$hide$">
        <style>
          #submit_button{
            width:80px !important;
          }
          #submit_button div[data-component="splunk-core:/splunkjs/mvc/components/LinkList"]{
            width:80px !important;
          }
          #submit_button  button{
            padding: 6px 15px !important;
            border-radius: 3px !important;
            font-weight: 500 !important;
            background-color: #5cc05c !important;
            border: transparent !important;
            color: #fff !important;
          }
          #submit_button  button:hover{
            background-color: #40a540 !important;
            border-color: transparent !important;
          }
        </style>
      </html>
      <input type="time" id="timepicker">
        <label>Time range:</label>
        <default>
          <earliest>@d</earliest>
          <latest>now</latest>
        </default>
        <change>
          <eval token="earliest_epoch_onChange">case(isnum($earliest$), $earliest$, $earliest$=="now", time(), $earliest$="", 0, true(), relative_time(time(), $earliest$))</eval>
          <eval token="latest_epoch_onChange">case(isnum($latest$), $latest$, $latest$=="now", time(), true(), relative_time(time(), $latest$))</eval>
        </change>
      </input>
      <input type="text" token="network_id_onChange">
        <label>NetworkID:</label>
        <default></default>
      </input>
      <input type="link" id="submit_button">
        <label></label>
        <choice value="submit">Submit</choice>
      </input>
    </panel>
  </row>

  <row>
    <panel>
      <title></title>
      <table>
        <search>
          <query>
| makeresults | eval user="$network_id$" | eval trigger="$submit_trigger$" | table user
          </query>
          <earliest>$earliest_epoch$</earliest>
          <latest>$latest_epoch$</latest>
        </search>
        <option name="wrap">true</option>
        <option name="rowNumbers">false</option>
        <option name="drilldown">none</option>
        <option name="dataOverlayMode">none</option>
        <option name="count">20</option>
      </table>
    </panel>
  </row>

</dashboard>

button_submit.js

 require([
     'jquery',
     'splunkjs/mvc',
     'splunkjs/mvc/simplexml/ready!'
 ], function($,mvc){
     var submittedTokens = mvc.Components.get("submitted");
     $("#submit_button").click(function(){
         submittedTokens.set("submit_trigger", ""+Math.random());
         submittedTokens.set("earliest_epoch",submittedTokens.get("earliest_epoch_onChange"));
         submittedTokens.set("latest_epoch",submittedTokens.get("latest_epoch_onChange"));
         submittedTokens.set("network_id",submittedTokens.get("network_id_onChange"));
     });
 });

Comments

  • Solved moveability by implementing a JS button. This button can be moved around to any part of the dashboard and you can implement multiple per dashboard. Even after 758977, the clickable area of this button is still slightly off but much improved.
  • Solved resubmit by having JS script update the submit_trigger token on click. If you don't include the junk submit_trigger eval statement in your search, then resubmission will not work (although non-resubmit searches will work, since the other tokens will be updated in your JS)
  • Solved searchWhenChanged functionality by having the SimpleXML update a separate token_onChange, and then having the JS update the actual token, from token_onChange, but on click. With time values, you cannot have quotes around the tokens, and you also cannot inline as earliest and latest in the search because this will not solve the searchWhenChanged functionality. In this case earliest and latest tokens would still be updated onChange, not on click, because earliest and latest are special keywords in SPL. You MUST specify earliest and latest in the stanzas (even if this is just a non-time-related |makeresults search, you still need to write stanzas of earliest of 1 and latest of 2, for example, or else that search will run whenever the timepicker is adjusted).

Also, none of this works in Splunk Mobile.

View solution in original post

woodcock
Esteemed Legend

The simpleXML submit button is horribly broken and for complex usecases, cannot be made to work.  Try this dahsboard's no-JavaScript approach instead:

 

<form theme="dark">
  <label>PoC demonstrating a fully-functioning no-JS SUBMIT "button" (actually "checkbox").</label>
  <description>https://community.splunk.com/t5/Dashboards-Visualizations/SimpleXML-Inherent-brokenness-regarding-autorun-and-Submit/m-p/407351  For intricate technical reasons that Splunk considers "working as intended", the "real" SUBMIT button is fundamentally broken and CANNOT BE MADE TO WORK for many usecases (i.e. when you must use "true" for "searchWhenChanged").  Fortunately, the method demonstrated herein does everything that anyone could desire with only 1 downside which is this: there is no way to make the dashboard autorun on first load (not even if you click the CHECKBOX with a URI in the URL).  Notice that even though some of the controls interact with one-another, the actual search does not run until the SUBMIT box is checked.  Here are the pieces that are required. 1: DO NOT CHANGE ANYTHING ABOUT THE "SUBMIT" checkbox other than cosmetic things (e.g. html).  2: Ensure that EVERY OTHER CONTROL has a "&lt;change&gt;...&lt;/change&gt;" section that unsets BOTH these tokens: {"SUBMIT_CHECKBOX", "form.SUBMIT_CHECKBOX"}.  3: Ensure that 1 search in every chain of searches uses the do-nothing "$SUBMIT_CHECKBOX$" token somewhere (i.e. if all searches are driven by a base search, this only has to be done in the base search, not the post-process searches).  This token will always be either unset or blank so it does not matter where you put it.  4: Neither the individual "searchWhenChanged" values of the controls NOR the global "Autorun dashboard" value makes any difference.  For support contact woodcock@splunxter.com.</description>
  <fieldset submitButton="false" autoRun="true">
    <input type="multiselect" token="INDEX" searchWhenChanged="true">
      <label>Select Index value(s)</label>
      <fieldForLabel>label</fieldForLabel>
      <fieldForValue>value</fieldForValue>
      <default>*</default>
      <search>
        <query>|tstats count dc(host) WHERE index=* AND $SOURCETYPE$ BY index
| rename index AS value
| eval label = value
| append [|makeresults | eval label = "All", value="*"]
| table label value</query>
        <earliest>$timepicker.earliest$</earliest>
        <latest>$timepicker.latest$</latest>
      </search>
      <delimiter> OR index=</delimiter>
      <valuePrefix>"</valuePrefix>
      <valueSuffix>"</valueSuffix>
      <prefix>(index=</prefix>
      <change>
        <eval token="form.INDEX">case(mvcount($form.INDEX$) == 2 AND mvindex($form.INDEX$, 0) == "*", mvindex($form.INDEX$, 1), mvfind($form.INDEX$, "^[*]") == mvcount($form.INDEX$) - 1, "*", true(), $form.INDEX$)</eval>
        <unset token="SUBMIT_CHECKBOX"></unset>
        <unset token="form.SUBMIT_CHECKBOX"></unset>
      </change>
      <suffix>)</suffix>
    </input>
    <input type="multiselect" token="SOURCETYPE" searchWhenChanged="true">
      <label>Select sourcetype value(s)</label>
      <fieldForLabel>label</fieldForLabel>
      <fieldForValue>value</fieldForValue>
      <default>*</default>
      <search>
        <query>|tstats count dc(host) WHERE $INDEX$ AND sourcetype=* BY sourcetype
| rename sourcetype AS value
| eval label = value
| append [|makeresults | eval label = "All", value="*"] 
| table label value</query>
        <earliest>$timepicker.earliest$</earliest>
        <latest>$timepicker.latest$</latest>
      </search>
      <delimiter> OR sourcetype=</delimiter>
      <valuePrefix>"</valuePrefix>
      <valueSuffix>"</valueSuffix>
      <prefix>(sourcetype=</prefix>
      <change>
        <eval token="form.SOURCETYPE">case(mvcount($form.SOURCETYPE$) == 2 AND mvindex($form.SOURCETYPE$, 0) == "*", mvindex($form.SOURCETYPE$, 1), mvfind($form.SOURCETYPE$, "^[*]") == mvcount($form.SOURCETYPE$) - 1, "*", true(), $form.SOURCETYPE$)</eval>
        <unset token="SUBMIT_CHECKBOX"></unset>
        <unset token="form.SUBMIT_CHECKBOX"></unset>
      </change>
      <suffix>)</suffix>
    </input>
    <input type="text" token="COUNT">
      <label>Name for "count" field</label>
      <default>count</default>
      <change>
        <unset token="SUBMIT_CHECKBOX"></unset>
        <unset token="form.SUBMIT_CHECKBOX"></unset>
      </change>
    </input>
    <input type="time" token="timepicker" searchWhenChanged="true">
      <label>Timepicker</label>
      <default>
        <earliest>-24h@h</earliest>
        <latest>now</latest>
      </default>
      <change>
        <unset token="SUBMIT_CHECKBOX"></unset>
        <unset token="form.SUBMIT_CHECKBOX"></unset>
      </change>
    </input>
    <input id="submit_checkbox" type="checkbox" token="SUBMIT_CHECKBOX">
      <label></label>
      <delimiter> </delimiter>
      <choice value="">SUBMIT</choice>
    </input>
    <html depends="$hide$">
      <style>
        #submit_checkbox{
          width:80px !important;
        }
        #submit_checkbox
div[data-component="splunk-core:/splunkjs/mvc/components/LinkList"]{
          width:80px !important;
        }
        #submit_checkbox  button{
          padding: 6px 15px !important;
          border-radius: 3px !important;
          font-weight: 500 !important;
          background-color: #5cc05c !important;
          border: transparent !important;
          color: #fff !important
        }
        #submit_checkbox  button:hover{
          background-color: #40a540 !important;
          border-color: transparent !important;
        }
    </style>
  </html>
  </fieldset>
  <row>
    <panel>
      <table>
        <title>Searches ONLY on checking the SUBMIT box (which resets itself)</title>
        <search>
          <query>|tstats count AS $COUNT|s$ dc(host) WHERE $INDEX$ AND $SOURCETYPE$ BY index sourcetype $SUBMIT_CHECKBOX$</query>
          <earliest>$timepicker.earliest$</earliest>
          <latest>$timepicker.latest$</latest>
        </search>
        <option name="refresh.display">progressbar</option>
      </table>
    </panel>
  </row>
</form>

 

0 Karma

nick405060
Motivator

Below is a run anywhere example. I asked this question so that I could detail a comprehensive workaround for the Splunk community. This is a list of some of the relevant issues here, many thanks to @niketnilay and @vnravikumar for their help!

https://answers.splunk.com/answers/758332/is-it-impossible-to-resubmit-a-dashboard-search-in.html
https://answers.splunk.com/answers/742451/searchwhenchangedfalse-not-honored-1.html
https://answers.splunk.com/answers/758726/how-can-i-implement-a-pseudo-searchwhenchanged-fun-1.html
https://answers.splunk.com/answers/758977/how-to-adjust-the-click-width-of-a-js-button.html
https://answers.splunk.com/answers/758599/is-it-possible-to-add-a-button-in-line-with-inputs.html

SimpleXML:

<dashboard theme="light" script="button_submit.js">
  <label>Non-Trash Submit Button</label>
  <description></description>

  <row>
    <panel>
      <html depends="$hide$">
        <style>
          #submit_button{
            width:80px !important;
          }
          #submit_button div[data-component="splunk-core:/splunkjs/mvc/components/LinkList"]{
            width:80px !important;
          }
          #submit_button  button{
            padding: 6px 15px !important;
            border-radius: 3px !important;
            font-weight: 500 !important;
            background-color: #5cc05c !important;
            border: transparent !important;
            color: #fff !important;
          }
          #submit_button  button:hover{
            background-color: #40a540 !important;
            border-color: transparent !important;
          }
        </style>
      </html>
      <input type="time" id="timepicker">
        <label>Time range:</label>
        <default>
          <earliest>@d</earliest>
          <latest>now</latest>
        </default>
        <change>
          <eval token="earliest_epoch_onChange">case(isnum($earliest$), $earliest$, $earliest$=="now", time(), $earliest$="", 0, true(), relative_time(time(), $earliest$))</eval>
          <eval token="latest_epoch_onChange">case(isnum($latest$), $latest$, $latest$=="now", time(), true(), relative_time(time(), $latest$))</eval>
        </change>
      </input>
      <input type="text" token="network_id_onChange">
        <label>NetworkID:</label>
        <default></default>
      </input>
      <input type="link" id="submit_button">
        <label></label>
        <choice value="submit">Submit</choice>
      </input>
    </panel>
  </row>

  <row>
    <panel>
      <title></title>
      <table>
        <search>
          <query>
| makeresults | eval user="$network_id$" | eval trigger="$submit_trigger$" | table user
          </query>
          <earliest>$earliest_epoch$</earliest>
          <latest>$latest_epoch$</latest>
        </search>
        <option name="wrap">true</option>
        <option name="rowNumbers">false</option>
        <option name="drilldown">none</option>
        <option name="dataOverlayMode">none</option>
        <option name="count">20</option>
      </table>
    </panel>
  </row>

</dashboard>

button_submit.js

 require([
     'jquery',
     'splunkjs/mvc',
     'splunkjs/mvc/simplexml/ready!'
 ], function($,mvc){
     var submittedTokens = mvc.Components.get("submitted");
     $("#submit_button").click(function(){
         submittedTokens.set("submit_trigger", ""+Math.random());
         submittedTokens.set("earliest_epoch",submittedTokens.get("earliest_epoch_onChange"));
         submittedTokens.set("latest_epoch",submittedTokens.get("latest_epoch_onChange"));
         submittedTokens.set("network_id",submittedTokens.get("network_id_onChange"));
     });
 });

Comments

  • Solved moveability by implementing a JS button. This button can be moved around to any part of the dashboard and you can implement multiple per dashboard. Even after 758977, the clickable area of this button is still slightly off but much improved.
  • Solved resubmit by having JS script update the submit_trigger token on click. If you don't include the junk submit_trigger eval statement in your search, then resubmission will not work (although non-resubmit searches will work, since the other tokens will be updated in your JS)
  • Solved searchWhenChanged functionality by having the SimpleXML update a separate token_onChange, and then having the JS update the actual token, from token_onChange, but on click. With time values, you cannot have quotes around the tokens, and you also cannot inline as earliest and latest in the search because this will not solve the searchWhenChanged functionality. In this case earliest and latest tokens would still be updated onChange, not on click, because earliest and latest are special keywords in SPL. You MUST specify earliest and latest in the stanzas (even if this is just a non-time-related |makeresults search, you still need to write stanzas of earliest of 1 and latest of 2, for example, or else that search will run whenever the timepicker is adjusted).

Also, none of this works in Splunk Mobile.

View solution in original post

gabriel_vasseur
Contributor

Thanks, this helped me so much! To make this perfect, I would suggest the following:

Simplify the javascript so that it only sets submit_trigger. That way it can be used in more than one dashboard and you don't have to keep tweaking it when you develop your dashboard. To prevent the annoyance of the searchWhenChanged=false being ignored again, simply add this to the search that is to be ran when submit is pressed:

<search>
  <done>
    <unset token="submit_trigger"/>
  </done>
  ...

That way, after the search is ran once, you can take your time to adjust your inputs and only when you're ready you can click submit to run it again. Works a treat.

Finally, unlike what I initially assumed when I saw your solution, the inputs (including the submit button) can be part of the standard <fieldset> at the top of your dashboard, in case you want them to have a grey background as usual, not a white one.

Also, it's worth noting that your solution allows to hide the submit button with a "depends" clause so that it only appears if the inputs satisfy some kind of condition. I found that useful.

Thanks again!

0 Karma

nick405060
Motivator

Related: here is my guide to implementing multiple time-pickers in conjunction with this solution. https://answers.splunk.com/answers/763194/how-do-you-create-two-epoch-generating-on-submit-t.html

0 Karma

niketnilay
Legend

@nick405060 thanks a lot for documenting this solution. My inspiration for the possibility of user controlled Submit button was the following blog by Octoinsight. It was a stepping stone for my understanding of Simple XML JS extension.

https://www.google.com/amp/s/blog.octoinsight.com/there-can-be-only-one-submit-button/amp/

Also as mentioned in one of the answers you have quoted, I was able to grasp the behaviour of Submit button with Default and Submitted Token models through the Developer Gadgets App for Splunk by @rjthibod

____________________________________________
| makeresults | eval message= "Happy Splunking!!!"
0 Karma
Did you miss .conf21 Virtual?

Good news! The event's keynotes and many of its breakout sessions are now available online, and still totally FREE!