【问题标题】:ExtJS 4: TreeStore with both static and dynamically-loaded data?ExtJS 4:具有静态和动态加载数据的 TreeStore?
【发布时间】:2015-10-22 20:27:47
【问题描述】:

我正在制作一个看起来像这样的 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?

谢谢!

【问题讨论】:

  • 什么部分保持静态?一般设置?如果没有动态加载的数据,树会以某种方式工作吗?如果答案是否定的,那么我可能会建议只加载所有内容(假设树真的这么简单并且开销很低)。
  • @LittleTreeX:“设置”节点是静态的。我希望从服务器(即从 RESTful API)动态加载所有“用户”节点。

标签: extjs extjs4


【解决方案1】:

最适合我的解决方案是:

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

我编写了一个小教程,其中包含一个可运行的演示 here(以防万一有人想要更详细的答案),但在高层次上,代码如下所示:

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

【讨论】:

  • +1 ...这是非常有用的,并且能够阅读一些内容。虽然,此页面中的某些内容似乎变得无响应并在上面提供的链接上使 Google Chrome 崩溃。 clintharris.net/2011/…
【解决方案2】:

我相信node 参数会对您有所帮助。设置autoLoad: false,然后利用实际树面板的beforerender 事件。在事件内部调用 store 的 load 函数,并传递给它一个node。文档指出,如果在 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)。

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

【讨论】:

    【解决方案3】:

    我有一个非常相似的问题,虽然我还没有让它完全按照我想要的那样工作,但它大部分都可以工作。我有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;
                    }
                }               
            },
    

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

    【讨论】:

      【解决方案4】:

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

      记录:记录数组。 文本:项目名称(从记录中获取) 孩子:孩子的名字(默认为'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;}
      

      【讨论】:

        【解决方案5】:

        我使用阅读器来实现这种效果,我觉得这是一种优雅的方式。请注意,这是一家平面商店,与树木商店可能看起来有些不同。这个概念应该翻译。

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

        【讨论】:

          猜你喜欢
          • 2012-08-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多