07.05 如何使用自定义图层编辑节点属性 —— 关于 节点编辑

原创
2022/05/09 06:27
阅读数 253

简介

很多时候,当你需要新建节点时,并不仅仅只需要个节点的名称,你会需要一系列的数据属性,这时候 zTree 提供的 input 输入框就绝对无法满足你的需求,本篇将全面讲解如何让新增按钮配合 zTree 外面的表单实现这种功能。

看这篇文档时,你需要对照 API 文档进行学习(http://www.treejs.cn/v3/api.php

css

这是 demo,只是实现功能,所以只显示简单的表单,不会做什么美化的样式处理

表单图层具体显示位置请自行处理,可以在 树旁边 显示,也可以做成浮动图层显示

// 新增按钮的样式
.ztree li span.button.add {
    margin-left: 2px;
    margin-right: -1px;
    background-position: -144px 0;
    vertical-align: top;
    *vertical-align: middle
}

// demo 界面简单样式
# ztree-layer {
    margin: 0 auto;
    width: 500px;
}
# new-node-layer {
    display: none;
    position: absolute;
    width: 300px;
    height: 150px;
    top: 100px;
    left: 50%;
    margin-left: -150px;
    background-color: #ffffff;
    border: 1px solid silver;
    box-shadow: 0 0 5px #1E1E1E;
    text-align: center;
    padding: 30px;
}
# new-node-layer div {
    margin: 20px;
}

body 内的HTML

<div id="ztree-layer">
    <ul id="treeDemo" class="ztree"></ul>
</div>
<!-- Demo 使用的简单表单,你可以使用外面的表单组件,也可以制作自己需要的表单结构 -->
<div id="new-node-layer">
    <div>
        名称:<input id="nodeName" name="nodeName">
    </div>
    <div>
        简介:<input id="nodeInfo" name="nodeInfo">
    </div>
    <div>
        <button type="button" onclick="submitNewNode()">确定</button>
        <button type="button" onclick="hideForm()">取消</button>
    </div>
</div>

js 代码

var setting = {
    view: {
        addHoverDom: addHoverDom,
        removeHoverDom: removeHoverDom,
        selectedMulti: false
    },
    edit: {
        enable: true,
        editNameSelectAll: true
    },
    data: {
        simpleData: {
            enable: true
        }
    },
    callback: {
        beforeDrag: beforeDrag,
        beforeEditName: beforeEditName,
        onRemove: onRemove
    }
};

var zNodes = [
    {id: 1, pId: 0, name: "父节点 1", open: true},
    {id: 11, pId: 1, name: "叶子节点 1-1"},
    {id: 12, pId: 1, name: "叶子节点 1-2"},
    {id: 13, pId: 1, name: "叶子节点 1-3"},
    {id: 2, pId: 0, name: "父节点 2", open: true},
    {id: 21, pId: 2, name: "叶子节点 2-1"},
    {id: 22, pId: 2, name: "叶子节点 2-2"},
    {id: 23, pId: 2, name: "叶子节点 2-3"},
    {id: 3, pId: 0, name: "父节点 3", open: true},
    {id: 31, pId: 3, name: "叶子节点 3-1"},
    {id: 32, pId: 3, name: "叶子节点 3-2"},
    {id: 33, pId: 3, name: "叶子节点 3-3"}
];

// Demo 中禁止拖拽操作
function beforeDrag(treeId, treeNodes) {
    return false;
}

// 让表单同时具有编辑节点的功能
// 利用 beforeEditName 回调函数,关闭 zTree 默认编辑功能,同时显示表单
function beforeEditName(treeId, treeNode) {
    zTreeObj.selectNode(treeNode);
    showForm(treeNode, false);
    return false;
}

// 删除节点时,如果是正在编辑的节点,就直接隐藏表单
function onRemove(e, treeId, treeNode) {
    if (newNodeLayer.curNode == treeNode) {
        hideForm();
    }
}

// 新增按钮的处理,这部分与前两篇文章基本一样,有区别的地方主要在 click 事件中
var newCount = 1;
function addHoverDom(treeId, treeNode) {
    var sObj = $("#" + treeNode.tId + "_span");
    if (treeNode.editNameFlag || $("#addBtn_" + treeNode.tId).length > 0) return;
    var addStr = "<span class='button add' id='addBtn_" + treeNode.tId
        + "' title='add node' onfocus='this.blur();'></span>";
    sObj.after(addStr);
    var btn = $("#addBtn_" + treeNode.tId);
    if (btn) {
        btn.bind("click", function () {
            // 选中当前父节点
            zTreeObj.selectNode(treeNode);
            // 显示表单
            showForm(treeNode, true);
            return false;
        });
    }
}
// 移除新增按钮
function removeHoverDom(treeId, treeNode) {
    $("#addBtn_" + treeNode.tId).unbind().remove();
}

// 表单提交
function submitNewNode() {
    var nodeName = nodeNameObj.val();
    var nodeInfo = nodeInfoObj.val();
    // 数据校验
    if (nodeName.length === 0) {
        alert('名称不允许为空!');
        return;
    }

    // 这里采用 setTimeout 模拟 ajax 的异步功能,
    // 延迟 2 秒后处理界面上的 新增、编辑操作
    // 实际应用中,肯定还要考虑 服务端处理数据出错的情况, 
    // 出错后就不应该在界面上 新增、编辑了
    setTimeout(function() {
        if (newNodeLayer.addNode) {
            // 新增节点操作
            zTreeObj.addNodes(newNodeLayer.curNode, {
                id: (100 + newCount),
                pId: newNodeLayer.curNode.id,
                name: nodeName,
                info: nodeInfo
            });
        } else {
            // 编辑节点操作
            newNodeLayer.curNode.name = nodeName;
            newNodeLayer.curNode.info = nodeInfo;
            zTreeObj.updateNode(newNodeLayer.curNode);
        }
        // 保存后,隐藏表单
        hideForm();
    }, 2000);
}

// 隐藏表单
function hideForm() {
    newNodeLayer.hide();
}

// 显示表单
function showForm(treeNode, addNode) {
    treeNode = treeNode || {};
    newNodeLayer.curNode = treeNode;
    newNodeLayer.addNode = !!addNode;
    if (!newNodeLayer.addNode) {
        nodeNameObj.val(treeNode.name || '');
        nodeInfoObj.val(treeNode.info || '');
    }
    newNodeLayer.show();
    nodeNameObj.get(0).focus();
}

// 页面加载后初始化 zTree
var zTreeObj, newNodeLayer, nodeNameObj, nodeInfoObj;
$(document).ready(function () {
    zTreeObj = $.fn.zTree.init($("#treeDemo"), setting, zNodes);
    newNodeLayer = $('#new-node-layer');
    nodeNameObj = $('#nodeName');
    nodeInfoObj = $('#nodeInfo');
});

因为 Demo 无法真正模拟在服务端保存数据库,所以这里使用 setTimeout 去模拟 ajax 的异步过程,请一定要注意。 Demo 中采用的是一次性加载的数据,当你换成异步加载时,你会发现给没有展开的父节点添加子节点后,新节点出现了两个,这是为什么呢?请看下一篇:7.06 为什么异步加载时,新增节点后会出现重复的节点

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部