Zizou
Zizou

Reputation: 503

Multiple reactive selectinput based on another in R shiny

I am using the code below to allow multiple selected inputs to react to each other. So, when one is changed, the values in the other fields should be updated. However, I have a problem with that, from what I read here I am supposed to use updateSelectInput but I don't know how, can anyone help me? When I choose aa category and then source everything is ok, but when I add bb category then the sources go back to their initial values.

This is my code:

library(shiny)
library(shinydashboard)
library(magrittr)
library(dplyr)
library(DT)
library(lubridate)
library(tidyr)


DATE = rep(seq(as.Date('2018/01/01'), as.Date('2018/03/01'), by = "day"), each = 4, 3)
CATEGORY = rep(c('aa', 'bb'), each = 360)
SOURCE = rep(c("A", "B", "C", "D"), 180)
REVENUE = as.numeric(sample(c(1000:2000), 720, replace = T)) 
PLAN = 1500
WEEKDAYS <- weekdays(DATE)
MONTH = months(DATE)
df <- data.frame(DATE, WEEKDAYS, MONTH, CATEGORY, SOURCE, REVENUE, PLAN)

is.not.null <- function(x)
  ! is.null(x)

ui <- fluidPage(titlePanel("Test revenue"),
                sidebarLayout(
                  sidebarPanel(
                    uiOutput("month"),
                    uiOutput("category"),
                    uiOutput("sources")
                    
                  ),
                  mainPanel(tabsetPanel(
                    type = "tabs",
                    tabPanel("Revenue",
                             DT::dataTableOutput("table_subset_revenue"))
                    
                  ))
                ))

################################################

server = shinyServer(function(input, output) {
  data <- df
  
  output$table <- DT::renderDataTable({
    if (is.null(data)) {
      return()
    }
    DT::datatable(data, options = list(scrollX = T))
  })
  
  output$month <- renderUI({
    selectInput(
      inputId = "MONTH",
      "Select month",
      choices = var_month(),
      multiple = F
    )
  })
  output$category <- renderUI({
    selectInput(
      inputId = "CATEGORY",
      "Select category",
      choices = var_category(),
      multiple = T
    )
  })
  output$sources <- renderUI({
    selectInput(
      inputId = "SOURCE",
      "Select source",
      choices = var_source(),
      multiple = T
    )
  })
  
  data_filtered_revenue <- reactive({
    filter(df,
           MONTH %in% month(),
           CATEGORY %in% category(),
           SOURCE %in% sources()) %>%
      group_by(DATE, WEEKDAYS, MONTH) %>%
      summarise(Revenue = sum(REVENUE),
                Plan = sum(PLAN)) %>%
      ungroup() %>%
      mutate(Revenue_cum = cumsum(Revenue),
             Plan_cum = cumsum(Plan)) 
      
  })
  
  ######################################################################################
  
  month <- reactive({
    if (is.null(input$MONTH))
      unique(df$MONTH)
    else
      input$MONTH
  })
  
  category <- reactive({
    if (is.null(input$CATEGORY))
      unique(df$CATEGORY)
    else
      input$CATEGORY
  })
  
  sources <- reactive({
    if (is.null(input$SOURCE))
      unique(df$SOURCE)
    else
      input$SOURCE
  })
  
  var_month <- reactive({
    file1 <- data
    if (is.null(data)) {
      return()
    }
    as.list(unique(file1$MONTH))
  })
  
  var_category <- reactive({
    filter(data, MONTH %in% month()) %>%
      pull(CATEGORY) %>%
      unique()
  })
  
  var_source <- reactive({
    filter(data, MONTH %in% month(), CATEGORY %in% category()) %>%
      pull(SOURCE) %>%
      unique()
  })
  
  output$table_subset_revenue <- DT::renderDataTable({
    DT::datatable(data_filtered_revenue())
  })
  
  
})

shinyApp(ui, server)

Upvotes: 0

Views: 385

Answers (1)

Gerda
Gerda

Reputation: 43

Set choices to NULL within renderUI and update it via updateSelectInput while keeping the current selection:

 output$sources <- renderUI({
    selectInput(
      inputId = "SOURCE",
      "Select source",
      choices = NULL,
      multiple = T
    )
  })
  
  observeEvent(var_source(),{
  updateSelectInput(
    inputId = "SOURCE",
    choices = var_source(),
    selected = input$SOURCE
  )
  })

Upvotes: 1

Related Questions