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

Tree does not render when modal is re-opened #79

Open
m-merchant opened this issue Jun 17, 2019 · 5 comments
Open

Tree does not render when modal is re-opened #79

m-merchant opened this issue Jun 17, 2019 · 5 comments

Comments

@m-merchant
Copy link

The following app has a button, Show, that opens a modal dialog when clicked. The modal contains a shinyTree with the search feature enabled and a datatable. When the modal is opened for the first time, both the tree and the datatable are rendered:

image

However, when the modal is dismissed and re-opened, the DT is rendered but the tree is not:

image

The screenshot above shows that the searchbox of the tree is rendered but its nodes are missing.

I can get around this by putting input$show inside renderTree but was wondering why it doesn't re-render without it like the DT.

Here is the code to reproduce the above:

library(shiny)
library(shinyTree)
library(DT)

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

# UI

ui <- fluidPage(
  actionButton('show', 'Show modal')
)

# server

server <- function(input, output, session) {
  
  
  output$tree = renderTree({
    # input$show
    
    tree
    
  })
  
  output$data = renderDT({
    
    iris 
    
  })
  
  observeEvent(input$show, {
    
    showModal(modalDialog(
      shinyTree("tree", search = T), 
      DTOutput('data')
    ))
    
  })
}

shinyApp(ui, server)
@m-merchant
Copy link
Author

m-merchant commented Jul 7, 2019

In addition to re-rendering the tree when the modal is reopened, is there a way to also preserve the selected nodes when the modal is reopened? I am currently using a workaround that makes use of delay() and addClass from shinyjs. Here is my updated code:

library(shiny)
library(shinyTree)
library(shinyjs)
library(DT)

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

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

# UI

ui <- fluidPage(
  useShinyjs(),
  actionButton('show', 'Show modal')
)

# server

server <- function(input, output, session) {
  
  
  output$tree = renderTree({
    
    input$show
    
    tree
    
  })
  
  output$data = renderDT({
    
    iris 
    
  })
  
  observeEvent(input$show, {
    
    showModal(modalDialog(
      shinyTree("tree", checkbox = T, search = T, themeIcons = F, theme = 'proton'), 
      DTOutput('data')
    ))
    
    # Add 'jstree-clicked' class to selected nodes
    delay(1000, {
      ids = lapply(get_selected(input$tree, 'classid'), function(x) attr(x, 'id'))
      
      lapply(ids, function(x) addClass(id = paste0(x, '_anchor'), class = 'jstree-clicked'))
    })
    
  })
}

shinyApp(ui, server)

So if you select node a2 and dismiss the modal, then when you subsequently reopen it, the tree is re-rendered with node a2 selected.

@bellma-lilly
Copy link
Contributor

When input$tree changes, save the contents in "tree". The state is preserved in the structure. (The only thing that isn't saved is the types. I have code to fix that which I have not submitted yet)

@MayaGans
Copy link

MayaGans commented May 5, 2020

@bellma-lilly would you mind adding that logic to my reprex below? I've encountered the same error:

library(shiny)
library(shinyTree)

ui = basicPage(
    actionButton("show", "Show modal dialog")
)

server = function(input, output) {
    
    output$tree <- renderTree({
        list(
            root1 = "",
            root2 = list(
                SubListA = list(leaf1 = "", leaf2 = "", leaf3=""),
                SubListB = list(leafA = "", leafB = "")
            ),
            root3 = list(
                SubListA = list(leaf1 = "", leaf2 = "", leaf3=""),
                SubListB = list(leafA = "", leafB = "")
            )
        )
    })
    
    observeEvent(input$show, {
        showModal(modalDialog(
                    shinyTree("tree", stripes = TRUE, multiple = FALSE, animation = FALSE)
        ))
    })
}


# Run the application 
shinyApp(ui = ui, server = server)

Thank you!

@trafficonese
Copy link
Contributor

As @m-merchant noted, you can get around this error, if you add input$show in the renderTree section. But anyway, I hope @bellma-lilly can soon find some time to include the fix.

@MayaGans
Copy link

MayaGans commented May 5, 2020

Ah I see that now, thanks!!!

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

No branches or pull requests

4 participants