0

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

所以考虑下图,假设黄色背景的节点已经被选中。如果我现在选择 1.1,系统应该自动取消选择 1.1.2,如果我选择节点 1,它应该取消选择 1.1.2、.1.2.1、1.2.2。

请提供您的建议

在此处输入图像描述

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;
                }
            }
        }
    }
});
4

1 回答 1

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;
                }
            }
        }
    }
});
于 2013-07-31T23:24:03.610 回答