我可以在更改时保存反应对象的旧值吗?

时间:2014-10-17 20:13:36

标签: r shiny reactive-programming shiny-reactivity

注意:在提出答案后,我重新提出问题,以便更清楚。

有时在shiny应用中。我想使用用户为窗口小部件选择的值,以及为该窗口小部件选择的先前值。这可以应用于从用户输入派生的反应值,其中我想要旧值和新值。

问题在于,如果我尝试保存窗口小部件的值,那么包含该值的变量必须是被动的,或者每次窗口小部件更改时都不会更新。但是,如果我将值保存在被动上下文中,它将始终为我提供当前值,而不是前一个值。

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

每次用户更改内容时,是否有一种方法不需要使用actionButton?避免使用actionButton可能是合乎需要的,否则添加一个是不必要的,并为用户创建多余的点击。

2 个答案:

答案 0 :(得分:8)

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

经过一番游戏后,我想出了这个。 ui.r没什么特别的

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

server.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。我给了它价值&#34;开始&#34;明确加载时发生的事情。

然后我添加了session$onFlush功能。请注意,我在session函数中将server作为参数。每当闪亮的反应系统冲洗时,这将运行 - 例如当用户更改selectizeInput时。重要的是,它会在input$XX获得新值之前运行 - 因此值已在selectizeInput处更改,但未在XX处更改。

session$onFlush内,我将XX的传出值分配给Values$old。这是在isolate()内完成的,因为这可以防止使用新值更新input$XX的任何问题。然后,我可以在input$XX函数中使用Values$oldrenderText()

答案 1 :(得分:6)

由于会话刷新事件方法似乎为此目的而被破坏,因此这是使用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)

产量:

enter image description here