I'm using a rather complex flexdashboard structure with 10 pages and several graphics. The loading time is about 30" and I would like to show on each page the text "Loading data..." until the charts are effectively available.
To reach this, I've inserted in each page a Loading data... and I'm using a Javascript to detect when the page is loaded to set the visibility to hidden for all the .
When the charts are loaded, the text "Loading data..." does not hide.
Here is a reproducible example:
---
title: 'Reprex'
output:
flexdashboard::flex_dashboard:
orientation: column
vertical_layout: fill
runtime: shiny
---
```{r setup, include=FALSE}
tags$head(tags$script(src = "script.js"))
```
Reprex{data-icon="fa-chart-bar"}
=====================================
<div id="loading">Loading data...</div>
```{r}
renderPlot({
Sys.sleep(5) #it's just to mimic the elaboration time
plot(cars)
})
```
Here is the content of the javascript file (that sits in the same directory of the RMD file:
$(document).on('shiny:busy', function(event) {
var cont = document.getElementById("loading");
cont.style.visibility = "visible";
});
$(document).on('shiny:idle', function(event) {
var cont = document.getElementById("loading");
cont.style.visibility = "hidden";
});
Thank you in advance for your kind support.
Do this:
---
title: 'Reprex'
output:
flexdashboard::flex_dashboard:
orientation: column
vertical_layout: fill
runtime: shiny
---
```{js}
Shiny.addCustomMessageHandler("loading-done", function(data){
document.querySelector(`[data-loading="${data.loading_id}"]`).style.display = "none"
})
```
Reprex{data-icon="fa-chart-bar"}
=====================================
<div data-loading="loading-1">Loading data...</div>
```{r}
renderPlot({
Sys.sleep(5) #it's just to mimic the elaboration time
on.exit(session$sendCustomMessage("loading-done", list(loading_id = "loading-1")))
plot(cars)
})
```
id
to custom data-loading
property, because flexdashboard
adds some prefix to your IDs. Don't want to waste time predicting the pattern.<div data-loading="loading-1"> ... </div>
on each of your page, just remember to change the loading ID. data-loading="loading-X"
is paired with list(loading_id = "loading-x")
on server.I would suggest you use other loader libraries so you don't need to write your own JS.
---
title: 'Reprex'
output:
flexdashboard::flex_dashboard:
orientation: column
vertical_layout: fill
runtime: shiny
---
```{r include=FALSE}
library(spsComps)
```
Reprex{data-icon="fa-chart-bar"}
=====================================
```{r}
plotOutput("plot1")
```
```{r}
loader1 <- addLoader$new(
target_selector = "plot1",
footer = h4("Loading data...")
)
output$plot1 <- renderPlot({
loader1$show()
Sys.sleep(5) #it's just to mimic the elaboration time
on.exit(loader1$hide())
plot(cars)
})
```
For this, each page needs its own loader.
If you want multiple pages, we can use the full_screen
loader so all pages can share the same loader.
---
title: 'Reprex'
output:
flexdashboard::flex_dashboard:
orientation: column
vertical_layout: fill
runtime: shiny
---
```{r include=FALSE}
library(spsComps)
```
Reprex{data-icon="fa-chart-bar"}
=====================================
```{r}
plotOutput("plot1")
```
```{r}
loader1 <- addLoader$new(
target_selector = "body", isID = FALSE, method = "full_screen",
footer = h4("Loading data..."), height = "300px"
)
output$plot1 <- renderPlot({
loader1$show()
Sys.sleep(2) #it's just to mimic the elaboration time
on.exit(loader1$hide())
plot(cars)
})
```
Reprex{data-icon="fa-home"}
=====================================
```{r}
renderUI({
loader1$show()
Sys.sleep(2)
on.exit(loader1$hide())
div("another page")
})
```