在R Shiny应用中通过JavaScript添加GridStack组件遇到问题
问题背景
正在开发R Shiny应用,尝试通过JavaScript向GridStack网格添加组件,参考相关思路编写代码后,.grid-stack选择器验证有效,但调用add_widget方法无法添加组件;同时用V8包加载GridStack.js时出现SyntaxError: Unexpected token {错误,不清楚是否需要安装GridStack.js包及解决办法。
用户编写的代码如下:
library(shinydashboard) library(shiny) library(shinyjs) library(shinyjqui) library(gridstackeR) ui <- fluidPage ( useShinyjs(), includeCSS("www/app.css"), tags$head( tags$script(src = "https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/gridstack.min.js"), tags$script(' function addFirstWidget() { var el = $.parseHTML("<div class=\"grid-stack-item-content\">First Widget Content</div>"); var grids = $(".grid-stack").data("gridstack"); grids.add_widget(el, 1, 1, 4, 1, true); } ') ), grid_stack( grid_stack_item() ), actionButton("first_widget", "First Widget"), title = "Gridstack Prototype" ) server <- function(input, output, session) { observeEvent(input$first_widget, { # browser() runjs("addFirstWidget();") }) } shinyApp(ui = ui, server = server)
V8测试代码及错误:
engine <- v8() uri <- paste0("https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/gridstack.min.js") engine$source(uri)
错误信息:Error in context_eval(join(src), private$context, serialize, await) : SyntaxError: Unexpected token {
解决方案
1. 修复GridStack组件添加的JavaScript代码问题
你当前的代码存在两个核心问题:
- GridStack v10+的API已升级,旧版
add_widget方法改为驼峰命名的addWidget,参数传递方式也从零散参数改为配置对象 - 添加组件需要完整的GridStack Item结构(外层容器+内容层),而非仅内容层
修改后的JavaScript函数:
function addFirstWidget() { // 创建完整的GridStack Item元素结构 var item = document.createElement('div'); item.className = 'grid-stack-item'; var content = document.createElement('div'); content.className = 'grid-stack-item-content'; content.textContent = 'First Widget Content'; item.appendChild(content); // 获取GridStack实例 var grid = GridStack.init('.grid-stack')[0]; if (grid) { // 使用新版API添加组件,传入配置对象 grid.addWidget(item, {x: 1, y: 1, width: 4, height: 1, autoPosition: true}); } }
同时注意:gridstackeR包已内置GridStack库,无需额外在<head>中引入外部CDN资源,重复引入会导致版本冲突,建议移除tags$script(src = "https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/gridstack.min.js")这一行。
2. 解决V8加载GridStack.js的错误
GridStack v10+采用ES模块语法,V8引擎无法直接解析模块代码,且前端代码本就应该在浏览器环境中运行,不需要用V8测试这部分逻辑,直接在Shiny应用的浏览器控制台调试即可。
3. 无需单独安装GridStack.js包
gridstackeR已经集成了GridStack的所有前端资源,不需要单独安装前端的GridStack包,确保gridstackeR为最新版本即可:
update.packages("gridstackeR")
修改后的完整Shiny代码
library(shinydashboard) library(shiny) library(shinyjs) library(shinyjqui) library(gridstackeR) ui <- fluidPage ( useShinyjs(), includeCSS("www/app.css"), tags$head( tags$script(' function addFirstWidget() { // 创建完整的GridStack Item结构 var item = document.createElement("div"); item.className = "grid-stack-item"; var content = document.createElement("div"); content.className = "grid-stack-item-content"; content.textContent = "First Widget Content"; item.appendChild(content); // 获取GridStack实例 var grid = GridStack.init(".grid-stack")[0]; if (grid) { grid.addWidget(item, {x: 1, y: 1, width: 4, height: 1, autoPosition: true}); } } ') ), grid_stack( grid_stack_item() ), actionButton("first_widget", "First Widget"), title = "Gridstack Prototype" ) server <- function(input, output, session) { observeEvent(input$first_widget, { runjs("addFirstWidget();") }) } shinyApp(ui = ui, server = server)
内容的提问来源于stack exchange,提问作者LinguiniThePasta

