Hi all,
I've been trying to come up with a solution for what seems like a common use case related to this discussion for a couple of weeks now with no luck. This conversation comes the closest to explaining how global variables might be created and used across Shiny apps - but I'm having difficulty understanding the nuances of the code provided.
The Global Profile Problem
We have an app that walks a user through a "wizard setup"
intro that allows them to configure certain parameters that impact the functioning of individual Shiny application modules in a multiple app flexdashboard. These need to be stored globally, passed into the sub applications, and in the "profile" app need to be modifiable at the global level such that changes made to the global profile modify the functioning of the other modules accordingly.
I'm attempting to make sense of the code provided in this post and adapt it to this use case but thus far I've been unable to determine how to do so. Any help would be greatly appreciated!
---
title: "Global Profile Reprex"
output:
flexdashboard::flex_dashboard:
orientation: columns
vertical_layout: fill
runtime: shiny
---
```{r setup, include=FALSE}
library(flexdashboard)
library(shiny)
library(magrittr)
Global <- function(input, output, session) {
profile <- reactiveValues(goal = 5)
return(profile)
}
Module1 <- function(input, output, session, globals) {
goal = globals$profile
}
```
Column {data-width=500}
-----------------------------------------------------------------------
### Access
```{r 'Access'}
# This is just intented to access the global reactive values
ui <- renderUI(fluidPage(
shiny::htmlOutput("viewProfile")
))
server <- function(input, output, session) {
globalProfile <- callModule(Global, "global")
output$viewProfile <- shiny::renderText({
paste0("Goal:",globalProfile$profile$goal)
})
}
# Run the application
shinyApp(ui = ui, server = server)
```
Column {data-width=500}
-----------------------------------------------------------------------
### Update
```{r 'Update'}
# This is intended to allow a user to update the global reactive values.
ui <- renderUI(fluidPage(
fluidRow(width = 12,
column(12,
textInput(inputId = "goal",
label = "Goals (time per week)",
placeholder = "ex 4h42m 4:42"))),
fluidRow(width = 12,
column(5), column(2, submitButton("Save Changes", icon("save", lib = "font-awesome"))), column(5)) ,
shiny::htmlOutput("test.text")
))
# Define server logic required to draw a histogram
server <- function(input, output, session) {
globalProfile <- callModule(Global, "global")
reactive({
print("profile Saved")
mod1 <- callModule(Module1, "mod1", globalProfile)
mod1$profile$goal <- input$goal
})
output$test.text <- shiny::renderText({
c("Goal",globalProfile$profile$goal) %>% paste0(collapse = " ")
})
}
# Run the application
shinyApp(ui = ui, server = server)
```
R version 3.5.3 (2019-03-11)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 18362)
Matrix products: default
locale:
[1] LC_COLLATE=English_United States.1252
[2] LC_CTYPE=English_United States.1252
[3] LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C
[5] LC_TIME=English_United States.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] magrittr_1.5 shiny_1.4.0.9000 RevoUtils_11.0.3
[4] RevoUtilsMath_11.0.0
loaded via a namespace (and not attached):
[1] Rcpp_1.0.3.1 pillar_1.4.2
[3] compiler_3.5.3 later_1.0.0
[5] plyr_1.8.4 tools_3.5.3
[7] digest_0.6.22.3 packrat_0.4.9-3
[9] lubridate_1.7.4.9000 jsonlite_1.6.9000
[11] evaluate_0.14 tibble_2.1.3
[13] gtable_0.2.0 pkgconfig_2.0.3
[15] rlang_0.4.1 rstudioapi_0.10.0-9000
[17] yaml_2.2.0 xfun_0.11.1
[19] fastmap_1.0.1 withr_2.1.2
[21] dplyr_0.8.3 httr_1.4.1.9000
[23] knitr_1.26 grid_3.5.3
[25] tidyselect_0.2.5 flexdashboard_0.5.1.9000
[27] glue_1.3.1.9000 R6_2.4.1
[29] rmarkdown_1.17 ggplot2_3.1.0
[31] purrr_0.3.3.9000 promises_1.1.0.9000
[33] scales_1.0.0.9000 htmltools_0.4.0.9000
[35] rsconnect_0.8.13 assertthat_0.2.1
[37] xtable_1.8-4 mime_0.7
[39] colorspace_1.4-0 httpuv_1.5.2.9000
[41] lazyeval_0.2.1 munsell_0.5.0
[43] crayon_1.3.4
Update
The access function works with this simplified code, but I am still unable to figure out how to update the global reactiveValues from inside the Update app.
---
title: "Global Profile Reprex"
output:
flexdashboard::flex_dashboard:
orientation: columns
vertical_layout: fill
runtime: shiny
---
```{r setup, include=FALSE}
library(flexdashboard)
library(shiny)
library(magrittr)
profile <- reactiveValues(goal = 5)
Module1 <- function(input, output, session, globals) {
goal = globals$profile
}
```
Column {data-width=500}
-----------------------------------------------------------------------
### Access
```{r 'Access'}
# This is just intented to access the global reactive values
ui <- renderUI(fluidPage(
shiny::htmlOutput("viewProfile")
))
server <- function(input, output, session) {
output$viewProfile <- shiny::renderText({
paste0("Goal:", profile$goal)
})
}
# Run the application
shinyApp(ui = ui, server = server)
```
Column {data-width=500}
-----------------------------------------------------------------------
### Update
```{r 'Update'}
# This is intended to allow a user to update the global reactive values.
ui <- renderUI(fluidPage(
fluidRow(width = 12,
column(12,
textInput(inputId = "goal",
label = "Goals (time per week)",
placeholder = "ex 4h42m 4:42"))),
fluidRow(width = 12,
column(5), column(2, submitButton("Save Changes", icon("save", lib = "font-awesome"))), column(5)) ,
shiny::htmlOutput("test.text")
))
# Define server logic required to draw a histogram
server <- function(input, output, session) {
reactive({
print("profile Saved")
profile$goal <<- input$goal
})
output$test.text <- shiny::renderText({
c("Goal: ",profile$goal) %>% paste0(collapse = " ")
})
}
# Run the application
shinyApp(ui = ui, server = server)
```
Update 2019-11-15 1657
Alright, solved this after some tinkering! Use of observeEvent
and the save actionButton
correctly updates the reactive profile values.
---
title: "Global Profile Reprex"
output:
flexdashboard::flex_dashboard:
orientation: columns
vertical_layout: fill
runtime: shiny
---
```{r setup, include=FALSE}
library(flexdashboard)
library(shiny)
library(magrittr)
profile <- reactiveValues(goal = 5)
Module1 <- function(input, output, session, globals) {
goal = globals$profile
}
```
Column {data-width=500}
-----------------------------------------------------------------------
### Access
```{r 'Access'}
# This is just intented to access the global reactive values
ui <- renderUI(fluidPage(
shiny::htmlOutput("viewProfile")
))
server <- function(input, output, session) {
output$viewProfile <- shiny::renderText({
paste0("Goal:", profile$goal)
})
}
# Run the application
shinyApp(ui = ui, server = server)
```
Column {data-width=500}
-----------------------------------------------------------------------
### Update
```{r 'Update'}
# This is intended to allow a user to update the global reactive values.
profile <- reactiveValues(goal = 5)
uiUpdate <- fluidPage(
fluidRow(width = 12,
column(12,
textInput(inputId = "goal",
label = "Goals (time per week)",
placeholder = "ex 4h42m 4:42")), actionButton("save","Save Changes", icon("save", lib = "font-awesome"))),
shiny::htmlOutput("test.text")
)
# Define server logic required to draw a histogram
serverUpdate <- function(input, output, session) {
observeEvent(input$save,{
# print("profile Saved")
message("Profile Saved")
profile$goal <<- input$goal
})
output$test.text <- shiny::renderText({
c("Goal: ",profile$goal) %>% paste0(collapse = " ")
})
}
# Run the application
shinyApp(ui = uiUpdate, server = serverUpdate)
```