0

I'm building a Shiny gadget using miniUI. I would like to display a loading screen while the gadget does some prep work and have tried implementing this simple and convenient solution: https://github.com/daattali/advanced-shiny/blob/master/loading-screen/app.R

Here's a small example of what the gadget might look like:

library(shiny)
library(shinyjs)
library(miniUI)

sampleApp <- function() {
  ui <- miniPage(
    gadgetTitleBar("Sample App"),
    miniTabstripPanel(
      miniTabPanel(
        "Panel 1",
        fillCol(div("Content of Panel 1"))
      ),
      miniTabPanel(
        "Panel 2",
        fillCol(div("Content of Panel 2"))
      ),
      between = p("") # Needed later on to avoid error in shinyjs::hidden()
    )
  )

  server <- function(input, output) {
  }

  runGadget(ui, server, viewer = dialogViewer("Sample dialog"))
}
sampleApp()

I have tried several ways of adapting the loading screen code to my example. I can't seem to get the content to hide:

  1. Place hidden() around miniTabstripPanel():

    library(shiny)
    library(shinyjs)
    library(miniUI)
    
    appCSS <- "
    #loading-content {
     position: absolute;
     background: #000000;
     opacity: 0.9;
     z-index: 100;
     left: 0;
     right: 0;
     height: 100%;
     text-align: center;
    color: #FFFFFF;
    }
    "
    
    sampleApp <- function() {
    ui <- miniPage(
      useShinyjs(),
      inlineCSS(appCSS),
    
      # Loading message
      div(
        id = "loading-content",
        h2("Loading...")
      ),
    
      # The main app code goes here
      gadgetTitleBar("AppTitle"),
      hidden(
        miniTabstripPanel(
          miniTabPanel(
            "Panel 1",
            fillCol(div("Content of Panel 1"))
          ),
          miniTabPanel(
            "Panel 2",
            fillCol(div("Content of Panel 2"))
          ),
          between = p("") # Needed later on to avoid error in shinyjs::hidden()
        ),
        id = "app-content"
      )
    )
    server <- function(input, output) {
      # Simulate work being done for 1 second
      Sys.sleep(1)
    
      # Hide the loading message when the rest of the server function has executed
      hide(id = "loading-content", anim = TRUE, animType = "fade")
      show("app-content")
    }
     runGadget(ui, server, viewer = dialogViewer("Sample dialog"))
    }
    sampleApp()
    
  2. Wrap content in a div().

  3. Use a tagList() according to this answer https://stackoverflow.com/a/32386689/5664232
Community
  • 1
  • 1
msenn
  • 3
  • 3

1 Answers1

0

Your second block of code doesn't run. You're missing a comma before between = p("").

This code does work for showing a loading screen and fading it out, the only thing it doesn't do is also hide the content initially. It looks like the miniUI tabsetpanel really doesn't like being inside any other div or element, so I just let it be. miniUI does have a lot of bugs and is much harder to deal with than regular shiny UI, it's just a quirk we have to deal with when building gadgets unfortunately. It's partly because miniUI uses a different CSS system (flex boxes), but anyway, this code works without hiding the content:

library(shiny)
library(shinyjs)
library(miniUI)

appCSS <- "
#loading-content {
position: absolute;
background: #000000;
opacity: 0.9;
z-index: 100;
left: 0;
right: 0;
height: 100%;
text-align: center;
color: #FFFFFF;
}
"

sampleApp <- function() {
  ui <- miniPage(
    useShinyjs(),
    inlineCSS(appCSS),

    # Loading message
    div(
      id = "loading-content",
      h2("Loading...")
    ),

    # The main app code goes here
    gadgetTitleBar("AppTitle"),
    miniTabstripPanel(
      miniTabPanel(
        "Panel 1",
        fillCol(div("Content of Panel 1"))
      ),
      miniTabPanel(
        "Panel 2",
        fillCol(div("Content of Panel 2"))
      ),
      between = p("") # Needed later on to avoid error in shinyjs::hidden()
    )
  )
  server <- function(input, output) {
    # Simulate work being done for 1 second
    Sys.sleep(1)

    # Hide the loading message when the rest of the server function has executed
    hide(id = "loading-content", anim = TRUE, animType = "fade")
  }
  runGadget(ui, server, viewer = dialogViewer("Sample dialog"))
}
sampleApp()

If you really want to hide the content from the UI and then show it, I'm sure it can be done with some workaround but it could take some time to debug it and I don't have that time now so I'll just show you a similar less ideal workaround: hide the tabs and the panel contents as soon as the server is alive, and show them at the end. It's not as good because they don't initialize as hidden, but it's the best I could come with in 2 minutes.

library(shiny)
library(shinyjs)
library(miniUI)

appCSS <- "
#loading-content {
position: absolute;
background: #000000;
opacity: 0.9;
z-index: 100;
left: 0;
right: 0;
height: 100%;
text-align: center;
color: #FFFFFF;
}
"

sampleApp <- function() {
  ui <- miniPage(
    useShinyjs(),
    inlineCSS(appCSS),

    # Loading message
    div(
      id = "loading-content",
      h2("Loading...")
    ),

    # The main app code goes here
    gadgetTitleBar("AppTitle"),
    miniTabstripPanel(
      miniTabPanel(
        "Panel 1",
        fillCol(div("Content of Panel 1"))
      ),
      miniTabPanel(
        "Panel 2",
        fillCol(div("Content of Panel 2"))
      ),
      between = p("") # Needed later on to avoid error in shinyjs::hidden()
    )
  )
  server <- function(input, output) {
    hide(selector = ".gadget-tabs-content-container, .gadget-tabs-container")

    # Simulate work being done for 1 second
    Sys.sleep(1)

    # Hide the loading message when the rest of the server function has executed
    hide(id = "loading-content", anim = TRUE, animType = "fade")
    show(selector = ".gadget-tabs-content-container, .gadget-tabs-container")
  }
  runGadget(ui, server, viewer = dialogViewer("Sample dialog"))
}
sampleApp()
DeanAttali
  • 25,268
  • 10
  • 92
  • 118
  • Thanks for your help. That's a feasible solution and I'll go with it for the time being. Also, I fixed the comma that I lost during editing. Sorry for that. – msenn Oct 18 '16 at 08:22