2016-09-25 69 views
1

我有一個複雜的Shiny應用程序。我有一個selectize輸出對象,selectTest,它的值由反應對象isTestReady讀取。 isTestReady評估某些條件是否滿足selectTestisTestReady然後用於各種塊作爲門。我已將selectTest設置爲outputOptions(suspendWhenHidden = F, priority 999)以確保它立即啓動並運行。強制反應塊進行評估

在運行時,我注意到selectTest的塊首先被執行。當isTestReady在此之後運行時,它仍將selectTest的值讀取爲NULL,而不是在第一個塊中分配給selectTest的任何值。在返回重新評估isTestReady之前,Shiny會經過許多其他模塊。重新評估後,其他塊再次被調用,現在它們運行良好。

這是預期的行爲?如果是這樣,那麼關於如何讓我的場景按照我描述的方式發揮作用?

實施例 -

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) 

的日誌輸出到控制檯用於上述應用如下所示 -

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

任何方式,以避免NULL?在我的應用程序中,有很多塊查找temp(),所有這些塊都在temp()之前運行。

+0

相關,但不是一個解決方案 - http://stackoverflow.com/questions/30378310/shiny-renderui-selectinput-returned-null?rq=1 – TheComeOnMan

+1

可以綁定'eventReactives'也與其他反應。像這樣:'eventReactives {temp(),{}}'。 –

+0

@PorkChop,我正在基於'temp()創建新的輸出對象,所以'eventReactive'不是一個選項。除非我做雜亂的「本地」等業務。 – TheComeOnMan

回答

0

嘗試使用observe()和reactiveValues(),請參閱接受的答案this question。 reactive()是懶惰的。

我編輯了你的問題,所以你的文本中的變量名稱與你的代碼匹配。但我可能想念你。像這樣?

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) 
+0

謝謝。這個建議與我在評論中提到的鏈接類似。 – TheComeOnMan

0

只需使用validate在每個反應塊來檢查所有需要的投入和條件。然後,您的服務器功能會是這個樣子

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()) 
    '-' 
    }) 

} 
+0

謝謝。這看起來有希望。我會在我的應用程序中檢查一次(這可能需要我一兩天)。我會檢查標記答案,如果它的工作。 – TheComeOnMan

+0

我有一種感覺,這基本上阻止了其他觀察塊的執行,因爲temp的NULL值,並且實際上並沒有強制執行temp的評估。 – TheComeOnMan