0

actually I'm working for the first time on a shiny app.

Based on an uploaded xlsx, the shiny app creates an reactive output called garnetRF(). Based on the number of differently named samples in the uploaded xlsx, the app creates dynamic tabs in output$tabp. In the tabs, the user can pick a color to be displayed for each sample. So far, so good.

Now, in the ouput$setting I want to plot the results with the colors the user picked. Thus, my idea was to rename the sample levels (cls.0) by the picked color names (cls.1). However, when performing the code as following, print(cls.1) shows me empty lists and the vector including the color codes. I guess this is because the colorInput is nested in the dynamic tab list.

Does anyone know how to extract the color vector only?

output$tabp <- renderUI({
    req(garnetRF())
    l = length(unique((garnetRF()[,"sample"])))
    
    myTabs <- lapply(1:l, function(i) {
      tabPanel(title = as.list(factor(unique(garnetRF()[,"sample"])))[[i]],
               colourInput(paste0("col_", i), NULL, paste0("FF000", i), showColour = "background")
      )
    })
    do.call(tabsetPanel, myTabs)
  })
  
  output$setting <- renderPlot({
    req(garnetRF())
    l2 = length(unique((garnetRF()[,"sample"])))
    cls.0 = factor(garnetRF()[,"sample"])
    cls.1 = sapply(1:l2, function(j){input[[paste0("col_", j)]]})
    print(cls.1)

Result:

[[1]]
NULL

[[2]]
NULL

[[3]]
NULL

[1] "#FF0001" "#FF0002" "#FF0003"

Here is a minimally reproducable example:

ui <- fluidPage(
  
  titlePanel("Example"),
  
  fluidRow(
    column(8,
           plotOutput("setting"),
    ),
    column(4,
           uiOutput("tabp")
    )
  )
)
server <- function(input, output) {
  
  garnetRF <- reactive({
    mydata = data.frame(
      "sample" = c("example1", "example2", "example3"),
      "A" = (c(30, 30, 30)),
      "B" = (c(40, 30, 20)),
      "C" = (c(30, 40, 50)))
    return(mydata)
  })
  
  output$tabp <- renderUI({
    req(garnetRF())
    l = length(unique((garnetRF()[,"sample"])))
    
    myTabs <- lapply(1:l, function(i) {
      tabPanel(title = factor(unique(garnetRF()[,"sample"]))[[i]],
               colourInput(paste0("col_", i), NULL, paste0("FF000", i), showColour = "background")
      )
    })
    do.call(tabsetPanel, myTabs)
  })
  
  output$setting <- renderPlot({
    req(garnetRF())
    l2 = length(unique((garnetRF()[,"sample"])))
    cls.0 = factor(garnetRF()[,"sample"])
    cls.1 = sapply(1:l2, function(j){input[[paste0("col_", j)]]})
    print(cls.1)
    
    #plot following
    })
}
mee1988
  • 3
  • 3
  • Welcome to SO. Please post a minimally reproducible example code with some sample data: https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example. – YBS Nov 24 '20 at 14:20
  • Thanks. I added a reproducable example.... – mee1988 Nov 24 '20 at 16:49

1 Answers1

0

You need a req() as shown below when defining cls.1.

output$setting <- renderPlot({
    req(garnetRF())
    l2 = length(unique((garnetRF()[,"sample"])))
    cls.0 = factor(garnetRF()[,"sample"])
    cls.1 <- sapply(1:l2, function(j){req(input[[paste0("col_", j)]])})
    print(cls.1)
    
    #plot following
    output$plot1 <- renderPlot(plot(cars))
  })
YBS
  • 19,324
  • 2
  • 9
  • 27
  • That works perfectly!!!! Thank you soo much!!! Could you briefly explain why a req() is necessary? – mee1988 Nov 24 '20 at 19:19
  • Initial value of `input$col_1` is `NULL`. With `req()`, `cls.1` is not defined until `input$col_1` is defined (same for all col_j). Please see here for more on `req()`: https://shiny.rstudio.com/reference/shiny/latest/req.html – YBS Nov 24 '20 at 19:26