David Chris
David Chris

Reputation: 255

Facing issues with renderUI in Shiny in R

I am trying to create a Shiny App and I am facing issues with respect to the Usage of renderUI. Kindly find the below code which I used creating the shiny app. Here is the UI Script and the sample data frame.

library(shiny)
library(tidyverse)
library(data.table)
library(ggplot2)

Source_Data <-
data.frame(
key = c(1, 1, 1, 2, 2, 2, 3, 3, 3),
Product_Name = c(
  "Table",
  "Table",
  "Chair",
  "Table",
  "Bed",
  "Bed",
  "Sofa",
  "Chair",
  "Sofa"
),
Product_desc = c("XX", "XXXX", "YY", "X", "Z", "ZZZ", "A", "Y", "A"),
Cost = c(1, 2, 3, 4, 2, 3, 4, 5, 6)
)

ui <- fluidPage(titlePanel("Demo"),
            sidebarLayout(
              sidebarPanel(
                sliderInput(
                  "key",
                  "keys",
                  min = 1,
                  max = 3,
                  value = c(1, 3),
                  step = 1
                ),
                selectInput("Product", "List of Products", choices = NULL),
                uiOutput("sublist")
              ),
              mainPanel(tabsetPanel(
                type = "tabs",
                tabPanel("table_data", DT::dataTableOutput("table")),
                tabPanel("Visualizing Data", plotOutput("plot"))
              ))

            ))

Here is the Server R script

server <- function(input, output, session) {
observe({
x <-
  Source_Data %>% filter(key %in% input$key) %>% select (Product_Name)
updateSelectInput(session, "Product", "List of Products", choices =
                    unique(x))
})

#### Using render UI here #######

output$sublist <- renderUI({
tagList(
  z <- Source_Data %>% filter(key %in% input$keys & Product_Name %in%
                                input$Product) %>% select (Product_desc),
  checkboxGroupInput("sublist_1", "Descriptions", z)
)
})


output_func <- reactive({
key_input <- input$key
Product_input <- input$Product
cat_input <- input$sublist

d <- Source_Data %>% dplyr::select(key,
                                   Product_Name,
                                   Product_desc,
                                   Cost) %>% dplyr::filter (key %inrange% 
key_input,
                                                            Product_Name == 
Product_input,
                                                            Product_desc == 
cat_input)
return(d)
})

output$table1 <-
DT::renderDataTable({
  output_func()
})

output$plot <-
renderPlot({
  ggplot(output_func(), aes (key, cost, fill = Product_desc))
})
}

shinyApp(ui = ui, server = server)

Here the Variable key will be in the form of a Slider Input and Depending upon the Selected Key/Keys, I display the product names in a Dropdown list. Now with render UI What i am trying to do is depending upon the selected product name I want the product descriptions to be displayed in the form of a Checkbox. So that I can select the single/Multiple checkboxes and change the table and plot displays Dynamically.

In such a way that the Product Descriptions will change for each product name under Each each key value. Also if i have not selected any product name then no check boxes should be appearing.

But when i try to do this, I fail very badly and also I am getting error "Error in : Result must have length 9, not 0"

Any help on how to proceed further on this will help me a lot. Thanks in Advance.

Upvotes: 1

Views: 588

Answers (1)

Ben
Ben

Reputation: 30474

Maybe this has been fixed by now, but just in case here is a working solution.

A few issues were identified:

  • There were a number of typos for variables. For example, you want input$key not input$keys, input$sublist_1 instead of input$sublist, output$table instead of output$table1, Cost (capital 'C') instead of cost, etc.
  • When subsetting your Source_Data use pull instead of select to provide a vector of checkbox options to checkboxGroupInput
  • In output_func use req for inputs as recommended to require key, Product, and sublist_1 before trying to subset Source_Data
  • Subsetting data in output_func you may want Product_desc %in% cat_input to address multiple checkboxes checked at one time, so not comparing a string with a vector of strings
  • I altered your ggplot a bit for the example, but I noticed you have a separate open question for that

Here is the server code:

server <- function(input, output, session) {
  observe({
    x <- Source_Data %>% 
           filter(key %in% input$key) %>% 
             select (Product_Name)
    updateSelectInput(session, "Product", "List of Products", choices = unique(x))
  })

  #### Using render UI here #######

  output$sublist <- renderUI({
    z <- Source_Data %>% 
      filter(key %in% input$key & Product_Name %in% input$Product) %>% 
        pull (Product_desc)
    tagList(
      checkboxGroupInput("sublist_1", "Descriptions", z)
    )
  })


  output_func <- reactive({
    req(input$key, input$Product, input$sublist_1)

    key_input <- input$key
    Product_input <- input$Product
    cat_input <- input$sublist_1

    d <- Source_Data %>% 
      dplyr::select(key,
                     Product_Name,
                     Product_desc,
                     Cost) %>% 
      dplyr::filter (key %inrange% key_input,
                    Product_Name == Product_input,
                    Product_desc %in% cat_input)

    return(d)
  })

  output$table <-
    DT::renderDataTable({
      output_func()
    })

  output$plot <-
    renderPlot({
      output_func() %>%
        ggplot(aes(Product_Name, Cost)) + 
        geom_col(aes(fill = Product_desc), position = position_dodge(preserve = "single"))
    })
}

I hope this is helpful - let me know if this is what you had in mind. Good luck!

Upvotes: 3

Related Questions