0

I need a reactive variable (declared server-side) available after start-up. Using what I learned here How to create a conditional renderUI in Shiny dashboard I tried wrapping in reactive() before defining the UI but no luck. Moving topValuesSelector to the UI inside a conditionalPanel would work except conditional panels apparently do not like the %in% operator (a separate issue that I also tried to resolve w/o success).

if (interactive()) {
  library(shiny)
  library(shinydashboard)
  library(shinydashboardPlus)

  ui <-
    dashboardPage(header = dashboardHeaderPlus(left_menu = tagList(
      dropdownBlock(
        id = "prefDropdown",
        title = "Preferences",
        icon = NULL,
        badgeStatus = NULL,
        checkboxGroupInput(
          inputId = "prefDropdown",
          label = NULL,
          choices = c("Pareto",
                      "Legend on chart",
                      "Cases/1K uniques",
                      "Top 10 only"),
          selected = c("Pareto", "Cases/1K uniques", "Top 10 only")
        ),
        uiOutput("topValues")
      )
    )),
    dashboardSidebar(),
    dashboardBody(fluidRow(box(
      title = "Top",
      textOutput("topN")
    ))))
  server <- function(input, output) {
    topValuesSelector <- reactive({
      if ("Top 10 only" %in% input$prefDropdown) {
        numericInput(
          inputId = "topValues",
          label = NULL,
          width = "25%",
          value = 10,
          min = 1,
          max = 30,
          step = 1
        )
      }
    })
    output$topValues <- renderUI({
      topValuesSelector()
    })

    observe({
      if ("Top 10 only" %in% input$prefDropdown) {
        output$topN <- renderText(input$topValues)
      } else{
        output$topN <- renderText(100)
      }
    })
  }
  shinyApp(ui, server)
}

The intent is for the initial value of "topValues" to be 10 with this value immediately available. However, no value is available which causes an error. Using req() avoids the error by pausing execution but that is not a viable approach because "topValues" is needed for a plot. So no plot until selecting "prefDropdown".

Ron Sokoloff
  • 130
  • 1
  • 11
  • ```==``` is not helpful because ```checkboxGroupInput()``` returns multiple values. Using ```req()``` does not address the problem. I am not getting an error; I am in a quandary because "topValues" is not defined until the user clicks on the drop-down block. – Ron Sokoloff Sep 12 '19 at 20:12
  • Sorry, misread it as a normal selection ... – r2evans Sep 12 '19 at 20:37
  • When I run this code it runs without any error and shows the 10 filled in automatically. Are you sure your error isn't somewhere else in your code? – Adam Sampson Sep 12 '19 at 20:42
  • @AdamSampson: You are seeing a 10 in the text window titled "Top"? – Ron Sokoloff Sep 12 '19 at 20:58
  • Ah, I see what you are saying. This problem is quite hard to follow because I have had to figure out what each step is supposed to look like. Now I can see the issue. – Adam Sampson Sep 13 '19 at 14:53
  • It looks like the problem is that `input$topValues` does not yet exist until you click on Preferences. All you have to do to activate the value is to click on preferences. Interesting. – Adam Sampson Sep 13 '19 at 15:34

1 Answers1

0

It looks like the problem is that input$topValues does not exist until you click on the Preferences button. Since the UI element isn't needed it hasn't been created yet.

In order to work around that you can create a variable that detects whether or not the input is available and if not use a default value.

if (interactive()) {
  library(shiny)
  library(shinydashboard)
  library(shinydashboardPlus)

  ui <-
    dashboardPage(header = dashboardHeaderPlus(left_menu = tagList(
      dropdownBlock(
        id = "prefDropdown",
        title = "Preferences",
        icon = NULL,
        badgeStatus = NULL,
        checkboxGroupInput(
          inputId = "prefDropdown",
          label = NULL,
          choices = c("Pareto",
                      "Legend on chart",
                      "Cases/1K uniques",
                      "Top 10 only"),
          selected = c("Pareto", "Cases/1K uniques", "Top 10 only")
        ),
        uiOutput("topValues")
      )
    )),
    dashboardSidebar(),
    dashboardBody(fluidRow(box(
      title = "Top",
      textOutput("topN")
    ))))
  server <- function(input, output) {
    ## We want to use the same default value in two places so create a var
    default_value <- 10
    topValuesSelector <- reactive({
      if ("Top 10 only" %in% input$prefDropdown) {
        numericInput(
          inputId = "topValues",
          label = NULL,
          width = "25%",
          value = default_value, ## Change to use the default value
          min = 1,
          max = 30,
          step = 1
        )
      }
    })
    output$topValues <- renderUI({
      topValuesSelector()
    })
    ## Create a variable that is the default value unless the input is available
    myTopN <- reactive({
      if(length(input$topValues)>0){
        return(input$topValues)
      }
      return(default_value)
    })
    observe({
      if ("Top 10 only" %in% input$prefDropdown) {
        # output$topN <- renderText(input$topValues)
        output$topN <- renderText(myTopN()) ## Use our new variable instead of the input directly
      } else{
        output$topN <- renderText(100)
      }
    })
  }
  shinyApp(ui, server)
}

There are a couple of other things going on with your code. Notice that "Top 10 only" %in% input$prefDropdown will not do what you think it is doing. You have to check to see if "Top 10 only" is TRUE... I'll leave you there to start another question if you get stuck again.

Adam Sampson
  • 1,971
  • 1
  • 7
  • 15