Alex Witsil
Alex Witsil

Reputation: 862

update shiny input with observeEvent

I would like the user to define an initial numeric value that is then updated (i.e. added to) by a set amount with each click of an action button. I use reactiveVal to try and make this update but am getting the dreaded Operation not allowed without an active reactive context error. I am confused because I thought using reactiveVal is doing something inside a reactive expression but obviously I am wrong.

I have looked for relevant questions/articles/tutorials but came up empty. Any advice is much appreciated. And please let me know if there is a better way of accomplishing this task, i.e. if I should be using different functions or methods.

A stripped down version of my code is below:

library(shiny)

ui <- fluidPage(

    ## initilize the value
    numericInput('init.i','initial i',10),

    ## click this button to add one to the initial value
    actionButton("run","Run"),

    ## output the current count
    textOutput("cur.i")

)

server <- function(input,output) {

    ## define the current value according to the inital value
    i <- reactiveVal({
        input$init.i ## this line fails
        ##1 ## this line doesn't fail but value always initializes at 1 
    })

    observeEvent(input$run, {
        ## make a new value by adding 1 to the current value
        new.i <- i() + 1
        ## update the value
        i(new.i)

        output$cur.i <- renderText({
            ## print the current value
            i()
        })
    })

}

shinyApp(ui=ui,server=server)

Upvotes: 2

Views: 2625

Answers (1)

Anders Ellern Bilgrau
Anders Ellern Bilgrau

Reputation: 10263

The following works. As shiny reports to you, what you are trying to do is not allowed. It is the initialization of i() where you use input$init.i which needs the reactive context.

The wanted effect can be achieved by making another observeEvent on the initial value you want (input$init.i) as set your reactive value to that.

library(shiny)
ui <- fluidPage(

  ## initilize the value
  numericInput('init.i','initial i', 10),

  ## click this button to add one to the initial value
  actionButton("run","Run"),

  ## output the current count
  textOutput("cur.i")

)
server <- function(input,output) {

  ## Define the reactive value (with no 'inital' value)
  i <- reactiveVal()

  ## Set i() based on "initialize" input widget
  observeEvent(input$init.i, { 
    i(input$init.i)
  })

  observeEvent(input$run, {
    ## make a new value by adding 1 to the current value
    new.i <- i() + 1
    ## update the value
    i(new.i)
   })

  output$cur.i <- renderText({
    i()
  })
}
shinyApp(ui = ui, server = server)

Also, there is no need to nest renderText inside the observeEvent.

Upvotes: 2

Related Questions