【问题标题】:R Shiny: Use update* From Outside a ModuleR Shiny:从模块外部使用更新*
【发布时间】:2018-08-03 07:14:51
【问题描述】:

从 Shiny 模块外部使用 update* 而不重复 callModule() 调用或参数的最佳方法是什么?

小例子:

library(shiny)

numericInputModUI <- function (id) {
  ns <- NS(id)
  tagList(
    numericInput(ns("val"), "Value", value = 0),
    textOutput(ns("text"))
  )
}

numericInputMod <- function (input, output, session,
                             updateVal = NA, displayText = "default text") {
  output$text <- renderText(displayText)
  if (!is.na(updateVal)) updateNumericInput(session, "val", value = updateVal)
}

ui = fluidPage(
  numericInputModUI("module"),
  actionButton("updateBad", label = "Bad Update"),
  actionButton("updateBetter", label = "Better Update")
)

server = function(input, output, session) {
  callModule(numericInputMod, "module", displayText = "original text")
  observeEvent(
    input$updateBad,
    callModule(numericInputMod, "module", updateVal = 1)
  )
  observeEvent(
    input$updateBetter,
    callModule(numericInputMod, "module", updateVal = 2, displayText = "original text")
  )
}

shinyApp(ui, server)

错误更新使用默认值覆盖原始文本。更好的更新通过重新传递原始文本来避免这种情况,但这并不理想,因为:

  1. 至少需要两次 callModule() 调用。
  2. 您必须重复 callModule() 参数。

理想情况下,一个 callModule() 调用将负责指定模块参数和更新行为。不过,我还没有找到或想出这样做的方法。

【问题讨论】:

    标签: r shiny


    【解决方案1】:

    您可以使用reactiveValues() 执行此操作。您只需要确保您允许传递给模块的参数的反应性质:

    library(shiny)
    
    numericInputModUI <- function (id) {
      ns <- NS(id)
      tagList(
        numericInput(ns("val"), "Value", value = 0),
        textOutput(ns("text"))
      )
    }
    
    numericInputMod <- function (input, output, session, updateVal = NA,
                                 displayText = "default text", trig) {
    
      output$text <- renderText(displayText())
    
      observeEvent(trig(), ignoreInit = TRUE, {
        updateNumericInput(session, "val", value = updateVal())
      })
    
    }
    
    ui = fluidPage(
      numericInputModUI("module"),
      actionButton("updateBad", label = "Bad Update"),
      actionButton("updateBetter", label = "Better Update")
    )
    
    server = function(input, output, session) {
    
      vals <- reactiveValues(dText = "original text", uVal = NA, trig = 0)
    
      observeEvent(input$updateBad, {
        vals$dText <- "default text"
        vals$uVal <- 1
        vals$trig <- vals$trig + 1
      })
    
      observeEvent(input$updateBetter, {
        vals$dText <- "original text"
        vals$uVal <- 2
        vals$trig <- vals$trig + 1
      })
    
      callModule(numericInputMod, "module", 
                 displayText = reactive(vals$dText), 
                 updateVal = reactive(vals$uVal),
                 trig = reactive(vals$trig))
    
    }
    
    shinyApp(ui, server)
    

    【讨论】:

    • 看起来应该可以了。我会试一试并报告。
    • 刚刚测试过了。更新有效,但副作用是给定按钮不能使用两次,除非在两者之间单击另一个按钮。例如,单击 Better Update,手动将值更改回 0,然后再次尝试 Better Update。如果在第二个更好的更新之前单击错误更新,它将再次起作用。有什么建议吗?
    • 我已经编辑了代码以包含第三个反应值trig,无论顺序如何,每次单击按钮时都会更改该值,并将updateNumericInput 设置为在更改时运行。这样可以确保每次点击时都会更新输入
    • 编辑后的答案与宣传的一样。标记为已回答。
    猜你喜欢
    • 1970-01-01
    • 2021-12-11
    • 2018-09-30
    • 2021-06-04
    • 2020-03-31
    • 2021-12-27
    • 2021-02-28
    • 1970-01-01
    • 2020-03-19
    相关资源
    最近更新 更多