rshinybslibslickr

How to prevent slickR from removing inputs and how to keep original size?


I have a shiny app where I'm trying to update some plots to slickR. I'm getting some unexpected effects:

  1. The card_footer disappears.
  2. How can I keep the original height and width and make it resize when I collapse the sidebar as if I would just plotOutput?
  3. I get a scroll bar for the plot although there is space below.
library(shiny)
library(slickR)
library(svglite)
library(tidyverse)
library(gdtools)
library(bslib)
library(shinyWidgets)

ui <-
  page_fluid(layout_sidebar(
    sidebar = tagList(
      pickerInput("select_a", "Select", choices = LETTERS[1:10]),
      pickerInput("select_b", "Select", choices = LETTERS[1:10]),
      pickerInput("select_c", "Select", choices = LETTERS[1:10]),
      pickerInput("select_d", "Select", choices = LETTERS[1:10])
    ) ,
    
    bslib::accordion(open = FALSE, accordion_panel("Ab Panel", actionButton("run", "Run"))),
    
    #plotOutput("plt"), slickROutput("slickr"), card_footer(card_body( layout_column_wrap( width = 1 / 2, actionButton("ab1", "Go1"), actionButton("ab2", "Go2") ) ))
    
  ))

server <-
  function(input, output, session) {
    output$plt <-
      renderPlot({
        ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) + geom_point()
        
      })
    
    output$slickr <-
      renderSlickR({
        slickR(svglite::xmlSVG({
          methods::show(ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) + geom_point())
        }, standalone = TRUE))
        
      })
    
  }

shinyApp(ui, server)

Solution

  • The inputs are not removed, but simply hidden beneath the svg which is 7 x 7 inches by default. Assuming a DPI of 96 this exceeds the default height (400px) of the slickROutput.

    Thus, you need to tell xmlSVG to use suitable dimensions and bring them in-sync with the height and the widths of the output. You can use session$clientData$output_slickr_width which gives you the current width of the slickr output width in pixels and use this information to transform to inches:

    library(shiny)
    library(slickR)
    library(svglite)
    library(tidyverse)
    library(gdtools)
    library(bslib)
    library(shinyWidgets)
    
    p2i <- function(pixels, dpi = 96) {
      pixels / dpi
    }
    
    ## anyways defaults but explicit beats implicit
    height <- 400
    width <- "100%"
    
    ui <-
      page_fluid(
        layout_sidebar(
        sidebar = tagList(
          pickerInput("select_a", "Select", choices = LETTERS[1:10]),
          pickerInput("select_b", "Select", choices = LETTERS[1:10]),
          pickerInput("select_c", "Select", choices = LETTERS[1:10]),
          pickerInput("select_d", "Select", choices = LETTERS[1:10])
        ) ,
        
        bslib::accordion(open = FALSE, accordion_panel("Ab Panel", actionButton("run", "Run"))),
        plotOutput("plt"),
        slickROutput("slickr", width = width, height = height), 
        card_footer(
          card_body(
            layout_column_wrap(width = 1 / 2, 
                               actionButton("ab1", "Go1"), 
                               actionButton("ab2", "Go2")
            )
          )
        )
      )
      )
    
    
    
    server <-
      function(input, output, session) {
        
        output$plt <-
          renderPlot({
            ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) + geom_point()
            
          })
        
        output$slickr <-
          renderSlickR({
            plt <- svglite::xmlSVG({
              show(
                ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) + geom_point()
              )
            }, height = p2i(height), width = p2i(session$clientData$output_slickr_width), 
            standalone = TRUE)
            slickR(
              list(plt, plt)
            )
          })
        
      }
    
    shinyApp(ui, server)
    

    Shinyapp with a slickROutput showing a ggplot and a sidebar and some buttons below