My goal is to create a selectizeInput and update it directly after it exists via updateSelectizeInput()
.
For various reasons, my selectizeInput is not created when the app starts. This only happens in the server with renderUI()
when the user opens a modalDialog()
via an actionButton()
. Also my selectizeInput()
should be created with choices = NULL
and selected = NULL
. As soon as the selectizeInput exists, the arguments "choices" and "selected" are to be filled via updateSelectizeInput()
. This does not work because updateSelectizeInput()
runs in the server before the input exists.
Current workaround: I call updateSelectizeInput()
in an observeEvent(input$selectize, once = TRUE)
, which runs as soon as the input exists (but only once).
Problem with workaround: Only works the first time. If the modalDialog()
is closed and reopened, the inputs are recreated, but the observer is destroyed and cannot run again.
Goal: updateSelectizeInput()
should run as soon as the input is created and ready to be updated with updateSelectizeInput()
. But how to know that my input is ready?
I have created two working examples. In the first example, the problem occurs every time the modal is opened.
# example 1
library(shiny)
ui <- fluidPage(
tagList(
actionButton("go", "go"),
)
)
server <- function(input, output) {
observeEvent(input$go, {
showModal(
modalDialog(
tagList(
selectizeInput(
inputId = "selectize",
label = "selectize",
choices = NULL,
selected = NULL
),
textOutput("text")
)
)
)
})
updateSelectizeInput(
inputId = "selectize",
choices = c("A", "B"),
selected = "B"
)
output$text <- renderText({
input$selectize
})
}
shinyApp(ui = ui, server = server)
In the second example (with workaround), the filling works the first time the modal is opened, but it does not work the second time.
# example 2
library(shiny)
ui <- fluidPage(
tagList(
actionButton("go", "go"),
)
)
server <- function(input, output) {
observeEvent(input$go, {
showModal(
modalDialog(
tagList(
selectizeInput(
inputId = "selectize",
label = "selectize",
choices = NULL,
selected = NULL
),
textOutput("text")
)
)
)
})
observeEvent(input$selectize, once = TRUE,{
updateSelectizeInput(
inputId = "selectize",
choices = c("A", "B"),
selected = "B"
)
})
output$text <- renderText({
input$selectize
})
}
shinyApp(ui = ui, server = server)
CodePudding user response:
Based on your first code one option would be to use a reactiveVal
to store the state of the selectizeInput
, i.e. whether it has been created and is ready to be filled or not. When TRUE
it triggers the updating via an observeEvent
. Inside this oberseEvent
the reactiveVal
is reset to FALSE
:
library(shiny)
ui <- fluidPage(
tagList(
actionButton("go", "go"),
)
)
server <- function(input, output) {
is_ready <- reactiveVal(FALSE)
observeEvent(input$go, {
is_ready(TRUE)
showModal(
modalDialog(
tagList(
selectizeInput(
inputId = "selectize",
label = "selectize",
choices = NULL,
selected = NULL
),
textOutput("text")
)
)
)
})
observeEvent(is_ready(), {
is_ready(FALSE)
updateSelectizeInput(
inputId = "selectize",
choices = c("A", "B"),
selected = "B"
)
})
output$text <- renderText({
input$selectize
})
}
shinyApp(ui = ui, server = server)