簡體   English   中英

如何將 R Shiny 反應式表達式作為自定義 function 中的默認參數傳遞

[英]How to pass a R Shiny reactive expression as a default argument in a custom function

我正在嘗試將input$myInput文本字段作為預定義參數傳遞給自定義 function。 這對於將來控制文檔 (roxygen2) 的功能 arguments 很重要。

這是一個最小的工作示例:應用程序應將輸入字段綁定到 mtcars 數據集,並將自定義 function my_DTarguments與兩個 arguments(1. 數據,2. 輸入)一起應用:

library(shiny)
library(DT)


#function
my_DTarguments <- function(data, input=input$myInput) {
  
  DT::datatable(
    rownames = FALSE,
    data,
    extensions = 'Buttons',
    options = list(
      dom = 'frtipB',
      buttons = list(
        list(
          extend = 'csv',
          filename = paste0("mydesiredname-", "cyl-", input, "-", Sys.Date())
        ),
      )
    )
  )
}

shinyApp(
  ui <- fluidPage(
    textInput(inputId = "myInput", label = "My Input", placeholder = "a"),
    DT::dataTableOutput("table")
  ),
  
  server <- function(input, output) {

  #  combine mtcars with input field 
   mtcars1 <- reactive({ 
     cbind(mtcars, input$myInput)
     })
   
   # apply function to mtcars1 
    output$table <- DT::renderDataTable(
    my_DTarguments(mtcars1())
    )
    })    
  }
)

多次嘗試后的最后一個錯誤是: promise already under evaluation: recursive default argument reference or earlier problems?

反應式表達式的事情是 Shiny 將它們添加到反應式鏈中,然后將鏈中的所有反應式表達式一一求值。 我們不知道 Shiny 執行此操作的順序。

在您的情況下, Shiny 嘗試評估renderDataTable並通過這樣做調用my_DTarguments() 但是, myInput尚未被評估,因此出現錯誤。

當您使用反應式表達式作為默認 function 參數時,您應該始終在req(...)調用中添加一個(示例: req(input$myInput) )。 但是您仍然必須在從 renderDataTable 調用my_DTarguments()時添加input$myInput renderDataTable 但是如果input$myInput仍然是空的,你會得到一個空列。

或者,您可以在調用my_DTarguments之前確保input$myInput為真。 在這種情況下,只有當input$myInput不為空並且 Shiny 已經對其求值時,該表才會顯示。

我個人認為第二種方法更簡潔。 我建議我們一般不要將反應式表達式用作函數的默認 arguments 當調用者無論如何都必須添加它時,它不僅違反了默認參數的想法。 反應式表達式的工作方式使它們僅在需要時在運行時環境中可用。 但是,只要調用 function,默認參數就應該可用。 這就像在我們的代碼中添加一個預定的斷點……當然,我們不希望這樣。

library(shiny)
library(DT)


#function
my_DTarguments <- function(data, input=req(input$myInput)) {
  DT::datatable(
    rownames = FALSE,
    data,
    extensions = 'Buttons',
    options = list(
      dom = 'frtipB',
      buttons = list(
        #list(
          extend = 'csv',
          filename = paste0("mydesiredname-", "cyl-", input, "-", Sys.Date())
        #),
      )
    )
  )
}

shinyApp(
  ui <- fluidPage(
    textInput(inputId = "myInput", label = "My Input", placeholder = "a"),
    DT::dataTableOutput("table")
  ),
  
  server <- function(input, output) {
    
    #  combine mtcars with input field 
    mtcars1 <- reactive({ 
      cbind(mtcars, input$myInput)
    })
    
    # apply function to mtcars1 
    output$table <- DT::renderDataTable({
      my_DTarguments(mtcars1())
      # Alternative approach: call req() here
      # my_DTarguments(mtcars1(), req(input$myInput))
    })
  }
)

順便說一句,按鈕選項似乎有問題。 我注釋掉了 2 行,以便代碼運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM