Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R shiny: how to change values in a reactiveValues object

I am developing some shiny apps with various inputs. In general, I have a setup where I want the user to push a button to accept the input values, which will then create objects that need to be set up. The a simulation should run when the user presses the play button on a animated sliderInput object. The objects that have been created will be updated at each iteration.

One problem is that one of the objects is a reactiveValues list. I would like the whole set of objects to be recreated (erasing earlier values) whenever a user changes a setting and clicks "Accept" and runs them. Instead, the objects in the reactiveValues list are not being overwritten but are being augmented each time with the next settings. So each object slot actually holds several objects.

To see this, try setting the maximum iteration to a value, hit accept, then change the value and accept again, then click play. You will see it will print out different lengths of the reactiveValues object.

I tried a few things like rm() to try to delete the reactiveValues. Also I tried the solution here (shiny: How to update a reactiveValues object?) but it didn't work either.

library(shiny)

iter_test <- shinyApp(

ui=shinyUI(fluidPage(
  titlePanel("title panel"),

  sidebarLayout(position = "left",
                             sidebarPanel("Simulation parameters",                                
                               sliderInput("iter","Progress of simulation",value=1, min=1, max=30, round=TRUE, step=1,
                                 animate=animationOptions(interval=1, loop=FALSE)),
                                 actionButton('run',"Accept settings, press play above"),
                                 sliderInput('max_iter','Maximum number of iterations',value=20, min=1, max=30, round=TRUE, step=1)
                              ),
                mainPanel(  plotOutput("plots"))
               )#end of layout
  )
)#end of UI definition
,

server=shinyServer(function(input, output, session) 
{

   observeEvent( input$run, { 
        #only set up simulation objects if accept is clicked

    updateSliderInput(session, "iter",  label="Progress of simulation", value=1, min=1, max=input$max_iter, step=1)
    #try(rm(params))
    #set up objects needed for simulation
    params <- reactiveValues(tmp=rep(1, input$max_iter))

    #when the play button is pressed, the following loop should trigger.       

    observeEvent( input$iter, { 
           print(length(params$tmp))

   })
 }) 
}
)
)
like image 368
Sam A. Avatar asked Feb 12 '17 01:02

Sam A.


1 Answers

I think this gets you what you want:

library(shiny)

iter_test <- shinyApp(

  ui=shinyUI(fluidPage(
    titlePanel("title panel"),

    sidebarLayout(position = "left",
                  sidebarPanel("Simulation parameters",                                
                               sliderInput("iter","Progress of simulation",value=1, min=1, max=30, round=TRUE, step=1,
                                           animate=animationOptions(interval=1, loop=FALSE)),
                               actionButton('run',"Accept settings, press play above"),
                               sliderInput('max_iter','Maximum number of iterations',value=20, min=1, max=30, round=TRUE, step=1)
                  ),
                  mainPanel(  plotOutput("plots"))
    )#end of layout
  )),#end of UI definition
  server=shinyServer(function(input, output, session) 
  {
    params <- reactiveValues(tmp=NULL)

    observeEvent( input$run, { 
      req(input$run)          
      updateSliderInput(session, "iter",  label="Progress of simulation", value=1, min=1, max=input$max_iter, step=1)
      #try(rm(params))
      #set up objects needed for simulation
      params$tmp =rep(1, input$max_iter)
    })          
    #when the play button is pressed, the following loop should trigger.       
    observeEvent( input$iter, { 
      req(input$iter)
      print(length(params$tmp))
    })
  })
)

Yielding this:

enter image description here

In the above I set to 20, ran it, then set to 6, and ran it again. You can see it is no longer repeating the values, before it would have alternated 20 and 6.

The changes I made were:

  • initialized param$tmp outside the loop
  • removed the nesting of the observeEvent calls.

I kind of think you should be using an eventReactive here for the input$run case, but I am not really sure where you are going with this, so I let it be.

like image 92
Mike Wise Avatar answered Nov 11 '22 00:11

Mike Wise