Правильный JSON и модель с TreeStore и TreePanel

У меня есть строка 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)?


person user1567829    schedule 01.08.2012    source источник


Ответы (3)


Я использовал следующую структуру:

Модель

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}
person sunny    schedule 25.10.2012
comment
Нет никакой ошибки. Если вы установите autoLoad:false, а затем выполните expanded: true, вы ПОЛУЧИТЕ нагрузку от дерева. - person Magno C; 07.11.2016

Начнем с определения магазина:

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 нет, так как модель по умолчанию idProperty равна id, ExtJS достаточно умен, чтобы понять, что если в вашем JSON есть поле 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
     },         
    ]
}

Вот и все!

person Izhaki    schedule 01.08.2012
comment
Можете ли вы объяснить больше об API прокси в вашем примере? мне это не известно.. - person liaK; 20.08.2012
comment
Это для облегчения операций CRUD на удаленном сервере. Документы. Также это может быть представляет для вас интерес. - person Izhaki; 20.08.2012
comment
Я могу использовать сам тип прокси-сервера ajax, верно? Так же, как я дал в вопросе? - person liaK; 20.08.2012
comment
Конечно. Вы можете выбирать между Ajax или Direct — что вам больше подходит. - person Izhaki; 20.08.2012
comment
Я изменил свой.. Но все равно я получаю ту же ошибку Uncaught TypeError: Cannot read property 'internalId' of undefined при доступе к дочерним узлам.. Также видны узлы первого уровня, но без текста.. Я что-то упустил? - person liaK; 20.08.2012
comment
Я думаю, будет лучше, если мы продолжим это на вашем исходном вопросе с вашим обновленным кодом. - person Izhaki; 20.08.2012

Первый ответ на эту тему от Ижаки великолепен, но он кажется вводящим в заблуждение и не будет работать как есть, если вы ожидаете увидеть описание для узлов. Я провел несколько часов, борясь с этим. Единственный способ увидеть это описание — переименовать «имя» в «текст». увидеть ниже.

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'},        
],
person extjs newbie    schedule 24.01.2014