jsTreeR
jsTreeR copied to clipboard
jsTree not updating when using `uiOutput()`
Here is a minimal example of the behavior. If the jstree output is created using renderUI()
in the server, the updating of the tree does not work as expected. (Sidenote: I do not know why the second Root folder is not showing in my example either.)
library(shiny)
library(jsTreeR)
nodes1 <- list(
list(
text = "Root1A",
children = list(
list(text = "Child1A1")
)
),
list(
text = "Root1B",
children = list(
list(text = "Child1B1"),
list(text = "Child1B2")
)
)
)
nodes2 <- list(
list(
text = "Root2A",
children = list(
list(text = "Child2A1"),
list(text = "Child2A2")
)
),
list(
text = "Root2B",
children = list(
list(text = "Child2B1")
)
)
)
ui <- fluidPage(
selectInput("node_select", "Select Node List", list("Node 1" = "n1", "Node 2" = "n2")),
jstreeOutput("dirtree1"),
uiOutput("dirtree2_ui")
)
server <- function(input, output, session) {
nodes <- reactiveVal(list())
observeEvent(input$node_select, nodes(ifelse(input$node_select == "n1", nodes1, nodes2)))
output$dirtree2_ui <- renderUI({
tagList(
h2(paste("You have selected", input$node_select)),
jstreeOutput("dirtree2")
)
})
output$dirtree1 <- renderJstree(jstree(isolate(nodes())))
output$dirtree2 <- renderJstree(jstree(isolate(nodes())))
observeEvent(nodes(), {
jsTreeR::jstreeUpdate(session, "dirtree1", nodes())
jsTreeR::jstreeUpdate(session, "dirtree2", nodes())
}, ignoreInit = TRUE)
}
shinyApp(ui, server)
Don't use ifelse
for lists. Do:
observeEvent(
input$node_select,
nodes(if(input$node_select == "n1") nodes1 else nodes2)
)
and the second child will appear as expected.
I'm working on the other issue.
Not sure why but it works if you comment a line:
output$dirtree2_ui <- renderUI({
tagList(
#h2(paste("You have selected", input$node_select)),
jstreeOutput("dirtree2")
)
})
If you comment that line it won't re-render when input$node_select
is changed. If you insert a browser()
, you will see it doesn't trigger if you comment out that line when changing the input.
No, it works, because there is jstreeUpdate
. I tested and it works.
Try this
output$dirtree2_ui <- renderUI({
input$node_select
tagList(
jstreeOutput("dirtree2")
)
})
It removes the h2()
element but still triggers renderUI()
whenever input$node_select
is changed. This causes it to break.
But don't do this, this is the cause of the problem.
When input$node_select
changes, then nodes
changes, and the observer is triggered, which triggers the jsTreeUpdate
.
Maybe this example using {shinyTree}
will highlight the problem. I would not expect different behavior if using renderUI()
. My point is that this situation is producing unexpected behavior.
library(shiny)
library(jsTreeR)
library(shinyTree)
nodes1 <- list(
list(
text = "Root1A",
children = list(
list(text = "Child1A1")
)
),
list(
text = "Root1B",
children = list(
list(text = "Child1B1"),
list(text = "Child1B2")
)
)
)
nodes2 <- list(
list(
text = "Root2A",
children = list(
list(text = "Child2A1"),
list(text = "Child2A2")
)
),
list(
text = "Root2B",
children = list(
list(text = "Child2B1")
)
)
)
nodes3 <- list(
Root1A = list(Child1A1 = ""),
Root1B = list(Child1B1 = "", Child1B2 = "")
)
nodes4 <- list(
Root2A = list(Child2A1 = "", Child2A2 = ""),
Root2B = list(Child2B1 = "")
)
ui <- fluidPage(
selectInput("node_select", "Select Node List", list("Node 1" = "n1", "Node 2" = "n2")),
column(
6,
jstreeOutput("dirtree1"),
br(),
uiOutput("dirtree2_ui")
),
column(
6,
shinyTree("dirtree3"),
br(),
uiOutput("dirtree4_ui")
)
)
server <- function(input, output, session) {
nodes <- reactiveVal(list())
shinyTree_nodes <- reactiveVal(list())
observeEvent(input$node_select, {
nodes(if (input$node_select == "n1") nodes1 else nodes2)
shinyTree_nodes(if (input$node_select == "n1") nodes3 else nodes4)
})
output$dirtree2_ui <- renderUI({
input$node_select
tagList(
jstreeOutput("dirtree2")
)
})
output$dirtree4_ui <- renderUI({
input$node_select
tagList(
shinyTree("dirtree4")
)
})
output$dirtree1 <- renderJstree(jstree(isolate(nodes())))
output$dirtree2 <- renderJstree(jstree(isolate(nodes())))
output$dirtree3 <- renderTree(isolate(shinyTree_nodes()))
output$dirtree4 <- renderTree(isolate(shinyTree_nodes()))
observeEvent(nodes(), {
jstreeUpdate(session, "dirtree1", nodes())
jstreeUpdate(session, "dirtree2", nodes())
updateTree(session, "dirtree3", shinyTree_nodes())
updateTree(session, "dirtree4", shinyTree_nodes())
}, ignoreInit = TRUE)
}
shinyApp(ui, server)
I agree it's strange but that's the way it works. My code for the updating is the same as the one of shinyTree
.
Another solution is to remove isolate
from isolate(nodes)
.