Reputation: 759
I am using observeEvent to insert a UI (in the example below, it adds an additional numeric input box) with insertUI
and likewise observeEvent to remove those UIs via removeUI
. The issue is that the data that is created through those UIs does not clear or reset. In the example below, you can enter numbers in separate numeric input boxes and press Go!
to sum them together. Upon removing elements, it should clear our that data and re-sum, but it keeps the last number added.
For example, if 1 is in the first box and two more input boxes are added, both with 1s, pressing Go!
correctly sums them to 3. However, removing the two text boxes and pressing Go!
keeps 3 when it should just show 1.
I am sure I have missed something simple. My reprex is below:
library(shiny)
ui <- fluidPage(
# Application title
titlePanel("example"),
# button input
sidebarLayout(
sidebarPanel(
numericInput(
"number",
"A Number 1-10",
1,
min = 1,
max = 10,
step = NA,
width = NULL),
#add/remove buttons
fluidRow(column(
6,
actionButton('insertBtn', 'Add Number'),
actionButton('removeBtn', 'Remove Number'),
tags$div(id = 'placeholder')
)),
# go button
fluidRow(column(
6, actionButton(inputId = "go", label = "Go!"),
))
),
# output
mainPanel(
htmlOutput("total")
)
)
)
server <- function(input, output) {
# add text boxes when clicked
inserted <- c()
observeEvent(input$insertBtn, {
btn <- input$insertBtn
id <- paste0('number', btn)
insertUI(
selector = '#placeholder',
## wrap element in a div with id for ease of removal
ui = tags$div(
fluidRow(
numericInput(
id,
"A Number 1-10",
1,
min = 1,
max = 10,
step = NA,
width = NULL)
),
id = id)
)
inserted <<- c(id, inserted)
})
# remove text boxes
observeEvent(input$removeBtn, {
removeUI(
## pass in appropriate div id
selector = paste0('#', inserted[length(inserted)])
)
inserted <<- inserted[-length(inserted)]
})
# add numbers in boxes
final_number_text <- eventReactive(input$go, {
btn <- input$insertBtn
if(btn > 0){
total <- input$number
for(i in 1:btn){
total<- total+ (input[[paste0("number", i)]])
}
} else {
total <- input$number
}
HTML(paste(total))
})
output$total <- renderText({
final_number_text()
})
}
# Run the application
shinyApp(ui = ui, server = server)
Upvotes: 0
Views: 56
Reputation: 21297
Please note that when you remove a number, you are not decreasing the value of input$insertBtn
. Therefore, you want to count only the elements that are in inserted
. Therefore, replace
for(i in 1:btn){...}
with
lapply(inserted, function(par) {total <<- total + input[[par]]})
Full code
library(shiny)
ui <- fluidPage(
# Application title
titlePanel("example"),
# button input
sidebarLayout(
sidebarPanel(
numericInput(
"number",
"A Number 1-10",
1,
min = 1,
max = 10,
step = NA,
width = NULL),
#add/remove buttons
fluidRow(column(
6,
actionButton('insertBtn', 'Add Number'),
actionButton('removeBtn', 'Remove Number'),
tags$div(id = 'placeholder')
)),
# go button
fluidRow(column(
6, actionButton(inputId = "go", label = "Go!"),
))
),
# output
mainPanel(
htmlOutput("total")
)
)
)
server <- function(input, output, session) {
# add text boxes when clicked
inserted <- c()
observeEvent(input$insertBtn, {
btn <- input$insertBtn
id <- paste0('number', btn)
insertUI(
selector = '#placeholder',
## wrap element in a div with id for ease of removal
ui = tags$div(
fluidRow(
numericInput(
id,
"A Number 1-10",
1,
min = 1,
max = 10,
step = NA,
width = NULL)
),
id = id)
)
# inserted <<- c(id, inserted) ## removes first one first
inserted <<- c(inserted, id) ## removes last one first
})
# remove text boxes
observeEvent(input$removeBtn, {
removeUI(
## pass in appropriate div id
selector = paste0('#', inserted[length(inserted)])
)
inserted <<- inserted[-length(inserted)]
})
# add numbers in boxes
final_number_text <- eventReactive(input$go, {
total <- input$number
if(length(inserted) > 0){
lapply(inserted, function(par) {total <<- total + input[[par]]})
}
HTML(paste(total))
})
output$total <- renderText({
final_number_text()
})
}
# Run the application
shinyApp(ui = ui, server = server)
Upvotes: 1
Reputation: 887098
We may need seq_along
which would be bug free when the length is 0
for(i in seq_along(inserted)) {...}
Upvotes: 1