4

I know that similar question was already answered, however the solution creates a new actionButton with different label upon string-input. What I need is to keep the button(the counter of the button), because when I change the label and create a new button it has a counter of 0(not clicked).

So basically I need something like an update function to just change the label of the actionButton, when it is pressed. You press it once and the label changes.

input$Button <- renderUI({
    if(input$Button >= 1) label <- "new label"
    else label <- "old label"
    actionButton("Button", label = label)
})

Something like this, but without reseting the value of the button(by creating a whole new one).

Thanks!

Community
  • 1
  • 1
user4065758
  • 309
  • 3
  • 12

3 Answers3

4
  1. reactiveValues() can help. Check http://shiny.rstudio.com/articles/reactivity-overview.html for details. In the following example, I renamed your input$Button to input$click to avoid double usage of the "Button" name. Since we wrap the label in a renderUI(), input$click initially fires once it is created?!?, that's why I put the label condition as: if(vars$counter >= 2)

  2. An alternative solution could be to remove the read-only attribute (found here: https://github.com/rstudio/shiny/issues/167)

    attr(input, "readonly") <- FALSE
    input$click <- 1
    
  3. For an example paste the following in your R console:

    ui <- bootstrapPage(
        uiOutput('Button')
    )
    
    server <- function(input, output) {
    
        # store the counter outside your input/button
        vars = reactiveValues(counter = 0)
    
        output$Button <- renderUI({
            actionButton("click", label = label())
        })
    
        # increase the counter
        observe({
            if(!is.null(input$click)){
                input$click
                isolate({
                    vars$counter <- vars$counter + 1
                })
            }
        })
    
        label <- reactive({
            if(!is.null(input$click)){
                if(vars$counter >= 2) label <- "new label"
                else label <- "old label"
            }
        })
    }
    
    # run the app
    shinyApp(ui = ui, server = server)
    
Mathias711
  • 6,568
  • 4
  • 41
  • 58
Tonio Liebrand
  • 17,189
  • 4
  • 39
  • 59
  • My problem was, that I was using the input$click(in your template) to activate another function, and when a new button is generated it is automatically unclicked, so my function disappeares. With this solution the problem remains, but since your solution is elegant and made me realisize my mistake in the control flow and fix it, thank you. I hope others find this usefull aswell. – user4065758 Nov 18 '15 at 14:02
  • I think using `session$sendCustomMessage` to update the button would be a better approach as it would eliminate the need to re-create the button – Pork Chop Nov 18 '15 at 15:07
  • I can't seem to find any documentation on this function. Can you briefly explain how do you imagine the usage of the sendCustomMessage in the desired behaviour? – user4065758 Nov 25 '15 at 12:29
4

You can use updateActionButton from native shiny package:

ui <- fluidPage(
  actionButton('someButton', ""),
  h3("Button value:"),
  verbatimTextOutput("buttonValue"),
  textInput("newLabel", "new Button Label:", value = "some label")
)

server <- function(input, output, session) {

  output$buttonValue <- renderPrint({
    input$someButton
  })

  observeEvent(input$newLabel, {
    updateActionButton(session, "someButton", label = input$newLabel)
  })
}

shinyApp(ui, server)

enter image description here

shosaco
  • 5,915
  • 1
  • 30
  • 48
0

A few years later some small addition: If you want to switch between button icons, e.g. play / pause button (and switching between labels would be similar) you could do something like this (based on shosaco's answer).

library(shiny)

ui <- fluidPage(
  fluidRow(
    actionButton("PlayPause", NULL, icon = icon("play"))
    )
)

server <- function(input, output, session) {
  # whenever the ActionButton is clicked, 1 is added to input$PlayPause
  # check if input$PlayPause is even or odd with modulo 2 
  # (returns the remainder of division by 2)
  observeEvent(input$PlayPause, {
    if (input$PlayPause %% 2 != 0) {
      updateActionButton(session, "PlayPause", NULL, icon = icon("pause"))
    } else {
      updateActionButton(session, "PlayPause", NULL, icon = icon("play"))
    }
  })
}

shinyApp(ui = ui, server = server)
Rumpl
  • 333
  • 1
  • 11