Anon.user111
Anon.user111

Reputation: 508

RShiny: Refer to data from UI in server

Example Case: I have a function in my global.R called get_data which returns a list of many items. The reason I don't just put the data in global is so the data can automatically refresh after a certain amount of time

ui.R

my_data <- uiOutput("data") # Doesn't work
### Some more generic manipulation before final use

# The output of my_data will look like the following below.
my_data <- list()
my_data$first_entry <- c("a", "b", "d")
my_data$second_entry <- c("x", "y", "z") # and so on

shinyUI(navbarPage(theme=shinytheme("flatly"), 
  'App Name',
 tabPanel('Title',
           # Sidebar with a slider input for number of bins
           sidebarLayout(
             sidebarPanel(
               width=3,
            

              
              # new box
              checkboxGroupButtons(
                'name',
                'label:',
                choices = sort(my_data$first_value),
                status = 'primary',
            
                 selected = sort(my_data$first_value)[1],
                size = 'xs'
                # inline = TRUE
              ))





server.R

shinyServer(function(input, output, session) {
  data <- reactive({
    invalidateLater(100000,session)
    
    get_data()
  })

  output$data <- renderUI({
    data()
    })
})

Two questions:

  1. Is there any way of referencing my_data correctly?
  2. If my function get_data is simply reading a (large) csv which is updated systematically. Is there a better way of doing it than I am currently doing it?

Upvotes: 0

Views: 74

Answers (1)

r2evans
r2evans

Reputation: 160407

I think you're wondering how to define possible choices= for something within the UI element, when the data is both (1) undefined at the start, and (2) changing periodically. The answer to that is to define it "empty" and update it as the new data is found.

library(shiny)
library(shinyWidgets)

get_data <- function() as.list(mtcars[sample(nrow(mtcars), size=3), sample(ncol(mtcars), size=3)])
logg <- function(...) message(paste0("[", format(Sys.time()), "] ", ...))

shinyApp(
  ui = fluidPage(
    title = "Hello",
    checkboxGroupButtons(inputId = "cb", label = "label:", choices = c("unk"), selected = NULL,
                         status = "primary", size = "xs"),
    br(),
    textOutput("txt"),
    br(),
    textAreaInput("txtarea", NULL, rows = 4)
  ),
  server = function(input, output, session) {
    data <- reactive({
      logg("in 'data'")
      invalidateLater(3000, session)
      get_data()
    })
    observe({
      logg("in 'observe'")
      req(length(data()) > 0)
      updateCheckboxGroupButtons(session = session, inputId = "cb", choices = names(data()))
      updateTextAreaInput(session, "txtarea", value = paste(capture.output(str(data())), collapse = "\n"))
    })
    output$txt <- renderPrint({
      logg("in 'txt'")
      req(length(data()) > 0)
      str(data())
    })
  }
)

Notice that the definition of checkboxGroupButtons starts with no real choices. I'd prefer to start it empty, but unlike selectInput and similar functions, it does not like starting with an empty vector. It is quickly (nearly-immediately) changed, so I do not see "unk" in the interface.

I demoed two options for "displaying" the data in its raw form: as an output "txt", and as an updatable input "txtarea". I like the latter because it deals well with fixed-width, but it requires an update* function (which is really not a big deal).

Upvotes: 1

Related Questions