Shiny Dashboard - отображать специальную страницу загрузки .. до завершения начальной загрузки данных.

У меня есть начальная загрузка данных из БД в server.R, которая занимает несколько секунд. Пока это не будет сделано, отображаемая страница будет искажена (неверные данные в поле выбора и странное расположение полей, см. Ниже). «Искаженное

Я хочу отображать другую страницу (или, по крайней мере, другой контент на моей первой отображаемой вкладке), пока данные не будут полностью загружены.

Я думал о том, чтобы сделать что-то conditionalPanel, используя условие, основанное на выделенной глобальной переменной (initial_loading_done), но где бы я ни пытался разместить conditionalPanel, это не сработало.

Это структура моего 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')  
                  )
           )
       )
    )
 )
)

person KeshetE    schedule 24.02.2016    source источник
comment
см. 1   -  person Batanichek    schedule 25.02.2016


Ответы (3)


Вот очень простой пример использования пакета shinyjs.

Идея состоит в том, чтобы создать загрузочную «страницу» и «страницу» контента под разными идентификаторами, изначально скрыть страницу контента и использовать show() и hide() после того, как приложение будет готово.

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)
person DeanAttali    schedule 27.02.2016
comment
Прежде всего - спасибо! Main_content действительно скрыт и отображается после загрузки данных, и это здорово. Но 9 из 10 раз, когда я запускаю приложение, страница loading_page не отображается вообще ... Что я делаю не так? - person KeshetE; 28.02.2016
comment
Похоже, где бы я ни поместил первый div (с loading_page), он не рассчитывается до тех пор, пока данные приложения не будут загружены - я попытался удалить часть отображения / скрытия, и она отображается только после полной загрузки данных. Это как-то связано с тем, что я использую shinydashboard? - person KeshetE; 01.03.2016
comment
нет, неважно, где вы размещаете элементы. Страница loading_page должна появиться немедленно, а другой div не должен отображаться (потому что он находится внутри функции hidden()), и он должен появиться только после завершения работы Sys.sleep(2). Если вы запустите этот пример кода, который я показываю, он должен сработать 10/10 раз. Он также будет работать с блестящей приборной панелью. - person DeanAttali; 01.03.2016
comment
Для других, которые ищут в Google медленное время начальной загрузки shinyapps.io, похоже, это тоже помогает. - person Frans Rodenburg; 03.03.2019

В server мне нравится использовать reactiveValues() для хранения setupComplete условия. Затем, когда данные загружены, мой setupComplete устанавливается на TRUE.

Затем в ui мы можем оценить это setupComplete условие в conditionalPanel и отобразить только содержимое (в моем примере три box() виджета).

Вот рабочий пример

## 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)
person SymbolixAU    schedule 25.02.2016
comment
Спасибо, это действительно помогло! Я хочу отображать страницу загрузки до завершения загрузки, поэтому создал еще одну условную панель с условием! Output.setupComplete. Но он не может оценить параметр setupComplete. Что мне нужно изменить в server.r, чтобы он заработал? - person KeshetE; 28.02.2016
comment
Я обновил свой ответ, добавив вторую условную панель, которая показывает поле «загрузка» перед загрузкой данных. Если вы хотите начать выполнять более сложные операции, я рекомендую использовать отличный пакет shinyjs от @daattali (как указано в его ответе) - person SymbolixAU; 28.02.2016
comment
Теперь ваш пример не работает для меня - остается с загрузкой и не изменяется на фактическую страницу содержимого. При попытке в своем приложении я вижу поле до тех пор, пока данные не будут загружены, но не вижу его содержимого (просто пустое поле). Совершенно уверен, что это как-то связано с расположением conditionalPanel в моем коде - он находится внутри tabItem. - person KeshetE; 28.02.2016

Код

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

не работает с tabsetPanel. Но если вы переместите идентификатор на уровень div, он отлично работает. Спасибо автору shinyjs Дину Аттали за этот совет. https://stackoverflow.com/users/4432127/keshete

  hidden(
        div(id = "mainTabsetPanel",
          tabsetPanel(
....
person JerryN    schedule 03.05.2017