Luyao Ruan
Luyao Ruan

Reputation: 83

Two actionButtons in Shiny

I am writing a shiny function which contains two actionButtons. These two are left and right buttons which help the plot to shift when clicked. Both buttons work OK when they were first clicked. The problem occurs when I re-click them. It will bounce back and forth between two ranges no matter which button I click. I guess it might be the problem that "right" and "left" button do not return to 0 after clicked. What will be an alternative way to solve my question? Thanks ahead!

My code is below:

shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
  sliderInput("test", label="test", min=0, max=1808, value=c(0,50)),
  actionButton("left", "Left"),
  actionButton("right", "Right")

),
mainPanel(
  plotOutput("bar")
)
)
))


shinyServer(function(input, output, session){
observe({
if(input$right){
  isolate({
    if(input$test[2]+ round((input$test[2]-input$test[1])/2) <= 1808)
    updateSliderInput(session, "test", value=c(input$test[1] + round((input$test[2]-input$test[1])/2), input$test[2] + round((input$test[2]-input$test[1])/2)))
})
}
if (input$left){
  isolate({
    if(input$test[1] - round((input$test[2]-input$test[1])/2) > 0)
    updateSliderInput(session, "test", value=c(input$test[1] - round((input$test[2]-input$test[1])/2), input$test[2] - round((input$test[2]-input$test[1])/2)))
})      
}
})

subdata <- reactive({
  sub.data <- data[input$test[1]:input$test[2]]
})

output$bar <- renderPlot({
  barplot(subdata())
})  

})

Upvotes: 5

Views: 2417

Answers (2)

Mikael Jumppanen
Mikael Jumppanen

Reputation: 2486

In shiny 0.11 there was really nice update for eventhandling, which streamline use of actionButton greatly. Now you can use observeEvent() for this kind of tasks where you want to perform function in response of event(eg. pressing of actionButton)

Minimal working example(requires shiny version 0.11):

library(shiny)
server <- function(input, output, session) {
    observeEvent(input$left, function() {
        if(input$test[2]+ round((input$test[2]-input$test[1])/2) <= 1808)
        updateSliderInput(session, "test", value=c(input$test[1] + round((input$test[2]-input$test[1])/2), input$test[2] + round((input$test[2]-input$test[1])/2)))
    }

    )
    observeEvent(input$right, function() {
         if(input$test[1] - round((input$test[2]-input$test[1])/2) > 0)
    updateSliderInput(session, "test", value=c(input$test[1] - round((input$test[2]-input$test[1])/2), input$test[2] - round((input$test[2]-input$test[1])/2)))
    }
    )
}

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
    sliderInput("test", label="test", min=0, max=1808, value=c(0,50)),
      actionButton("left", "Left"),
      actionButton("right", "Right")
    ),
    mainPanel(


    )
  )
)

shinyApp(ui = ui, server = server)

Upvotes: 4

NicE
NicE

Reputation: 21443

You can try using two observe expression, one for each button.

observe({
  if(input$right){
    isolate({
        if(input$test[2]+ round((input$test[2]-input$test[1])/2) <= 1808)
          updateSliderInput(session, "test", value=c(input$test[1] + round((input$test[2]-input$test[1])/2), input$test[2] + round((input$test[2]-input$test[1])/2)))
      })
    }
})

observe({
  if(input$left){ 
    isolate({
        if(input$test[1] - round((input$test[2]-input$test[1])/2) > 0)
          updateSliderInput(session, "test", value=c(input$test[1] - round((input$test[2]-input$test[1])/2), input$test[2] - round((input$test[2]-input$test[1])/2)))
      }) 
  }
})

Each button will then only be triggered when it is clicked on and you won't need to reset the value of the buttons.

Upvotes: 1

Related Questions