In the meantime I have found a solution to my question. I'll clarify what I was trying to achieve using a minimal example and my current solution.
I am using a modal dialog to allow a user to change a range of settings (e.g. plot properties). In the modal dialog there are input elements to change the different settings. On loading the modal dialog each of the input elements is filled with the current setting. After making some changes in the modal dialog the user can choose to either discard or submit the changes made in the modal dialog. Only in the latter case the application is impacted.
A minimal example:
ui <- fluidPage(
fluidRow(
column(width = 12,
actionButton(inputId = "open_settings",
label = "Change settings"),
p("The first setting is: ", tags$b(textOutput("setting01", inline = TRUE))),
p("The second setting is: ", tags$b(textOutput("setting02", inline = TRUE)))
)
)
)
server <- function(input, output, session) {
# current settings (also the default settings upon opening the application)
current_settings <- reactiveValues(
setting01 = "dogs",
setting02 = "sunny"
)
# open the settings modal upon clicking 'Change settings'
new_settings <- reactiveValues()
observeEvent(input$open_settings, {
# copy reactiveValues() to reactiveValues()
for (var in names(current_settings)) {
new_settings[[var]] <- current_settings[[var]]
}
showModal(settings())
})
settings <- function() {
modalDialog(title = "Settings",
footer = tagList(
modalButton("Cancel"),
actionButton(inputId = "submit_settings",
label = "Submit")
),
renderUI({selectInput(inputId = "new_setting01",
label = "Setting 01",
choices = c("cats", "dogs"),
selected = new_settings$setting01)}),
renderUI({selectInput(inputId = "new_setting02",
label = "Setting 02",
choices = c("rain", "sunny"),
selected = new_settings$setting02)})
)
}
# interaction between the setting inputs
observeEvent(input$new_setting01, {
# more complex interactions between new_settings$setting02 and input$new_setting01
# can be added here (example given)
if (input$new_setting01 != new_settings$setting01) { # needed to avoid a side-effect when opening the modal dialog
new_settings$setting01 <- input$new_setting01
if (input$new_setting01 == "dogs") {
new_settings$setting02 <- "rain" # default choice for dogs
} else if (input$new_setting01 == "cats") {
new_settings$setting02 <- "sunny" # default choice for cats
}
}
})
observeEvent(input$new_setting02, {
if (input$new_setting02 != new_settings$setting02) { # needed to avoid a side-effect when opening the modal dialog
new_settings$setting02 <- input$new_setting02
# more complex interactions between new_settings$setting01 and input$new_setting02
# can be added here
}
})
# submit the new settings
observeEvent(input$submit_settings, {
# copy reactiveValues() to reactiveValues()
for (var in names(new_settings)) {
current_settings[[var]] <- new_settings[[var]]
}
removeModal()
})
# render the settings as text for display in the main page
output$setting01 <- renderText({
current_settings$setting01
})
output$setting02 <- renderText({
current_settings$setting02
})
}
shinyApp(ui = ui, server = server)
To obtain the described behavior I keep the current settings in a reactiveValues() variable called 'current_settings'. The non-submitted settings I keep in a reactiveValues() variable called 'new_settings'.
Upon opening the modal dialog I need to copy the 'current_settings' variable to the 'new_settings' variable, which I currently solve in the following way
observeEvent(input$open_settings, {
# copy reactiveValues() to reactiveValues()
for (var in names(current_settings)) {
new_settings[[var]] <- current_settings[[var]]
}
showModal(settings())
})
Upon submitting the changes I need to copy the 'new_settings' variable to the 'current_settings' variable, which I currently solve in the following way
# submit the new settings
observeEvent(input$submit_settings, {
# copy reactiveValues() to reactiveValues()
for (var in names(new_settings)) {
current_settings[[var]] <- new_settings[[var]]
}
removeModal()
})
I was looking for a solution where I did not have to iterate through the respective lists, but couldn't find any.
EDIT: Added an example of possible interaction between input elements in the modal dialog.