2

I have a complex Shiny app. I have a selectize output object, selectTest, the value of which is read by a reactive object, isTestReady. isTestReady evaluates whether certain conditions are satisfed by selectTest. isTestReady is then used in various chunks as a gate. I have set selectTest as outputOptions(suspendWhenHidden = F, priority 999) to ensure it gets up and running immediately.

On running, I notice the chunk for selectTest gets executed first. When isTestReady runs after this, it still reads the value of selectTest as NULL instead of whatever value that was assigned to selectTest in the first chunk. Shiny then goes through many of the other modules before returning to re-evaluate isTestReady. After the re-evaluation, the other chunks are called again and now they run fine.

Is that expected behaviour? If so, any ideas on how to make my scenario play the way I described it?

Example -

library(shiny)
library(shinydashboard)


# Setup Shiny app UI components -------------------------------------------

ui <- dashboardPage(

   dashboardHeader(),
   ## Sidebar content
   dashboardSidebar(
      sidebarMenu(
         uiOutput('someelement'),
         textOutput('temp2')
      )
   ),
   dashboardBody(  )

)


# Setup Shiny app back-end components -------------------------------------

server <- function(input, output) {

   output[['someelement']] = renderUI({
      selectizeInput(
         inputId = 'someelement',
         choices = letters,
         selected = letters[1],
         label = 'Custom Functions',
         multiple = F
      )
   })

   outputOptions(
      output,
      'someelement',
      suspendWhenHidden = F
   )

   temp = reactive({
      print('?')
      input[['someelement']]
   })

   observe({
      print('!')
      print(temp())
   })

   output[['temp2']] = renderText({
      print('!!')
      print(temp())
      '-'
   })

}

# Render Shiny app --------------------------------------------------------

shinyApp(ui, server)

The logs output to the console for the above app look as follows -

[1] "!"
[1] "?"
NULL
[1] "!!"
NULL
[1] "!"
[1] "?"
[1] "a"
[1] "!!"
[1] "a"

Any way to avoid that NULL? In my app, there are a lot of chunks that look for temp(), all of which run before temp().

TheComeOnMan
  • 12,535
  • 8
  • 39
  • 54
  • Related but not a solution - http://stackoverflow.com/questions/30378310/shiny-renderui-selectinput-returned-null?rq=1 – TheComeOnMan Sep 25 '16 at 14:18
  • 1
    You can bind `eventReactives` with other reactives too. Like so:`eventReactives{temp(), {}}`. Also you can have multiple of them in there too – Pork Chop Sep 25 '16 at 15:00
  • @PorkChop, I'm creating new output objects based on `temp()` so `eventReactive` isn't an option. Unless I do the messy `local`, etc. business. – TheComeOnMan Sep 25 '16 at 17:13

2 Answers2

0

try using observe() and reactiveValues(), see the accepted answer to this question. reactive() is lazy.

I edited your question so variable names in your text match you code. But I might have miss you point. Something like this?

library(shiny)
library(shinydashboard)


# Setup Shiny app UI components -------------------------------------------

ui <- dashboardPage(

  dashboardHeader(),
  ## Sidebar content
  dashboardSidebar(
    sidebarMenu(
      uiOutput('ui_selectTest') 
    )
  ),
  dashboardBody(  )

)


# Setup Shiny app back-end components -------------------------------------

server <- function(input, output) { 

  rv<- reactiveValues()

  output$ui_selectTest = renderUI({
    selectizeInput(
      inputId = 'selectTest',
      choices = letters,
      selected = letters[1],
      label = 'Custom Functions',
      multiple = F
    )
  })

  observe(
    if(!is.null(input$selectTest)) { 
      #check select test
      rv$testReady <- input$selectTest
    }
  )

  observeEvent(rv$testReady,{
    print(  rv$testReady  )
  })
} 

shinyApp(ui, server)
Community
  • 1
  • 1
Eduardo Bergel
  • 2,685
  • 1
  • 16
  • 21
0

Just use validatein each of your reactive chunks to check for all needed inputs and conditions. Your server function would then look something like this

server <- function(input, output) {

  output[['someelement']] = renderUI({
    selectizeInput(
      inputId = 'someelement',
      choices = letters,
      selected = letters[1],
      label = 'Custom Functions',
      multiple = F
    )
  })

  outputOptions(
    output,
    'someelement',
    suspendWhenHidden = F
  )

  temp = reactive({
    #check if someelement is a valid input
    validate(need(input[['someelement']] %in% letters, "need input")) 
    print('?')
    input[['someelement']]
  })

  observe({
    #check if tmp() has already been evaluated
    validate(need(temp(), "need tmp"))  
    print('!')
    print(temp())
  })

  output[['temp2']] = renderText({
    validate(need(temp(), "need tmp"))
    print('!!')
    print(temp())
    '-'
  })

}
wici
  • 1,681
  • 1
  • 14
  • 21
  • Thanks. This looks promising. I'll check this on my app once (which might take me a day or two). I'll check mark the answer if it work. – TheComeOnMan Sep 25 '16 at 17:13
  • 1
    I have a feeling this basically blocks the execution of the rest of the observe chunk because of temp's NULL value, and doesn't actually force the evaluation of temp. – TheComeOnMan Sep 25 '16 at 17:39