使 renderUI 成为 observeEvent 的输入
Make renderUI an input for observeEvent
如标题所示,我希望创建一个动态创建的 UI object(使用 renderUI
),稍后可以在 Shiny App 中进一步操作。
在下面的 reprex 中,我有一个玩具应用程序,允许用户根据萼片宽度过滤 iris
数据集。根据用户选择的范围,我然后生成一个复选框列表,其中包含该萼片宽度范围内的所有独特物种。
我的问题是:一旦用户过滤了 table,我怎样才能让应用告诉我选择了哪个物种的复选框?例如,在默认的应用程序设置下,当萼片宽度范围介于 1 和 2 之间时,只有一个物种满足过滤要求(杂色)。当用户选中 versicolor 框时,我希望应用程序更新以告诉我已选择 versicolor。
同样,当萼片宽度范围更大时(动态生成的复选框列表中包含更多物种)我希望 UI 再次更新以告诉我选择了哪个物种(1 , 2 种或全部 3 种)。
我脑海中的基本工作流程是:
(1) 用户过滤数据集 (2) 显示 Table 基于过滤器的更新 (3) App 生成独特物种的复选框列表 (4) 用户点击物种,物种名称被呈现 on-screen.
library(shiny)
library(DT)
library(dplyr)
ui <- basicPage(
fluidRow(
uiOutput("ui"),
sliderInput("slider", "Sepal Width", min = 0, max=20, value=c(1:2)),
tableOutput("data")
),
)
server <- function(input, output){
data("iris")
filtered<-reactive({
iris %>% filter(`Sepal.Width` %in% input$slider[1]:input$slider[2])
})
output$data<-renderTable({
filtered()
})
output$ui<-renderUI({
species<-filtered()
checkboxGroupInput(inputId = 'occurence_checkboxes', label = 'Species', choices = unique(species$Species))
})
}
shinyApp(ui, server)
这应该可以解决问题:
library(shiny)
library(dplyr)
ui <- basicPage(
fluidRow(
uiOutput("ui"),
sliderInput("slider", "Sepal Width", min = 0, max=20, value = 1:2),
tableOutput("data")
)
)
server <- function(input, output){
get_width_filter <- reactive({
iris %>% filter(between(Sepal.Width, input$slider[1], input$slider[2]))
})
get_ovl_filter <- reactive({
get_width_filter() %>%
filter(Species %in% input$occurence_checkboxes)
})
output$data <- renderTable({
get_ovl_filter()
})
output$ui <- renderUI({
choices <- get_width_filter() %>% pull(Species) %>% unique()
checkboxGroupInput("occurence_checkboxes",
"Species",
choices = choices,
selected = choices)
})
}
shinyApp(ui, server)
说明
我们需要将 filtered
例程分成两部分:一部分仅应用宽度过滤器,另一部分还包含物种过滤器。您可以通过在 renderUI
函数中使用的名称访问动态创建的复选框。我们必须拆分响应式过滤器的原因是,否则 renderUI
将依赖于我们想要避免的复选框本身。
更新
我刚读到您只想 return 复选框的值而不用它来过滤。但是我想现在应该清楚了,只要在需要的地方使用input$occurence_checkboxes
即可。
如标题所示,我希望创建一个动态创建的 UI object(使用 renderUI
),稍后可以在 Shiny App 中进一步操作。
在下面的 reprex 中,我有一个玩具应用程序,允许用户根据萼片宽度过滤 iris
数据集。根据用户选择的范围,我然后生成一个复选框列表,其中包含该萼片宽度范围内的所有独特物种。
我的问题是:一旦用户过滤了 table,我怎样才能让应用告诉我选择了哪个物种的复选框?例如,在默认的应用程序设置下,当萼片宽度范围介于 1 和 2 之间时,只有一个物种满足过滤要求(杂色)。当用户选中 versicolor 框时,我希望应用程序更新以告诉我已选择 versicolor。
同样,当萼片宽度范围更大时(动态生成的复选框列表中包含更多物种)我希望 UI 再次更新以告诉我选择了哪个物种(1 , 2 种或全部 3 种)。
我脑海中的基本工作流程是:
(1) 用户过滤数据集 (2) 显示 Table 基于过滤器的更新 (3) App 生成独特物种的复选框列表 (4) 用户点击物种,物种名称被呈现 on-screen.
library(shiny)
library(DT)
library(dplyr)
ui <- basicPage(
fluidRow(
uiOutput("ui"),
sliderInput("slider", "Sepal Width", min = 0, max=20, value=c(1:2)),
tableOutput("data")
),
)
server <- function(input, output){
data("iris")
filtered<-reactive({
iris %>% filter(`Sepal.Width` %in% input$slider[1]:input$slider[2])
})
output$data<-renderTable({
filtered()
})
output$ui<-renderUI({
species<-filtered()
checkboxGroupInput(inputId = 'occurence_checkboxes', label = 'Species', choices = unique(species$Species))
})
}
shinyApp(ui, server)
这应该可以解决问题:
library(shiny)
library(dplyr)
ui <- basicPage(
fluidRow(
uiOutput("ui"),
sliderInput("slider", "Sepal Width", min = 0, max=20, value = 1:2),
tableOutput("data")
)
)
server <- function(input, output){
get_width_filter <- reactive({
iris %>% filter(between(Sepal.Width, input$slider[1], input$slider[2]))
})
get_ovl_filter <- reactive({
get_width_filter() %>%
filter(Species %in% input$occurence_checkboxes)
})
output$data <- renderTable({
get_ovl_filter()
})
output$ui <- renderUI({
choices <- get_width_filter() %>% pull(Species) %>% unique()
checkboxGroupInput("occurence_checkboxes",
"Species",
choices = choices,
selected = choices)
})
}
shinyApp(ui, server)
说明
我们需要将 filtered
例程分成两部分:一部分仅应用宽度过滤器,另一部分还包含物种过滤器。您可以通过在 renderUI
函数中使用的名称访问动态创建的复选框。我们必须拆分响应式过滤器的原因是,否则 renderUI
将依赖于我们想要避免的复选框本身。
更新
我刚读到您只想 return 复选框的值而不用它来过滤。但是我想现在应该清楚了,只要在需要的地方使用input$occurence_checkboxes
即可。