I'm building an interactive Rmarkdown html document with plotly in R. It is composed by 3 elements: a main scatterplot (interactive), a secondary scatterplot, and a table.
The design looks like this:
Each figure is built using different data. However, they all share a main key.
The main scatterplot is made with plot_ly
. It uses highlight_key
and highlight
to, well, highlight all the points that share that key. It also has a ¿selectize? drop-down menu on top that lets them search for a specific key.
The secondary scatterplot is made with ggplotly
+ highlight_key
. It uses crosstalk::filter_select
+ bscols
to subset the data shown, to only those of the specific key.
The table is made with reactable
. Like the secondary plot, it also uses crosstalk::filter_select
(a different one, though, on a different data.frame) + bscols
to subset the data shown, to only those of the specific key.
What I have right now:
When the user hovers or clicks on a point of the main scatterplot, I have added a piece of JavaScript code that takes the key of the newly selected element on the main plot, and changes the value of the two separate filter_select menus on both the secondary plot and the table.
When there is a on('plotly_click')
event in figure1, capture the new key and change the value of the filter_select fields:
fig1_plotly(.....) %>%
highlight(on = "plotly_hover", off = "plotly_doubleclick", selectize=TRUE) %>%
onRender("function(el) {
el.on('plotly_click', function(d) {
console.log('Click detail: ', d.points[0].data.key);
document.getElementById('id_filter_counts').getElementsByClassName('selectized')[0].selectize.setValue(d.points[0].data.key, false)
document.getElementById('id_filter_table').getElementsByClassName('selectized')[0].selectize.setValue(d.points[0].data.key, false)
});
}
")
I also added this chunk to give a default starting value to the secondary plot and the table, because their full data is too large and useless to look into. It also hides the filter_select
dropdown menus from them both, so the user only interacts with the main one:
```{js}
function filter_default() {
document.getElementById("id_filter_counts").getElementsByClassName("selectized")[0].selectize.setValue(****DEFAULT_VALUE****, false);
document.getElementById("id_filter_table").getElementsByClassName("selectized")[0].selectize.setValue(****DEFAULT_VALUE****, false);
document.getElementById("id_filter_counts").style.display="none"
document.getElementById("id_filter_table").style.display="none"
}
window.onload = filter_default;
```
This is 100% working as intended. When I click on a point in figure1, it automatically changes the filter field on both figure2 and the table, which updates them both.
When the user interacts with figure 1's highlight/selectize
menu, it correctly updates figure1. However, that doesn't trigger my custom on('plotly_click')
, and neither the secondary plot nor the table change.
I want to add the code in my snippet to whatever triggers when the user changes figure1's menu. However, so far, I haven't been able to come up with any solution.
I have tried adding this to my JS snippet, but it isn't triggering anything.
document.getElementsByClassName('selectize-control multi')[0].parentElement.getElementsByClassName("selectized")[0].selectize.onChange = function(d){console.log('Menu change: ', d)}
I haven't toyed with JavaScript in nearly 20 years and I'm a bit lost.
How do I find and modify the event that triggers when changing the highlight/selectize menu?
Thanks
It seems I almost had it.
It was .on("change", function(d){....})
:
document.getElementsByClassName('selectize-control multi')[0].parentElement.getElementsByClassName("selectized")[0].selectize.on("change",
function(d){....})