Search code examples
shinyshinydashboardshinyappsshiny-reactivity

rShiny Looping on ui filter conditions


I am trying to create a dashboard in rShiny which follow the following steps

  1. Select a parameter
  2. Filter data from a source table for this parameter
  3. Create a list of this filtered data for one of the column
  4. Iterate over this list to display graphs etc... I have tried various options for making this work but the communication between ui and server is not happening as expected

I have created a setup as below fot testing

library(shiny)
df_mtcars <- mtcars
df_mtcars <- cbind(CarName = rownames(df_mtcars), df_mtcars)
df_mtcars$CarName <- sub(" ", "_", df_mtcars$CarName)

select the number of gears Find the cars with that number of gears Create a list of these cars Display the data for each of the car by using loop. Loop is needed as other output types like graphs can be latter added

simpUI <- function(id) {
    tagList(tableOutput(NS(id, "dat_output"))
            numericInput(NS(id, "GearNumber"), "Gear Numbers", 3),
            lapply(seq(1, length(v_lst_CarName), by = 1), function(i) {
                v_CarName = v_lst_CarName[i]
                v_obj_CarName = paste0('sp_cars_', v_CarName)
                tableOutput(NS(id, v_obj_CarName))
            }))
}

simpServer <- function(id) {
    moduleServer(id, function(input, output, session) {
        output$dat_output <- renderTable(df_mtcars)
        v_lst_CarName <-
            reactive(df_mtcars[GearNumber == input$GearNumber]$CarName)
        for (v_CarName in v_lst_CarName)
            v_obj_CarName = paste0('sp_cars_', v_CarName)
        output$v_obj_CarName <- renderTable(v_obj_CarName)
    })
}

ui <- fluidPage(fluidRow(simpUI("cars")))

server <- function(input, output, session) {
    simpServer("cars")
}
shinyApp(ui =  ui, server = server)

Solution

  • It is better to do server side processing. Try this

    library(shiny)
    library(ggplot2)
    df_mtcars <- mtcars
    df_mtcars <- cbind(CarName = rownames(df_mtcars), df_mtcars)
    df_mtcars$CarName <- sub(" ", "_", df_mtcars$CarName)
    
    simpUI <- function(id) {
      ns <- NS(id)
      tagList(tableOutput(ns("dat_output")),
              numericInput(ns("GearNumber"), "Gear Numbers", 3),
              uiOutput(ns("plotxy")),
              tableOutput(ns("v_obj_CarName")),
              verbatimTextOutput(ns("mylist")),
              plotOutput(ns("myplot"))
              )
    }
    
    simpServer <- function(id) {
      moduleServer(id, function(input, output, session) {
        ns <- session$ns
        output$dat_output <- renderTable(head(df_mtcars))
        mydf <- reactive(df_mtcars[df_mtcars$gear == input$GearNumber,])
        v_lst_CarName <-  eventReactive(mydf(), {paste0("sp_cars_",mydf()$CarName)})
        
        output$plotxy <- renderUI({
          req(mydf())
          tagList(
            selectInput(ns("xvar"), label = "X-axis variable", choices = names(mydf()), selected=names(mydf())[2] ),
            selectInput(ns("yvar"), label = "Y-axis variable", choices = names(mydf()), selected=names(mydf())[5] )
          )
        })
        
        output$v_obj_CarName <- renderTable({mydf()})
        output$mylist <- renderPrint(list(v_lst_CarName() ))
        
        output$myplot <- renderPlot({
          req(input$xvar,input$yvar)
          ggplot(mydf(),aes(x=.data[[input$xvar]], y=.data[[input$yvar]])) + geom_point()
        })
      })
    }
    
    ui <- fluidPage(fluidRow(simpUI("cars")))
    
    server <- function(input, output, session) {
      simpServer("cars")
    }
    shinyApp(ui =  ui, server = server)