ExtJS 4:具有静态和动态加载数据的 TreeStore?

发布于 2024-12-06 04:06:20 字数 1371 浏览 0 评论 0原文

我正在制作一个如下所示的 TreePanel:

在此处输入图像描述

目前我已将其“模拟”下面的代码:

treePanel.setRootNode({
    text: 'Root',
    expanded: true,
    children: [
        {
            text: 'General Settings',
            icon: kpc.cfg.baseUrl.img+'/icon_gears-bluegreen.gif',
            leaf: true
        },
        {
            text: 'Users',
            icon: kpc.cfg.baseUrl.img+'/icon_users-16x16.gif',
            expanded: true,
            children: [
                {
                    text: 'Dummy User 1',
                    icon: kpc.cfg.baseUrl.img+'/icon_user-suit.gif',
                    leaf: true
                },
                {
                    text: 'Dummy User 2',
                    icon: kpc.cfg.baseUrl.img+'/icon_user-suit.gif',
                    leaf: true
                },
                {
                    text: 'Dummy User 3',
                    icon: kpc.cfg.baseUrl.img+'/icon_user-suit.gif',
                    leaf: true
                },
                {
                    text: 'Dummy User 4',
                    icon: kpc.cfg.baseUrl.img+'/icon_user-suit.gif',
                    leaf: true
                }
            ]
        }
    ]
});

如何动态加载单个用户(即通过商店)? 换句话说,如何制作一个混合了静态和动态加载项目的 TreeStore?

谢谢!

I'm making a TreePanel that looks like this:

enter image description here

At the moment I have it "mocked up" with the following code:

treePanel.setRootNode({
    text: 'Root',
    expanded: true,
    children: [
        {
            text: 'General Settings',
            icon: kpc.cfg.baseUrl.img+'/icon_gears-bluegreen.gif',
            leaf: true
        },
        {
            text: 'Users',
            icon: kpc.cfg.baseUrl.img+'/icon_users-16x16.gif',
            expanded: true,
            children: [
                {
                    text: 'Dummy User 1',
                    icon: kpc.cfg.baseUrl.img+'/icon_user-suit.gif',
                    leaf: true
                },
                {
                    text: 'Dummy User 2',
                    icon: kpc.cfg.baseUrl.img+'/icon_user-suit.gif',
                    leaf: true
                },
                {
                    text: 'Dummy User 3',
                    icon: kpc.cfg.baseUrl.img+'/icon_user-suit.gif',
                    leaf: true
                },
                {
                    text: 'Dummy User 4',
                    icon: kpc.cfg.baseUrl.img+'/icon_user-suit.gif',
                    leaf: true
                }
            ]
        }
    ]
});

How can I load the individual users dynamically (i.e., via a store)? In other words, how do I make a TreeStore that is a mixture of both static and dynamically-loaded items?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

北渚 2024-12-13 04:06:20

最适合我的解决方案是:

  1. 创建两个树存储 - 一个包含静态内容,另一个设置用于从服务器加载我的用户模型。
  2. 将动态加载的树“绘制”到静态树上。

我写了一个小教程,其中包括一个可运行的演示 此处(以防有人想要更详细的答案),但在较高级别上,代码如下所示:

Ext.define('demo.UserModel', {
    extend: 'Ext.data.Model',
    fields: ['id', 'name', 'profile_image_url']
});


var userTreeStore = Ext.create('Ext.data.TreeStore', {

    model: 'demo.UserModel',

    proxy: {
        type: 'jsonp',
        url : 'https://myserver/getusers',
        reader: {
            type: 'json',
            root: 'users'
        }
    },

    listeners: {

        // Each demo.UserModel instance will be automatically 
        // decorated with methods/properties of Ext.data.NodeInterface 
        // (i.e., a "node"). Whenever a UserModel node is appended
        // to the tree, this TreeStore will fire an "append" event.
        append: function( thisNode, newChildNode, index, eOpts ) {

            // If the node that's being appended isn't a root node, then we can 
            // assume it's one of our UserModel instances that's been "dressed 
            // up" as a node
            if( !newChildNode.isRoot() ) {
                newChildNode.set('leaf', true);

                newChildNode.set('text', newChildNode.get('name'));
                newChildNode.set('icon', newChildNode.get('profile_image_url'));
            }
        }
    }
});

userTreeStore.setRootNode({
    text: 'Users',
    leaf: false,
    expanded: false // If this were true, the store would load itself 
                    // immediately; we do NOT want that to happen
});

var settingsTreeStore = Ext.create('Ext.data.TreeStore', {
    root: {
        expanded: true,
        children: [
            {
                text: 'Settings',
                leaf: false,
                expanded: true,
                children: [
                    {
                        text: 'System Settings',
                        leaf: true
                    },
                    {
                        text: 'Appearance',
                        leaf: true
                    } 
                ]
            }
        ]
    }
});

