【问题标题】:Accessing parent namespace inside a Shiny Module访问闪亮模块中的父命名空间
【发布时间】:2018-08-06 13:29:44
【问题描述】:

我正在尝试updateSelectInput 来自子模块内的父命名空间的 selectInput。在模块函数中,据我所知,我在命名空间内,因此我无法从父命名空间访问和更新 selectInput。我该如何解决这个问题?

library(shiny)
library(shinydashboard)

moduleUI <- function(id) {
  ns <- NS(id)
  box(
    title=actionLink(ns("link"),"This is a link"),
    plotOutput(ns("plot"))
  )
}

module <- function(input, output,session,number) {
  output$plot <- renderPlot({
    plot(number)
  })

  observeEvent(input$link,{
    print(paste0("Number is: ",number))
    updateSelectInput(session,"selectInput",selected=number)  #Doesn't work
  })
}

ui <-  
  dashboardPage(
    dashboardHeader(title="Title"),
    dashboardSidebar(
      selectInput("selectInput","Choose one option",choices=seq(1,10),selected=1)
    ),
    dashboardBody(
      moduleUI("5"),
      moduleUI("10")
    )
  )

server <- function(session,input, output) {
  callModule(module=module,id="5",5)
  callModule(module=module,id="10",10)
}

shinyApp(ui = ui, server = server)

【问题讨论】:

  • 是否有理由将观察者放置在模块中?一种替代方法是让模块返回一个值,让服务器观察这个值的变化。
  • 我不太确定如何做到这一点。见上面的编辑。我不能像上面那样从模块中返回值并保存在同一个变量中。
  • 您的问题取决于如何使用 Shiny 模块跨名称空间工作。这是一个更广泛的问题。如果您要编辑和重命名您的问题以反映这一点,那就太好了 - 然后许多其他人可能会受益。
  • 已更新标题和问题并删除了第二个示例,因为它没有多大帮助。谢谢。

标签: r shiny


【解决方案1】:

花了我一段时间,但我找到了一种让子模块更新超级模块的方法。

Shiny 被设计成必须通过模块参数或返回值来访问其他模块。我们不能在模块之间传递widget ID,但是可以传递父级的会话信息。

library(shiny)

moduleUI <- function(id) {
  ns <- NS(id)
  uiOutput(ns("my_link"))
}

module <- function(input, output, session, number, parent) {
  output$my_link <- renderUI({ 
    actionLink(session$ns("link"), paste0("This is a link to ", number))
  })

  observeEvent(input$link,{
    updateSelectInput(session = parent,"selectInput",selected = number)  ### use parent session
  })
}

ui <-  fluidPage(
    selectInput("selectInput","Choose one option",choices=seq(1,10),selected=1),
    moduleUI("5"),
    moduleUI("10")
)

server <- function(session,input, output) {
  callModule(module = module, id = "5", 5, parent = session) ### pass session information
  callModule(module = module, id = "10", 10, parent = session) ### pass session information
}

shinyApp(ui = ui, server = server)

特别注意:

  • 我们在调用子模块时传递当前会话信息
  • 我们在更新输入选择器时使用父会话

【讨论】:

    【解决方案2】:

    我认为理想的做法是让子模块观察和更新超级模块。但是,我只能根据我上面的评论提供一个解决方案:超级模块中的每个子模块都有一个观察者。如果您有很多子模块,这将很快变得很麻烦。

    library(shiny)
    library(shinydashboard)
    
    moduleUI <- function(id) {
      ns <- NS(id)
      box(
        title=actionLink(ns("link"),"This is a link"),
        plotOutput(ns("plot"))
      )
    }
    
    module <- function(input, output,session,number) {
      current = reactiveValues()
      current$return_value = 0
    
      returnvalue <- reactive(current$return_value)
    
      output$plot <- renderPlot({
        plot(number)
      })
    
      observeEvent(input$link,{
        print(paste0("Number is: ",number))
        current$return_value = current$return_value + 1
      })
    
      return(list(rv = returnvalue, num = number))
    }
    
    ui <-  
      dashboardPage(
        dashboardHeader(title="Title"),
        dashboardSidebar(
          selectInput("inputID","Choose one option",choices=seq(1,10),selected=1),
          actionButton("button","Knap")
        ),
        dashboardBody(
          moduleUI("5"),
          moduleUI("10")
        )
      )
    
    server <- function(session,input, output) {
      val1 <- callModule(module=module,id="5",5)
      val2 <- callModule(module=module,id="10",10)
    
      observeEvent(val1$rv(),{
        updateSelectInput(session,inputId="inputID",selected=val1$num)
      })
    
      observeEvent(val2$rv(),{
        updateSelectInput(session,inputId="inputID",selected=val2$num)
      })
    
    }
    
    shinyApp(ui = ui, server = server)
    

    Tobias 问题的主要变化:

    • 子模块有不同的名字
    • 每个子模块的独立观察者
    • 子模块包含一个return_value,每次点击链接时都会更新。这确保了超级模块中的观察者可以观察到变化。
    • 子模块返回一个包含两个值的列表:return_value,如上所述,以及更新 UI 的值。

    【讨论】:

    • 感谢您的建议。正如你所说,我有很多子模块,所以确实很麻烦。
    猜你喜欢
    • 2017-12-23
    • 1970-01-01
    • 2019-03-03
    • 1970-01-01
    • 2020-12-11
    • 1970-01-01
    • 1970-01-01
    • 2020-12-11
    • 2016-11-29
    相关资源
    最近更新 更多