闪亮的仪表板 - 显示一个专用的“正在加载..”页面,直到数据的初始加载完成
Posted
技术标签:
【中文标题】闪亮的仪表板 - 显示一个专用的“正在加载..”页面,直到数据的初始加载完成【英文标题】:Shiny Dashboard - display a dedicated "loading.." page until initial loading of the data is done 【发布时间】:2016-06-06 14:01:45 【问题描述】:我已经从server.R
的数据库中初始加载数据,这需要几秒钟。在完成此操作之前,显示的页面会失真(选择框中的数据错误,并且框的位置很奇怪,见下文)。
我想在数据完全加载之前显示一个不同的页面(或至少在我第一个显示的选项卡中显示不同的内容)。
我曾想过使用基于专用全局变量 (initial_loading_done) 的条件来执行某种 conditionalPanel
,但无论我尝试放置 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')
)
)
)
)
)
)
【问题讨论】:
见1 【参考方案1】:这是一个使用 shinyjs
包的非常简单的示例
想法是创建不同ID下的加载“页面”和内容“页面”,初始隐藏内容页面,并在应用程序准备好后使用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)
【讨论】:
首先 - 谢谢! main_content 确实是在数据加载完成后隐藏显示出来的,非常棒。但是在我启动应用程序的 10 次中,有 9 次根本没有显示“loading_page”……我做错了什么? 看起来就像我放置第一个 div(带有 loading_page)的任何地方,直到应用程序数据完成加载才计算它 - 我尝试删除显示/隐藏部分,它仅在数据已完全加载。这与我使用 shinydashboard 的事实有关吗? 不,放置元素的位置无关紧要。 loading_page 应该立即显示,而另一个 div 不应该显示(因为它在hidden()
函数内),它应该只在 Sys.sleep(2)
完成运行后显示。如果你运行我展示的这个示例代码,它应该可以工作 10/10 次。它也适用于闪亮的仪表板
对于其他人在谷歌上搜索缓慢的 shinyapps.io 初始加载时间,这似乎也可以解决这个问题。
Dean 的解决方案确实有效。有没有办法让过渡更平滑,让它淡入加载的页面,而不是消失以显示加载的页面?【参考方案2】:
在server
中,我喜欢使用reactiveValues()
来存储setupComplete
条件。然后,当加载数据时,我的setupComplete
设置为TRUE
。
在ui
中,我们可以在conditionalPanel
中评估这个setupComplete
条件,并且只显示内容(在我的示例中是三个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)
【讨论】:
谢谢,这真的很有帮助!我想在加载完成之前显示一个“正在加载”页面,因此创建了另一个条件为“!output.setupComplete”的条件面板。但它无法评估 setupComplete 参数。我应该在 server.r 中进行哪些更改才能使其正常工作? 我已经用第二个条件面板更新了我的答案,该面板在加载数据之前显示了一个“加载”框。如果您想开始执行更复杂的操作,我建议您使用 @daattali 的出色shinyjs
包(如他的回答中所引用)
现在您的示例对我不起作用 - 停留在“正在加载”并且不会更改为实际内容页面。在我的应用程序中尝试时,我会看到该框,直到加载数据 - 但看不到它的内容(只是一个空框)。很确定它与我的代码中 conditionalPanel 的位置有关 - 它位于 tabItem 内。【参考方案3】:
代码
hidden(
div(
id = "main_content",
"Data loaded, content goes here"
)
不适用于 tabsetPanel。但是,如果您将 id 移动到 div 级别,它会很好地工作。感谢 shinyjs 作者 Dean Attali 提供的这个技巧。 https://***.com/users/4432127/keshete
hidden(
div(id = "mainTabsetPanel",
tabsetPanel(
....
【讨论】:
以上是关于闪亮的仪表板 - 显示一个专用的“正在加载..”页面,直到数据的初始加载完成的主要内容,如果未能解决你的问题,请参考以下文章
R 闪亮的仪表板由于某种原因不显示图表。不允许我在一个 ggplot 渲染中添加 2 个反应式表达式
错误的显示 - 如何在闪亮的仪表板标题中很好地适应选择输入并设置它的样式