// Graft our userTreeStore into the settingsTreeStore. Note that the call
// to .expand() is what triggers the userTreeStore to load its data.
settingsTreeStore.getRootNode().appendChild(userTreeStore.getRootNode()).expand();

Ext.create('Ext.tree.Panel', {
    title: 'Admin Control Panel',
    store: settingsTreeStore,
});

The solution that worked best for me was to:

  1. create two tree stores--one with the static content, another set up to load my User models from the server.
  2. "graph" the dynamically-loaded tree onto the static tree.

I wrote up a little tutorial that includes a runnable demo here (in case anyone wants a more detailed answer), but at a high level the code looks like this:

Ext.define('demo.UserModel', {
    extend: 'Ext.data.Model',
    fields: ['id', 'name', 'profile_image_url']
});


var userTreeStore = Ext.create('Ext.data.TreeStore', {

    model: 'demo.UserModel',

    proxy: {
        type: 'jsonp',
        url : 'https://myserver/getusers',
        reader: {
            type: 'json',
            root: 'users'
        }
    },

    listeners: {

        // Each demo.UserModel instance will be automatically 
        // decorated with methods/properties of Ext.data.NodeInterface 
        // (i.e., a "node"). Whenever a UserModel node is appended
        // to the tree, this TreeStore will fire an "append" event.
        append: function( thisNode, newChildNode, index, eOpts ) {

            // If the node that's being appended isn't a root node, then we can 
            // assume it's one of our UserModel instances that's been "dressed 
            // up" as a node
            if( !newChildNode.isRoot() ) {
                newChildNode.set('leaf', true);

                newChildNode.set('text', newChildNode.get('name'));
                newChildNode.set('icon', newChildNode.get('profile_image_url'));
            }
        }
    }
});

userTreeStore.setRootNode({
    text: 'Users',
    leaf: false,
    expanded: false // If this were true, the store would load itself 
                    // immediately; we do NOT want that to happen
});

var settingsTreeStore = Ext.create('Ext.data.TreeStore', {
    root: {
        expanded: true,
        children: [
            {
                text: 'Settings',
                leaf: false,
                expanded: true,
                children: [
                    {
                        text: 'System Settings',
                        leaf: true
                    },
                    {
                        text: 'Appearance',
                        leaf: true
                    } 
                ]
            }
        ]
    }
});

// Graft our userTreeStore into the settingsTreeStore. Note that the call
// to .expand() is what triggers the userTreeStore to load its data.
settingsTreeStore.getRootNode().appendChild(userTreeStore.getRootNode()).expand();

Ext.create('Ext.tree.Panel', {
    title: 'Admin Control Panel',
    store: settingsTreeStore,
});
捂风挽笑 2024-12-13 04:06:20

我相信 node 参数会对您有所帮助。设置 autoLoad: false,然后利用实际树面板的 beforeerender 事件。在事件内部调用商店的加载函数,并向其传递一个节点。文档指出,如果从 load() 调用中省略它,它将默认为根节点。看来您可以将设置保留在根节点中,然后通过调用 load 并将其传递给子节点,您就可以仅更新用户。

请参阅:http:// /docs.sencha.com/ext-js/4-0/#!/api/Ext.data.TreeStore-method-load 供参考。请注意,此加载函数与 Ext.data.Store 中的不同(Ext.data.TreeStore 不是从 Ext.data.Store 继承的)代码>)。

我还没有机会对此进行测试,但看起来很有希望。

I believe the node parameter will help you. Set autoLoad: false, then leverage the beforerender event of the actual tree panel. Inside the event call the store's load function, and pass it a node. The docs state that if this is ommited from the load() call, it will default to the root node. It would appear that you could leave your settings in the root node and then by calling load and passing it a child node, you'd be able to update just the users.

Please see: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.data.TreeStore-method-load for reference. Note that this load function is not the same as in Ext.data.Store (Ext.data.TreeStore does not inherit from Ext.data.Store).

I have not had the opportunity to test this, but it seems promising.

ゞ花落谁相伴 2024-12-13 04:06:20

我有一个非常相似的问题,虽然我还没有让它完全按照我想要的方式工作,但它基本上可以工作。我有 autoLoad: false 并添加了此事件处理程序:

beforerender: function(comp, opts) {
    var node = this.getRootNode();
    node.appendChild({test: 'Recent', id: 'recent', expandable: true, expanded: false});
    node.appendChild({text: 'Current', id: 'current', expandable: true, expanded: false});
    node.appendChild({text: 'All', id: 'all', expandable: true, expanded: false});
}

根的 3 个直接子级是静态的,然后代理在我展开它们时发出填充它们的请求(传递适当的 id)。

我还必须禁止根节点在 store 上加载侦听器:

        listeners: {
            beforeload: function(store, operation, opts) {
                if (operation.node.data.id == 'root') {
                    return false;
                }
            }               
        },

希望这会有所帮助。看来应该有更好的办法!?!

