Forum Discussion
y5famfnatudu
Resolver I
10 months agoExtending Deneb/Vega-Lite Toggle Switch from 2-State to 3-State (Working Day / Non-Working Day / All
Hi everyone, In my dataset, I have a flag column called “Is Working Day”, which contains values of either 0 or 1. I’ve created a toggle switch in Deneb using Vega-Lite, allowing users to switch bet...
Ahmed-Elfeel
Super User
9 months agoHi y5famfnatudu,
I hope you are doing well ☺️❤️
To implement a 3 state toggle switch in Deneb/Vega-Lite you need to use a parameter (signal) with a cyclic update expression. Here is a couple of Approaches:
First Approach: Complete Deneb/Vega-Lite Specification
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"params": [
{
"name": "filterToggle",
"value": 0,
"bind": {
"input": "radio",
"options": [0, 1, 2],
"labels": ["Working Days (1)", "Non-Working Days (0)", "All Records"]
}
}
],
"data": {"name": "dataset"},
"transform": [
{
"filter": {
"condition": {
"param": "filterToggle",
"value": 2,
"empty": false
},
"value": {
"field": "IsWorkingDay",
"equal": {
"signal": "filterToggle == 0 ? 1 : 0"
}
}
}
},
{
"calculate": "datum.IsWorkingDay == 1 ? 'Working Day' : 'Non-Working Day'",
"as": "Day_Type"
}
],
"mark": "bar", // or your preferred mark type
"encoding": {
// Your encoding here
"x": {"field": "SomeField", "type": "nominal"},
"y": {"aggregate": "count", "type": "quantitative"},
"color": {"field": "Day_Type", "type": "nominal"}
}
}
Alternative Approach: ClickCycling Button
If you want a single button that cycles through states on each click:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {"name": "dataset"},
"signals": [
{
"name": "toggleState",
"value": 0,
"on": [
{
"events": {"type": "click", "markname": "toggleButton"},
"update": "(toggleState + 1) % 3"
}
]
}
],
"marks": [
{
"type": "rect",
"name": "toggleButton",
"encode": {
"enter": {
"x": {"value": 0},
"y": {"value": 0},
"width": {"value": 120},
"height": {"value": 30},
"fill": {"value": "lightgray"},
"cornerRadius": {"value": 15}
},
"update": {
"fill": {
"signal": "toggleState == 0 ? '#4CAF50' : toggleState == 1 ? '#F44336' : '#2196F3'"
}
}
}
},
{
"type": "text",
"name": "toggleLabel",
"encode": {
"enter": {
"x": {"value": 60},
"y": {"value": 18},
"align": {"value": "center"},
"baseline": {"value": "middle"},
"fontSize": {"value": 12},
"fill": {"value": "white"}
},
"update": {
"text": {
"signal": "toggleState == 0 ? 'Working Days' : toggleState == 1 ? 'Non-Working Days' : 'All Days'"
}
}
}
}
],
"transform": [
{
"filter": {
"condition": {"signal": "toggleState == 2"},
"value": {
"field": "IsWorkingDay",
"equal": {"signal": "toggleState == 0 ? 1 : 0"}
}
}
}
],
"layer": [
// Your visualization layers here
{
"mark": "bar",
"encoding": {
"x": {"field": "SomeField", "type": "nominal"},
"y": {"aggregate": "count", "type": "quantitative"},
"color": {
"field": "IsWorkingDay",
"type": "nominal",
"scale": {
"domain": [0, 1],
"range": ["#F44336", "#4CAF50"]
},
"legend": {
"title": "Day Type",
"labelExpr": "datum.value == 1 ? 'Working Day' : 'Non-Working Day'"
}
}
}
}
]
}
Bonus Approach: Simple Radio Button Version
- If you prefer a simpler radio button
{
"params": [
{
"name": "dayFilter",
"value": 2,
"bind": {
"input": "select",
"options": [0, 1, 2],
"labels": ["Working Days Only", "Non-Working Days Only", "All Days"],
"name": "Filter: "
}
}
],
"transform": [
{
"filter": {
"condition": {"param": "dayFilter", "value": 2},
"value": {"field": "IsWorkingDay", "equal": {"param": "dayFilter"}}
}
}
]
}
Choose the Approach that best fits your visualization needs. The first approach with a cycling button is more interactive while the radio/select approaches are more explicit for users
if this post helps, then I would appreciate a thumbs up and mark it as the solution to help the other members find it more quickly.