jsTree层级树拖拽操作时如何自动重排节点连续序号
jsTreeR结合Shiny实现拖拽复制与自动连续序号需求
我正在基于jsTreeR、Shiny搭建层级树组件,需实现两类核心功能:
- 支持用户将源节点下标记为
moveable类型的元素,拖拽复制到类型为target的目标节点下,可自由选择元素放置位置 - 目标节点下的所有元素,在新增、删除、位置调整操作完成后,需按当前排列顺序生成连续序号,序号需随元素位置变化同步更新
效果参考文末附的示意图,以下提供可复现代码,求实现思路。
注:为精简代码篇幅,已删除部分实用扩展功能,待完成jsTreeR包的功能探索后,会公开完整代码供大家参考。本问题是此前Stack Overflow提问《如何将jsTree中的指定节点元素提取为R数据框》的后续问题。
初始版本可复现代码
library(jsTreeR) library(shiny) nodes <- list( list( text = "Menu", state = list(opened = TRUE), children = list( list( text = "A", type = "moveable", state = list(disabled = TRUE) ), list( text = "B", type = "moveable", state = list(disabled = TRUE) ) ) ), list( text = ">>> Drag here <<<", type = "target", state = list(opened = TRUE) ) ) checkCallback <- JS( "function(operation, node, parent, position, more) { ", " if(operation === 'copy_node') {", " if(parent.id === '#' || node.parent !== 'j1_1' || parent.type !== 'target') {", " return false;", " }", " }", " if(operation === 'delete_node') {", " Shiny.setInputValue('deletion', position + 1);", " }", " return true;", "}" ) dnd <- list( always_copy = TRUE, is_draggable = JS( "function(node) {", " return node[0].type === 'moveable';", "}" ) ) mytree <- jstree( nodes, dragAndDrop = TRUE, dnd = dnd, checkCallback = checkCallback, types = list(moveable = list(), target = list()) ) script <- ' $(document).ready(function(){ $("#mytree").on("copy_node.jstree", function(e, data){ var instance = data.new_instance; var node = data.node; var id = node.id; var index = $("#"+id).index() + 1; var text = index + ". " + node.text; Shiny.setInputValue("choice", text); instance.rename_node(node, text); }); }); ' library(shiny) ui <- fluidPage( tags$head(tags$script(HTML(script))), fluidRow( column(width = 4,jstreeOutput("mytree")), column(width = 8,verbatimTextOutput("choices")) ) ) server <- function(input, output, session){ output[["mytree"]] <- renderJstree(mytree) Choices <- reactiveVal(data.frame(choice = character(0))) observeEvent(input[["choice"]],{Choices(rbind(Choices(),data.frame(choice = input[["choice"]])))}) observeEvent(input[["deletion"]], {Choices(Choices()[-input[["deletion"]], , drop = FALSE])}) output[["choices"]] <- renderPrint({Choices()}) } shinyApp(ui, server)
初始版本效果示意图
调整版本:限制拖拽仅可放置到目标节点末尾
针对首条评论做的修改:限制用户仅可拖拽复制到“>>> Drag here <<<”节点的末尾位置
修改说明:两处新增内容已在代码中以#注释标注,修改后仍存在序号异常问题。
nodes <- list(nodes <- list( list( text = "Menu", state = list(opened = TRUE), children = list( list( text = "A", type = "moveable", state = list(disabled = TRUE) ), list( text = "B", type = "moveable", state = list(disabled = TRUE) ), list( # 新增第三个可拖拽元素 text = "C", type = "moveable", state = list(disabled = TRUE) ) ) ), list( text = ">>> Drag here <<<", type = "target", state = list(opened = TRUE) ) ) checkCallback <- JS( "function(operation, node, parent, position, more) { ", " if(operation === 'copy_node') {", " if(parent.id === '#' || node.parent !== 'j1_1' || parent.type !== 'target') {", " return false;", " }", " }", " if(operation === 'delete_node') {", " Shiny.setInputValue('deletion', position + 1);", " }", " return true;", "}" ) dnd <- list( always_copy = TRUE, inside_pos = "last", # 新增配置:拖拽到节点内时默认放末尾 is_draggable = JS( "function(node) {", " return node[0].type === 'moveable';", "}" ) ) mytree <- jstree( nodes, dragAndDrop = TRUE, dnd = dnd, checkCallback = checkCallback, types = list(moveable = list(), target = list()) ) script <- ' $(document).ready(function(){ $("#mytree").on("copy_node.jstree", function(e, data){ var instance = data.new_instance; var node = data.node; var id = node.id; var index = $("#"+id).index() + 1; var text = index + ". " + node.text; Shiny.setInputValue("choice", text); instance.rename_node(node, text); }); }); ' library(shiny) ui <- fluidPage( tags$head(tags$script(HTML(script))), fluidRow( column(width = 4,jstreeOutput("mytree")), column(width = 8,verbatimTextOutput("choices")) ) ) server <- function(input, output, session){ output[["mytree"]] <- renderJstree(mytree) Choices <- reactiveVal(data.frame(choice = character(0))) observeEvent(input[["choice"]],{Choices(rbind(Choices(),data.frame(choice = input[["choice"]])))}) observeEvent(input[["deletion"]], {Choices(Choices()[-input[["deletion"]], , drop = FALSE])}) output[["choices"]] <- renderPrint({Choices()}) } shinyApp(ui, server)
序号异常问题示意图
内容的提问来源于stack exchange,提问作者Curious Jorge - user9788072
相关产品推荐
相关产品推荐





