changed.jstree event is not captured
I was trying to implement a button to select / deselect all nodes. However, it seems this change is not reflected in the shiny input:
Example:
library(jsTreeR)
library(shiny)
library(shinyjs)
library(jsonlite)
nodes <- list(
list(
text = "Branch 1",
state = list(
opened = TRUE,
disabled = FALSE
),
type = "parent",
children = list(
list(
text = "Leaf A",
state = list(
opened = TRUE,
disabled = FALSE,
selected = FALSE
),
type = "child"
),
list(
text = "Leaf B",
state = list(
opened = TRUE,
disabled = FALSE,
selected = FALSE
),
type = "child"
),
list(
text = "Leaf C",
state = list(
opened = TRUE,
disabled = FALSE,
selected = FALSE
),
type = "child"
),
list(
text = "Leaf D",
state = list(
opened = TRUE,
disabled = FALSE,
selected = FALSE
),
type = "child"
)
)
),
list(
text = "Branch 2",
type = "parent",
state = list(
opened = TRUE,
disabled = FALSE,
selected = FALSE
)
)
)
ui <- fluidPage(
useShinyjs(),
jstreeOutput("mytree"),
actionButton("select_all_nodes", "Select all"),
actionButton("deselect_all_nodes", "Deselect all"),
verbatimTextOutput("mytree_full")
)
server <- function(input, output, session) {
output[["mytree"]] <- renderJstree({
jstree(nodes, contextMenu = TRUE, checkboxes = TRUE)
})
observeEvent(input$select_all_nodes, {
runjs("$('#mytree').jstree('select_all', false);")
})
observeEvent(input$deselect_all_nodes, {
runjs("$('#mytree').jstree('deselect_all', false);")
})
output$mytree_full <- renderPrint({toJSON(input$mytree_full, pretty = TRUE)})
}
shinyApp(ui, server)
Hello,
Thank you for your message. I've just checked my JavaScript code and then I've seen that I commented out one line in the handler of the changed.jstree event so that input$mytree_full is not updated. Unfortunately I don't remember why I commented out this line.
Hi, that's strange. The changed event seems to be pretty straight forward. How are the manual selections captured?
There's nothing strange.
A selection triggers the select_node.jstree event. And in inst/htmlwidgets/jstreer.js I have a handler for this event:
$el.on("select_node.jstree", function(e, data) {
if(inShiny) {
setShinyValue(data.instance, checkboxes);
} // modif 9/10/2023
});
My function setShinyValue updates input$mytree_full.
But as I said, I commented out the call to this function in my handler of the changed.jstree event:
$el.on("changed.jstree", function(e, data) {
if(inShiny) {
// Shiny.setInputValue(
// id, getNodesWithChildren(data.instance.get_json())
// );
setShinyValueSelectedNodes(data.instance, leavesOnly, checkboxes);
if(checkboxes) {
setShinyValueCheckedNodes(data.instance, leavesOnly);
}
//setShinyValue(data.new_instance); // modif 9/10/2023
}
});
I don't remember why. Perhaps because this function was called multiple times in some circumstances.
Strange, as I would have expected select_all to trigger a more general event like select_node.
And it seems changed.jstree should be the way to go:
https://groups.google.com/g/jstree/c/3LLvol8nx1A/m/xvoTIonFticJ
However, select_all also triggers select_all.jstree. Same logic for deselect. Maybe this would be an option.
It seems changed.jstree was commented out after I filed this issue which you fixed with this commit.
Maybe it would have been sufficient to just add the after_open and after_close events?
I just left a PR which seems to fix this.
The original line //setShinyValue(data.new_instance); // modif 9/10/2023
didn't work but
setShinyValue(data.instance);
did.
(an alternative still would be listening on select_all.jstree / deselect_all.jstree)