如何在Shiny观察者间传递响应式值并限制响应式对象取值?
Shiny按钮计数器限制实现方案
我需要用两个observeEvent实现按钮点击计数器,要求第二个响应式对象y(「Neg」按钮的点击数)的取值上限不能超过第一个响应式对象x(「Pos」按钮的点击数)的值。比如点击「Pos」按钮3次、「Neg」按钮4次后,y应该停在3,净点击数为0,预期效果如下:

以下是我的初始代码,其中尝试限制y的代码会导致计数每次跳2,已注释:
library(shiny) ui <- fluidPage(br(), actionButton("Btn1", "Pos"), actionButton("Btn2", "Neg"), br(),br(), textOutput("posClicks"), textOutput("negClicks"), textOutput("netClicks") ) server <- function(input, output, session) { x = reactiveVal(0) y = reactiveVal(0) observeEvent(input$Btn1,{x(x()+1)}) observeEvent(input$Btn2,{y(y()+1)}) # 这段代码注释掉了,因为会导致计数每次跳2 # observeEvent(input$Btn2,{ # if(x()-y(y()+1) >= 0){y(y()+1)} # }) output$posClicks <- renderText({paste('Pos clicks =',x())}) output$negClicks <- renderText({paste('Neg clicks =',y())}) output$netClicks <- renderText({paste('Net clicks =',x()-y())}) } shinyApp(ui, server)
问题原因分析
注释代码的问题在于:y(y()+1)在if的判断条件中就已经执行了一次赋值操作,当条件满足时又会执行一次y(y()+1),所以每次点击「Neg」按钮,y会被加2,导致跳数异常。
正确实现方式
修改「Neg」按钮的observeEvent逻辑,先判断当前y的取值是否小于x,只有满足条件时才让y加1:
library(shiny) ui <- fluidPage(br(), actionButton("Btn1", "Pos"), actionButton("Btn2", "Neg"), br(),br(), textOutput("posClicks"), textOutput("negClicks"), textOutput("netClicks") ) server <- function(input, output, session) { x = reactiveVal(0) y = reactiveVal(0) observeEvent(input$Btn1,{ x(x() + 1) }) observeEvent(input$Btn2,{ # 仅当当前y小于x时,才允许y加1 if(y() < x()){ y(y() + 1) } }) output$posClicks <- renderText({paste('Pos clicks =', x())}) output$negClicks <- renderText({paste('Neg clicks =', y())}) output$netClicks <- renderText({paste('Net clicks =', x() - y())}) } shinyApp(ui, server)
这样点击「Pos」3次后,x的值为3,此时无论点击「Neg」多少次,y最多只会到3,净点击数保持为0,符合预期效果。
内容的提问来源于stack exchange,提问作者Village.Idyot
相关产品推荐
相关产品推荐

