问题
I am using assign in for loop to create new variables that I want to use in more than one outputs in shiny ui. Following is a sample code:
library(shiny)
ui <- fluidPage(
mainPanel(fluidRow(textOutput("a")),
fluidRow(textOutput("b")))
)
server <- function(input, output) {
m <- reactive({1:5})
output$a <- renderPrint({
for (i in 1:length(m())){
assign(paste0("h",i), "u")
}
list(h1,h2)
})
output$b <- renderPrint({
list(h1,h2)
})
}
shinyApp(ui = ui, server = server)
Problem
Each output in server has its own environment. So, the variables h1 to h5 are created within output a and therefore not accessible by output b. See the result of running app:
[[1]] [1] "u" [[2]] [1] "u"
[[1]] function (...) tags$h1(...) <environment: namespace:htmltools> [[2]] function (...) tags$h2(...) <environment: namespace:htmltools>
Ideally, the second line should be same as the first line. If I move the for loop to server, there is a problem of reactivity:
Error in .getReactiveEnvironment()$currentContext() :
Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)
Question
How can I make the for loop reactive so that all the outputs could access them?
EDIT
I have also tried doing following outside outputs:
observe({for (i in 1:length(m())){
assign(paste0("om",i), "u")
}})
and
reactive({for (i in 1:length(m())){
assign(paste0("om",i), "u")
}})
Since h1 is already a function in shiny, I changed the object name to "om". But using either of the above yields no good results:
output$a <- renderPrint({
list(length(m()), om1)
})
output$b <- renderPrint({
om1()
})
Error: object 'om1' not found
Error: could not find function "om1"
回答1:
As I tried to relay in the comment, move the for loop outside the first renderPrint() function, so the h1-h5 is available for both output$a and output$b.
From your code there is no reason the loop needs to be restricted to only output$a as its parameter m is defined outside anyway:
library(shiny)
ui <- fluidPage(
mainPanel(fluidRow(textOutput("a")),
fluidRow(textOutput("b")))
)
server <- function(input, output) {
m <- reactive({1:5})
for (i in 1:length(m)){
assign(paste0("h",i), "u")
}
output$a <- renderPrint({
list(h1,h2)
})
output$b <- renderPrint({
list(h1,h2)
})
}
shinyApp(ui = ui, server = server)
来源:https://stackoverflow.com/questions/32366432/how-to-make-for-loop-reactive-in-shiny-server-in-r