创建指示最后修改哪个小部件的闪亮反应变量

Creating Shiny reactive variable that indicates which widget was last modified

假设我们有一组小部件,每个小部件都有自己的输入标签。我们如何创建一个反应对象,其值是代表最后一个被修改的小部件的输入 ID 的字符?

例如,如果我们有

ui.R

shinyUI(fluidPage(
   textInput('txt_a', 'Input Text A'),
   textInput('txt_b', 'Input Text B")
))

server.R

shinyServer(function(input, output) {
   last_updated_widget <- reactive({
      #hypothetical code that indicates ID value of last updated widget
   })
})

想要的结果如下。如果用户修改了第一个文本框,那么 last_updated_widget() 的值将是 "txt_a"。如果他们修改第二个框,last_updated_widget() 的值将变为 "txt_b"。我正在寻找一个结果,该结果延伸到将值设置为最后调整的任何小部件的 ID 的明显概括。

我希望它适用于任意数量的小部件输入,包括它们由 renderUI() 语句生成的情况。因此,不能为每个小部件制作单独的 reactive() 语句。但是,如果反应语句需要遍历所有小部件名称(或类似名称),我当然可以使用它。并且多个反应语句是可以的,只要它是一个固定的数量,而不是小部件数量的函数。

这似乎是一个非常简单的问题,所以当它成为我的障碍时,我感到很惊讶。我觉得解决方案真的很明显,我只是没有看到,所以如果是的话,我很抱歉把它变成一个新问题。但如有任何帮助,我们将不胜感激。

您可以使用 reactiveValues() 创建的反应值来存储上次使用的小部件的名称。稍后使用观察者跟踪每个小部件的 activity 并使用上次使用的小部件的名称更新反应值。

在下面的示例中,最后使用的小部件的名称存储在 last_updated_widget$v 中,并且每次更改时都会激活 verbatimTextOutput。您可以在服务器的任何地方使用 last_updated_widget$v

    library(shiny)
    runApp(list(
      ui = shinyUI(
            fluidPage(
                textInput('txt_a', 'Input Text A'),
                textInput('txt_b', 'Input Text B'),
                verbatimTextOutput("showLast")
            )
        ),
        server = function(input, output, session) {
            last_updated_widget <- reactiveValues( v = NULL)
            observe ({
                input$txt_a
                last_updated_widget$v <- "txt_a"
            })
            observe ({
                input$txt_b
                last_updated_widget$v <- "txt_b"
            })
            output$showLast <- renderPrint({
                last_updated_widget$v
            })
        }
    ))

这是一个可行的解决方案,但由于嵌套 observe(),它看起来有点笨拙。我不确定有什么更好的方法,但可能会有更好的方法。

基本上,使用 observe() 遍历所有可用输入,对于每个输入,使用另一个 observe(),它只会在该输入更改时触发,并将变量设置为 id输入的。

runApp(shinyApp(
  ui = shinyUI(
    fluidPage(
      textInput('txt_a', 'Input Text A'),
      textInput('txt_b', 'Input Text B'),
      uiOutput('txt_c_out'),
      verbatimTextOutput("show_last")
    )
  ),
  server = function(input, output, session) {
    output$txt_c_out <- renderUI({
      textInput('txt_c', 'Input Text C')
    })

    values <- reactiveValues(
      lastUpdated = NULL
    )

    observe({
      lapply(names(input), function(x) {
        observe({
          input[[x]]
          values$lastUpdated <- x
        })
      })
    })

    output$show_last <- renderPrint({
      values$lastUpdated
    })
  }
))