【问题标题】:observeEvent Shiny function used in a module does not work模块中使用的 observeEvent Shiny 函数不起作用
【发布时间】:2017-12-23 12:06:15
【问题描述】:

我正在开发一个应用程序,我在其中使用模块来显示不同选项卡的 ui 内容。但是,该模块似乎不与主(或父)应用程序通信。它显示正确的 ui,但在单击 actionButton 时无法执行 observeEvent 函数,它应该更新当前选项卡并显示第二个选项卡。

在我的代码中,我创建了一个命名空间函数并将actionButton 的ID 包装在ns() 中,但是它仍然不起作用。有谁知道怎么回事?

library(shiny)

moduleUI <- function(id){

  ns <- NS(id)
      sidebarPanel(

        actionButton(ns("action1"), label = "click")
      )
}

module <- function(input, output, session){


  observeEvent(input$action1, {
    updateTabItems(session, "tabsPanel", "two")
  })
}

ui <- fluidPage(

            navlistPanel(id = "tabsPanel",

                         tabPanel("one",moduleUI("first")),
                         tabPanel("two",moduleUI("second"))
))
server <- function(input, output, session){
  callModule(module,"first")
  callModule(module,"second")

}

shinyApp(ui = ui, server = server)

【问题讨论】:

    标签: r module shiny shiny-server


    【解决方案1】:

    observeEvent 可以工作,但由于模块只能看到和知道作为输入参数提供给它们的变量,它不知道指定的 tabsetPanel,因此无法更新它。这个问题可以使用响应式值来解决,该值作为参数传递并在模块内部进行更改。一旦更改,主应用程序就知道它并可以更新 tabsetPanel:

    library(shiny)
    library(shinydashboard)
    
    moduleUI <- function(id){
    
      ns <- NS(id)
      sidebarPanel(
        actionButton(ns("action1"), label = "click")
      )
    }
    
    module <- function(input, output, session, tabsPanel, openTab){
    
      observeEvent(input$action1, {
        if(tabsPanel() == "one"){  # input$tabsPanel == "one"
          openTab("two")
        }else{                     # input$tabsPanel == "two"
          openTab("one")
        }
      })
    
      return(openTab)
    }
    
    ui <- fluidPage(
      h2("Currently open Tab:"),
      verbatimTextOutput("opentab"),
      navlistPanel(id = "tabsPanel",
                   tabPanel("one", moduleUI("first")),
                   tabPanel("two", moduleUI("second"))
      ))
    
    
    server <- function(input, output, session){
      openTab <- reactiveVal()
      observe({ openTab(input$tabsPanel) }) # always write the currently open tab into openTab()
    
      # print the currently open tab
      output$opentab <- renderPrint({
        openTab()
      })
    
      openTab <- callModule(module,"first", reactive({ input$tabsPanel }), openTab)
      openTab <- callModule(module,"second", reactive({ input$tabsPanel }), openTab)
    
      observeEvent(openTab(), {
        updateTabItems(session, "tabsPanel", openTab())
      })
    }
    
    shinyApp(ui = ui, server = server)
    

    【讨论】:

    • 感谢您的帮助 shosaco,我现在对正在发生的事情有了更好的了解。然而,这个解决方案似乎只工作一次。如果单击按钮,然后返回第一个选项卡并重新单击它,则没有任何反应
    • 是的,这只是一个小例子,我们只是将打开的选项卡更改为“两个”,而从未返回到一个。相应地更新了我的示例。技巧:为模块提供有关当前打开选项卡的信息(input$tabsPanel),但是,这必须包装为反应式,我称之为tabsPanel。然后,模块可以通过调用tabsPanel() 始终知道打开的选项卡。这里解释一下:rstudio.com/resources/webinars/understanding-shiny-modules(42:15左右)
    • 我无法在我的代码中实现 input$tabsPanel,以便应用程序始终知道它位于哪个选项卡上。在您的示例中,如果您单击一次按钮然后返回第一个选项卡而不是使用该按钮,则应用程序不知道您在新选项卡上并且该按钮不起作用。我不知道如何确保应用随时知道打开了哪个标签
    • 我对答案中的代码进行了小幅改进以将其合并(添加了 observe({ openTab(input$tabsPanel) }) 行)。
    • @shosaco,你为什么要使用`openTab openTab<- reactiveVal() 然后openTab&lt;-input$tabsPanel?跨度>
    猜你喜欢
    • 2019-04-28
    • 2018-11-18
    • 2018-08-09
    • 2021-02-13
    • 2018-05-19
    • 2021-06-01
    • 2020-11-17
    • 2017-11-06
    • 2021-10-18
    相关资源
    最近更新 更多