0

下面的应用程序包含一个selectInput( input$month) 和一个按钮 ,Show Modal单击时会启动一个模式窗口。模式包含一个按钮,Add UI插入一些文本,Element x其中x是计数器的值,每次Add UI单击时增加 1。

打开模式窗口的应用程序启动时的屏幕截图:

在此处输入图像描述

该应用程序是模块化的,因此与模式关联的 UI 由 function 呈现,modUI相应的服务器逻辑在 function 中定义modServermodUI每次input$month更改以覆盖先前插入的文本元素时都会重新呈现。

我需要以编程方式插入第一块文本,以便在应用加载用户更改input$month时,Element 1已经在模式中呈现

在此处输入图像描述

为此,我试图让 insertUI 观察者在input$add_ui大于或等于 0 时触发 - 即observeEvent(if(req(input$add_ui) >= 0) TRUE else return(), { #insertUI expr })。但是,这不起作用,我不明白为什么。由于观察者被热切地评估,这个观察者不应该在input$add_ui完成初始化后触发吗?

每次input$month更改时,计数器也必须重置为 0,以便插入的文本元素从 开始Element 1。为此,我将以下观察者包括在modServer

observe({
    req(input$add_ui == 0) #checking that modUI has finished rerendering
    print(paste('month changed to:', month, 'resetting counter')); 
    counter(0)
  })

req(input$add_ui == 0)检查是否已完成重新渲染,modUI并且仅在检查通过时才重置计数器。但是我觉得这使得它modServer不那么自给自足,并且想知道是否有一种不那么迂回的方式?

最后,我对模块比较陌生,想知道是否有人可以解释为什么在通过调用 counter()时不自动重置?modServerobserve(callModule(modServer, 'hi', month = input$month))如果模块有自己的环境,为什么它的价值仍然存在?

我将不胜感激任何帮助,因为我已经坚持了一段时间。

重现上述内容的代码:

library(shiny)
library(shinyBS)

#MODULE UI ----
modUI <- function(id) {

  ns <- NS(id)

  tagList(
    actionButton(ns("show_modal"), "Show modal"),
    bsModal(
      id = ns('modal'),
      trigger = ns('show_modal'),

      actionButton(ns("add_ui"), "Add UI"),
      tags$div(id = ns("placeholder1"))
    )
  )
}

#MODULE SERVER ----
modServer <- function(input, output, session, month) {

  ns <- session$ns

  counter <- reactiveVal(0)

  # Observer to insert UI element
  observeEvent(if(req(input$add_ui) >= 0) TRUE else return(), {

    counter(counter() + 1)

    insertUI(
      selector = paste0("#", ns("placeholder1")),
      ui = tags$div(paste('Element', counter()))
    )
  })

  # Reset counter() if month is changed
  observe({
    req(input$add_ui == 0)
    print(paste('month changed to:', month, 'resetting counter')); 
    counter(0)
  })

  # Print
  observe({ print(paste('input$add_ui:', input$add_ui, 'counter:', counter())) })

}

#MAIN UI ----
ui <- fluidPage(
  tagList(
    selectInput('month', 'Month', month.abb),
    uiOutput('modal_ui')
  )
)

#MAIN SERVER ----
server <- function(input, output, session) {

  #Call modUI if input$month is changed
  observe(callModule(modServer, 'hi', month = input$month))

  #Rerender modUI if input$month is changed
  output$modal_ui <- renderUI({
    input$month
    modUI('hi')
  })

  observe(print(input$month))
}

shinyApp(ui = ui, server = server)
4

0 回答 0