Search code examples
rshinyshinydashboardshiny-reactivitytabpanel

How to use just one daterangeinput that syncs across multiple tabs?


I'm building an app where users can filter the date of the data. On the first tab, it shows a view of the employees, and on the second, it shows a view of the project (for this example, the numbers are the same).

The side bars look different in the final app, but they both have the same date filter option that I want to sync across tabs. However, currently the app only responds to the date filter on the first tab, ignores the second daterangeinput, and doesn't sync what they're both saying (e.g., I might select Aug-2021 to Oct-2021 on the first input, but the second date range input still shows the default (even though the table on both tabs looks correct).

I gave both daterangeinputs the same inputId, but that's not helping. Any help would be greatly appreciated!

library(shiny)
library(shinyjs)
library(shinydashboard)
library(shinyWidgets) 
library(dplyr)
library(htmltools)
library(lubridate)
library(stringr)


ui = fluidPage(
    tabsetPanel(
        tabPanel("View 1", fluid = TRUE,
                 sidebarLayout(
                     sidebarPanel(
                         h4("Select Your Desired Filters"),
                         div(id = "inputs",
                             dateRangeInput(
                                 inputId = "date_filter",
                                 label = "Filter by Month and Year",
                                 start = today(),
                                 end = (today() + 90),
                                 min = "Apr-2021",
                                 max = NULL,
                                 format = "M-yyyy",
                                 startview = "month",
                                 weekstart = 0,
                                 language = "en",
                                 separator = " to ",
                                 width = NULL,
                                 autoclose = TRUE
                             ),
                             br()),
                     ),
                     mainPanel(
                         DT::dataTableOutput("mytable")
                         
                     )
                 )
        ),
        tabPanel("View 2", fluid = TRUE,
                 sidebarLayout(
                     sidebarPanel(
                         h4("Select Your Desired Filters"),
                         div(id = "inputs",
                             dateRangeInput(
                                 inputId = "date_filter",
                                 label = "Filter by Month and Year",
                                 start = today(),
                                 end = (today() + 90),
                                 min = "Apr-2021",
                                 max = NULL,
                                 format = "M-yyyy",
                                 startview = "month",
                                 weekstart = 0,
                                 language = "en",
                                 separator = " to ",
                                 width = NULL,
                                 autoclose = TRUE
                             ),
                             br()),
                     ),
                     mainPanel(
                         DT::dataTableOutput("my_other_table")
                         
                     )
                 )
                 )
    )
)
server = function(input, output, session) {
    
    #Here's the dataset
    testdata <- tibble(employee = c("Justin", "Corey","Sibley"),
                       project = c("big", "medium", "small"),
                       apr_2021 = c(10, 100, 101),
                       may_2021 = c(1, 4, 7),
                       jun_2021 = c(4, 5, 6),
                       jul_2021 = c(11, 11, 45),
                       aug_2021 = c(4, 5, 7),
                       sep_2021 = c(2, 1, 0),
                       oct_2021 = c(4, 5, 8),
                       nov_2021 = c(4, 1, 1))
    
    select_values <- reactive({

        from_date <- tibble(date = as.character(input$date_filter[1]))
        
        
        from_date <- from_date %>%
            mutate(date = str_remove_all(date, "-..$")) %>%
            separate(date, into = c("year", "month"), sep = "-") %>%
            mutate(month = case_when(
                month == "01" ~ "jan",
                month == "02" ~ "feb",
                month == "03" ~ "mar",
                month == "04" ~ "apr",
                month == "05" ~ "may",
                month == "06" ~ "jun",
                month == "07" ~ "jul",
                month == "08" ~ "aug",
                month == "09" ~ "sep",
                month == "10" ~ "oct",
                month == "11" ~ "nov",
                month == "12" ~ "dec",
                TRUE~ "ERROR"
            )) %>%
            unite("month_year", c(month, year), sep = "_")
        
        from_date <- parse_character(from_date$month_year)
        
        
        
        to_date <- tibble(date = as.character(input$date_filter[2]))
        
        to_date <- to_date %>%
            mutate(date = str_remove_all(date, "-..$")) %>%
            separate(date, into = c("year", "month"), sep = "-") %>%
            mutate(month = case_when(
                month == "01" ~ "jan",
                month == "02" ~ "feb",
                month == "03" ~ "mar",
                month == "04" ~ "apr",
                month == "05" ~ "may",
                month == "06" ~ "jun",
                month == "07" ~ "jul",
                month == "08" ~ "aug",
                month == "09" ~ "sep",
                month == "10" ~ "oct",
                month == "11" ~ "nov",
                month == "12" ~ "dec",
                TRUE~ "ERROR"
            )) %>%
            unite("month_year", c(month, year), sep = "_")  
        
        to_date <- parse_character(to_date$month_year)
        
        testdata %>%
            dplyr::select(employee, project, from_date:to_date)
    })

    
    output$mytable = DT::renderDataTable({
        datatable(select_values() %>%
                      dplyr::select(-project))
    })
    
    output$my_other_table = DT::renderDataTable({
        datatable(select_values() %>%
                      dplyr::select(-employee))
    })

    
}
shinyApp(ui = ui, server = server)



Solution

  • Yes, you should use unique IDs. If you used date_filter2 as the ID in the second tab, you can use updateDateRangeInput as shown below to update it whenever you update the date in the first tab.

    observeEvent(input$date_filter, {
      updateDateRangeInput(session, "date_filter2",
                           label = "Filter by Month and Year",
                           start = input$date_filter[1],
                           end = input$date_filter[2]
      )
    })