Joh*_*aul 12 r reactive-programming shiny shiny-reactivity
注意:在得出答案后,我重写了问题,如果更清楚的话.
有时在shiny应用程序中.我想使用用户为窗口小部件选择的值,以及为该窗口小部件选择的先前值.这可以应用于从用户输入派生的反应值,其中我想要旧值和新值.
问题是,如果我尝试保存窗口小部件的值,那么包含该值的变量必须是被动的,或者每次窗口小部件更改时都不会更新.但是,如果我将值保存在被动上下文中,它将始终为我提供当前值,而不是前一个值.
如何保存窗口小部件的先前值,但每次用户更改窗口小部件时仍会更新它?
有没有一种方法不需要actionButton每次用户更改东西时使用?避免actionButton添加一个是可取的,否则不必要,并为用户创建多余的点击.
更新此答案是在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,isolate和session$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$XX和Values$old在renderText()函数中.
看起来会话刷新事件方法似乎为此目的而被打破,这里是使用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)
产量: