在ExtJs 4树面板中取消选择节点的子节点的内置方法

时间:2013-07-31 14:49:18

标签: extjs tree extjs4

我正在使用ExtJs树面板。是否有任何内置方法或属性将在您选择该节点时取消选择节点的所有子节点。

因此,请考虑下面的图像,假设已经选择了黄色背景颜色的节点。如果我现在选择1.1,系统应自动取消选择1.1.2&如果我选择了节点1,它应该取消选择1.1.2,.1.2.1,1.2.2。

请提供您的建议

enter image description here

Ext.create('Ext.tree.Panel', {
    title: 'Simple Tree',
    renderTo: Ext.getBody(),
    width: 400,
    height: 400,

    store: {
        root: {
            expanded: true,
            children: [{
                text: "1 detention",
                expanded: true,
                "checked": false,
                children: [{
                    text: '1.1 foo',
                    leaf: true,
                    "checked": false
                }, {
                    text: '1.2 bar',
                    leaf: true,
                    "checked": false
                }]
            }, {
                text: "2 homework",
                expanded: true,
                "checked": false,
                children: [{
                    text: "2.1 book report",
                    leaf: true,
                    "checked": false
                }, {
                    text: "2.2 algebra",
                    expanded: true,
                    "checked": false,
                    children: [{
                        text: "2.2.1 buy lottery tickets",
                        leaf: true,
                        "checked": false
                    }, {
                        text: "2.2.2 buy lottery tickets 2",
                        leaf: true,
                        "checked": false
                    }]
                }]
            }, {
                text: "3 buy lottery tickets",
                leaf: true,
                "checked": false
            }]
        }
    },
    useArrows: false,
    rootVisible: false,
    selModel: {
        mode: 'SIMPLE'
    },
    listeners: {
        deselect: function (tree, record) {
            if (record.data.text === '1 detention') {

            }
        },
        select: function (tree, record) {
            var parentNode = record.parentNode;

            // Deselect children
            function deselectChildren(record) {
                tree.deselect(record.childNodes, false);
                record.eachChild(deselectChildren);
            }
            deselectChildren(record);

            // See if all siblings are selected now
            var allSiblingSelected = false;
            if (parentNode) {
                allSiblingSelected = parentNode.childNodes.reduce(function (previous, node) {
                    return previous && tree.isSelected(node)
                }, true);
            }

            if (allSiblingSelected) {
                tree.select(parentNode, true); // will trigger req 1
            }

            // Deselect ancestors
            else {
                while (parentNode) {
                    tree.deselect(parentNode);
                    parentNode = parentNode.parentNode;
                }
            }
        }
    }
});

1 个答案:

答案 0 :(得分:2)

不,没有内置的东西。哦,现在我想起来了,那些内置于Ext的事件。你可以在那里找到一个并实现自己的逻辑!在您的情况下,那将是select事件。

以下是我建议您完全按照您所描述的内容进行操作(使用文档中的示例树面板):

Ext.create('Ext.tree.Panel', {
    title: 'Simple Tree',
    renderTo: Ext.getBody(),
    width: 400,
    height: 400,
    store: {
        root: {
            expanded: true,
            children: [
                { text: "detention", leaf: true },
                { text: "homework", expanded: true, children: [
                    { text: "book report", leaf: true },
                    { text: "algebra", expanded: true, children: [
                        { text: "buy lottery tickets", leaf: true }
                    ]}
                ] },
                { text: "buy lottery tickets", leaf: true }
            ]
        }
    },
    rootVisible: false,
    selModel: {
        mode: 'SIMPLE'
    },
    listeners: {
        select: function(tree, record) {
            function deselectChildren(record) {
                tree.deselect(record.childNodes);
                record.eachChild(deselectChildren);
            }
            deselectChildren(record);
        }
    }
});

但这给了我们一个非常奇怪的用户体验,因为你可以再次选择子节点,一旦选择了父节点...并触发行为(通过再次点击他们的祖先取消选择子节点),你必须首先取消选择父母,然后重新选择...简而言之,IMO,这令人困惑。

因此,为了让所有这些事情对用户更具可预测性,我建议在选择节点时通过以这种方式更改select侦听器来取消选择所有祖先:

select: function(tree, record) {
    // Deselect children
    function deselectChildren(record) {
        tree.deselect(record.childNodes);
        record.eachChild(deselectChildren);
    }
    deselectChildren(record);

    // Deselect ancestors
    var parentNode = record.parentNode;
    while (parentNode) {
        tree.deselect(parentNode);
        parentNode = parentNode.parentNode;
    }
}

