Set Global Object in Shiny

Are there global variables in R Shiny?

This page on the Shiny webpage explains scoping of Shiny variables.

Global variables can either be put in server.R (as per Ricardo's answer) or in global.R.

Objects defined in global.R are similar to those defined in server.R outside shinyServer(), with one important difference: they are also visible to the code in ui.R. This is because they are loaded into the global environment of the R session; all R code in a Shiny app is run in the global environment or a child of it.

In practice, there aren’t many times where it’s necessary to share variables between server.R and ui.R. The code in ui.R is run once, when the Shiny app is started and it generates an HTML file which is cached and sent to each web browser that connects. This may be useful for setting some shared configuration options.

How to make a local variable global in R using Shiny?

Just create the variable outside any sub-function and update its value using <<-. This variable will be global per each session.

server <- function(input, output) {

# init variable here
algorithm_output <- NULL

out_plots <- eventReactive(input$ok_input, {

# to modify a global variable use <<- instead of <- or =
algorithm_output <<- some_global_function(3, 2, 1)

do.call("grid.arrange", c(algorithm_output$indexes, nrow=3))
})

output$indexes <- renderPlot({
out_plots()
})

out_means <- eventReactive(input$ok_means, {
k = as.integer(input$k)

# you can get access to the updated value of your variable
matplot(algorithm_output$means[[k-1]], type = "l", lty=1)

})
output$means <- renderPlot({
out_means()
})
}

How to assign global variables that can be accessed by other output$function in R shiny?

If you really want to assign something to global, you can use the <<- operator. Or assign("x", value = data, envir = .GlobalEnv).

But, you really don't want to. It's almost never, ever a good idea. Especially since you need to make use of reactive inputs.

If sample_d <- data() is too many keystrokes, just ignore assigning within the local environment (the output object) and use data().

output$plot <- renderPlot({
plot(density(data()[,1]), main = input$title)
})

If you want an object with multiple values, a list of objects, make your reactive object into a list and reference with $

Be sure to note however, your reactive object is a function call. So if the reactive object is data and we want the list item normalized_df we would call the reactive object data() with () and then index into the list that function returns with $. So all together we would have data()$normalized_df.

  data <- reactive({
req(input$filedata)
d <- read.csv(input$filedata$datapath, header = T)
list(data = d,
normalized_df = d + 1.5,
advanced_normalized = df + 1.5 * 45.454)
})

output$normalized_plot <- renderPlot({ #Does not work
plot(density(data()$normalizd_df[,1]), main = input$title)
})

output$advanced_normalized_plot <- renderPlot({
plot(density(data()$advanced_normalized[,1]), main = input$title)
})

Below is a minimal example that shows this in action:

library(shiny)

ui <- fluidPage(
titlePanel("Old Faithful Geyser Data"),
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 10,
value = 2)
),
mainPanel(
column(6, verbatimTextOutput("console1")),
column(6, verbatimTextOutput("console2"))
)
)
)

server <- function(input, output) {

data1 <- reactive({
datum <- mtcars
d1 <- mtcars[1:input$bins]
d2 <- d1 + 1
d3 <- d1 * 1.5
list(d1, d2, d3)
})

data2 <- reactive({
datum <- mtcars
list(d1 = mtcars[1:input$bins],
d2 = mtcars[1:input$bins] + 1,
d3 = mtcars[1:input$bins] * 1.5)
})

output$console1 <- renderPrint({
data1()
})

output$console2 <- renderPrint({
data2()
})
}

# Run the application
shinyApp(ui = ui, server = server)

How to use reactive global variable in global.R in R Shiny

I agree with @JohnPaul and @Lee88, your catPath probably belongs within server.R. Having said that, I'll keep it here for now (assuming you have other reasons for this in your MWE).

global.R:

catPath <- ""

I needed to set it to something in order to be reference-able later, otherwise the value used here should be meaningless (though it will be returned if no action taken).

ui.R:

I added a "stop?" action button so that you can "exit" your app and capture the value of catPath into the calling environment. Not required if you don't intend to intentionally exit the app.

fluidPage(
titlePanel("Using global variable"),
fluidRow(
uiOutput("ui1"),
uiOutput("ui2"),
uiOutput("ui3"),
actionButton("stopme", "Stop?")
)
)

server.R:

I changed output$ui3 to create the HTML object (not perform calculations), and then observe two events and act on them. Again, if you don't need the "stop?" button above, you probably don't need the second observe here. (If you do use it, note that the argument to stopApp is returned invisibly to the caller.)

function(input, output, session) {
output$ui1 <- renderUI({
selectInput("dataset", "firstValue", choices = c("first", "second", "third"))
})
output$ui2 <- renderUI({
actionButton("doIt", class="btn-primary", "change")
})
output$ui3 <- renderUI({
textInput("myinput", "catPath", "")
})
observeEvent(input$doIt, {
catPath <<- paste(input$dataset, "/completed", sep = "")
updateTextInput(session, inputId = "myinput", value = catPath)
})
observeEvent(input$stopme, { stopApp(catPath); })
}

Doing something like newCatPath <- runApp("path/to/dir").

Assign to global shiny environment in package

You can setup the data using the global.R file. Any R objects that are created in the global.R file become available to the app.R file, or the ui.R and server.R files respectively. Take a look at how to modularize shiny apps.

EDIT: As pointed out in the comments, you can use local = TRUE to only load objects into the shiny environment.

R Shiny: global variable for all functions in server.R

The idea to use reactive is the right direction; however you didn't do it quite right. I just added one line and it is working:

shinyServer(function(input, output, session) {
df <- NULL
in_data <- reactive({
inFile <- input$file1
if (is.null(inFile)) return(NULL)
else df <<- read.csv(inFile$datapath, as.is=TRUE)
return(NULL)
})
output$frame <- renderTable({
call.me = in_data() ## YOU JUST ADD THIS LINE.
df
})
})

Why? Because a reactive object is very similar to a function, which gets executed only when you call it. Thus the 'standard' way of your code should be:

shinyServer(function(input, output, session) {
in_data <- reactive({
inFile <- input$file1
if (is.null(inFile)) return(NULL)
else read.csv(inFile$datapath, as.is=TRUE)
})
output$frame <- renderTable({
in_data()
})
})


Related Topics



Leave a reply



Submit