I have a very similar problem, and while I haven't gotten it to work completely like I want it to, it mostly works. I have autoLoad: false and added this event handler:

beforerender: function(comp, opts) {
    var node = this.getRootNode();
    node.appendChild({test: 'Recent', id: 'recent', expandable: true, expanded: false});
    node.appendChild({text: 'Current', id: 'current', expandable: true, expanded: false});
    node.appendChild({text: 'All', id: 'all', expandable: true, expanded: false});
}

The 3 immediate children of the root are static, then the proxy makes a request to populate them when I expand them (passing the appropriate id).

I also had to suppress the root node from loading with a listener on the store:

        listeners: {
            beforeload: function(store, operation, opts) {
                if (operation.node.data.id == 'root') {
                    return false;
                }
            }               
        },

Hope this helps. It seems like there should be a better way!?!

如果没有你 2024-12-13 04:06:20

这是我将普通数据转换为treeStore数据的函数,您可以使用它。这样,您就不再需要treeStore:

Records:记录数组。
文本:项目名称(从记录中获取)
Children:孩子的名字(默认为“children”)

dynamicReportsStore.load({
    scope: this,
    callback: function (records, operation) {
        if (operation.isComplete()) {
            var tree = this.buildTreeByRecords(records, 'name');
            treePanel.getRootNode().removeAll();
            treePanel.getRootNode().appendChild(tree);
        }
    }
});



buildTreeByRecords: function (records, text, children) {
var childs = [],
    results = [],
    tree = [];
records = Ext.Array.map(records, function (record) {
    return {
        text: record.get(text) || record.get('id'),
        leaf: record.get('leaf'),
        expanded: true,
        parentId: record.get('parentId'),
        id: record.get('id')
    };
}, this);
Ext.each(records, function (record) {
    if (Ext.isEmpty(childs[record.parentId])) {
        childs[record.parentId] = [];
    }
    childs[record.parentId].push(record);
}, this);
Ext.each(records, function (record) {
    if (!Ext.isEmpty(childs[record.id])) {
        record[children || 'children'] = childs[record.id];
        results.push(record);
    }
}, this);
Ext.each(results, function (result) {
    if (result.parentId === 0) {
        tree.push(result);
    }
}, this);
return tree;}

Here is my function to convert normal data to treeStore data, you can use that. By that way, you don't need treeStore anymore:

Records: array of record.
Text: name of item (get from record)
Children: name of children (default is 'children')

dynamicReportsStore.load({
    scope: this,
    callback: function (records, operation) {
        if (operation.isComplete()) {
            var tree = this.buildTreeByRecords(records, 'name');
            treePanel.getRootNode().removeAll();
            treePanel.getRootNode().appendChild(tree);
        }
    }
});



buildTreeByRecords: function (records, text, children) {
var childs = [],
    results = [],
    tree = [];
records = Ext.Array.map(records, function (record) {
    return {
        text: record.get(text) || record.get('id'),
        leaf: record.get('leaf'),
        expanded: true,
        parentId: record.get('parentId'),
        id: record.get('id')
    };
}, this);
Ext.each(records, function (record) {
    if (Ext.isEmpty(childs[record.parentId])) {
        childs[record.parentId] = [];
    }
    childs[record.parentId].push(record);
}, this);
Ext.each(records, function (record) {
    if (!Ext.isEmpty(childs[record.id])) {
        record[children || 'children'] = childs[record.id];
        results.push(record);
    }
}, this);
Ext.each(results, function (result) {
    if (result.parentId === 0) {
        tree.push(result);
    }
}, this);
return tree;}
装迷糊 2024-12-13 04:06:20

我使用阅读器以我认为优雅的方式实现了这种效果。请注意,这是一个扁平商店,与树商店看起来可能有点不同。这个概念应该翻译。

Ext.define('Ext.data.reader.a8PolicyReader', {
    extend: 'Ext.data.reader.Json',
    read: function(response) {
        var staticStuff,
            responseArr;

        // Static stuff
        staticStuff = [{name: 'some static user', id:1}, {name: 'another user', id:2}];
        // extract response
        responseArr = Ext.decode(response.responseText);
        // shove them together
        responseArr.concat(staticStuff);
        // read
        this.readRecords(responseArr);
    }
})

I used a reader to achieve this effect in what I feel to be an elegant fashion. Mind you this is with a flat store and may look a little different with a tree store. The concept should translate.

Ext.define('Ext.data.reader.a8PolicyReader', {
    extend: 'Ext.data.reader.Json',
    read: function(response) {
        var staticStuff,
            responseArr;

        // Static stuff
        staticStuff = [{name: 'some static user', id:1}, {name: 'another user', id:2}];
        // extract response
        responseArr = Ext.decode(response.responseText);
        // shove them together
        responseArr.concat(staticStuff);
        // read
        this.readRecords(responseArr);
    }
})
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文