Отображать только месяцы в dateRangeInput или dateInput для блестящего приложения [R-программирование]

Я использую блестящий для создания веб-приложения. Один из моих сюжетов использует только месяцы определенного года для создания точек в сюжете.

Я хочу, чтобы пользователи выбирали только месяцы. Хотя я упомянул

format = 'mm-yyyy' и startview = 'year' в dateInput или dateRangeInput

Всякий раз, когда пользователь нажимает на поле ввода даты, пользователь будет отображать месяцы, а затем при нажатии на любой месяц пользователь отображается с датами в месяце.

Я хочу, чтобы пользователь отображался до нескольких месяцев. Если пользователь нажимает на месяц, даты не должны отображаться.

Как это можно достичь?

Ответ 1

Я не верю, что dateInput внедрил параметр bootstrap minViewMode в качестве аргумента функции, поэтому я добавил его в свою собственную копию функции (см. ниже). Мне пришлось добавить некоторые другие необходимые функции. Это не здорово. Лучшим вариантом было бы, вероятно, отправить запрос в RStudio, так как кажется простым добавить этот параметр minviewmode.

mydateInput <- function(inputId, label, value = NULL, min = NULL, max = NULL,
                      format = "yyyy-mm-dd", startview = "month", weekstart = 0, language = "en", minviewmode="months",
                      width = NULL) {

  # If value is a date object, convert it to a string with yyyy-mm-dd format
  # Same for min and max
  if (inherits(value, "Date"))  value <- format(value, "%Y-%m-%d")
  if (inherits(min,   "Date"))  min   <- format(min,   "%Y-%m-%d")
  if (inherits(max,   "Date"))  max   <- format(max,   "%Y-%m-%d")

  htmltools::attachDependencies(
    tags$div(id = inputId,
             class = "shiny-date-input form-group shiny-input-container",
             style = if (!is.null(width)) paste0("width: ", validateCssUnit(width), ";"),

             controlLabel(inputId, label),
             tags$input(type = "text",
                        # datepicker class necessary for dropdown to display correctly
                        class = "form-control datepicker",
                        `data-date-language` = language,
                        `data-date-weekstart` = weekstart,
                        `data-date-format` = format,
                        `data-date-start-view` = startview,
                        `data-date-min-view-mode` = minviewmode,
                        `data-min-date` = min,
                        `data-max-date` = max,
                        `data-initial-date` = value
             )
    ),
    datePickerDependency
  )
}

`%AND%` <- function(x, y) {
  if (!is.null(x) && !is.na(x))
    if (!is.null(y) && !is.na(y))
      return(y)
  return(NULL)
}

controlLabel <- function(controlName, label) {
  label %AND% tags$label(class = "control-label", `for` = controlName, label)
}

datePickerDependency <- htmlDependency(
  "bootstrap-datepicker", "1.0.2", c(href = "shared/datepicker"),
  script = "js/bootstrap-datepicker.min.js",
  stylesheet = "css/datepicker.css")

Ответ 2

@MartinJohnHadley: По сути, путем добавления тех же трех строк @StevenMortimer добавляется в код dateInput в dateRangeInput. Это добавляет minViewMode к shinys dateRangeInput.

  1. Найдите код по адресу https://github.com/rstudio/shiny/blob/master/R/input-daterange.R
  2. добавить аргумент по умолчанию minviewmode="months"
  3. добавить data-date-min-view-mode = minviewmode для обоих data-date-min-view-mode = minviewmode
  4. Добавить недостающие аргументы (поиск в github архиве из глянцевых)
  5. Наслаждайтесь вашим пользовательским вводом dateRange :-)

С наилучшими пожеланиями, Сандро

Код:

