R 闪亮 在加载 UI 之前观察运行,这会导致 Null 参数



我遇到了一个问题,因为在 UI 加载之前首先调用了观察。

这是我的用户界面。R

  sidebarPanel(
    selectInput("Desk", "Desk:" ,  as.matrix(getDesksUI())),
    uiOutput("choose_Product"), #this is dynamically created UI
    uiOutput("choose_File1"), #this is dynamically created UI
    uiOutput("choose_Term1"), #this is dynamically created UI  ....

这是我的服务器。

shinyServer(function(input, output,session) {
  #this is dynamic UI
  output$choose_Product <- renderUI({ 
    selectInput("Product", "Product:", as.list(getProductUI(input$Desk)))
  })
   #this is dynamic UI
  output$choose_File1 <- renderUI({
    selectInput("File1", "File 1:", as.list(getFileUI(input$Desk, input$Product)))
  })
  #this is dynamic UI and I want it to run before the Observe function so the call
  # to getTerm1UI(input$Desk, input$Product, input$File1) has non-null parameters
  output$choose_Term1 <- renderUI({
    print("Rendering UI for TERM")
    print(paste(input$Desk," ", input$Product, " ", input$File1,sep=""))
    selectInput("Term1", "Term:", getTerm1UI(input$Desk, input$Product, input$File1))
  })

这是我的观察函数,它在填充输入 $Product 和输入 $File1 之前运行,所以我收到错误,因为它们都是 NULL。 但我需要使用来自 UI 的输入。

   observe({ 
    print("in observe")
    print(input$Product)
    max_plots<-length(getTerm2UI(input$Desk, input$Product, input$File1))
    #max_plots<-5
            # Call renderPlot for each one. Plots are only actually generated when they
            # are visible on the web page.
            for (i in 1:max_plots )   {
              # Need local so that each item gets its own number. Without it, the value
              # of i in the renderPlot() will be the same across all instances, because
              # of when the expression is evaluated.
              local({
               my_i <- i
                plotname <- paste("plot", my_i, sep="")
                output[[plotname]] <- renderPlot({
                  plot(1:my_i, 1:my_i,
                       xlim = c(1, max_plots ),
                       ylim = c(1, max_plots ),
                        main = paste("1:", my_i, ". n is ", input$n, sep = "") )
                })
              })
            }##### End FoR Loop
 },priority = -1000)

知道如何在观察运行之前填充输入 $Product 和输入 $File1?

谢谢。

编辑:向下滚动到克拉维尔的答案以获得更好的解决方案。虽然这个答案的赞成票最多,但我是在 Shiny 的功能比今天少的时候写的。

最简单的方法是在每个观察的顶部添加一个is.null(input$Product)检查,以防止它在初始化它使用的输入之前运行。

如果你不希望你的观察者每次运行时都执行 null-check,你也可以在注册它们时使用 suspended = TRUE 参数来防止它们运行;然后编写一个单独的观察器来执行检查,当它发现所有输入都是非空时,在挂起的观察器上调用 resume() 并挂起自身。

您可以使用

req()在执行反应式表达式之前"需要"输入,根据此处的 Shiny 文档:https://shiny.rstudio.com/articles/req.html 和此处的函数文档:https://shiny.rstudio.com/reference/shiny/latest/req.html

例如

observeEvent({
  req(input$Product)
  req(input$File1)
  # ...
})

您需要使用 Shiny 事件处理程序并使用 observeEvent 而不是 observe 。这似乎是摆脱由应用程序启动时的 NULL 值引起的"未处理的错误"消息的唯一方法。之所以如此,是因为与observe不同,事件处理程序默认忽略 NULL 值。

因此,您的观察功能最终可能会看起来像这样(不需要优先级,或恢复/暂停等!

observeEvent(input$Product, ({
  max_plots<-length(getTerm2UI(input$Desk, input$Product, input$File1))
  ... (etc)      
  })# end of the function to be executed whenever input$Product changes
 )

我无法轻松地复制粘贴您的示例代码以使其运行,所以我不完全确定您的完整观察函数会是什么样子。

我们需要一个 MRE 来提供一个有效的答案,但是,假设你需要input$Productinput$File1,但不想依赖它们,只依赖于input$Desk,你可以:

observe({ 
  product <- isolate(input$Product)
  file1 <- isolate(input$File1)
  print("in observe")
  print(product)
  max_plots<-length(getTerm2UI(input$Desk, product, file1))
  for (i in 1:max_plots )   {
    # ...
  }
})

这可能实际上等同于observeEvent(input$Desk, ....),但可能会提供更大的灵活性。

最新更新