简体   繁体   中英

Show shinycssloaders spinner until full DT table (in shiny) is ready

The R shinycssloaders package does a nice job of showing a spinner initially. But if the table is very big then it only shows initially and then you see the header for a while as the user waits for the table. In my real data this wait is longer than this example so the user doesn't really know what's going on.

I'd like to have the spinner continue to show until the whole dataset (not just the header) is ready to view.

Suggestions?

Zev

library(shiny)
library(DT)
library(shinycssloaders)
shinyApp(
  ui = fluidPage(fluidRow(column(12,withSpinner(DT::DTOutput('tbl'))))),
  server = function(input, output) {
    Sys.sleep(2)
    output$tbl = renderDT(
      data.frame(a = 1:10000000, b = 1:10000000)
    )
  }
)

shinycssloaders is not working after Shiny rendering event is done. In this case datatable.js is asynchronous. After the table skeleton is rendered, it is fetching the data and waits for the data to be load then updates the table. Shiny rendering is done on the first part, so shinycssloaders cannot cover the second part.

To do this, we need to use advanced custom loaders, in this case, my example uses addLoader from spsComps , which adds loaders from the server-side and you can decide when to add it and when to hide it.

The way I know when to apply the loader is based on datatable events . I added some js to tell Shiny server these events happened, eg table starts to load, page change triggers, etc. You can add more if you want. Then, from server, I show the loader. When the table data is loaded, I tell Shiny server again, then I hide the loader.

library(shiny)
library(DT)
library(spsComps)
shinyApp(
    ui = fluidPage(
        fluidRow(column(12,DT::DTOutput('tbl'))),
        tags$script(
            "
            function loaderStart() {
                Shiny.setInputValue('loader_state', 1)
            }
            function loaderEnd() {
                Shiny.setInputValue('loader_state', 0)
            }
            $('#tbl').on('draw.dt', function () {
                loaderEnd();
            });
            $('#tbl').on('page.dt', function () {
                loaderStart();
            });
            $('#tbl').on('preInit.dt', function () {
                loaderStart();
            });
            $('#tbl').on('order.dt', function () {
                loaderStart();
            });
            "
        )
    ),
    server = function(input, output) {
        tbl_loader <- addLoader$new("tbl")
        output$tbl = renderDT(
            data.frame(a = 1:10000000, b = 1:10000000)
        )
        observeEvent(input$loader_state, {
            req(!is.null(input$loader_state))
            if(input$loader_state == 1) {
                tbl_loader$recreate(
                    type = "facebook",
                    footer = tags$span("Loading data ...", style = "display: block")
                )$show()
            } 
            else tbl_loader$hide()
        })
    }
)

Read more about addLoader , and try some demos

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM