ExtJS 4: TreeStore со статическими и динамически загруженными данными?

Я делаю TreePanel, который выглядит так:

enter image description here

на данный момент я его "переделала" со следующим кодом:

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, который представляет собой смесь статических и динамически загружаемых элементов?

спасибо!

5 ответов


лучшим решением для меня было:

  1. создайте два дерева-одно со статическим содержимым, другое настроено для загрузки моих пользовательских моделей с сервера.
  2. "график" динамически загруженное дерево на статическое дерево.

Я написал небольшой учебник, который включает в себя runnable demo здесь (если кому-то нужен более подробный ответ), но на высоком уровне код выглядит так:

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

Я считаю node параметр поможет вам. Set autoLoad: false, а затем использовать beforerender событие фактической панели дерева. Внутри события вызовите функцию загрузки магазина и передайте ей node. Врачи заявляют, что если это опущено с load() вызова, он будет по умолчанию для корневого узла. Казалось бы, вы можете оставить свои настройки в корневом узле, а затем, вызвав load и передав ему дочерний узел, вы сможете обновить только пользователей.

см.: http://docs.sencha.com/ext-js/4-0/#!/api / Ext.данные.TreeStore-method-load Для справки. Обратите внимание, что эта функция загрузки не такая, как в Ext.data.Store (Ext.data.TreeStore не наследуется от Ext.data.Store).

у меня не было возможности проверить это, но, похоже, перспективный.


у меня очень похожая проблема, и хотя я не получил ее полностью, как я хочу, она в основном работает. У меня 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 непосредственных дочерних элемента корня статичны, затем прокси-сервер делает запрос на их заполнение, когда я их разворачиваю (передавая соответствующий идентификатор).

мне также пришлось подавить загрузку корневого узла с помощью прослушивателя на магазине:

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

надеюсь, что это помогает. Кажется, должен быть лучший способ!?!


вот моя функция для преобразования обычных данных в treeStore, вы можете использовать это. Таким образом, вам больше не нужен treeStore:

Records: массив записей. Текст: название элемента (получить из записи) Дети: имя детей (по умолчанию "дети")

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

я использовал читателя для достижения этого эффекта в том, что я считаю элегантной модой. Имейте в виду, что это с плоским магазином и может выглядеть немного иначе с магазином дерева. Концепция должна быть переведена.

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