Reputation: 365
I'm trying to build an application, where the user can add a piece of UI (in this case an input text field) by clicking a button. As this is only part of a bigger application, I wish to use modules to keep structure in my project.
However, my text field won't show after clicking the action button. I'm using the new function moduleServer()
that was recently introduced by shiny
.
Here is a reprex
library(shiny)
ModularizedUI <- function(id) {
ns <- NS(id)
fluidPage(
# Input: Action button to add text field
actionButton(inputId = ns("add_text"),
label = "Add text field"),
)
}
ModularizedServer <- function(id) {
moduleServer(
id,
function(input, output, session) {
ns <- session$ns
# Track the number of input boxes to render for test training
counter_text <- reactiveVal(0)
# Input/Output fields for start dates test training
observeEvent(input$add_text, {
counter_text(counter_text() + 1)
# Add UI if this button is clicked
insertUI(
selector = "#add",
where = "afterEnd",
ui = textInput(inputId = ns(paste0("textfield_", counter_text())),
label = "New text")
)
})
}
)
}
ui <- navbarPage("Dashboard",
tabPanel("Text fields",
ModularizedUI(id = "Text_Fields")
)
)
server <- function(input, output, session) {
ModularizedServer("Text_Fields")
}
shinyApp(ui = ui, server = server)
Any help is appreciated!
Upvotes: 1
Views: 291
Reputation: 23919
You gave insertUI
the selector #add
, which defines where the new elements have to be inserted. But there is no element with id #add
in your UI.
Add div(id = '#add')
after your actionButton
and it should work.
(I would then use where = beforeEnd
, so that all Inputs are inside that new div
and can be easily targeted using CSS or JS, or....)
Complete example:
library(shiny)
ModularizedUI <- function(id) {
ns <- NS(id)
fluidPage(
# Input: Action button to add text field
actionButton(inputId = ns("add_text"),
label = "Add text field"),
div(id = "add")
)
}
ModularizedServer <- function(id) {
moduleServer(id, function(input, output, session) {
ns <- session$ns
# Track the number of input boxes to render for test training
counter_text <- reactiveVal(0)
# Input/Output fields for start dates test training
observeEvent(input$add_text, {
counter_text(counter_text() + 1)
# Add UI if this button is clicked
insertUI(
selector = "#add",
where = "beforeEnd",
ui = textInput(inputId = ns(paste0("textfield_", counter_text())),
label = "New text")
)
})
}
)
}
ui <- navbarPage("Dashboard",
tabPanel("Text fields",
ModularizedUI(id = "Text_Fields")))
server <- function(input, output, session) {
ModularizedServer("Text_Fields")
}
shinyApp(ui = ui, server = server)
Upvotes: 2