16

注意:在提出答案后,我改写了问题以使其更清晰。

有时在shiny应用程序中。我想利用用户为小部件选择的值,以及为同一小部件​​选择的先前值。这可能适用于从用户输入派生的反应值,我想要旧值和新值。

问题是,如果我尝试保存小部件的值,那么包含该值的变量必须是反应性的,否则每次小部件更改时它都不会更新。但是,如果我将值保存在响应式上下文中,它将始终给我当前值,而不是前一个值。

如何保存小部件的先前值,但每次用户更改小部件时仍然更新它?

有没有一种方法不需要actionButton在用户每次更改时都使用?通过添加一个来避免actionButton可能是可取的,否则是不必要的,并且会为用户带来过多的点击。

4

2 回答 2

12

看到会话刷新事件方法似乎为此目的而被破坏,这里是使用observeEvent构造和反应变量的另一种方法。

library(shiny)

ui <- fluidPage(
  h1("Memory"),
  sidebarLayout(
    sidebarPanel(
      numericInput("val", "Next Value", 10)
    ),
    mainPanel(
      verbatimTextOutput("curval"),
      verbatimTextOutput("lstval")
    )
  )
)

server <- function(input,output,session) {
  rv <- reactiveValues(lstval=0,curval=0)

  observeEvent(input$val, {rv$lstval <- rv$curval; rv$curval <- input$val})

  curre <- reactive({req(input$val);  input$val; rv$curval})
  lstre <- reactive({req(input$val);  input$val; rv$lstval})

  output$curval <- renderPrint({sprintf("cur:%d",curre())})
  output$lstval <- renderPrint({sprintf("lst:%d",lstre())})
}
options(shiny.reactlog = TRUE)
shinyApp(ui, server)

产量:

在此处输入图像描述

于 2016-12-17T13:35:28.880 回答
9

更新reactiveValues这个答案是在/observeEvent模型出现之前发布的shiny。我认为@MikeWise 的答案是更好的方法。

在玩了一些之后,这就是我想出的。ui.r 没什么特别的

用户界面

library(shiny)

ui <- shinyUI(fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectizeInput(inputId="XX", label="Choose a letter",choices=letters[1:5])
    ),
    mainPanel(
      textOutput("Current"),
      textOutput("old")
    )
  ) 
))  

"Current"将显示当前选择并"old"显示先前选择。

server.r我使用了三个关键功能reactiveValuesisolatesession$onFlush

服务器.r

library(shiny)

server <- function(input, output,session) {

  Values<-reactiveValues(old="Start")

  session$onFlush(once=FALSE, function(){
    isolate({ Values$old<-input$XX })
  })


  output$Current <- renderText({paste("Current:",input$XX)})

  output$old <- renderText({ paste("Old:",Values$old) })
}  

像这样的server.r作品。

首先,Values$old是使用reactiveValues函数创建的。我给了它“开始”的值,以明确加载时发生了什么。

然后我添加了一个session$onFlush功能。请注意,我session的函数中有一个参数server。这将在每次闪亮刷新反应系统时运行 - 例如当selectizeInput用户更改时。重要的是它会在input$XX获得新值之前运行 - 因此该值已更改为 atselectizeInput而不是 at XX

然后在I 内部分配tosession$onFlush的传出值。这是在内部完成的,因为这将防止使用新值更新时出现任何问题。然后我可以在函数中使用和。XXValues$oldisolate()input$XXinput$XXValues$oldrenderText()

于 2014-10-17T23:51:55.093 回答