R Shiny:使用输入 $ 值创建 reactiveValues 对象
R Shiny: create reactiveValues object with input$ values
我想在 Shiny 中创建一个 reactiveValues
对象,其内容定义为输入小部件中包含的值。我设法做到了,但我的实现似乎不必要地笨拙:
- 创建一个空的
reactiveValues
对象
- 当输入小部件的值随
observeEvent
发生变化时进行监控
- 使用来自输入小部件 (
isolate
) 的非反应性值将值分配给 reactiveValues
对象
这是一个例子:
ui <- fluidPage(
fluidRow(
column(2, radioButtons("main", label = "Main dish", choices = list("salad", "pasta"))),
column(2, radioButtons("desert", label = "Desert", choices = list("fruit", "cake"))),
column(8, actionButton("extra", "Louder!", style="background-color: #ffdb99"))
),
verbatimTextOutput("myorder")
)
server <- function(input, output, session) {
# 1. Create reactiveValues object
menuR <- reactiveValues()
# 2. Update values whenever widgets change
observeEvent(c(input$main, input$desert),
menuR[["meal"]] <- paste(c(isolate(input$main), isolate(input$desert)), collapse = " & ")
)
# 3. Perform operations on object values
observeEvent(input$extra,
menuR[["meal"]] <- paste0(toupper(menuR[["meal"]]), "!!!")
)
output$myorder <- renderText(menuR[["meal"]])
}
shinyApp(ui, server)
我非常想像这样直接创建 reactiveValues
对象(大大简化了上面的代码):
# Set values upon creation
menuR <- reactiveValues(meal = paste(c(input$main, input$desert), collapse = " & "))
这不起作用,因为 input$main
是反应性的...
我猜想用从小部件获得的值定义 reactiveValues
对象会很常见。
我是不是漏掉了什么?
感谢您的帮助,
雨果
您可以使用 reactive()
而不是 reactiveValues()
来做到这一点。 menuR
是一个反应对象,它依赖于 main
和 desert
的输入值。定义后,您可以通过在服务器代码中调用 menu()
来使用它。此外,这使您无需使用 isolate()
,因为您可以将 menu
的值设置为 observeEvent()
.
中的反应对象
library(shiny)
ui <- fluidPage(
fluidRow(
column(2, radioButtons("main", label = "Main dish", choices = list("salad", "pasta"))),
column(2, radioButtons("desert", label = "Desert", choices = list("fruit", "cake"))),
column(8, actionButton("extra", "Louder!", style="background-color: #ffdb99"))
),
verbatimTextOutput("myorder")
)
server <- function(input, output, session) {
menuR <- reactive({
paste(c(input$main, input$desert), collapse = " & ")
})
observeEvent(
input$extra,
menuR <- reactive({
toupper(paste(c(input$main, input$desert), collapse = " & "))
})
)
output$myorder <- renderText(menuR())
}
shinyApp(ui, server)
编辑
我之前误解了这个问题。您可以使用 eventReactive()
来监视输入并在用户输入更改时更改。我还添加了用户尚未单击操作按钮时的默认值。
library(shiny)
ui <- fluidPage(
fluidRow(
column(2, radioButtons("main", label = "Main dish", choices = list("salad", "pasta"))),
column(2, radioButtons("desert", label = "Desert", choices = list("fruit", "cake"))),
column(8, actionButton("extra", "Louder!", style="background-color: #ffdb99"))
),
verbatimTextOutput("myorder")
)
server <- function(input, output, session) {
# Set a 'default' value for the output
default.menuR <- reactive({
paste(c(input$main, input$desert), collapse = " & ")
})
menuR <- eventReactive(input$extra, {
toupper(paste(c(input$main, input$desert), collapse = " & "))
})
# Initial state of the button is 0, which displays 'default' value
output$myorder <- renderText({
if (input$extra == 0) {
return(default.menuR())
}
menuR()
})
}
shinyApp(ui, server)
希望对您有所帮助!
我采纳了 Vishesh 的建议并使其生效。它看起来和我原来的例子没有太大区别,仍然需要重复几行代码。
每次其中一个小部件发生变化时,它都会覆盖反应对象。
library(shiny)
ui <- fluidPage(
fluidRow(
column(2, radioButtons("main", label = "Main dish", choices = list("salad", "pasta"))),
column(2, radioButtons("dessert", label = "dessert", choices = list("fruit", "cake"))),
column(8, actionButton("extra", "Louder!", style="background-color: #ffdb99"))
),
verbatimTextOutput("myorder")
)
server <- function(input, output, session) {
menuR <- reactive({
paste(c(input$main, input$dessert), collapse = " & ")
})
# Render text when app loads
output$myorder <- renderText(menuR())
# Update reactive object and re-render text (button 'extra')
observeEvent(
input$extra,{
temp <- toupper(paste(c(input$main, input$dessert), collapse = " & "))
menuR <<- reactive(temp)
output$myorder <- renderText(menuR())
}
)
# Update reactive object and re-render text (button 'main' or 'dessert')
observeEvent(c(input$main, input$dessert),{
menuR <- reactive(paste(c(input$main, input$dessert), collapse = " & "))
output$myorder <- renderText(menuR())
})
}
shinyApp(ui, server)
我想在 Shiny 中创建一个 reactiveValues
对象,其内容定义为输入小部件中包含的值。我设法做到了,但我的实现似乎不必要地笨拙:
- 创建一个空的
reactiveValues
对象 - 当输入小部件的值随
observeEvent
发生变化时进行监控
- 使用来自输入小部件 (
isolate
) 的非反应性值将值分配给reactiveValues
对象
这是一个例子:
ui <- fluidPage(
fluidRow(
column(2, radioButtons("main", label = "Main dish", choices = list("salad", "pasta"))),
column(2, radioButtons("desert", label = "Desert", choices = list("fruit", "cake"))),
column(8, actionButton("extra", "Louder!", style="background-color: #ffdb99"))
),
verbatimTextOutput("myorder")
)
server <- function(input, output, session) {
# 1. Create reactiveValues object
menuR <- reactiveValues()
# 2. Update values whenever widgets change
observeEvent(c(input$main, input$desert),
menuR[["meal"]] <- paste(c(isolate(input$main), isolate(input$desert)), collapse = " & ")
)
# 3. Perform operations on object values
observeEvent(input$extra,
menuR[["meal"]] <- paste0(toupper(menuR[["meal"]]), "!!!")
)
output$myorder <- renderText(menuR[["meal"]])
}
shinyApp(ui, server)
我非常想像这样直接创建 reactiveValues
对象(大大简化了上面的代码):
# Set values upon creation
menuR <- reactiveValues(meal = paste(c(input$main, input$desert), collapse = " & "))
这不起作用,因为 input$main
是反应性的...
我猜想用从小部件获得的值定义 reactiveValues
对象会很常见。
我是不是漏掉了什么?
感谢您的帮助,
雨果
您可以使用 reactive()
而不是 reactiveValues()
来做到这一点。 menuR
是一个反应对象,它依赖于 main
和 desert
的输入值。定义后,您可以通过在服务器代码中调用 menu()
来使用它。此外,这使您无需使用 isolate()
,因为您可以将 menu
的值设置为 observeEvent()
.
library(shiny)
ui <- fluidPage(
fluidRow(
column(2, radioButtons("main", label = "Main dish", choices = list("salad", "pasta"))),
column(2, radioButtons("desert", label = "Desert", choices = list("fruit", "cake"))),
column(8, actionButton("extra", "Louder!", style="background-color: #ffdb99"))
),
verbatimTextOutput("myorder")
)
server <- function(input, output, session) {
menuR <- reactive({
paste(c(input$main, input$desert), collapse = " & ")
})
observeEvent(
input$extra,
menuR <- reactive({
toupper(paste(c(input$main, input$desert), collapse = " & "))
})
)
output$myorder <- renderText(menuR())
}
shinyApp(ui, server)
编辑
我之前误解了这个问题。您可以使用 eventReactive()
来监视输入并在用户输入更改时更改。我还添加了用户尚未单击操作按钮时的默认值。
library(shiny)
ui <- fluidPage(
fluidRow(
column(2, radioButtons("main", label = "Main dish", choices = list("salad", "pasta"))),
column(2, radioButtons("desert", label = "Desert", choices = list("fruit", "cake"))),
column(8, actionButton("extra", "Louder!", style="background-color: #ffdb99"))
),
verbatimTextOutput("myorder")
)
server <- function(input, output, session) {
# Set a 'default' value for the output
default.menuR <- reactive({
paste(c(input$main, input$desert), collapse = " & ")
})
menuR <- eventReactive(input$extra, {
toupper(paste(c(input$main, input$desert), collapse = " & "))
})
# Initial state of the button is 0, which displays 'default' value
output$myorder <- renderText({
if (input$extra == 0) {
return(default.menuR())
}
menuR()
})
}
shinyApp(ui, server)
希望对您有所帮助!
我采纳了 Vishesh 的建议并使其生效。它看起来和我原来的例子没有太大区别,仍然需要重复几行代码。 每次其中一个小部件发生变化时,它都会覆盖反应对象。
library(shiny)
ui <- fluidPage(
fluidRow(
column(2, radioButtons("main", label = "Main dish", choices = list("salad", "pasta"))),
column(2, radioButtons("dessert", label = "dessert", choices = list("fruit", "cake"))),
column(8, actionButton("extra", "Louder!", style="background-color: #ffdb99"))
),
verbatimTextOutput("myorder")
)
server <- function(input, output, session) {
menuR <- reactive({
paste(c(input$main, input$dessert), collapse = " & ")
})
# Render text when app loads
output$myorder <- renderText(menuR())
# Update reactive object and re-render text (button 'extra')
observeEvent(
input$extra,{
temp <- toupper(paste(c(input$main, input$dessert), collapse = " & "))
menuR <<- reactive(temp)
output$myorder <- renderText(menuR())
}
)
# Update reactive object and re-render text (button 'main' or 'dessert')
observeEvent(c(input$main, input$dessert),{
menuR <- reactive(paste(c(input$main, input$dessert), collapse = " & "))
output$myorder <- renderText(menuR())
})
}
shinyApp(ui, server)