簡體   English   中英

多個輸入到無功值R Shiny

[英]Multiple inputs to reactive value R Shiny

對於我正在構建的Shiny應用程序的一部分,我需要讓用戶選擇一個目錄。 目錄路徑存儲在一個反應​​變量中。 用戶可以從文件窗口中選擇目錄,也可以通過textInput手動輸入路徑。 我已經想出如何做到這一點,但我不明白為什么我的解決方案有效! 工作應用程序的最小示例:

library(shiny)

ui <- fluidPage(  
   actionButton("button1", "First Button"),
   textInput("inText", "Input Text"),
   actionButton("button2", "Second Button"),
   textOutput("outText"),
   textOutput("outFiles")
)

server <- function(input, output) {
  values <- reactiveValues(inDir = NULL)
  observeEvent(input$button1, {values$inDir <- tcltk::tk_choose.dir()})
  observeEvent(input$button2, {values$inDir <- input$inText})
  inPath <- eventReactive(values$inDir, {values$inDir})
  output$outText <- renderText(inPath())
  fileList <- reactive(list.files(path=inPath()))
  output$outFiles <- renderPrint(fileList())
}

shinyApp(ui, server)

我嘗試的第一件事就是使用eventReactive並將兩個輸入源分配給反應變量:

server <- function(input, output) {
   inPath <- eventReactive(input$button1, {tcltk::tk_choose.dir()})
   inPath <- eventReactive(input$button2, {input$inText})
   output$outText <- renderText(inPath())  
   fileList <- reactive(list.files(path=inPath()))
   output$outFiles <- renderPrint(fileList()) 
} 

據我所知,這種效果只有一個按鈕可以做任何事情。 我真正不明白的是為什么這不起作用。 我認為會發生的第一個按鈕會創建inPath然后后續推送會更新值並觸發對依賴值的更新(這里output$outText )。 到底發生了什么?

我試過的第二件事就是基於這個答案

server <- function(input, output) {
  values <- reactiveValues(inDir = NULL)
  observeEvent(input$button1, {values$inDir <- tcltk::tk_choose.dir()})
  observeEvent(input$button2, {values$inDir <- input$inText})
  inPath <- reactive({if(is.null(values$inDir)) return()
                      values$inDir})
  output$outText <- renderText(inPath())
  fileList <- reactive(list.files(path=inPath()))
  output$outFiles <- renderPrint(fileList())
}

這正常工作,除了它顯示list.files的“錯誤:無效'路徑'參數”消息。 我認為這可能意味着正在使用inPath = NULL評估fileList 為什么當我使用reactive而不是eventReactive時會發生這種情況?

謝謝!

你可以擺脫inPath反應,只需使用values$inDir 使用req()您將等到值可用。 否則你將得到相同的錯誤( 無效的'path'參數 )。

reactive會立即觸發,而eventReactive將等待,直到發生給定事件並調用eventReactive。

if(is.null(values$inDir)) return()將無法正常工作,因為如果values$inDir為NULL,它將返回NULL,然后傳遞給list.files 並且list.files(NULL)給出錯誤: invalid 'path' argument

將其替換為req(values$inDir) ,您將不會收到該錯誤。

你的2 inPath - eventReactive的例子將不起作用,因為第一個將被第二個覆蓋,所以input$button1不會觸發任何東西。

library(shiny)

ui <- fluidPage(  
  actionButton("button1", "First Button"),
  textInput("inText", "Input Text"),
  actionButton("button2", "Second Button"),
  textOutput("outText"),
  textOutput("outFiles")
)

server <- function(input, output) {
  values <- reactiveValues(inDir = NULL)

  observeEvent(input$button1, {values$inDir <- tcltk::tk_choose.dir()})
  observeEvent(input$button2, {values$inDir <- input$inText})
  output$outText <- renderText(values$inDir)

  fileList <- reactive({
    req(values$inDir); 
    list.files(path=values$inDir)
  })

  output$outFiles <- renderPrint(fileList())
}

shinyApp(ui, server)

你也可以使用一個eventReactivebutton1observeEventbutton2 ,但請注意,你需要一個額外的observe({ inPath() })使其工作。 我更喜歡上面的解決方案,因為它更清楚發生了什么,也減少了代碼。

server <- function(input, output) {
  values <- reactiveValues(inDir = NULL)

  inPath = eventReactive(input$button1, {values$inDir <- tcltk::tk_choose.dir()})
  observe({
    inPath()
  })

  observeEvent(input$button2, {values$inDir <- input$inText})
  output$outText <- renderText(values$inDir)

  fileList <- reactive({
    req(values$inDir); 
    list.files(path=values$inDir)
  })

  output$outFiles <- renderPrint(fileList())
}

並說明為什么if(is.null(values$inDir)) return()不起作用,請考慮以下函數:

test <- function() { if (TRUE) return() }
test()

雖然if -condition的計算結果為TRUE ,但仍然會有一個返回值(在這種情況下為NULL ),它將被傳遞給以下函數,在你的例子中是list.files ,這將導致錯誤。

暫無
暫無

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

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