1. Моя цель
Я хочу использовать модули Shiny для создания приложения, в котором:
- категория A, B или C выбрана с помощью
radioButtons
dateRangeInput
, чьи min
и max
аргументы определяются выбранной категорией с использованием updateDateRangeInput
- подмножества вектора дат, так что он содержит элементы только между
start
и end
из dateRangeInput
Пока у меня есть шаги 1. и 2. для работы с использованием модуля Shiny. Я предпочитаю выполнять шаг 3. в отдельном модуле или, по крайней мере, в отдельной модульной серверной функции (см. Часть 4).
Мой реальный вариант использования заключается в считывании нескольких файлов из каталога в приложение Shiny. Все файлы имеют строку даты и строку категории как часть их имени. Только файлы выбранной категории и даты в диапазоне дат должны быть прочитаны в моем приложении Shiny. В этом минимальном примере предположим, что файлы представлены all_dates
. Обратите внимание, что в моем реальном приложении я использую flexdashboard R вместо приложения Shiny в скрипте.
2. Мой код
Вот первая функция интерфейса модуля:
library(shiny)
# date range depends on the selected category A, B or C
dateRangeCategoryUI <- function(id) {
ns <- NS(id)
tagList(
dateRangeInput(ns("date_range"), label = "select dates"),
radioButtons(
ns("category"),
label = "select category",
choices = list("A", "B", "C"),
selected = "A"
)
)
}
Вот первая функция сервера модуля:
# Server function to find min and max date for a selected category
dateRangeCategory <- function(input, output, session) {
observe({
category_min <- switch(
input$category,
"A" = Sys.Date() - lubridate::days(1),
"B" = Sys.Date() - lubridate::days(2),
"C" = Sys.Date() - lubridate::days(3)
)
category_max <- switch(
input$category,
"A" = Sys.Date() + lubridate::days(1),
"B" = Sys.Date() + lubridate::days(2),
"C" = Sys.Date() + lubridate::days(3)
)
updateDateRangeInput(
session,
"date_range",
start = Sys.Date(),
end = Sys.Date(),
min = category_min,
max = category_max
)
})
}
Вот приложение Shiny, использующее приведенное выше модуль, который работает должным образом:
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
dateRangeCategoryUI("range_and_category")
),
mainPanel()
)
)
server <- function(input, output, session) {
callModule(dateRangeCategory, "range_and_category")
}
shinyApp(ui, server)
Для шага 3. выше я хочу создать второй модуль (в другом скрипте .R), который:
- обращается к
start
и end
значения dateRangeInput
, созданные dateRangeCategoryUI
- , загружают вектор дат (в этом минимальном примере я просто создаю объект
all_dates
) - возвращает подмножество этот объект называется
selected_dates
, сохраняя даты только в пределах start
и end
Функция сервера второго модуля может выглядеть примерно так:
selectDates <- function(input, output, session) {
all_dates <- seq.Date(
from = Sys.Date() - lubridate::days(3),
to = Sys.Date() + lubridate::days(3),
by = "days"
)
selected_dates <- reactive({
# input$date_range should refer to `dateRangeInput` from `dateRangeCategoryUI`
range_start <- input$date_range[1]
range_end <- input$date_range[2]
all_dates[all_dates >= range_start & all_dates <= range_start]
})
return(selected_dates)
}
Я бы тогда хотелось бы иметь эти selected_dates
в функции сервера моего приложения Shiny:
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
dateRangeCategoryUI("range_and_category")
),
mainPanel()
)
)
server <- function(input, output, session) {
callModule(dateRangeCategory, "range_and_category") # first module
selected_dates <- callModule(selectDates, "range_and_category") # second module
}
shinyApp(ui, server)
3. Мой главный вопрос
Как selectDates
получить доступ к значениям start
и end
из dateRangeInput
, созданным dateRangeCategoryUI
?
4. Вопросы по организации модулей
- Если я выберу работу с двумя модулями, второй модуль будет иметь только серверную функцию и функцию пользовательского интерфейса. Это разрешено?
- Было бы проще получить доступ к
start
и end
, если бы я поместил функции selectDates
и dateRangeCategory
в один файл? В этом случае у меня будет один модуль с двумя функциями сервера. Это разрешено? - Имеет ли смысл обрабатывать обе операции (установка диапазона дат по категориям и создание
selected_dates
) с помощью одной и той же функции сервера модуля? результат будет выглядеть так: selected_dates <- callModule(dateRangeCategory, "range_and_category")