I want to populate Shiny numericInput boxes with initial values from a named list. (The values and names are imported, but here just coded.) The initial values are summed and appear to the right of the numeric inputs.
I want the sum to update if I change the values in either numericInput. (I may not need to update either.) I can populate the values and get the initial sum. But, if I change a value, the sum does not update.
I tried an observeEvent to update the sum if I change a numericInput. The reactive "logic" I assumed in the MWE below is:
- The initial values are reactive so that they can be updated.
totalis a reactive value with the sum of the two reactive values.- The observeEvent watches for a change in
numericInput(here just the first one) and updates the associated reactive value (amounts$amt1). - Because the reactive value is updated, I thought the
totalreactive would also update and thus updateoutput$total1.
If I do not use the observeEvent for amt1, then the numeric inputs are properly initialized and summed, but subsequent changes to the inputs do not change the sum (total = 21). This makes sense because I don't have an observeEvent watching for changes.
If I include an observeEvent, then the observed numericInput resets to the default value (1) coded in the UI instead of using the initial value. The values are then summed. Subsequent changes to the inputs do not change the sum (total = 12).
Question
How do I populate the numeric inputs with initial values then update the sum if I change the initial values from the interface? I'm sure I'm not using the reactives correctly but I have not been able to figure out the correct way.
MWE
library(shiny)
vals <- as.list(c(10, 11))
names(vals) <- c("val1", "val2")
ui <- fluidPage(
fluidRow(
column(3,
numericInput(
inputId = "amt1",
label = "Amount 1",
value = 1)
),
column(3,
numericInput(
inputId = "amt2",
label = "Amount 2",
value = 2)
),
column(3,
textOutput("total1")
)
),
)
server <- function(input, output, session) {
amounts <- reactiveValues(
amt1 = vals$val1,
amt2 = vals[["val2"]]
)
observe({
updateNumericInput(
session,
inputId = "amt1",
value = amounts$amt1
)
updateNumericInput(
session,
inputId = "amt2",
value = amounts$amt2
)
})
total <- reactive({
sum(amounts$amt1, amounts$amt2)
})
# If this runs, it resets input$amt1 to default value.
observeEvent("amt1", {
amounts$amt1 <- input$amt1
})
output$total1 <- renderText(total())
# Tried this too, but it didn't change anything.
#output$ui <- renderUI({
# tagList(
# numericInput("amt1", value = amounts$amt1),
# numericInput("amt2", value = amounts$amt2),
# output$total1 <- renderText(total())
# )
#})
}
shinyApp(ui, server)