2016-02-24 16 views
6

Ich habe das erste Laden von Daten aus dem DB in der server.R, die ein paar Sekunden dauert. Bis dahin ist die angezeigte Seite verzerrt (falsche Daten in der Auswahlbox und seltsame Platzierung der Boxen, siehe unten). Distorted displayShiny Dashboard - Anzeige einer dedizierten "loading .." Seite, bis das erste Laden der Daten erfolgt

Ich möchte eine andere Seite (oder zumindest anderen Inhalt in meiner zuerst angezeigten Registerkarte) anzeigen, bis die Daten vollständig geladen sind.

Ich dachte über eine Art von conditionalPanel mit einer Bedingung basierend auf einer dedizierten globalen Variable (initial_loading_done), aber wo immer ich versuchte conditionalPanel es hat nicht funktioniert.

Dies ist die Struktur meiner UI.R:

shinyUI(

    dashboardPage(
    dashboardHeader(title = "Title"), 
    dashboardSidebar(
     sidebarMenu(
      menuItem("Tab1", tabName = "Tab1",icon = icon("dashboard")), 
      menuItem("Tab2", tabName = "Tab2", icon = icon("bar-chart-o")) 
     ) 
    ), 
    dashboardBody(
     includeCSS("custom_css.css"), 
     tabItems(
      tabItem(tabName = "Tab1", 
        fluidRow(<content>), 
        mainPanel(
         fluidRow(<content>) 
        ) 
      ), 
      tabItem(tabName = "Tab2", 
        fluidRow(<content>), 
        mainPanel(
         dataTableOutput('my_data_table') 
       ) 
      ) 
     ) 
    ) 
) 
) 
+0

siehe [1] (http://stackoverflow.com/questions/17325521/r-shiny-display-loading-message-while-function-is-running) – Batanichek

Antwort

1

In server Ich mag reactiveValues() verwenden, um einen setupComplete Zustand zu speichern. Dann, wenn die Daten geladen sind, ist mein setupComplete auf TRUE gesetzt.

Im ui können wir dann beurteilen diese setupComplete Zustand in einem conditionalPanel, und nur die Inhalte angezeigt werden (in meinem Beispiel die drei box() Widgets).

Hier ist ein funktionierendes Beispiel

## app.R ## 
library(shiny) 
library(shinydashboard) 
library(shinyjs) 

ui <- dashboardPage(
    dashboardHeader(), 
    dashboardSidebar(), 
    dashboardBody(
     actionButton(inputId = "btn_data", label = "Download"), 
     conditionalPanel(condition = "output.setupComplete", 
      box(title = "box1"), 
      box(title = "box2"), 
      box(title = "boc3") 
     ), 
     conditionalPanel(condition = "!output.setupComplete", 
         box(title = "loading")) 
    ) 
) 

server <- function(input, output) { 

    rv <- reactiveValues() 
    rv$setupComplete <- FALSE 

    ## simulate data load 
    observe({ 

     if(input$btn_data){ 

      df <- data.frame(id = seq(1,200), 
          val = rnorm(200, 0, 1)) 

      ## Simulate the data load 
      Sys.sleep(5) 
      ## set my condition to TRUE 
      rv$setupComplete <- TRUE 
     } 

     ## the conditional panel reads this output 
     output$setupComplete <- reactive({ 
      return(rv$setupComplete) 
     }) 
     outputOptions(output, 'setupComplete', suspendWhenHidden=FALSE) 

    }) 
} 

shinyApp(ui, server) 
+0

Danke, das wirklich hilfreich! Ich möchte eine "Lade" -Seite anzeigen, bis der Ladevorgang abgeschlossen ist. Also habe ich ein ConditionalPanel mit der Bedingung "! Output.setupComplete" erstellt. Aber es kann den setupComplete-Parameter nicht auswerten. Was sollte ich in der server.r ändern, damit es funktioniert? – KeshetE

+0

Ich habe meine Antwort mit einem zweiten Bedingungsfenster aktualisiert, das eine 'Lade'-Box zeigt, bevor die Daten geladen werden. Wenn Sie komplexere Operationen ausführen möchten, empfehle ich @daattalis exzellentes Paket 'shinyjs' (wie in seiner Antwort erwähnt) – SymbolixAU

+0

Ihr Beispiel funktioniert jetzt nicht für mich - bleibt bei" Laden "und ändert sich nicht in die eigentliche Inhaltsseite. Wenn ich es in meiner App versuche, sehe ich die Box, bis die Daten geladen sind - aber ich sehe ihren Inhalt nicht (nur eine leere Box). Ziemlich sicher, es hat etwas mit der Position des ConditionalPanel in meinem Code zu tun - es ist in einem TabItem. – KeshetE

18

Hier ist ein sehr einfaches Beispiel mit shinyjs Paket

Die Idee ist, das Laden „Seite“ und den Inhalt „Seite“ unter verschiedenen IDs zu erstellen, haben den Inhalt Seite zunächst versteckt, und verwenden Sie show() und hide() nach der App bereit ist

library(shiny) 
library(shinyjs) 

load_data <- function() { 
    Sys.sleep(2) 
    hide("loading_page") 
    show("main_content") 
} 

ui <- fluidPage(
    useShinyjs(), 
    div(
    id = "loading_page", 
    h1("Loading...") 
), 
    hidden(
    div(
     id = "main_content", 
     "Data loaded, content goes here" 
    ) 
) 
) 

server <- function(input, output, session) { 
    load_data() 
} 

shinyApp(ui = ui, server = server) 
+0

Vor allem - danke! Der main_content wird tatsächlich ausgeblendet und nach dem Laden der Daten angezeigt, was großartig ist. Aber 9 von 10 Mal starte ich die App, die "loading_page" wird gar nicht angezeigt ... Was mache ich falsch? – KeshetE

+0

Sieht aus wie überall, wo ich das erste div (mit der loading_page) platziere, es wird nicht berechnet, bis die App-Daten fertig geladen sind - ich habe versucht, den show/hide-Teil zu entfernen und er wird erst angezeigt, wenn die Daten vollständig geladen sind. Hat das etwas damit zu tun, dass ich Shinydashboard benutze? – KeshetE

+0

Nein, es spielt keine Rolle, wo Sie die Elemente platzieren. Die loading_page sollte sofort erscheinen, und das andere div sollte nicht erscheinen (weil es in einer 'hidden()' Funktion ist), und es sollte nur erscheinen, nachdem 'Sys.sleep (2)' fertig ist. Wenn Sie diesen Beispielcode ausführen, sollte er 10/10 mal funktionieren. Es funktioniert auch mit einem Shinydashboard –

0

der Code

hidden(
    div(
     id = "main_content", 
     "Data loaded, content goes here" 
    ) 

funktioniert nicht mit TabsetPanel. Aber wenn du die ID auf die Div-Ebene verschiebst, funktioniert sie wunderbar. Danke an shinyjs Autor Dean Attali für diesen Tipp. https://stackoverflow.com/users/4432127/keshete

hidden(
     div(id = "mainTabsetPanel", 
      tabsetPanel(
....