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)