I have a shiny app that dynamically removes and inserts input UI based on user selection. The UI generated by selectingchoice1
and choice2
share part of their input fields. I wanted to use the shinyvalidate
package to add some validation rules that can apply to the shared inputs. In the following example, the user can make a selection on the sidebar. Once a choice is made, the div with ID "content" on the main panel will be deleted and a new div will be inserted. The rules seem to be working, but unless I type something in the input field first, the red warning message won't appear when I switch choices.
library(shiny)
library(glue)
library(shinyvalidate)
ui <- fluidPage(
sidebarPanel(
selectInput("select", label = "select", choices = c("", "choice1", "choice2"))
),
mainPanel(id = "main",
tags$div(id = "content"))
)
server <- function(input, output) {
# validate input
iv <- InputValidator$new()
iv$add_rule("input", sv_required())
iv$enable()
observeEvent(input$select, {
if(input$select == "choice1"){
removeUI("#content")
insertUI("#main", ui = tags$div(
id = "content",
textInput("input", "input")))
}
if(input$select == "choice2"){
removeUI("#content")
insertUI("#main", ui = tags$div(
id = "content",
textInput("input", "input")))
}
})
}
# Run the application
shinyApp(ui = ui, server = server)
CodePudding user response:
This works by triggering iv$enable
after the observeEvent
has finished its work (is "invalidated" is the correct wording I think).
server <- function(input, output) {
# validate input
iv <- InputValidator$new()
iv$add_rule("input", sv_required())
Validate <- reactiveVal(NULL)
observeEvent(input$select, {
iv$disable()
if(input$select == "choice1"){
removeUI("#content")
insertUI("#main", ui = tags$div(
id = "content",
textInput("input", "input")))
}
if(input$select == "choice2"){
removeUI("#content")
insertUI("#main", ui = tags$div(
id = "content",
textInput("input", "input")))
}
Validate(TRUE)
})
observeEvent(Validate(), {
iv$enable()
Validate(NULL)
})
}
EDIT
I don't know why, but you have to set immediate = TRUE
in both removeUI
and insertUI
:
if(input$select == "choice1"){
removeUI("#content", immediate = TRUE)
insertUI("#main", ui = tags$div(
id = "content",
textInput("input", "input")), immediate = TRUE)
}
if(input$select == "choice2"){
removeUI("#content", immediate = TRUE)
insertUI("#main", ui = tags$div(
id = "content",
textInput("input", "input")), immediate = TRUE)
}