1
votes

Good day.

I am writing a tree control with Ext.tree.Panel, which loads its configuration from external .json file, while data is being loaded as .json from the server.

So, I've got the view like this:

Ext.define('App.tree.TreeView', {
    extend: 'Ext.tree.Panel',
    ...
    initFilters: function(cfg) {
        /*several this.store.addFilter() based on cfg*/
    },   
    initComponent: function () {
        var me = this;
        me.cfg = getSomeCfgFromSomewhere();
        me.initFilters(me.cfg);
    }    
});

The store:

Ext.define('Site.widgets.tree.TreeStore', {
    extend: 'Ext.data.TreeStore',
    ...
    proxy: { 
        type: App.cfg.proxy, 
        reader: { type: 'json', rootProperty: 'data.children' }, 
        format: App.cfg.proxy.urlEnd, 
        url: App.cfg.treeRoot, 
        noCache: false
    }
    lazyFill: true,

    rootVisible: true,
    root: {
        full_path: '/', /*set as idProperty in model*/
        'display-name': 'root',
        expanded: true
    },
});

The problem is: my root is explicitly set in the store, which loads its contents because of expanded: true. But then only these contents are shown in the tree, without the root itself. When filtering is removed, the tre is loaded OK.

Possible reason: from debugging of Sencha code in ext-all-debug.js: view's initComponent is called before the store starts loading the data, therefore it adds filters before the data is loaded, when the root is still empty, and then calls

onNodeFilter: function(root, childNodes) {
    var me = this,
        data = me.getData(),
        toAdd = [];
    if (me.getRootVisible()) {
        if (childNodes.length) {
            toAdd.push(root);
        } else {
            root.set('visible', false, me._silentOptions);
        }
    }
    ...
}

, i.e. the root is set invisible because it is still empty, and only then root's children are loaded.

The question is: is there an initial design mistake in my filters initialisation, and how can I fix it?

2

2 Answers

1
votes

Considering that the problem is that view's initComponent is called before the store starts loading the data, I would try:

Calling initFilters inside store load event, like this:

Ext.define('Site.widgets.tree.TreeStore', {
    extend: 'Ext.data.TreeStore',
    ...
    proxy: { 
        type: App.cfg.proxy, 
        reader: { type: 'json', rootProperty: 'data.children' }, 
        format: App.cfg.proxy.urlEnd, 
        url: App.cfg.treeRoot, 
        noCache: false
    }
    lazyFill: true,

    rootVisible: true,
    root: {
        full_path: '/', /*set as idProperty in model*/
        'display-name': 'root',
        expanded: true
    },
    listeners : {
        load : function() {
             //Call initFilters. 
             //initFilters should call addFilter just once, 
             //with array of filters as first parameter, 
             //to avoid filtering the hole tree more than once!
        }
    }
});

This approach has a problem, because you have to deal with initFilters cfg parameter scope.

1
votes

Ok, turned out that part of the answer was just inside the question: I was able to fix this thing by simply overloading onNodeFilter() method inside my store, since I know that I want to always show the root. If anyone could advise anything better - be my guest, please.