You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让shiny.semantic的showNotification/toast支持top attached定位?

解决shiny.semantic中showNotification/toast支持'top attached'定位的问题

问题背景

根据Fomantic UI文档,原生JS可直接生成top attached类型的toast:

$.toast({
  position: 'top attached',
  title: 'Watch out!',
  message: `I am a top attached toast`
});

但在shiny.semantic包中,showNotification函数无法识别'top attached'参数,常规位置(如bottom left)则可正常生效。

解决方案

方案1:扩展showNotification的位置映射

shiny.semantic的showNotification内部会将position参数转换为对应CSS类,默认未包含top attached这类带附加属性的位置。我们可以自定义包装函数手动处理:

library(shiny)
library(shiny.semantic)

# 自定义支持top attached的showNotification
showNotificationCustom <- function(ui, type = "default", position = "top right", ...) {
  if (position == "top attached") {
    # 构造带top attached类的通知元素
    notification_tag <- div(
      class = paste("ui", type, "top attached notification"),
      ui,
      tags$button(class = "close icon", tags$i(class = "close icon"))
    )
    # 发送通知到页面
    session <- shiny::getDefaultReactiveDomain()
    session$sendCustomMessage(
      "addNotification",
      list(html = as.character(notification_tag), position = "top")
    )
    # 绑定关闭事件
    session$sendCustomMessage(
      "setupNotificationClose",
      list(selector = ".top.attached.notification")
    )
  } else {
    # 常规位置调用原函数
    showNotification(ui, type = type, position = position, ...)
  }
}

# 测试应用
if (interactive()) {
  shinyApp(
    ui = semanticPage(
      title = 'Title',
      actionButton('bottom_left', 'Bottom left!'),
      actionButton('top_attached', 'Top attached!')
    ),
    server = function(input, output) {
      observeEvent(input$bottom_left, {
        showNotification(
          ui = 'Bottom left notification',
          type = 'default',
          position = 'bottom left'
        )
      })
      
      observeEvent(input$top_attached, {
        showNotificationCustom(
          ui = 'Top attached notification',
          type = 'default',
          position = 'top attached'
        )
      })
    }
  )
}

方案2:直接调用原生Fomantic UI Toast(更简洁)

利用shiny::tags$script执行原生JS代码,绕过shiny.semantic封装,完全支持Fomantic UI所有toast参数:

library(shiny)
library(shiny.semantic)

# 封装自定义toast函数
toastCustom <- function(title, message, position = "top right", type = "default") {
  session <- shiny::getDefaultReactiveDomain()
  # 构造JS执行代码
  js_code <- sprintf(
    "$.toast({
       position: '%s',
       title: '%s',
       message: '%s',
       class: '%s'
     });",
    position, title, message, type
  )
  session$sendCustomMessage("executeJS", list(code = js_code))
}

# 测试应用
if (interactive()) {
  shinyApp(
    ui = semanticPage(
      title = 'Title',
      actionButton('show_top_attached', 'Show Top Attached Toast!'),
      actionButton('show_bottom_left', 'Show Bottom Left Toast!')
    ),
    server = function(input, output) {
      observeEvent(input$show_top_attached, {
        toastCustom(
          title = 'Watch out!',
          message = 'I am a top attached toast',
          position = 'top attached',
          type = 'warning'
        )
      })
      
      observeEvent(input$show_bottom_left, {
        toastCustom(
          title = 'Hello!',
          message = 'I am a bottom left toast',
          position = 'bottom left',
          type = 'info'
        )
      })
    }
  )
}

方案3:修正原toast函数的toast_tags使用

你提供的示例中toast函数的toast_tags写法会重复创建toast,正确做法是通过toast_tags修改已创建toast的CSS类:

observeEvent(input$show, {
  toast(
    title = 'See me!',
    message = 'Where am I?',
    toast_tags = tags$script(
      "$('.ui.toast').removeClass('top-right').addClass('top attached');"
    )
  )
})

该方法在toast创建后修改样式,也能实现效果,但不如前两种方案优雅。


内容的提问来源于stack exchange,提问作者Serkan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 11:37:03