Ben Smith
Ben Smith

Reputation: 85

Setting up two RShiny input values for the same value across different tab panels

I have an RShiny app using a navBarPage, something like:

default_run_date = Sys.Date()
ui <- navbarPage(
  "MyTitle",
  id="mainNavbarPage"
  ),
  tabPanel(
    "Panel1",
    fluidPage(
        dateInput("datePicker1",
                           "Run date:",
                           value = default_run_date,max = Sys.Date())
  ),
  tabPanel(
    "Panel2",
    fluidPage(
        dateInput("datePicker2",
                           "Run date:",
                           value = default_run_date,max = Sys.Date())
  )
)

I actually have 5-6 different tabs and I want the user to be able to change a date that applies a setting across all of these tabs. For convenience I want users to have this control when accessing either of two different tabs.

I tried setting up a pair of observers:

observeEvent(input$datePicker1,{updateDateInput(session,inputId ="datePicker2",value=input$datePicker1)})
observeEvent(input$datePicker2,{updateDateInput(session,inputId ="datePicker1",value=input$datePicker2)})

However each of these events actually triggers the other, resulting in an infinite loop.

Can anyone tell me a better way to handle this?

Upvotes: 0

Views: 43

Answers (2)

starja
starja

Reputation: 10365

In this case, I would not use renderUI as the complete dateInput has to be rendered on the server side. This causes delays in updating the value, already visible in this toy example. This blog post describes why using updateInput and doing the change on the client side is faster. You can apply this approach here as following:

library(shiny)

ui <- navbarPage("MyTitle", id="mainNavbarPage",
                 tabPanel("Panel1", dateInput("datePicker1",
                                              "Run date:",
                                              value = Sys.Date(),
                                              max = Sys.Date())),
                 tabPanel("Panel2", dateInput("datePicker2",
                                              "Run date:",
                                              value = Sys.Date(),
                                              max = Sys.Date())))

server <- function(input, output, session){
  
  # Default starting value for date pickers
  date_chosen <- reactiveVal(Sys.Date())
  
  observeEvent(input$datePicker1, {
    date_chosen(input$datePicker1)
  })
  observeEvent(input$datePicker2, {
    date_chosen(input$datePicker2)
  })
  
  observeEvent(date_chosen(), {
    updateDateInput(session,
                    "datePicker1",
                    value = date_chosen())
    updateDateInput(session,
                    "datePicker2",
                    value = date_chosen())
  })
}

shinyApp(ui = ui, server = server)

Upvotes: 2

Michael Dewar
Michael Dewar

Reputation: 3258

Store the chosen date in a reactiveVal. Then use renderUI to recreate the date pickers whenever the reactiveVal changes.

library(shiny)

ui <- navbarPage("MyTitle", id="mainNavbarPage",
                 tabPanel("Panel1", uiOutput("date_ui_1")),
                 tabPanel("Panel2", uiOutput("date_ui_2")))

server <- function(input, output, session){
  
  # Default starting value for date pickers
  date_chosen <- reactiveVal(Sys.Date())
  
  output$date_ui_1 <- renderUI({
    dateInput("datePicker1",
              "Run date:",
              value = date_chosen(),
              max = Sys.Date())
  })
  
  output$date_ui_2 <- renderUI({
    dateInput("datePicker2",
              "Run date:",
              value = date_chosen(),
              max = Sys.Date())
  })
  
  observeEvent(input$datePicker1, {
    date_chosen(input$datePicker1)
  })
  observeEvent(input$datePicker2, {
    date_chosen(input$datePicker2)
  })
}

shinyApp(ui = ui, server = server)

Upvotes: 1

Related Questions