Ext带复选框的Tree实现父子节点联动功能

昨晚有一个朋友问我EXT中带复选框的Tree控件是否可以实现节点被选中时父子节点联动的功能,之前做树形控件,一直都是在用Z-Tree的,速度快,功能强,这样的功能需求对于Z-Tree来说,完全小意思,原生API就可以支持的,偏偏到了EXT这里,就不行了。Ext本身是可以通过在节点属性中增加checked属性将一个普通节点变成带复选框的节点,但是奇怪的是,不支持父子节点联动功能,好怪异。

我觉得这个功能蛮简单的,刚好今天下午也有空,就自己写了一个demo,通过监听节点的checkchange事件来实现该功能,思路如下:

  1. 如果当前节点为父节点,则将当前节点的选中状态同步到所有的子节点;
  2. 如果当前节点被选中,则递归选中所有的祖先节点;
  3. 代码如下:
  4. Ext.require([
        'Ext.tree.*',
        'Ext.data.*',
        'Ext.window.MessageBox'
    ]);
    
    Ext.onReady(function() {
      //树数据存储器
        var store = Ext.create('Ext.data.TreeStore', {
            proxy: {
          //通过ajax代理获取数据
                type: 'ajax',
                url: 'check-nodes.json'
            },
        //排序器,可以没有
            sorters: [{
                property: 'leaf',
                direction: 'ASC'
            }, {
                property: 'text',
                direction: 'ASC'
            }]
        });
    
        var tree = Ext.create('Ext.tree.Panel', {
        //指定数据源
            store: store,
        //是否显示根节点
            rootVisible: false,
        //是否箭头图标
            useArrows: true,
        //是否以框架显示
            frame: true,
        //标题
            title: '多级节点联动树演示',
        //树结构的容器ID
            renderTo: 'tree-div',
        //树面板宽度
            width: 200,
        //树面板高度
            height: 250,
        //事件监听器
        listeners: {
          //监听复选框的选中属性改变事件
                checkchange : function(node,checked){
            //获得父节点
            pNode = node.parentNode;
            //改变当前节点的选中状态
            node.checked = checked;
            //判断当前节点是否为叶子节点
            var isLeaf = node.isLeaf();
            //当该节点有子节点时,将所有子节点的选中状态同化
            if (!isLeaf){
              //cascade是指从当前节点node开始逐层下报,即遍历当前节点的每一个节点(无论有多少层级结构,详参API)
              node.cascade(function(node){
                node.set("checked", checked);
              });
            }
            //如果当前节点是选中状态
            if (checked == true) {
              //将当前节点的所有未选中的父节点选中
              for (;pNode != null && !pNode.get("checked");pNode = pNode.parentNode) {
                pNode.set("checked", true);
              }
            }else{
              //取消当前节点的所有不包含选中的子节点的父节点的选中状态
              for (;pNode != null;pNode = pNode.parentNode) {	
                //如果当前的父节点包含选中的子节点,则终止搜索过程
                if(hasCheckedNode(pNode)){
                  break;
                }else{
                  //否则取消当前父节点的选中状态
                  pNode.set("checked", false);
                }
              }
            }
          }
            }
        });
      //检查指定的父节点是否包含有选中的子节点
      function hasCheckedNode(node){
        var has = false;
        //当前节点是否含有子节点
        if(node.childNodes){
          //遍历子节点
          Ext.each(node.childNodes, function(item){
            //如果当前节点是叶子节点
            if(item.isLeaf()){
              //遇到选中的子节点时终止搜索过程
              if(has = item.get("checked")){
                return false;
              }
            //遇到含有选中的子节点的父节点时终止搜索过程
            }else if(has = hasCheckedNode(item)){
              return false;
            }
          });
        }
        return has;
      }
    });

你可能感兴趣的:(Ext,Ext)