2

The app below contains a shinyTree, a reset button (Reset nodes) and a print output 'Selected nodes'. The print output prints the output of the get_selected function, which returns a list of selected nodes.

Here is a screenshot of the tree on start-up:

enter image description here

No nodes are selected so get_selected returns an empty list()

When I make a selection, e.g. node a, the get_selected correctly returns that selection:

enter image description here

When I click Reset nodes, the node selections are cleared in the tree UI but get_selected does not change from the previous selection:

enter image description here

When the reset button is clicked, an observer updates the tree via updateTree as follows:

observeEvent(input$reset, {

    updateTree(session,"tree", data = tree)
  })

I would like get_selected to return list() when I hit reset. Am I using updateTree incorrectly?

Here is the code to reproduce the above:

library(shiny)
library(shinyTree)

tree = structure(list(a=list(a1=1,a2=2) , b="b"), stopened = T) 

tree = lapply(tree, function(x) structure(x, stopened = T))

ui <- fluidPage(
  tags$head(tags$script('
                        $("#reset").onlick(function() {
                        $("#tree").jstree("deselect_all");
                        }
                        ')),
  fluidPage(
    sidebarLayout(
      sidebarPanel(
        actionButton('reset', 'Reset nodes')
      ),
      mainPanel(
        shinyTree("tree", ),
        hr(),
        "Selected nodes:",
        verbatimTextOutput("idSelected")#,
      )
    )
  )
)

# server

server <- function(input, output, session) {

  output$tree = renderTree({

    tree

  })


  output$idSelected <- renderPrint({
    str(get_selected(input$tree, format = "classid"))
  })


  # An observer is used to trigger a tree update when reset is clicked.
  observeEvent(input$reset, {

    updateTree(session,"tree", data = tree)

    print(get_selected(input$tree, format = "classid"))
  })
}

shinyApp(ui, server)

I've tried the following JQuery to no avail:

$("#reset").onlick(function() {
                        $("#tree").jstree("deselect_all");
                        }
ismirsehregal
  • 30,045
  • 5
  • 31
  • 78
user51462
  • 1,658
  • 2
  • 13
  • 41
  • 1
    By now [PR 89](https://github.com/shinyTree/shinyTree/pull/89) provides us with the possibilty of setting `options(shinyTree.refresh = TRUE)` to get the desired behaviour - Please see [this](https://stackoverflow.com/a/58517834/9841389) – ismirsehregal Oct 23 '19 at 07:47

1 Answers1

4

You could update a reactiveVal on hitting the reset button instead of directly referring to the data provided by get_selected:

library(shiny)
library(shinyTree)

tree <- lapply(structure(list(a=list(a1=1,a2=2) , b="b"), stopened = TRUE) , function(x) structure(x, stopened = TRUE))

ui <- fluidPage(
  fluidPage(
    sidebarLayout(
      sidebarPanel(
        actionButton('reset', 'Reset nodes')
      ),
      mainPanel(
        shinyTree("tree", ),
        hr(),
        "Selected nodes:",
        verbatimTextOutput("idSelected")#,
      )
    )
  )
)

server <- function(input, output, session) {

  treeSelection <- reactiveVal(list())

  output$tree = renderTree({
    tree
  })

  observeEvent(input$reset, {
    updateTree(session, "tree", data = tree)
    treeSelection(list())
  })

  observeEvent(input$tree, {
    treeSelection(get_selected(input$tree, format = "classid"))
  })

  output$idSelected <- renderPrint({
    treeSelection()
  })

}

shinyApp(ui, server)
ismirsehregal
  • 30,045
  • 5
  • 31
  • 78
  • Thank you @ismirsehregal! Would you know why `get_selected` wasn't changing? Was I using `updateTree` incorrectly? – user51462 Jun 12 '19 at 07:36
  • 1
    You were using `updateTree` correctly. I'm not really familiar with `library(shinyTree)` but it seems updating/re-rendering the tree doesn't trigger an update for the selected nodes by design. – ismirsehregal Jun 12 '19 at 08:08
  • 1
    shinyTree contributor here: people generally don't want a callback when update tree is called because they already know what is in the tree. Certainly, input$tree would not be updated immediately after updateTree was called; you would still need to get the new input$tree in an observe. The answer by @ismirsehregal is an elegant solution to your particular problem – michael Jun 24 '19 at 16:47