Here is an MWE:
library(shiny)
runApp(shinyApp(
ui = pageWithSidebar(
fluidRow(
column(3, wellPanel(
numericInput("numFields", "Select number of fields", 2, min = 1),
br(),
uiOutput("fields"),
br(),
actionButton("goButton", "Go!")
)),
column(3, wellPanel(
uiOutput("morefields")
)),
column(3, wellPanel(
numericInput("numFields2", "Select number of fields 2", 2, min = 1),
br(),
actionButton("goButton2", "Go2!")
))
),
server = function(input, output, session){
output$fields <- renderUI({
numFields <- as.integer(input$numFields)
lapply(1:numFields, function(i) {
textInput(paste0("field", i), paste0("Type in field ", i))
})
})
output$morefields <- renderUI({
if (input$goButton == 0) return(NULL)
isolate({
numFields <- as.integer(input$numFields)
lapply(1:numFields, function(i) {
checkboxInput(paste0("checkbox", i), paste0("Checkbox for field ",
input[[paste0("field", i)]]))
})
})
})
observeEvent(input$goButton2, {
numFields2 <- as.integer(input$numFields2)
last_field <- paste0("field", numFields2)
updateNumericInput(session, "numFields", value = numFields2)
updateTextInput(session, "field1", value = "This is the first field")
updateTextInput(session, last_field, value = "This is the last field")
})
}))
Now I perform the following set of actions:
- Starting the app
- Set the value of
Select number of fields 2
to e.g. 3 - Press the
Go2!
button - Within the left column, the number of input fields is changed, but I'd like the first and the last field to be filled with text, so I click on the
Go2!
button again - Click on the
Go!
button so that the UI in the middle is generated.
My aim would be to avoid steps 4 and 5, but to get the same result.
I tried to solve the issue with a reactiveValues
-variable and a simulated click (as proposed here):
library(shiny)
library(shinyjs)
jscode <- "shinyjs.click = function(id) { $('#' + id).click(); }"
runApp(shinyApp(
ui = pageWithSidebar(
useShinyjs(),
extendShinyjs(text = jscode),
fluidRow(...)),
server = function(input, output, session){
vals <- reactiveValues(update = 0)
output$fields <- renderUI({...})
output$morefields <- renderUI({...})
observeEvent(input$goButton2, {
numFields2 <- as.integer(input$numFields2)
updateNumericInput(session, "numFields", value = numFields2)
vals$update <- 1
})
observeEvent(vals$update, {
if (vals$update != 1) return(NULL)
numFields2 <- as.integer(input$numFields2)
last_field <- paste0("field", numFields2)
updateTextInput(session, "field1", value = "This is the first field")
updateTextInput(session, last_field, value = "This is the last field")
vals$update <- 2
})
observeEvent(vals$update, {
if (vals$update != 2) return(NULL)
js$click("goButton")
vals$update <- 0
})
}))
Now the second UI is generated, but the fields remain empty. I have to click on Go2!
three times before all the UIs get completely updated.
I also tried doing the following within the server
-part:
observeEvent(input$goButton2, {
numFields2 <- as.integer(input$numFields2)
updateNumericInput(session, "numFields", value = numFields2)
}, priority = 2)
observeEvent(vals$update, {
numFields2 <- as.integer(input$numFields2)
last_field <- paste0("field", numFields2)
updateTextInput(session, "field1", value = "This is the first field")
updateTextInput(session, last_field, value = "This is the last field")
}, priority = 1)
observeEvent(input$goButton2, {
js$click("goButton")
}, priority = 0)
Again the course of events look a bit different, but still clicking thrice is necessary to get what I want.
Any suggestions on how to achieve the final result by clicking on the Go2!
button only once?