问题
I want an button to triggers an action on a prespecified non-reactive variable x. Each time the button is hit x <- x + 1 shall be executed. To check if it was done correctly the result shall be displayed.
To achieve this I tried observeEvent(). But it is doing what it should only once. How does it work properly?
It seems that rv is only available within the observeEvent() function. If output$text_2 <- renderText({ rv$a }) is placed outside of observeEvent() an error occurs. How can I use something done within observeEvent() outside of it?
library(shiny)
x <- 0
ui <- fluidPage(
actionButton(inputId = "action",
label = "action"),
textOutput("text_1"),
textOutput("text_2")
)
server <- function(input, output) {
output$text_1<- renderText({ input$action })
observeEvent(input$action, {
x <- x + 1
rv <- reactiveValues(a = x)
output$text_2 <- renderText({ rv$a })
})
}
shinyApp(ui = ui, server = server)
回答1:
Daattalis answer is spot on but I figured I could post some examples on how you can use Shinys reactive values to do this.
library(shiny)
ui <- fluidPage(
actionButton(inputId = "action",
label = "action"),
textOutput("txt_example1"),
textOutput("txt_example2"),
textOutput("txt_example3")
)
server <- function(input, output) {
# ------------------ Example 1 ------------------
# Use a list of reactive values
rv <- reactiveValues(x=0)
# Will update text output when rv$x is updated
observe({
output$txt_example1 <- renderText({ rv$x })
})
# ------------------ Example 2 ------------------
# Make variable a reactive
x <- 0
makeReactiveBinding('x')
# The only 'trick' here is that x is made a reactive so that the observer is
# triggered every time x is updated.
# If x is not made a reactive the value of x will still be updated but the observer
# wont trigger (see example 3).
observe({
output$txt_example2 <- renderText({ x })
})
# ------------------ Example 3 ------------------
# Use ordinary R scoping
x2 <- 0
printUpdate <- function(){
output$txt_example3 <- renderText({ x2 })
}
printUpdate() # Print first value
# onClick listener, same for all examples
observeEvent(input$action, {
rv$x <- rv$x + 1 # Example 1, update reactive list
x <<- x + 1 # Example 2, Save x to parent enviroment
# Example 3
x2 <<- x2 + 1 # Again, save x2 to parent enviroment, see help('<<-')
printUpdate() # Update textOutput
})
}
shinyApp(ui = ui, server = server)
Hope this helps!
回答2:
As of 2017, there's an easier, better way of doing this using reactiveVal:
library(shiny)
ui <- fluidPage(
actionButton("go", "Click me"),
helpText("All values in the table below are incremented ",
"each time you press the button"),
verbatimTextOutput("tbl")
)
server <- function(input, output, session) {
x <- reactiveVal(1)
observeEvent(input$go, {
x(x() + 1)
})
output$tbl <- renderPrint({
x()
})
}
shinyApp(ui, server)
来源:https://stackoverflow.com/questions/36671011/action-button-and-observeevent