dateRangeMonthsInput <- function(inputId, label, start = NULL, end = NULL,
                            min = NULL, max = NULL, format = "yyyy-mm-dd", startview = "month",
                            minviewmode="months", # added manually
                            weekstart = 0, language = "en", separator = " to ", width = NULL) {

   # If start and end are date objects, convert to a string with yyyy-mm-dd format
   # Same for min and max
   if (inherits(start, "Date"))  start <- format(start, "%Y-%m-%d")
   if (inherits(end,   "Date"))  end   <- format(end,   "%Y-%m-%d")
   if (inherits(min,   "Date"))  min   <- format(min,   "%Y-%m-%d")
   if (inherits(max,   "Date"))  max   <- format(max,   "%Y-%m-%d")

   htmltools::attachDependencies(
     div(id = inputId,
         class = "shiny-date-range-input form-group shiny-input-container",
         style = if (!is.null(width)) paste0("width: ", validateCssUnit(width), ";"),

         controlLabel(inputId, label),
         # input-daterange class is needed for dropdown behavior
         div(class = "input-daterange input-group",
             tags$input(
               class = "input-sm form-control",
               type = "text",
               'data-date-language' = language,
               'data-date-weekstart' = weekstart,
               'data-date-format' = format,
               'data-date-start-view' = startview,
               'data-date-min-view-mode' = minviewmode, # added manually
               'data-min-date' = min,
               'data-max-date' = max,
               'data-initial-date' = start
             ),
             span(class = "input-group-addon", separator),
             tags$input(
               class = "input-sm form-control",
               type = "text",
               'data-date-language' = language,
               'data-date-weekstart' = weekstart,
               'data-date-format' = format,
               'data-date-start-view' = startview,
               'data-date-min-view-mode' = minviewmode, # added manually
               'data-min-date' = min,
               'data-max-date' = max,
               'data-initial-date' = end
             )
         )
     ),
     datePickerDependency
   )
 }

 '%AND%' <- function(x, y) {
   if (!is.null(x) && !is.na(x))
     if (!is.null(y) && !is.na(y))
       return(y)
   return(NULL)
 }

 controlLabel <- function(controlName, label) {
   label %AND% tags$label(class = "control-label", 'for' = controlName, label)
 }

 # the datePickerDependency is taken from https://github.com/rstudio/shiny/blob/master/R/input-date.R
 datePickerDependency <- htmltools::htmlDependency(
 "bootstrap-datepicker", "1.6.4", c(href = "shared/datepicker"),
 script = "js/bootstrap-datepicker.min.js",
 stylesheet = "css/bootstrap-datepicker3.min.css",
 # Need to enable noConflict mode. See #1346.
 head = "<script>
 (function() {
 var datepicker = $.fn.datepicker.noConflict();
 $.fn.bsDatepicker = datepicker;
 })();
 </script>")

Ответ 3

Кому хочет использовать коды в предыдущем ответе: вам нужно использовать обновленную датуPickerDependecy (которая может быть взята из https://github.com/rstudio/shiny/blob/master/R/input-date.R).

В настоящее время это:

datePickerDependency <- htmlDependency(
"bootstrap-datepicker", "1.6.4", c(href = "shared/datepicker"),
script = "js/bootstrap-datepicker.min.js",
stylesheet = "css/bootstrap-datepicker3.min.css",
# Need to enable noConflict mode. See #1346.
head = "<script>
(function() {
var datepicker = $.fn.datepicker.noConflict();
$.fn.bsDatepicker = datepicker;
})();
</script>")

Я оставляю это замечание как ответ из-за недостаточной репутации: (

Ответ 4

Вот еще один метод (с меньшей избыточностью кода и, мы надеемся, более простой), предоставленный коллегой. Вместо того, чтобы копировать код функции блестящий :: dateInput, можно добавить часть min/max-view-mode к объекту Shiny впоследствии. Тогда старый параметр 'startview' и новый 'minview'/'maxview' можно использовать как положено:

dateInput2 <- function(inputId, label, minview = "days", maxview = "decades", ...) {
  d <- shiny::dateInput(inputId, label, ...)
  d$children[[2L]]$attribs[["data-date-min-view-mode"]] <- minview
  d$children[[2L]]$attribs[["data-date-max-view-mode"]] <- maxview
  d
}

dateRangeInput2 <- function(inputId, label, minview = "days", maxview = "decades", ...) {
  d <- shiny::dateRangeInput(inputId, label, ...)
  d$children[[2L]]$children[[1]]$attribs[["data-date-min-view-mode"]] <- minview
  d$children[[2L]]$children[[3]]$attribs[["data-date-min-view-mode"]] <- minview
  d$children[[2L]]$children[[1]]$attribs[["data-date-max-view-mode"]] <- maxview
  d$children[[2L]]$children[[3]]$attribs[["data-date-max-view-mode"]] <- maxview
  d
}

И вот минимальный блестящий пример:

library(shiny)
shinyApp(
  ui = fluidPage(
    dateInput2("test1", "Year", startview = "year", minview = "months", maxview = "decades"),
    dateRangeInput2("test2", "Years", startview = "year", minview = "months", maxview = "decades")
  ),
  server = function(input, output, session) {}
)

Обновить:

Чтобы ответить на вопрос darKnight, приведенный ниже, я расширил пример и ввел параметр для настройки также максимального разрешения по времени. Для получения полного списка возможных параметров, пожалуйста, обратитесь к:

https://bootstrap-datepicker.readthedocs.io/en/latest/options.html