Shiny: dynamic UI & ggplot2 theme switcher

Trying to build a theme switcher for ggplot2 with ggplot2::theme_set for theming many subsequent plots

  • not a single theme_set which can be easily achieved, for example, by placing theme_set(...) in server function

  • not just a single plot which can be easily achieved, for example, with output$plot <- renderPlot({ theme_set(theme_bw()) ; ggplot(...) + ... }) or ggplot(...) + ... + theme_*

In my real case, I am doing it using Shiny modules. Below is a simplified version, showcasing what works and what doesn't work.

library(shiny)

# Dynamic UI using `renderUI`
shinyApp(

  fluidPage(
    selectInput('type',   'Type',   c('slider', 'numeric')),
    uiOutput('slider')
  ),

  function(input, output, session) {
    output$slider <- renderUI({
      if (input$type == 'slider') sliderInput('in', 'in', 1, 5, 1)
      else                        numericInput('in', 'in', 1)
    })
  }
)

Shiny applications not supported in static R Markdown documents


# Dynamic UI using `renderUI` not working for ggplot2 theme switcher
shinyApp(

  fluidPage(
    plotOutput('plot_1'),
    uiOutput('theme_out_1'), plotOutput('plot_2'),
    selectInput('theme_in', 'Theme in', c('light', 'dark')),
    uiOutput('theme_out_2'),
    plotOutput('plot_3')
  ),

  function(input, output, session) {

    p <- ggplot(mtcars, aes(mpg, disp, color = cyl)) + geom_point()

    # It works in normal expr
    theme_set(theme_bw()) ; output$plot_1 <- renderPlot(p)

    # It works in reactive expr
    output$theme_out_1 <- renderUI({ theme_set(theme_dark()) ; NULL})
    output$plot_2      <- renderPlot(p)

    # Not working in reactive expr with ggplot2 theme switcher
    output$theme_out_2 <- renderUI({
      cat('input$theme_in:', input$theme_in, '\n')
      if (input$theme_in == 'light') theme_set(theme_bw())
      else                           theme_set(theme_dark())
      NULL
    })
    output$plot_3 <- renderPlot(p)
    
    # Wrap with `observeEvent` doesn't work too
    # observeEvent(input$theme_in, {
    #   output$theme_out_2 <- renderUI({
    #     cat('input$theme_in:', input$theme_in, '\n')
    #     if (input$theme_in == 'light') theme_set(theme_bw())
    #     else                           theme_set(theme_dark())
    #   })
    # })
    # output$plot_3 <- renderPlot(p)
  }
)

Shiny applications not supported in static R Markdown documents

Created on 2019-12-22 by the reprex package (v0.3.0)

Playing around with the input$them_in input slider successfully print to console but it doesn't change the theme.

# input$theme_in: light
# input$theme_in: dark
# input$theme_in: light
# ...

Hi @Kar. You code have only one problem which in output$plot_3. The theme did change but the plot_3 didn't update. Just add the input$theme_in into renderPlot of output$plot_3 to trigger update when input$theme_in value change.

shinyApp(
  
  fluidPage(
    plotOutput('plot_1'),
    uiOutput('theme_out_1'), 
    plotOutput('plot_2'),
    selectInput('theme_in', 'Theme in', c('light', 'dark')),
    uiOutput('theme_out_2'),
    plotOutput('plot_3')
  ),
  
  function(input, output, session) {
    
    p <- ggplot(mtcars, aes(mpg, disp, color = cyl)) + geom_point()
    
    # It works in normal expr
    theme_set(theme_bw()) ; output$plot_1 <- renderPlot(p)
    
    # It works in reactive expr
    output$theme_out_1 <- renderUI({ theme_set(theme_dark()) ; NULL})
    output$plot_2      <- renderPlot(p)
    
    # Not working in reactive expr with ggplot2 theme switcher
    output$theme_out_2 <- renderUI({
      cat('input$theme_in:', input$theme_in, '\n')
      if (input$theme_in == 'light') theme_set(theme_bw())
      else                           theme_set(theme_dark())
      NULL
    })
    output$plot_3 <- renderPlot({
      input$theme_in
      p
    })
    
    # Wrap with `observeEvent` doesn't work too
    # observeEvent(input$theme_in, {
    #   output$theme_out_2 <- renderUI({
    #     cat('input$theme_in:', input$theme_in, '\n')
    #     if (input$theme_in == 'light') theme_set(theme_bw())
    #     else                           theme_set(theme_dark())
    #   })
    # })
    # output$plot_3 <- renderPlot(p)
  }
)
1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.