Specify visibility conditions for panels and other dashboard elements
Organize your dashboard or conceal empty panels by conditionally showing or hiding panels based on data availability. For example, suppose a chart on your dashboard is empty because it depends on a token setting from a different visualization. In that case, you can hide the chart until the token is set and data is available. You can also set conditions so that different panels display based on user interaction, making the dashboard more dynamic.
Both Grid and Absolute layout support conditionally showing or hiding panels. The following elements support hiding panels conditionally:
| Element | Grid layout | Absolute layout |
|---|---|---|
| Charts | Yes | Yes |
| Icons | n/a* | Yes |
| Line shape | n/a* | No |
| Rectangles | Yes | Yes |
| Ellipses | n/a* | Yes |
| Inputs | Yes | Yes |
| Markdown | Yes | Yes |
* These elements aren't available in Grid layout.
Hide a panel when no data is available
To conditionally hide a panel when no data is available, follow these steps:
- Select your visualization or input.
- Navigate to the Visibility section of the Configuration panel.
- Select "When data is unavailable, hide element" and a dotted blue line will surround your visualization or input.
The following example shows a visualization that is hidden when there is no data available:
"visualizations": {
"viz_Z0robcvp": {
"type": "splunk.singlevalue",
"dataSources": {
"primary": "ds_6j1uZkit"
},
"hideWhenNoData": true
}
},
Create custom conditions for panel visibility
To show or hide a panel under a custom set of conditions, follow these steps:
- Select your visualization or input.
- Navigate to the Visibility section of the Configuration panel.
- In the Custom visibility conditions sub-section, select and specify your conditions. You can use AND or OR to join conditions, or you can nest conditions. Conditions must evaluate to true or false.
Select Apply and close.
The following shows a conditional statement, Real users, that consists of 2 conditional expressions. One condition is that $env:user$ must be set. The other condition is that $env:user$ must not be equal to splunk-system-user. The conditional statement requires that both conditional expressions be satisfied.
"expressions": {
"conditions": {
"condition_hKUGzCgF": {
"name": "Real users",
"value": "isSet($env:user$) and\n$env:user$ != \"splunk-system-user\""
}
}
}Select the eye next to your condition to show or hide that panel.
An open eye means the object shows when the condition is true.
A crossed-out eye means the object is hidden when the condition is true.
If an object has conflicting conditions, then the object is hidden by default.
- If an object has multiple conditions, then the object is shown by default if any of the conditions for visibility apply. To change this default, edit the source to replace
any-truewithall-true, as in the following example."visualizations": { "viz_0EfWSS85": { "containerOptions": { "visibility": { [...] "showWhenConditions": "all-true" } } } }
hideConditions and showConditions:{
"containerOptions": {
"visibility": {
"hideConditions": [
"condition_gPai8EwP",
"condition_zTFIanTZ"
],
"showConditions": [
"condition_W6MKHKFw"
]
}
},
"dataSources": {
"primary": "ds_ZaoUFXR3"
},
"title": "Usage by teams",
"type": "splunk.pie",
"options": {},
"context": {}
}Specify expressions to evaluate token values
In addition to setting token values from user interactions or search results, you can set token values by evaluating custom expressions. Token evaluation expressions can evaluate to booleans, numbers, strings, or arrays. See the following examples, including some more complex use cases.
Combine multiple token values together, such as summing two products' revenues into a total revenue.
Transform a value, such as multiplying an input in pounds by 2.2 in order to get an output in kilograms.
Change the state of another evaluation. For example: If
$show$=true, change another evaluation to false, otherwise set it to true.Display a dynamic label. For example, If
$show$=true, display a button labeled "Hide", otherwise, display the label "Show."
Create your token evaluation expression in the source under the expressions stanza. Specify the expression ID, name, and expression. Then, reference the result of the expression using $eval:expression name$.
The following example shows a dashboard that evaluates the date, then displays a welcome message with that information. This evaluation uses only JSONata's built-in functions. Since the generated token, $eval:welcome message$ has no inputs, it is evaluated once when the dashboard loads and persists until the page refreshes. The following shows the expressions stanza with the "welcome message" evaluation expression:
"expressions": {
"eval": {
"eval_1": {
"name": "welcome message",
"value": "'Hello!\nToday is ' & $now('[MNn,-3] [D01], [Y0001]')"
}
}
},"visualizations": {
"viz_1": {
"type": "splunk.markdown",
"options": {
"markdown": "## $eval:welcome message$"
}
}
}Combine custom conditions and token evaluation expressions
One eval expression toggles between showing trends or showing metrics depending on whether the showTrend value is true or false.
A second eval expression changes the label displayed on the button between Show trends and Show metrics depending on whether the showTrend value is true or false.
The Set token interaction on this button calls an eval expression to change showTrend between true and false.
{
"title": "Token eval example",
"description": "",
"inputs": {
"input_global_trp": {
"containerOptions": {
"visibility": {
"hideInViewMode": true
}
},
"options": {
"defaultValue": "-24h@h,now",
"token": "global_time"
},
"title": "Global Time Range",
"type": "input.timerange"
},
"input_itPVVCMe": {
"eventHandlers": [
{
"options": {
"tokens": [
{
"token": "showTrend",
"value": "$eval:toggleTrend$"
}
]
},
"type": "drilldown.setToken"
}
],
"options": {
"label": "$eval:trendBtnLabel$"
},
"type": "input.button"
},
"input_yjMWv58P": {
"cornerRadius": [
8,
8,
0,
0
],
"options": {
"defaultValue": "GPT-4o",
"items": [
{
"label": "GPT-4o",
"value": "GPT-4o"
},
{
"label": "GPT-4",
"value": "GPT-4"
},
{
"label": "GPT-3.5",
"value": "GPT-3.5"
},
{
"label": "Claude 3.5 Sonnet",
"value": "Claude 3.5 Sonnet"
},
{
"label": "Gemini 2 Pro",
"value": "Gemini 2 Pro"
}
],
"token": "model_1"
},
"title": "Model",
"type": "input.dropdown"
}
},
"defaults": {
"dataSources": {
"ds.search": {
"options": {
"queryParameters": {
"earliest": "$global_time.earliest$",
"latest": "$global_time.latest$"
}
}
}
},
"tokens": {
"default": {
"show": {
"value": "trends"
},
"showTrend": {
"value": "false"
},
"metric": {
"value": "*"
}
}
},
"visualizations": {
"global": {
"cornerRadius": [
8,
8,
8,
8
],
"showProgressBar": true
}
}
},
"visualizations": {
"viz_0EfZCS58": {
"containerOptions": {
"visibility": {
"hideConditions": [
"condition_IQl2TmVB",
"condition_zTFIanTZ"
],
"showConditions": [
"condition_W6MKHKFw"
],
"showWhenConditions": "all-true"
}
},
"dataSources": {
"primary": "ds_2egZsakq"
},
"options": {
"backgroundColor": "#000000",
"majorValue": "> sparklineValues | lastPoint()",
"sparklineDisplay": "off",
"sparklineValues": "> primary | seriesByName(\"$model_1$\")",
"trendDisplay": "off",
"trendValue": "> sparklineValues | delta(-2)",
"unit": "%"
},
"title": "Acceptance ratio",
"type": "splunk.singlevalue"
},
"viz_YdETZJ3S": {
"containerOptions": {
"visibility": {
"hideConditions": [
"condition_IQl2TmVB",
"condition_zTFIanTZ"
],
"showConditions": [
"condition_MNC0mRhK"
],
"showWhenConditions": "all-true"
}
},
"dataSources": {
"primary": "ds_2egZsakq"
},
"eventHandlers": [
{
"options": {
"events": [
"range.select"
],
"token": "global_time"
},
"type": "drilldown.setTimeRange"
}
],
"options": {
"backgroundColor": "#000000",
"legendDisplay": "off",
"xAxisTitleVisibility": "hide",
"yAxisTitleVisibility": "hide"
},
"title": "Acceptance ratio",
"type": "splunk.line"
},
"viz_gD5IAOiR": {
"containerOptions": {
"visibility": {
"hideConditions": [
"condition_gPai8EwP",
"condition_zTFIanTZ"
],
"showConditions": [
"condition_MNC0mRhK"
],
"showWhenConditions": "all-true"
}
},
"dataSources": {
"primary": "ds_emH3CrTm"
},
"eventHandlers": [
{
"options": {
"events": [
"range.select"
],
"token": "global_time"
},
"type": "drilldown.setTimeRange"
}
],
"options": {
"backgroundColor": "#000000",
"x": "> primary | seriesByName('_time')",
"xAxisTitleVisibility": "hide",
"y": "> primary | frameBySeriesNames('Marketing','Product','_time','Engineering')"
},
"title": "Usage by teams",
"type": "splunk.line"
},
"viz_yS5JDjMN": {
"containerOptions": {
"visibility": {
"hideConditions": [
"condition_gPai8EwP",
"condition_zTFIanTZ"
],
"showConditions": [
"condition_W6MKHKFw"
]
}
},
"dataSources": {
"primary": "ds_1KfEDBSo"
},
"options": {
"backgroundColor": "#000000"
},
"title": "Usage by teams",
"type": "splunk.pie"
}
},
"dataSources": {
"ds_1KfEDBSo": {
"name": "Model 1 usage by team",
"options": {
"extend": "ds_1lG4GeRq",
"query": "| search model=\"$model_1$\"\n| fields - _time model"
},
"type": "ds.chain"
},
"ds_1lG4GeRq": {
"name": "Model usage by team",
"options": {
"query": "|makeresults count=10 | streamstats count\n|eval model=case(count=1, \"GPT-4o\", count=2, \"GPT-4\", count=3, \"GPT-3.5\", count=4, \"Gemini 2 Pro\", count=5, \"Claude 3.5 Sonnet\",count=9, \"GPT-4o\", count=6, \"GPT-4\", count=7, \"GPT-3.5\", count=8, \"Gemini 2 Pro\", count=10, \"Claude 3.5 Sonnet\"), team=case(count=1, \"Marketing\", count=2, \"Product\", count=3, \"Engineering\", count=4, \"Marketing\", count=5, \"Product\", count=6, \"Engineering\", count=7, \"Marketing\", count=8, \"Product\", count=9, \"Engineering\", count=10,\"Marketing\"), usage=random()%100+20\n| fields model team usage"
},
"type": "ds.search"
},
"ds_2egZsakq": {
"name": "model 1 acceptance ratio",
"options": {
"extend": "ds_FKaPLzRj",
"query": "| fields _time \"$model_1$\""
},
"type": "ds.chain"
},
"ds_FKaPLzRj": {
"name": "acceptance ratio base search",
"options": {
"query": "|makeresults count=100 |streamstats count |eval _time=_time-count*3600 | eval \"GPT-4o\"=random()%9+20, \"GPT-4\"=random()%7+17, \"GPT-3.5\"=random()%4+21, \"Claude 3.5 Sonnet\"=random()%8+19, \"Gemini 2 Pro\"=random()%5+20"
},
"type": "ds.search"
},
"ds_emH3CrTm": {
"name": "Model usage by team trend base",
"options": {
"query": "|makeresults count=100 |streamstats count |eval _time=_time-count*3600 | eval Marketing=random()%50+100, Product=random()%30+170, Engineering=random()%40+210"
},
"type": "ds.search"
}
},
"layout": {
"globalInputs": [
"input_global_trp"
],
"layoutDefinitions": {
"layout_hcVYUTPd": {
"structure": [
{
"item": "input_yjMWv58P",
"position": {
"h": 99,
"w": 1035,
"x": 0,
"y": 0
},
"type": "input"
},
{
"item": "viz_yS5JDjMN",
"position": {
"h": 289,
"w": 600,
"x": 0,
"y": 99
},
"type": "block"
},
{
"item": "viz_gD5IAOiR",
"position": {
"h": 364,
"w": 600,
"x": 0,
"y": 388
},
"type": "block"
},
{
"item": "viz_0EfZCS58",
"position": {
"h": 289,
"w": 600,
"x": 600,
"y": 99
},
"type": "block"
},
{
"item": "viz_YdETZJ3S",
"position": {
"h": 364,
"w": 600,
"x": 600,
"y": 388
},
"type": "block"
},
{
"item": "input_itPVVCMe",
"position": {
"h": 99,
"w": 165,
"x": 1035,
"y": 0
},
"type": "input"
}
],
"type": "grid"
}
},
"options": {},
"tabs": {
"items": [
{
"label": "Compare models",
"layoutId": "layout_hcVYUTPd"
}
]
}
},
"expressions": {
"conditions": {
"condition_7z6W2NUS": {
"name": "non-default timerange",
"value": "$global_time.earliest$ != \"-24h@h\" or\n$global_time.latest$ != \"now\""
},
"condition_IQl2TmVB": {
"name": "hide acceptance ratio",
"value": "$not(\"acceptance_ratio\" in [$metric$]) and\n$not(\"*\" in [$metric$])"
},
"condition_MNC0mRhK": {
"name": "show trends",
"value": "$showTrend$ = \"true\""
},
"condition_W6MKHKFw": {
"name": "show metrics",
"value": "$showTrend$ = \"false\""
},
"condition_dQtYPnC1": {
"name": "showButton",
"value": "isSet($model$)"
},
"condition_gPai8EwP": {
"name": "hide usage by team",
"value": "$not(\"usage_by_team\" in [$metric$]) and\n$not(\"*\" in [$metric$])"
},
"condition_zTFIanTZ": {
"name": "is same model",
"value": "$eval:isSameModel$ = \"true\""
}
},
"eval": {
"expr_1": {
"name": "isSameModel",
"value": "$model_1$ = $model_2$"
},
"expr_2": {
"name": "toggleTrend",
"value": "$showTrend$ = 'true' ? 'false' : 'true'"
},
"expr_3": {
"name": "trendBtnLabel",
"value": "$showTrend$ = 'true' ? 'Show metrics' : 'Show trends'"
}
}
}
}About the grid layout conditional visibility logic
If you hide a visualization in the grid layout, the dashboard balances the composition of the remaining visualizations by adjusting their sizes. The grid layout prioritizes filling any blank space within the canvas to achieve compositional completeness.
When the grid layout resizes visualizations, it prioritizes adjusting the visualizations neighboring a hidden element. The grid layout works across the dashboard from left to right and top to bottom.
Visualizations with equal proportions
The grid layout maintains the proportion of space used by the viewable visualizations based on shared columns or rows. For example, you might have 4 visualizations in a row, each occupying 25% of the width of the dashboard canvas, and you decide to hide 1 of the visualizations. The remaining 3 visualizations respond to the hidden visualization by adjusting their widths to 33%.
Visualizations with unequal proportions
If you intentionally create a dashboard visualization larger than its fellow visualizations, the larger visualization stays proportionally more prominent than the other visualizations throughout the resizing process. For example, you might have 3 visualizations in a row. 1 visualization takes up 50% of the dashboard, and the other 2 take up 25%. If you hide a small visualization, the larger visualization will adjust to about 65%, and the remaining small visualization will adjust to about 35%.