使用 TreeStore 和 TreePanel 更正 JSON 和模型

Posted

技术标签:

【中文标题】使用 TreeStore 和 TreePanel 更正 JSON 和模型【英文标题】:Correct JSON and Model with TreeStore and TreePanel 【发布时间】:2012-08-01 16:31:13 【问题描述】:

我有一个来自服务器端的 JSON 字符串:

"success":"true","total":"6","list":
  ["id":"1","name":"folder1","parentid":"null","type":"0",
   "id":"2","name":"r1","parentid":"1","type":"1",
   "id":"3","name":"folder2","parentid":"1","type":"0",
   "id":"4","name":"r2","parentid":"3","type":"1",
   "id":"5","name":"r3","parentid":"null","type":"1",
   "id":"6","name":"folder3","parentid":"null","type":"0"]

如何把它变成一棵树?谁能建议我如何获取列表中的元素(id、name、parentid、type)?

【问题讨论】:

【参考方案1】:

我使用了以下结构:

型号

Ext.define('MyApp.model.MyTreeModel', 
    extend: 'Ext.data.Model',
    fields: [
         'someStringIdentifier',
         'children',
         'dataForThisNode',
    ],
);

商店

Ext.define('MyApp.store.MyTreeStore', 
    extend: 'Ext.data.TreeStore',
    model: 'MyApp.model.MyTreeModel',
    storeId: 'cubeDynamicStoreId',
    autoLoad: false,

    proxy: 
        type: 'ajax',
        api: 
            read : '/myapp/rest/myquery',
        ,
        reader: 
            type: 'json',
            root: 'children',
            successProperty: 'success',
            idProperty: 'id',
        ,
    ,

    // bug in extjs4.1 autoLoad is ignored
    // specifying "loaded: true" resolves the problem
    root: 
        expanded: true,
        loaded: true,
    ,
);

示例 JSON(使用 http://jsonviewer.stack.hu/ 进行可视化)

使用叶子属性在任何节点停止扩展

"children":"leaf":false,"someStringIdentifier":"Total","dataForThisNode":,"children":["leaf":true,"someStringIdentifier":"data1","dataForThisNode":,"children":["leaf":false,"someStringIdentifier":"2012","dataForThisNode":,"children":null,"leaf":false,"someStringIdentifier":"2013","dataForThisNode":,"children":null,"leaf":false,"someStringIdentifier":"2014","dataForThisNode":,"children":null,"leaf":false,"someStringIdentifier":"2015","dataForThisNode":,"children":null,"leaf":false,"someStringIdentifier":"2016","dataForThisNode":,"children":null,"leaf":false,"someStringIdentifier":"2017","dataForThisNode":,"children":null,"leaf":false,"someStringIdentifier":"2018","dataForThisNode":,"children":null],"leaf":true,"someStringIdentifier":"data2","dataForThisNode":,"children":["leaf":false,"someStringIdentifier":"2012","dataForThisNode":,"children":null,"leaf":false,"someStringIdentifier":"2013","dataForThisNode":,"children":null,"leaf":false,"someStringIdentifier":"2014","dataForThisNode":,"children":null,"leaf":false,"someStringIdentifier":"2015","dataForThisNode":,"children":null,"leaf":false,"someStringIdentifier":"2016","dataForThisNode":,"children":null,"leaf":false,"someStringIdentifier":"2017","dataForThisNode":,"children":null,"leaf":false,"someStringIdentifier":"2018","dataForThisNode":,"children":null]],"success":true

【讨论】:

没有错误。如果您设置 autoLoad:false 然后执行 expanded: true 那么您将从树中获得负载。【参考方案2】:

让我们从商店定义开始:

Ext.define('app.store.Tasks', 

    extend: 'Ext.data.TreeStore',    
    model:  'app.model.Task',

    autoSync: true,
    autoLoad: true,

    root: 
        text: 'Root',
        id: 'NULL',
        expanded: true
    ,
);

需要注意的重要一点是,我们在这里扩展了TreeStore。因此,我们的模型记录将使用 Ext.data.NodeInterface 包装,其中包括许多与树相关的字段(例如,parentNode)。

然后到模型定义:

Ext.define('app.model.Task', 
    extend: 'Ext.data.Model',
    fields: [
        name: 'name'     , type: 'string',

        name: 'iconCls'  , type: 'string', defaultValue: 'treenode-no-icon',
        name: 'expanded' , type: 'boolean', defaultValue: true, persist: false,
        name: 'index'     , type: 'int',        
    ],

    proxy: 
        type: 'direct',

        api: 
            create:  Tasks.Create,
            read:    Tasks.Read,
            update:  Tasks.Update,
            destroy: Tasks.Destroy,
        ,
    ,

);

我们定义的唯一“真实”字段是name,所有其他字段都是NodeInterface 的一部分:iconCls 的默认值为无图标; expanded 设置为persist:false,因此折叠/展开节点不会导致更新服务器调用; index 包含在内,因此如果用户重新排序节点(使用拖放),将进行服务器调用。

请注意,没有 id 字段,因为模型的默认 idPropertyid,ExtJS 足够聪明,可以判断如果您的 JSON 中有 id 字段 - 它代表记录的唯一 ID。

另请注意,没有 parentId 字段 - 通过提供正确的 JSON(节点具有 children 属性),NodeInterface 计算出每个节点的正确 parentNode

然后是 JSON:


    "success":true,
    "children":[
     
        "id":"1",
        "name":"Home",
        "children":[
           
              "id":"6",
              "name":"Emails",
              "leaf":true
           ,
           
              "id":"7",
              "name":"Bath",
              "leaf":true
           
        ],
        "leaf":false
     ,         
    ]

差不多就是这样!

【讨论】:

你能在你的例子中解释更多关于代理的api吗?我不知道.. 方便远程服务器上的CRUD操作。 Docs。 this 你可能也会感兴趣。 我可以使用 ajax 代理类型本身对吗?就像我在问题中给出的那样? 当然。您可以选择 Ajax 或 Direct - 最适合您的。 我已经改变了我的.. 但是当访问子节点时我仍然收到相同的错误Uncaught TypeError: Cannot read property 'internalId' of undefined.. 第一级节点也是可见的但没有任何文本.. 我错过了什么吗? 【参考方案3】:

Izhaki 对这个主题的第一个回答很好,但它似乎具有误导性,并且如果您期望看到节点的描述,它就不会按原样工作。我花了几个小时来解决这个问题。查看此描述的唯一方法是将“名称”重命名为“文本”。见下文。

Ext.define('app.model.Task', 
extend: 'Ext.data.Model',
fields: [
    name: 'text'     , type: 'string',

    name: 'iconCls'  , type: 'string', defaultValue: 'treenode-no-icon',
    name: 'expanded' , type: 'boolean', defaultValue: true, persist: false,
    name: 'index'     , type: 'int',        
],

【讨论】:

以上是关于使用 TreeStore 和 TreePanel 更正 JSON 和模型的主要内容,如果未能解决你的问题,请参考以下文章

具有特定 TreeStore 的 TreePanel

Extjs 4 treepanel 重新加载和展开

为啥 Extjs 4.0.7 TreeStore 会自动调用 http delete 方法?

extjs 4中treepanel重复加载。

ExtJs 5:TreePanel:没有得到默认的叶子图标和线条

GTK+ 3.0:如何将 Gtk.TreeStore 与自定义模型项一起使用?