0

First of all, I am so sorry if the main question (the title) of the post is not clearly enough. I didn't how to write a question with my problem.

Well, the thing is that I have two select inputs. The main one: Dataset, which have 2 options: 1) Cars and 2) Iris. The other select input, it has information from the Cars' dataset and information from the Iris one.

I need to show the information from Cars if I select Cars and the information from Iris if I select Iris.

Now, my code is not able to do that. Simply it shows you the options to choose the datasets but in the second select input only shows the information from Cars.

I don't know how to do it, I have been a lot of posts but I couldn't get what I want. For example this post Filter one selectInput based on selection from another selectInput? was very similar and I thought that I could do something similar, but he doesn't use a dataset from R...

My code:

library(shiny)
ui <- fluidPage(
  
  titlePanel("Select a dataset"),
  
  sidebarLayout(
    sidebarPanel(
      selectInput("dataset", "Dataset",
                  choices = c("Cars" = "Cars", "Iris" = "Iris")),
      uiOutput("select_cars"),
      uiOutput("select_iris")
      
    ),
    
    mainPanel(
      verbatimTextOutput("text"),
      verbatimTextOutput("text2") 
    )
  )
)

server <- function(input, output) {
  
  cars <- reactive({
    data("mtcars")
    cars <- rownames(mtcars)
    return(cars)
  })
  
  iris <- reactive({
    data("iris")
    iris <- data.frame(unique(iris$Species))
    colnames(iris) <- "iris"
    return(iris)
  })
  
  output$select_cars <- renderUI({
    selectInput(inputId = "options_cars", "Select one", choices = cars())
  })

  output$select_iris <- renderUI({
    selectInput(inputId = "options_iris", "Select one iris", choices = iris())
  })

  output$text <- renderPrint(input$options_cars)
  output$text2 <- renderPrint(input$options_iris)
}

#Run the app
shinyApp(ui = ui, server = server)

On the other hand I get an error: object of type ‘closure’ is not subsettable. But I don't know why.

Finally, I apologize if someone has already asked something similar before, I really have been looking all morning and I do not know how to solve it. (I am quite new at Shiny and I am trying to do my best).

Thanks very much in advance,

Regards

Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
emr2
  • 1,436
  • 7
  • 23

2 Answers2

1

I have modified some of your code and added some JS functionality from shinyjs, which you may or may not find useful

  • You don't really need to create objects all the time if you only going to update the list, so we are going to use updateSelectInput to update the sliders
  • I used hidden functionality to hide the elements initially so they are invisible to begin with
  • I created dependency on input$dataset within observeEvent so we can update the sliders and hide and show both the sliders we dont want and the output we dont want
  • Also if your datasets are static, like mtcars and iris its best to take them outside the server.R so you dont do extra unnecessary work
  • Finally its always a good idea to add req so you're not creating any objects if they are NULL
  • Your original error was due to the fact that you were passing the dataframe and not the list or vector to the slider, try to print out the objects if you're unsure and see their types

library(shiny)
library(shinyjs)

ui <- fluidPage(
    titlePanel("Select a dataset"),
    useShinyjs(),
    
    sidebarLayout(
        sidebarPanel(
            selectInput("dataset", "Dataset",
                        choices = c("Cars" = "Cars", "Iris" = "Iris")),
            hidden(selectInput(inputId = "options_cars", "Select one", choices = NULL)),
            hidden(selectInput(inputId = "options_iris", "Select one iris", choices = NULL))
            
        ),
        mainPanel(
            verbatimTextOutput("text_cars"),
            verbatimTextOutput("text_iris") 
        )
    )
)

cars_data <- unique(rownames(mtcars))
iris_data <-  as.character(unique(iris$Species))

server <- function(input, output, session) {
    
    observeEvent(input$dataset,{
        if(input$dataset == "Cars"){
            show('options_cars')
            hide('options_iris')
            show('text_cars')
            hide('text_iris')
            updateSelectInput(session,"options_cars", "Select one", choices = cars_data)
        }else{
            show('options_iris')
            hide('options_cars')
            show('text_iris')
            hide('text_cars')
            updateSelectInput(session,"options_iris", "Select one iris", choices = iris_data)
        }
    })
    
    output$text_cars <- renderPrint({
        req(input$options_cars)
        input$options_cars
    })
    
    output$text_iris <- renderPrint({
        req(input$options_iris)
        input$options_iris
    })
}

#Run the app
shinyApp(ui = ui, server = server)
Pork Chop
  • 28,528
  • 5
  • 63
  • 77
  • Thanks very much!! You can't imagine how grateful I am right now. Thanks very much really. I have seen a lot of times that people usually use the `shinyjs` package, but I don't really know how it works. I am learning shiny with this [book](https://mastering-shiny.org/) and others tutorials, but I tried to find this package in the book and it is not there. Could you send me some sources to learn more about it? Thanks in advance!!! – emr2 Apr 09 '21 at 10:25
  • 1
    Hadley is really good, I think they finalized that book now, I think the `shinyjs` package isn't there is because it's not `official` release from shiny team, so he tried to stay with just the original codebase. The best way to learn is by doing it, official docs is all you really need https://shiny.rstudio.com/ – Pork Chop Apr 09 '21 at 10:30
1

Here is a code that allows the switch by selectInput

library(shiny)
library(datasets)
ui <- fluidPage(
  
  titlePanel("Select a dataset"),
  
  sidebarLayout(
    sidebarPanel(
      selectInput("dataset", "Dataset",
                  choices = c("Cars" = "Cars", "Iris" = "Iris")),
##------removed this---------------
    #  uiOutput("select_cars"),
      #uiOutput("select_iris")
##------------------------------
    uiOutput("select_by_input") 
    ),
    
    mainPanel(
      verbatimTextOutput("text")
     # verbatimTextOutput("text2") 
    )
  )
)

server <- function(input, output) {
  
  cars <- reactive({
    data("mtcars")
    cars <- rownames(mtcars)
    return(cars)
  })
  
  iris <- reactive({
   # data("iris")
   # iris <- data.frame(unique(iris$Species))
    data('iris')
    #colnames(iris) <- "iris"
 # iris_names <- as.character(unique(iris$Species) )
    iris_names <- c('a','b','c')
    return(iris_names)
  })
##------removed this---------------  
  # output$select_cars <- renderUI({
  #   selectInput(inputId = "options_cars", "Select one", choices = cars())
  # })
  # 
  # output$select_iris <- renderUI({
  #   selectInput(inputId = "options_iris", "Select one iris", choices = iris())
  # })
#-----------------------------  
  
   output$select_by_input <- renderUI({
     if (input$dataset=='Cars'){
       selectInput(inputId = "options_x", "Select one", choices = cars())
     }else if (input$dataset=='Iris'){
       selectInput(inputId = "options_x", "Select one iris", choices = iris())
     }
   
   })
  
  output$text <- renderPrint(input$options_x)

}

#Run the app
shinyApp(ui = ui, server = server)

the object of type ‘closure’ is not subsettable. error is caused by the iris data not being loaded after running the app. I used iris_names <- c('a','b','c') to demonstrate the dynamic change by selectInput

Keniajin
  • 1,649
  • 2
  • 20
  • 43