Search code examples
rshinyr6

Use selectInput() choice to select data in a R6 Class


I am trying to understand how I can use R6 Class Objects in a Shiny app and I wanted to render data in a R6 Object using a selectInput() choice. The select input choices contains the names of my R6 Objects.

I have the following objects:

library(R6)
Person <- R6Class("Person", list(
  name = NULL,
  age = NA,
  sons = NA,
  initialize = function(name, age = NA, sons = NA) {
    self$name <- name
    self$age <- age
    self$sons <- sons
  }
))

Manel <- Person$new("Manel", age = 42, sons = c('Joana', 'Gabriel'))
Carla <- Person$new("Maria", age = 44, sons = NA)
Matilde <- Person$new("Matilde", age = 52, sons = c('Bruno', 'Joana', 'Maria'))

In my Shiny app I have a selectInput() with choices Manel, Carla, Matilde. What I need is that when I select a choice I render the values for the object with the name I selected in the selectInput(). The Shiny app below:

library(shiny)
ui <- fluidPage(
  sidebarPanel(
    selectInput('names', 'Names', choices = c('Manel', 'Carla', 'Matilde'))
    ),
  mainPanel(
    uiOutput('name'),
    uiOutput('age'),
    uiOutput('sons')
  )
)

server <- function(input, output, session) {
  output$name <- renderText(Manel$name)
  output$age <- renderText(Manel$age)
  output$sons <- renderText(Manel$sons)
}

shinyApp(ui, server)

Thanks!


Solution

  • The input$names will always just turn a character value. To get the value of a variable from it's name as a character you can use the get() function. Here we can wrap that in a reactive object so we always have access to the "current" person for the reactive output. We can do

    server <- function(input, output, session) {
      person <- reactive(get(input$names))
    
      output$name <- renderText(person()$name)
      output$age <- renderText(person()$age)
      output$sons <- renderText(person()$sons)
    }
    

    Alternatively it probably makes more sense to store your people in a named list rather than a bunch of variables. For example

    people <- list(
      Manel = Person$new("Manel", age = 42, sons = c('Joana', 'Gabriel')),
      Carla = Person$new("Carla", age = 44, sons = NA),
      Matilde = Person$new("Matilde", age = 52, sons = c('Bruno', 'Joana', 'Maria'))
    )
    

    Then you can use the character value form the select just to index the named list rather than using get().

    server <- function(input, output, session) {
      person <- reactive(people[[input$names]])
    
      output$name <- renderText(person()$name)
      output$age <- renderText(person()$age)
      output$sons <- renderText(person()$sons)
    }