Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

changed.jstree event is not captured #34

Open
stewerner opened this issue Jul 12, 2024 · 6 comments · May be fixed by #35
Open

changed.jstree event is not captured #34

stewerner opened this issue Jul 12, 2024 · 6 comments · May be fixed by #35

Comments

@stewerner
Copy link

stewerner commented Jul 12, 2024

I was trying to implement a button to select / deselect all nodes. However, it seems this change is not reflected in the shiny input:

screen

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)
@stla
Copy link
Owner

stla commented Jul 13, 2024

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.

@ismirsehregal
Copy link

Hi,
that's strange. The changed event seems to be pretty straight forward. How are the manual selections captured?

@stla
Copy link
Owner

stla commented Jul 13, 2024

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.

@ismirsehregal
Copy link

ismirsehregal commented Jul 15, 2024

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.

@ismirsehregal
Copy link

ismirsehregal commented Jul 15, 2024

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?

@ismirsehregal ismirsehregal linked a pull request Jul 15, 2024 that will close this issue
@ismirsehregal
Copy link

ismirsehregal commented Jul 15, 2024

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants