[英]Filter data by Modularized Shiny R code: insertUI and callModule
通过简化我要解决的问题,我创建了一个可重现的示例。 我正在尝试:
我似乎无法正确解决我的代码。 将不胜感激任何帮助!
library(shiny)
# creating the actionbutton ui function
add.filter.UI = function(id) {
ns = NS(id)
div(
id = ns("break"),
fluidRow(
uiOutput(outputId = ns("sel.col")),
uiOutput(outputId = ns("rng.filter")))
)
}
# creating the actionbutton server function
add.filter.server = function(input, output, session) {
ns <- session$ns
tbl = reactive({ eval(parse(text = input$sel.tbl)) })
col.nms = reactive({ names(tbl() %>% select_if(is.numeric)) })
# creating the dynamic select column UI when the action button is clicked
output$sel.col <- renderUI({
selectInput(inputId = ns("sel.col"),
label = "Select a column",
choices = col.nms(),
multiple = F)
})
col.df = reactive({ tbl()[, input$sel.col] })
# creating the dynamic range filter UI when the action button is clicked
output$rng.filter <- renderUI({
sliderInput(inputId = ns("rng.filter"),
label = "Filter the range",
value = c(min(col.df(), na.rm = T), max(col.df(), na.rm = T)),
min = min(col.df(), na.rm = T),
max = max(col.df(), na.rm = T),
step = (max(col.df(), na.rm = T) - min(col.df(), na.rm = T)) / 1000) # 1,000 breaks
})
# applying the column / range filter to the table per filter created from the action button
eval(parse(text = values[[input$sel.tbl]])) <- eval(parse(text = values[[input$sel.tbl]])) %>%
rename(Var = one_of(input$sel.col)) %>%
filter(Var >= min(input$rng.filter), Var <= max(input$rng.filter)) %>%
rename(!!input$sel.col := Var)
}
# Define UI ----
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput(inputId = "sel.tbl", label = "Select a table",
choices = c("mtcars", "iris"),
selected = "mtcars", multiple = F),
actionButton("add_filter", "Filter", icon = icon("plus"))
),
mainPanel(
navbarPage(title = "Nav",
tabPanel("default", tableOutput(outputId = "tbl")),
tabPanel("filtered", tableOutput(outputId = "tbl.filtered"))
)
)
)
)
# Define server logic ----
server <- function(input, output, session) {
values = reactiveValues(mtcars = mtcars, iris = iris)
# setting up the dynamic filter action button
observeEvent(input$add_filter, {
insertUI(
selector = paste0("#filter_", input$add_filter - 1, "-break"),
where = "afterEnd",
ui = add.filter.UI(paste0("filter_", input$add_filter))
)
callModule(
module = add.filter.server,
id = paste0("#filter_", input$add_filter)
)
})
# displaying the raw table
output$tbl = renderTable(
eval(parse(text = input$sel.tbl))
)
# displaying the filtered table from the action button
output$tbl.filtered = renderTable(
eval(parse(text = values[[input$sel.tbl]]))
)
}
# Run the app ----
shinyApp(ui = ui, server = server)
这是部分答案。 你仍然需要弄清楚你想要filter
什么,以及如何处理数据集中的变化,因为从前一个数据集中选择的变量变得无效。 尝试这个
library(shiny)
library(tidyverse)
# creating the actionbutton ui function
add.filter.UI = function(id) {
ns = NS(id)
tagList(
#id = ns("break"),
fluidRow(uiOutput(ns("sel_col")),
uiOutput(ns("rng_filter"))
)
)
}
add.filter.server <- function(id,tbl) {
moduleServer(id, function(input, output, session) {
# creating the actionbutton server function
#add.filter.server = function(input, output, session) {
ns <- session$ns
values <- reactiveValues(mydf=NULL)
#tbl = reactive({ eval(parse(text = input$sel.tbl)) })
col.nms = reactive({ names(get(tbl()) %>% select_if(is.numeric)) })
# creating the dynamic select column UI when the action button is clicked
output$sel_col <- renderUI({
req(col.nms())
selectInput(inputId = ns("sel.col"),
label = "Select a column",
choices = col.nms(),
multiple = F)
})
col.df <- reactive({
req(input$sel.col)
df <- get(tbl())
df1 <- as.data.frame(df[,input$sel.col])
df1
})
#observe({print(col.df())})
# creating the dynamic range filter UI when the action button is clicked
output$rng_filter <- renderUI({
req(col.df())
sliderInput(inputId = ns("rng.filter"),
label = "Filter the range",
value = c(min(col.df(), na.rm = T), max(col.df(), na.rm = T)),
min = min(col.df(), na.rm = T),
max = max(col.df(), na.rm = T),
step = (max(col.df(), na.rm = T) - min(col.df(), na.rm = T)) / 1000) # 1,000 breaks
})
# applying the column / range filter to the table per filter created from the action button - needs work
values$mydf <- get(tbl()) # %>%
#eval(parse(text = values[[input$sel.tbl]])) <- eval(parse(text = values[[input$sel.tbl]])) %>%
# rename(Var = one_of(input$sel.col)) # %>%
# dplyr::filter(Var >= min(input$rng.filter), Var <= max(input$rng.filter)) %>%
# rename(!!input$sel.col := Var)
return(values)
})
}
# Define UI ----
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput(inputId = "sel.tbl", label = "Select a table",
choices = c("mtcars", "iris"),
selected = "mtcars", multiple = F),
actionButton("add_filter", "Filter", icon = icon("plus")),
tags$div(id = 'placeholder')
),
mainPanel(
navbarPage(title = "Nav",
tabPanel("default", tableOutput(outputId = "tbl")),
tabPanel("filtered", tableOutput(outputId = "tbl.filtered"))
)
)
)
)
# Define server logic ----
server <- function(input, output, session) {
values = reactiveValues(mtcars = mtcars, iris = iris, mydf=NULL)
observe({
if (input$add_filter==0) values$mydf <- eval(parse(text = values[[input$sel.tbl]]))
})
# setting up the dynamic filter action button
observeEvent(c(input$add_filter,input$sel.tbl), {
id <- paste0("#filter_", input$add_filter - 1, "-break")
insertUI(
selector = '#placeholder',
#selector = paste0("#filter_", input$add_filter - 1, "-break"),
where = "afterEnd",
ui =tags$div(
add.filter.UI(paste0("filter_", input$add_filter)),
id = id
)
)
value <- add.filter.server(id = paste0("filter_", input$add_filter), reactive(as.character(input$sel.tbl)))
values$mydf <- value$mydf
},ignoreInit = TRUE)
# displaying the raw table
output$tbl = renderTable(
eval(parse(text = input$sel.tbl))
)
# displaying the filtered table from the action button
output$tbl.filtered = renderTable(
values$mydf
#eval(parse(text = values[[input$sel.tbl]]))
)
}
# Run the app ----
shinyApp(ui = ui, server = server)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.