或阻止选择具有祖先选择的节点:

listeners: {
    select: function(tree, record) {
        function deselectChildren(record) {
            tree.deselect(record.childNodes);
            record.eachChild(deselectChildren);
        }
        deselectChildren(record);
    }
    // Returning false from this event handler will prevent selection (see the doc)
    ,beforeselect: function(tree, record) {
        function isAncestorSelected(record) {
            var parentNode = record.parentNode;
            return tree.isSelected(record) || parentNode && isAncestorSelected(parentNode);
        }
        return !isAncestorSelected(record);
    }
}

但是,如果你想要我的意见,那第二种行为也有点怪。我会使用第一个。

现在,如果你愿意,你可以将所有这些包装在一个ux(用户扩展名)中,在Sencha市场上发布,从那里下载,然后在你的代码中使用它...这样,你就可以了你的行为内置于某事物中;)

修改

要求1 + 2 + 3的代码

Ext.create('Ext.tree.Panel', {
    title: 'Simple Tree',
    renderTo: Ext.getBody(),
    width: 400,
    height: 400,
    store: {
        root: {
            expanded: true,
            children: [
                { text: "detention", leaf: true },
                { text: "homework", expanded: true, children: [
                    { text: "book report", leaf: true },
                    { text: "algebra", expanded: true, children: [
                        { text: "buy lottery tickets", leaf: true }
                    ]}
                ] },
                { text: "buy lottery tickets", leaf: true }
            ]
        }
    },
    rootVisible: false,
    selModel: {
        mode: 'SIMPLE'
    },
    listeners: {
        select: function(tree, record) {
            var parentNode = record.parentNode;

            // Deselect children
            function deselectChildren(record) {
                tree.deselect(record.childNodes);
                record.eachChild(deselectChildren);
            }
            deselectChildren(record);

            // See if all siblings are selected now
            var allSiblingSelected = false;
            if (parentNode) {
                allSiblingSelected = parentNode.childNodes.reduce(function(previous, node) {
                    return previous && tree.isSelected(node)
                }, true);
            }

            if (allSiblingSelected) {
                // EDIT3: adding true for second argument keepExisting
                tree.select(parentNode, true); // will trigger req 1
            }

            // Deselect ancestors
            else {
                while (parentNode) {
                    tree.deselect(parentNode);
                    parentNode = parentNode.parentNode;
                }
            }
        }
    }
});

编辑4

带复选框:

Ext.create('Ext.tree.Panel', {
    title: 'Simple Tree',
    renderTo: Ext.getBody(),
    width: 400,
    height: 400,
    store: {
        root: {
            expanded: true,
            children: [
                { checked: false, text: "1 detention", expanded: true, children: [
                    {checked: false, text: '1.1 foo', leaf: true},
                    {checked: false, text: '1.2 bar', leaf: true}
                ] },
                { checked: false, text: "2 homework", expanded: true, children: [
                    { checked: false, text: "2.1 book report", leaf: true },
                    { checked: false, text: "2.2 algebra", expanded: true, children: [
                        { checked: false, text: "2.2.1 buy lottery tickets", leaf: true },
                        { checked: false, text: "2.2.2 buy lottery tickets 2", leaf: true }
                    ]}
                ] },
                { checked: false, text: "3 buy lottery tickets", leaf: true }
            ]
        }
    },
    rootVisible: false,
    disableSelection: true,
    //selModel: {mode: 'SIMPLE'},
    listeners: {
        checkchange: function(record, checked, opts) {
            if (!checked) return;
            var parentNode = record.parentNode;

            // Deselect children
            function deselectChildren(record) {
                record.eachChild(function(record) {
                    record.set('checked', false);
                    deselectChildren(record);
                });
            }
            deselectChildren(record);

            // See if all siblings are selected now
            var allSiblingSelected = false;
            if (parentNode) {
                allSiblingSelected = parentNode.childNodes.reduce(function(previous, node) {
                    return previous && node.get('checked');
                }, true);
            }

            if (allSiblingSelected) {
                parentNode.set('checked', true);
                // Apparently won't fire on its own
                this.fireEvent('checkchange', parentNode, true, opts);
            }

            // Deselect ancestors
            else {
                while (parentNode) {
                    parentNode.set('checked', false);
                    parentNode = parentNode.parentNode;
                }
            }
        }
    }
});