【问题标题】:Display only months in dateRangeInput or dateInput for a shiny app [R programming]仅在 dateRangeInput 或 dateInput 中为闪亮的应用程序显示月份 [R 编程]
【发布时间】:2015-07-01 05:10:45
【问题描述】:

我正在使用 shiny 来创建网络应用程序。我的一个情节仅使用特定年份的几个月来生成情节中的点。

我希望用户只选择月份。虽然我已经提到了

format = 'mm-yyyy'startview = 'year'dateInputdateRangeInput

每当用户点击日期输入字段时,用户将看到月份,然后在点击任何月份时,用户将显示该月的日期。

我希望用户显示到几个月。如果用户单击月份,则不应显示日期。

如何做到这一点?

【问题讨论】:

    标签: r shiny


    【解决方案1】:

    我不相信dateInput 已经将bootstrap minViewMode option 实现为函数参数,所以我将它添加到我自己的函数副本中(见下文)。我不得不添加一些其他必需的功能。这不是很好。最好的选择可能是向 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")
    

    【讨论】:

    • 这太棒了!想知道如何为 dateRangeInput 扩展它
    • @MartinJohnHadley 我偶然发现了这个问题并在下面的答案中解决了它。
    【解决方案2】:

    @MartinJohnHadley:基本上是将添加到 dateInput 的代码中的相同的三行 @StevenMortimer 添加到 dateRangeInput。这会将 minViewMode 添加到闪亮的 dateRangeInput。

    1. https://github.com/rstudio/shiny/blob/master/R/input-daterange.R找到代码
    2. 添加默认参数minviewmode="months"
    3. 在两个 div 中添加 data-date-min-view-mode = minviewmode
    4. 添加缺少的参数(在闪亮的 github 存档中搜索)
    5. 享受您的自定义日期范围输入 :-)

    最好的问候, 桑德罗

    代码:

    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>")
    

    【讨论】:

    • 太棒了!非常感谢您在记住这个问题并提出这个问题时的惊人表现。
    • 提示:最好始终使用更新后的 datePickerDependency,它始终可以在 github.com/rstudio/shiny/blob/master/R/input-date.R 找到(感谢 gico 的评论)。
    【解决方案3】:

    这是另一种方法(代码冗余更少,希望更简单),由一位同事提供。可以在之后将 min/max-view-mode 部分添加到 Shiny 对象,而不是复制 shiny::dateInput 函数代码。那么老参数'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
    }
    

    这是一个最小的 Shiny 示例:

    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

    【讨论】:

    • 这非常有效.. 我在我的应用程序脚本的顶部添加了该功能,然后将它用于我的主要过滤器并获得所需的效果。据我所知,可以扩展该功能以限制其他参数,例如年/十年?例如,这将过滤器限制为月份内的日期,少量添加也可以限制年份或十年之外的日期吗?
    • David 这运行良好,直到闪亮的 1.6.0... dateInput2 现在完全空白。我不确定这是否是 shinydashboard 0.7.1 引入的问题。作为一个 mjnimal 示例仍然可以正常工作。只是发布这个以防其他人找到解决方法。我回滚到使用旧的 dateInput ,这真是太可惜了!
    【解决方案4】:

    谁想要使用上一个答案中的代码: 您需要使用更新后的 datePickerDependecy(可以取自 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>")
    

    由于声誉不足,我将此评论作为答案发布:(

    【讨论】:

      猜你喜欢
      • 2016-05-27
      • 1970-01-01
      • 1970-01-01
      • 2018-07-14
      • 2015-11-13
      • 2021-01-04
      • 2019-07-09
      • 2016-12-20
      • 1970-01-01
      相关资源
      最近更新 更多