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

Joh*_*aul 12 r reactive-programming shiny shiny-reactivity

注意:在得出答案后,我重写了问题,如果更清楚的话.

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

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

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

有没有一种方法不需要actionButton每次用户更改东西时使用?避免actionButton添加一个是可取的,否则不必要,并为用户创建多余的点击.

Joh*_*aul 8

更新此答案是在reactiveValues/ observeEventmodel 出现之前发布的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")
    )
  ) 
))  
Run Code Online (Sandbox Code Playgroud)

"Current"将显示当前选择并"old"显示上一个选择.

server.r我利用了三个主要功能:reactiveValues,isolatesession$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) })
}  
Run Code Online (Sandbox Code Playgroud)

这样的server.r作品.

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

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

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


Mik*_*ise 7

看起来会话刷新事件方法似乎为此目的而被打破,这里是使用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)
Run Code Online (Sandbox Code Playgroud)

产量:

在此输入图像描述