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

通过actionButton触发observeEvent实现shinyjqui指定向量拖拽至表格

解决方案

要实现点击按钮将指定元素批量放置到网格的特定位置,并同步移除原区域的元素,可通过以下步骤修改代码:

1. 调整UI,添加触发按钮

在UI中新增一个actionButton,用于触发元素放置操作,同时添加自定义JS函数处理元素移动逻辑:

ui <- fluidPage(
    tags$head(tags$script(
        JS(
            "
            $(function() {
                $('[id^=droppable_cell]').sortable({
                    connectWith: '#letters',
                    drop: function(event, ui) {
                        $(this).append(ui.draggable);
                    }
                })
            });
            
            // 全局函数:将指定元素移动到目标单元格
            window.moveElementToCell = function(elementId, targetCellId) {
                var $element = $('#' + elementId);
                var $target = $('#' + targetCellId);
                $target.append($element);
                // 刷新排序组件状态,保证后续拖拽功能正常
                $('#letters').sortable('refresh');
                $('[id^=droppable_cell]').sortable('refresh');
            }
            "
        )
    ),
    tags$style(HTML("...")), # 保留原样式代码
    
    # 添加触发按钮
    actionButton("place_elements", "放置指定元素"),
    
    div(class = "table-container", ...) # 保留原网格和orderInput代码
)

2. 服务器端逻辑处理

在server函数中监听按钮点击事件,定义要放置的元素和对应目标单元格,调用JS函数完成移动,并更新原区域的元素列表:

server <- function(input, output, session) {
    observeEvent(input$place_elements, {
        # 定义要放置的元素向量和对应目标单元格
        vec <- c("A", "B", "C")
        target_cells <- paste0("droppable_cell_", 1:3) # 对应第1-3个网格单元格
        
        # 遍历元素,逐个调用JS函数完成移动
        for(i in seq_along(vec)) {
            element_id <- paste0("letters_", vec[i]) # orderInput生成的元素ID格式为"[inputId]_[item]"
            runjs(sprintf("moveElementToCell('%s', '%s')", element_id, target_cells[i]))
        }
        
        # 更新letters区域,移除已放置的元素
        remaining_items <- setdiff(LETTERS[1:7], vec)
        updateOrderInput(session, "letters", items = remaining_items)
    })
}

3. 完整代码

整合后的完整可运行代码如下:

library(shiny)
library(shinyjqui)

connections <- paste0("droppable_cell_", 1:7) # 网格单元格ID

ui <- fluidPage(
    tags$head(tags$script(
        JS(
            "
            $(function() {
                $('[id^=droppable_cell]').sortable({
                    connectWith: '#letters',
                    drop: function(event, ui) {
                        $(this).append(ui.draggable);
                    }
                })
            });
            
            // 全局函数:将指定元素移动到目标单元格
            window.moveElementToCell = function(elementId, targetCellId) {
                var $element = $('#' + elementId);
                var $target = $('#' + targetCellId);
                $target.append($element);
                // 刷新排序组件状态,保证后续拖拽功能正常
                $('#letters').sortable('refresh');
                $('[id^=droppable_cell]').sortable('refresh');
            }
            "
        )
    ),
    # 样式代码
    tags$style(
        HTML(
            "
            .grid-table {
                width: 150px;
                border-collapse: collapse;
            }
            .grid-cell {
                width: 100%;
                height: 50px;
                border: 1px solid black;
                background-color: white;
                text-align: center;
                margin: 0;
                padding: 5px;
            }
            .grid-cell-text {
                display: flex;
                align-items: center;
                justify-content: center;
                height: 100%;
                background-color: steelblue;
                color: white;
                font-size: 18px;
            }
            .droppable-cell {
                background-color: lightgray;
            }
            .table-container {
                display: flex;
                position: absolute;
                left: 550px;
                top: 30px;
                margin-top: 0px;
                overflow: hidden;
            }
            "
        )
    )),
    
    # 触发按钮
    actionButton("place_elements", "放置指定元素"),
    
    div(
        class = "table-container",
        div(
            class = "grid-table",
            id = "my_grid",
            div(
                class = "grid-row",
                div(class = "grid-cell grid-cell-text", "my_grid"),
                div(id = "droppable_cell_1", class = "grid-cell droppable-cell", ""),
                div(id = "droppable_cell_2", class = "grid-cell droppable-cell", ""),
                div(id = "droppable_cell_3", class = "grid-cell droppable-cell", ""),
                div(id = "droppable_cell_4", class = "grid-cell droppable-cell", ""),
                div(id = "droppable_cell_5", class = "grid-cell droppable-cell", ""),
                div(id = "droppable_cell_6", class = "grid-cell droppable-cell", ""),
                div(id = "droppable_cell_7", class = "grid-cell droppable-cell", "")
            )
        ),
        
        orderInput('letters', 'Letters', items = LETTERS[1:7],
                   connect = connections)
    )
)

server <- function(input, output, session) {
    observeEvent(input$place_elements, {
        # 定义要放置的元素和对应目标单元格
        vec <- c("A", "B", "C")
        target_cells <- paste0("droppable_cell_", 1:3)
        
        # 逐个移动元素到目标单元格
        for(i in seq_along(vec)) {
            element_id <- paste0("letters_", vec[i])
            runjs(sprintf("moveElementToCell('%s', '%s')", element_id, target_cells[i]))
        }
        
        # 更新letters区域,移除已放置的元素
        remaining_items <- setdiff(LETTERS[1:7], vec)
        updateOrderInput(session, "letters", items = remaining_items)
    })
}

shinyApp(ui, server)

关键说明

  • orderInput生成的元素ID固定格式为[inputId]_[item],比如元素A的ID是letters_A,这是JS定位元素的核心依据
  • 自定义JS函数moveElementToCell负责完成元素的DOM移动,并刷新排序组件状态,避免后续拖拽功能异常
  • 使用updateOrderInput同步更新原区域的元素列表,确保视觉和功能上的一致性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 21:00:05