作为一个基本可行的示例,我从这里modularized https://rmarkdown.rstudio.com/flexdashboard/shiny.html#simple_example
.Rmd
运行):---
title: "stackoverflow example"
output: flexdashboard::flex_dashboard
runtime: shiny
---
```{r global, include=FALSE}
library(shiny)
library(flexdashboard) # install.packages("flexdashboard")
# load data in 'global' chunk so it can be shared by all users of the dashboard
library(datasets)
data(faithful)
# UI modules
sidebarCharts <- function(id) {
ns <- NS(id)
tagList(
p(),
actionButton(ns("settings"), "Settings", icon = icon("cogs"), width = '100%', class = "btn btn-info"),p(),
actionButton(ns("refreshMainChart") ,"Refresh", icon("refresh"), width = '100%', class = "btn btn-primary"),p()
,textOutput(ns("info")) # FOR DEBUGGING
)
}
mainChartUI <- function(id) {
ns <- NS(id)
plotOutput(ns("mainChart"), width = "100%")
}
# UI module for the 2 buttons in the modal:
modalFooterUI <- function(id) {
ns <- NS(id)
tagList(
modalButton("Cancel", icon("remove")),
actionButton(ns("modalApply"), "Apply", icon = icon("check"))
)
}
server <- function(input, output, session) {
# Init reactiveValues() to store values & debug info; https://github.com/rstudio/shiny/issues/1588
rv <- reactiveValues(clicks = 0, applyClicks = 0,
bins = 20,
bandwidth = 1)
# DEBUGGING
output$info <- renderText({
paste("You clicked the 'Settings' button", rv$clicks, "times. You clicked the 'Apply' button", rv$applyClicks, "times. The bin size is currently set to", rv$bins, "and the bandwidth is currently set to", rv$bandwidth)
})
settngsModal <- function(id) {
ns <- NS(id)
modalDialog(
withTags({ # UI elements for the modal go in here
fluidRow(
column(4, "Inputs",
selectInput(ns("n_breaks"), label = "Number of bins:", choices = c(10, 20, 35, 50), selected = rv$bins, width = '100%')),
column(4, "Go",
sliderInput(ns("bw_adjust"), label = "Bandwidth adjustment:", min = 0.2, max = 2, value = rv$bandwidth, step = 0.2, width = '100%')),
column(4, "Here")
)
}),
title = "Settings",
footer = modalFooterUI("inputs"),
size = "l",
easyClose = FALSE,
fade = TRUE)
}
# Sidebar 'Settings' modal
observeEvent(input$settings, {
showModal(settngsModal("inputs")) # This opens the modal; settngsModal() defined below
rv$clicks <- rv$clicks + 1 # FOR DEBUGGING
})
observeEvent(input$modalApply, {
rv$applyClicks <- rv$applyClicks + 1 # FOR DEBUGGING
rv$bins <- input$n_breaks # This is where I set the reactiveValues() to those inputted into the modal.
rv$bandwith <- input$bw_adjust
removeModal() # This should dismiss the modal (but it doesn't seem to work)
})
output$mainChart <- renderPlot({
input$refreshMainChart # Take dependency on the 'Refresh' buton
hist(faithful$eruptions, probability = TRUE, breaks = as.numeric(rv$bins),
xlab = "Duration (minutes)", main = "Geyser Eruption Duration")
dens <- density(faithful$eruptions, adjust = rv$bandwidth)
lines(dens, col = "blue")
})
}
```
Column {.sidebar}
-----------------------------------------------------------------------
```{r}
callModule(server, "main")
sidebarCharts("main")
```
Column
-----------------------------------------------------------------------
### Main chart goes here
```{r}
mainChartUI("main")
```
rv
reactiveValues()
中的bin大小和带宽的默认参数进行渲染-这似乎可行。 < / li>
rv
reactiveValues()
对象内的各个参数设置为已选择一个(s)-不起作用(模态既没有消失,reactiveValues
也没有更新)。reactiveValues()
内部的rv
更新之后,在用户点击“刷新” actionButton
之前,图表不应重新呈现-这也行不通,但取决于上面的(3)。我在做什么错?感觉就像我正在忽略一些超级简单的事情。
谢谢!
答案 0 :(得分:1)
问题来自以下事实:您的模态和服务器函数具有不同的namespace
id,因此无法以正常方式相互交谈。
使用server
调用callModule
函数时,将给模块命名空间"main"
。生成模态时,您为其指定了名称空间ID "inputs"
。因此,当您尝试使用actionButton
访问服务器中的observeEvent(input$modalApply...
时,它将无法正常工作,因为它正在其自己的命名空间的modalApply
中寻找inputs$
({{ 1}}),不存在。
您需要做的是将模式与调用它的服务器函数保持在相同的名称空间中。您可以通过将"main"
函数直接从会话传递到模式UI函数中来实现。
您可以直接使用ns
获得当前会话id
的功能,然后将其传递到ns <- NS(id)
中,而不用传入ns
然后再使用session$ns
重新生成ns。要使用的UI功能:
observeEvent(input$settings, {
showModal(settngsModal(session$ns))
}
...
settngsModal <- function(ns) {
...
footer = modalFooterUI(ns),
...
}
通过以这种方式传递session$ns
,可以确保模式的UI元素始终与调用它的服务器函数位于相同的名称空间中(并因此可以访问)。您可以在此处了解更多信息:http://shiny.rstudio.com/articles/modules.html#using-renderui-within-modules
对于您的第二个问题,只需将renderPlot
中的其余代码包装在isolate
函数中即可。 isolate
函数可以使reactive
内isolate
值的更改不会使表达式无效并使它重新求值。现在,唯一可以引起reactive
重新评估的renderPlot
值就是isolate
之外的值:input$refreshMainChart
:
output$mainChart <- renderPlot({
input$refreshMainChart # Take dependency on the 'Refresh' buton
isolate({
hist(faithful$eruptions, probability = TRUE, breaks = as.numeric(rv$bins),
xlab = "Duration (minutes)", main = "Geyser Eruption Duration")
dens <- density(faithful$eruptions, adjust = rv$bandwidth)
lines(dens, col = "blue")
})
})