[英]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.