Reputation: 13
My shiny app has multiple tabPanels and I want to have a selectizeInput on each of these. However, the input only appears to update on the first panel - ie selectizeInput appears to work only on the first tab. The code below has two identical selectizeInputs which are the updated. Apologies if this is not reproducible elsewhere as it does seem to be odd behavior.
d <- c('t','u','o')
library(shiny)
ui <- fluidPage(
tabsetPanel(
tabPanel('a',uiOutput('a')),
tabPanel('b',uiOutput('b'))
))
server <- function(input, output, session){
output$a <- renderUI({
req(d)
selectizeInput(
'a','test1',choices = NULL,
options = list(placeholder = 'Please select from below'),
multiple = TRUE)
})
observe({
req(d)
updateSelectizeInput(session,
'a',choices = d,
selected = NULL, server = TRUE)
})
output$b <- renderUI({
req(d)
selectizeInput(
'b','test2', choices = NULL,
options = list(placeholder = 'Please select from below'),
multiple = TRUE)
})
observe({
req(d)
updateSelectizeInput(session,
'b',choices = d,selected = NULL,
server = TRUE)
})
}
shinyApp(ui, server)
Upvotes: 1
Views: 334
Reputation: 9686
It is reproducible (thanks!) and the answer is quite simple.
The problem lies in the order your elements are rendered. (Description might be messy, because you named your elements ambiguously.)
Explanation: Your selected tabPanel
is a
since it's the first tab available. Your selectizeInput
a
is therefore rendered. It gets rendered as you specified, with choices = NULL
.
Then both observers fire (not because they observe something, but because the server runs through all commands from top to bottom including all observers.)
This leads to selectizeInput
a
being updated to your choices in d
and selectizeInput
b
is also being updated. Note, that at this point, selectizeInput
b
wasn't even rendered yet!
So, as you click on tabPanel
b
, selectizeInput
b
is rendered for the first time, and as you specified, it is rendered with choices = NULL
. Voilà, no choices available.
Solution: You want your observers to observe, so to be run anytime something happens that is important to the observers content. In this case, that is a tabPanel
change. In the code below, I added an id
to your tabsetPanel
and let the observers hear anything that happens with it.
d <- c('t','u','o')
library(shiny)
ui <- fluidPage(
tabsetPanel(id = "x",
tabPanel('a',uiOutput('a')),
tabPanel('b',uiOutput('b'))
))
server <- function(input, output, session){
output$a <- renderUI({
req(d)
selectizeInput(
'a','test1',choices = NULL,
options = list(placeholder = 'Please select from below'),
multiple = TRUE)
})
observe({
req(d)
trigger <- input$x
updateSelectizeInput(session,
'a',choices = d,
selected = NULL, server = TRUE)
})
output$b <- renderUI({
req(d)
selectizeInput(
'b','test2', choices = NULL,
options = list(placeholder = 'Please select from below'),
multiple = TRUE)
})
observe({
req(d)
trigger <- input$x
updateSelectizeInput(session,
'b',choices = d,selected = NULL,
server = TRUE)
})
}
shinyApp(ui, server)
Note: One might even cut one of the observers, and have the remaining one react to the value of input$x
.
Upvotes: 3