Multiple Triggers on SignalListener - Vega-Lite + Mutable #1829
-
I’m encountering an issue with a bar chart implementation using Vega-Lite in Observable. My problem lies in how the Expected Behavior:
Observed Behavior:
This behavior disrupts the dynamic of resetting another chart, which depends on a comparison between the CodeBelow is the relevant code: Data let energyConsumptionData = [
{ "consumption_type": "Others", "annual_consumption": 80704749 },
{ "consumption_type": "Commercial", "annual_consumption": 97715805 },
{ "consumption_type": "Industrial", "annual_consumption": 188268304 },
{ "consumption_type": "Residential", "annual_consumption": 164323258 }
]; Chart Specification let barChart = vl.render({
spec: {
width: 500,
height: 300,
data: { values: energyConsumptionData },
mark: { type: "bar" },
selection: {
barSelect: {
fields: ["consumption_type"],
on: "click",
type: "single"
}
},
encoding: {
x: {
field: "annual_consumption",
type: "quantitative",
title: "Annual Consumption (MWh)"
},
y: {
field: "consumption_type",
type: "nominal",
title: "Consumption Type"
}
}
}
});
let barChartView = view(barChart); Signal Handling let setSelectedBar = (x) => { barSelectionSignal.value = x };
let barSelectionSignal = Mutable(null);
let defaultSelectionSignal = Mutable(null);
function handleBarSelection(name, value) {
console.log("Handler called");
if (barSelectionSignal !== defaultSelectionSignal) {
console.log("barSelectionSignal mismatch. Resetting.");
setSelectedBar(null);
} else {
console.log("Setting to:", value.consumption_type[0]);
setSelectedBar(value.consumption_type[0]);
}
}
barChartView.addSignalListener("barSelect", handleBarSelection); I have
Any guidance, insights, or best practices would be greatly appreciated. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
At a glance, I don't see anywhere that you are unregistering the event handler. That would mean that every time the barchartView is updated and the signal handling block is re-run, you'd get duplicate events. This might not be the problem you're seeing, but as a matter of best practices I'd recommend removing the signal listener in response to the invalidation.then(() => barChartView.removeSignalListener("barSelect", handleBarSelection)); |
Beta Was this translation helpful? Give feedback.
-
Keep in mind that the perceived value of a So if I’m not actually sure you need to check whether the value changed before assigning to the mutable; that was probably a bug from registering multiple event listeners. And you won’t need to use the Putting all that together, this seems to work: const barChart = display(await vl.render(…));
const barSelection = Mutable(null);
barChart.value.addSignalListener("barSelect", (name, value) => {
barSelection.value = value.consumption_type?.[0] ?? null;
}); |
Beta Was this translation helpful? Give feedback.
At a glance, I don't see anywhere that you are unregistering the event handler. That would mean that every time the barchartView is updated and the signal handling block is re-run, you'd get duplicate events. This might not be the problem you're seeing, but as a matter of best practices I'd recommend removing the signal listener in response to the
invalidation
promise. I'd expect that to be something like