简体   繁体   中英

R Shiny: Use update* From Outside a Module

What's the best way to use update* from outside a Shiny module without repeating the callModule() call or arguments?

Minimal example:

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)

The Bad Update overrides the original text with the default. The Better Update avoids this by re-passing the original text but this isn't ideal because:

  1. It requires at least two callModule() calls.
  2. You must repeat the callModule() arguments.

Ideally, one callModule() call would take care of specifying the module arguments and the update behaviour. I haven't found or thought up a way of doing this though.

You can do this with reactiveValues() . You just need to make sure you allow for the reactive nature of the arguments you pass to the module:

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM