Hello, I'm creating a shiny app and trying to figure out how to update filters based on previous filters selection when using a shiny module.
In the module, the default, shows all countries and first purchase cohorts. I want the Customer ID
picker input to automatically filter, based on what Country
and First Purchase Cohort
are selected.
Please see reprex below. Note that the modules are in a separate script and being sourced in the main shiny app -
# Libraries
library(tidyverse)
library(shiny)
# ******************************************************************************
# Sample Data
df <- tibble(
data_1 = c(1758, 0, 0, 0, 0, 0, 0, 293, 0, 0),
data_2 = factor(c(1, 0, 0, 0, 0, 0, 0, 1, 0, 0)),
customer_id = c(12349, 12350, 12351, 12355, 12363, 12365, 12373, 12384, 12386, 12392),
first_purchase_cohort = c("Q2-2010", "Q1-2011", "Q4-2010", "Q2-2010", "Q2-2011", "Q1-2011", "Q1-2010", "Q3-2011", "Q4-2010", "Q2-2010"),
country = c("Italy", "Italy", "Mexico", "Bahrain", "Mexico", "Cyprus", "Austria", "France", "Australia", "Australia")
)
# ******************************************************************************
# Modules (in a separate file and sourced in main shiny app)
module_picker_input_UI <- function(id, label) {
ns <- NS(id)
if (str_detect(label, "Customer")) {
multiple = FALSE
} else {
multiple = TRUE
}
tagList(
div(
style = "margin-left: 10px;",
class = "col-md-2",
pickerInput(
inputId = ns("picker"),
label = h4(label),
choices = NULL,
selected = NULL,
multiple = multiple,
options = list(
`actions-box` = TRUE,
`deselct-all-text` = "Deselect All",
`select-all-text` = "Select All",
`none-selected-text` = "Select Country",
`selected-text-format` = "count > 3",
liveSearch = TRUE
)
)
)
)
}
module_picker_input_Server <- function(id, data = reactive(NULL), var = NULL) {
moduleServer(
id,
function(input, output, session) {
#ns <- getDefaultReactiveDomain()$ns
shiny::observe({
if (var == "customer_id") {
updatePickerInput(
session = getDefaultReactiveDomain(),
inputId = "picker",
choices = unique(data() %>% pull({{var}}) %>% sort() %>% as.character()),
selected = unique(data() %>% pull({{var}}) %>% sort() %>% as.character())[1],
)
} else {
updatePickerInput(
session = getDefaultReactiveDomain(),
inputId = "picker",
choices = unique(data() %>% pull({{var}}) %>% sort() %>% as.character()),
selected = unique(data() %>% pull({{var}}) %>% sort() %>% as.character())
)
}
})
}
)
}
# ******************************************************************************
# Shiny app
ui <- fluidPage(
fluidRow(
module_picker_input_UI("country", "Country"),
module_picker_input_UI("cohort", "Purchase Cohort"),
module_picker_input_UI("customer", "Customer ID")
),
br(),
fluidRow(
tableOutput("table")
)
)
server <- function(input, output, session) {
# Reactive Data
df_reactive <- reactive({df})
module_picker_input_Server("country", data = df_reactive, var = "country")
module_picker_input_Server("cohort", data = df_reactive, var = "first_purchase_cohort")
module_picker_input_Server("customer", data = df_reactive, var = "customer_id")
output$table <- renderTable({
df_reactive() %>%
filter(
country %in% input[["country-picker"]],
first_purchase_cohort %in% input[["cohort-picker"]],
customer_id %in% input[["customer-picker"]]
)
})
}
shinyApp(ui, server)
I tried doing something like -
observe({
customer_id_list <- data %>%
filter(country %in% input[["country-picker"]]) %>%
filter(first_purchase_cohort %in% input[["cohort-picker"]]) %>%
pull(customer_id) %>%
unique() %>%
sort()
updatePickerInput(
session = getDefaultReactiveDomain(),
inputId = "picker",
choices = customer_id_list,
selected = customer_id_list[1],
)
})
However I'm not sure if my module is written correctly. I'm not sure how to access the country input id in the shiny module.