0

I have a Shiny application that plots large treemaps. I create the treemap objects ahead of time and serialize them:

library(readr)
library(magrittr)
library(highcharter)
library(treemap)

tm_file_name <- function(num_leaves) {
  paste0(as.character(num_leaves), "_leaves.rds")
}

create_rand_treemap <- function(num_leaves) {
  random.hierarchical.data(n = num_leaves) %>%
    treemap(index = c("index1", "index2", "index3"),
            vSize = "x",
            draw = FALSE) %>%
    hctreemap(allowDrillDown = TRUE) %>%
    write_rds(tm_file_name(num_leaves))
}

for (leaves in c(50, 500, 5000)) {
  create_rand_treemap(leaves)
}

Then I load them like this:

library(shiny)
library(shinydashboard)
library(shinycssloaders)
library(readr)
library(highcharter)

tm_file_name <- function(num_leaves) paste0(as.character(num_leaves), "_leaves.rds")
load_treemap <- function(num_leaves) tm_file_name(num_leaves) %>% read_rds()

ui <- dashboardPage(
  dashboardHeader(
    title = "Reproducible Shiny Example",
    titleWidth = "100%"
  ),

  dashboardSidebar(
    radioButtons(
      "num_leaves", "Number of Leaves in Treemap:",
      c("50" = 50, "500" = 500, "5000" = 5000)
    ),
    actionButton("createTreemap", "Create Treemap")
  ),

  dashboardBody(
    # CSS spinner
    withSpinner(highchartOutput("treemap", width = "100%", height = "500px"),
                type = 7))
)

server <- function(input, output) {
  output$treemap <- renderHighchart({

    # load and render only on button press
    if (length(input$createTreemap) != 0) {
      if (input$createTreemap > 0) {

        # notification attempt
        progress <- shiny::Progress$new()
        on.exit(progress$close())
        progress$set(message = 'Generating treemap...')

        isolate({load_treemap(input$num_leaves)})
      }
    }
  })
}

shinyApp(ui = ui, server = server)

I would like to display a loading notification or spinner until the treemap has fully rendered.

The above example, live here, contains two attempts at this.

The first attempt uses Shiny progress objects to create a notification. However, the notification only displays for a very short time before disappearing. I believe this is because Shiny only has to read a serialized file and then it thinks the task is complete, but it takes the browser a long time to render the plot.

I've also tried a shinycssloaders approach, but

  • The CSS spinner displays briefly when the application first loads, which I don't want.
  • The spinner freezes after several seconds when rendering large treemaps (i.e 5000 leaves).

Lastly, I tried some blind copy-pasting from this SO question, but either couldn't get the solutions there to work with shinydashboard or to persist until the rendering was complete.

How can I display Shiny notifications until both Shiny and the browser are no longer busy?

alexpghayes
  • 673
  • 5
  • 17
  • you can use `withProgress` like [this](https://shiny.rstudio.com/reference/shiny/latest/withProgress.html) and rendering `treemaps` on large data is intensive progress but `withProgress` will definitely work – parth Jul 03 '17 at 06:41
  • 1
    added a live example... don't think `withProgress` will work because I'll call `load_treemap` inside it's scope, `load_treemap` will complete almost instantaneously, the `withProgress` scope will terminate and the notification will disappear, and then treemap will take a long time to render – alexpghayes Jul 03 '17 at 19:02

0 Answers0