Home > Blockchain >  How to dynamically render a button icon in R shiny
How to dynamically render a button icon in R shiny

Time:08-03

My current app has an actionButton dynamically rendered using uiOutput and renderUI such that its label changes depending upon what the user is up to. Here's a very dumb reprex:

library(shiny)
# Define UI
ui <- fluidPage(
  #Have a button to press
  actionButton("test_button",
               uiOutput("button_label"),
               icon = icon("forward"))
)
# Define server
server <- function(input, output) {
  #Have a reactive value serving as a switch
  reactives1 <- reactiveValues(label_switch = 0)
  #Increment the switch upon every button press
  observeEvent(input$test_button, {
    reactives1$label_switch = reactives1$label_switch   1
  })
  #Depending on whether the switch is odd or event, dynamically render the button label.
  observeEvent(reactives1$label_switch, {
    if(reactives1$label_switch %% 2 == 0) {
      output$button_label <- renderUI({ "I'm happy!" })
    } else {
      output$button_label <- renderUI({ "I'm sad!" })
    }
  })
}
# Run the application 
shinyApp(ui = ui, server = server)

Frustratingly, though, I can't seem to figure out how to do the exact same thing with the icon on the button. For example, this doesn't work:

library(shiny)
# Define UI
ui <- fluidPage(
  #Have a button to press
  actionButton("test_button",
               "Press this button to change the icon!",
               uiOutput("button_icon"))
)
# Define server
server <- function(input, output) {
  #Have a reactive value serving as a switch
  reactives1 <- reactiveValues(icon_switch = 0)
  #Increment the switch upon every button press
  observeEvent(input$test_button, {
    reactives1$icon_switch = reactives1$icon_switch   1
  })
  #Depending on whether the switch is odd or event, dynamically render the button icon.
  observeEvent(reactives1$icon_switch, {
    if(reactives1$icon_switch %% 2 == 0) {
    output$button_icon <- renderUI({ shiny::icon("arrow-left") })
    } else {
      output$button_icon <- renderUI({ shiny::icon("arrow-right") })
    }
  })
}
# Run the application 
shinyApp(ui = ui, server = server)

R Shiny doesn't seem to be recognizing that icon() is being called; I get an error that I need to use shiny::icon() to render the icon even though that's what I'm doing. I've seen here that I may need to be rendering the entire button dynamically, but I'd prefer not to do that unless I have to. It also doesn't explain why I can pull this trick with the button label but not the button icon. I've seen elsewhere that the renderUI() call may be overriding the classes/form of my icon object, but it doesn't seem to matter where I call icon(); I get an error either way.

What am I missing?

CodePudding user response:

You can include the icon in the label, with the help of the fontawesome package.

Do not use a render function inside an observer, this is not recommended.

library(shiny)
library(fontawesome)

# Define UI
ui <- fluidPage(
  #Have a button to press
  actionButton("test_button",
               uiOutput("button", inline = TRUE))
)
# Define server
server <- function(input, output) {
  #Have a reactive value serving as a switch
  reactives1 <- reactiveValues(icon_switch = 0)
  #Increment the switch upon every button press
  observeEvent(input$test_button, {
    reactives1$icon_switch = reactives1$icon_switch   1
  })
  #Depending on whether the switch is odd or event, dynamically render the button icon.
  output$button <- renderUI({
    if(reactives1$icon_switch %% 2 == 0) {
    tags$span("Press the button", fa_i("arrow-left"))
    } else {
    tags$span("Press the button", fa_i("arrow-right"))
    }
  })
}
# Run the application 
shinyApp(ui = ui, server = server)
  • Related