如何在Rshiny的长期演出中断行?

时间:2017-09-19 02:24:40

标签: r shiny

我正在努力在页面中间添加多行闪亮通知。但是,没有一个直观的断行命令,如\ r; \ n或
根本不工作。我想知道解决这个问题的解决办法是什么?

以下是最小的工作示例:

library(shiny)

shinyApp(
  ui = fluidPage(
    tags$head(
      tags$style(HTML(".shiny-notification { position:fixed; top: calc(300px);; left: calc(15px);; }" ))),

    textInput("txt", "Content", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, 
              sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
              Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut 
              aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in 
              voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur 
              sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt 
              mollit anim id est laborum."),

    radioButtons("duration", "Seconds before fading out",
                 choices = c("2", "5", "10", "Never"),
                 inline = TRUE
    ),
    radioButtons("type", "Type",
                 choices = c("default", "message", "warning", "error"),
                 inline = TRUE
    ),
    checkboxInput("close", "Close button?", TRUE),
    actionButton("show", "Show"),
    actionButton("remove", "Remove most recent")
  ),
  server = function(input, output) {
    id <- NULL

    observeEvent(input$show, {
      if (input$duration == "Never")
        duration <- NA
      else 
        duration <- as.numeric(input$duration)

      type <- input$type
      if (is.null(type)) type <- NULL

      id <<- showNotification(
        input$txt,
        duration = duration, 
        closeButton = input$close,
        type = type
      )
    })

    observeEvent(input$remove, {
      removeNotification(id)
    })
  }
)

非常感谢您回答这个问题的时间和精力。

1 个答案:

答案 0 :(得分:1)

我的第一个想法是将它包装在HTML(...)中,例如:

    HTML(paste(strwrap("Lorem ipsum dolor sit amet, consectetur adipiscing elit, 
              sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
              Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut 
              aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in 
              voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur 
              sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt 
              mollit anim id est laborum."), collapse="<br/>"))

这也不起作用。所以我查看了showNotification的来源:

function (ui, action = NULL, duration = 5, closeButton = TRUE, 
    id = NULL, type = c("default", "message", "warning", "error"), 
    session = getDefaultReactiveDomain()) 
{
    if (is.null(id)) 
        id <- createUniqueId(8)
    res <- processDeps(ui, session)
    actionRes <- processDeps(action, session)
    session$sendNotification("show", list(html = res$html, action = actionRes$html, 
        deps = c(res$deps, actionRes$deps), duration = if (!is.null(duration)) duration * 
            1000, closeButton = closeButton, id = id, type = match.arg(type)))
    id
}

调试时,您会看到:

> res
$html
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. &lt;br/&gt; Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. &lt;br/&gt; Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

$deps
list()

一个问题(我推断)是它不信任字符串,所以它是HTML编码的所有东西(我不知道是否或为什么会这样,但我建议允许用户定义的消息在通知中使用可能是可疑的,与sql-injection一样。因此,可以重写函数,确保文本不被转义。

showNotification2 <- function (ui, action = NULL, duration = 5, closeButton = TRUE, 
    id = NULL, type = c("default", "message", "warning", "error"), 
    session = shiny:::getDefaultReactiveDomain()) {
    if (is.null(id)) 
        id <- shiny:::createUniqueId(8)
    res <- shiny:::processDeps(HTML(ui), session)
    actionRes <- shiny:::processDeps(action, session)
    session$sendNotification("show", list(html = res$html, action = actionRes$html, 
        deps = c(res$deps, actionRes$deps), duration = if (!is.null(duration)) duration * 
            1000, closeButton = closeButton, id = id, type = match.arg(type)))
    id
}

shiny不会导出多个函数,因此绝对会受到API更改和一切破坏的影响。或许这种行为是一个错误,我在这里的重写将被视为它的新版本。谁知道呢。

当你使用这个功能时,事情就像你希望的那样有效。

enter image description here

使用这个新功能,你实际上不需要HTML(),这可能表明这个hack实现有一个短缺。