Question

I want to apply filter on Ext.Data.TreeStore. The model which the tree store is using is having a property by the name 'ID' & based on this 'ID' I want to apply filter on the tree store.

I looked at the following links:

Filter 1

Filter 2

But these options are not working.

On the store 'load' event, I have added following code.

 'load': function (thisStore, records, successful, eOpts) {

            var v = 'Product';
            var count = 0;
            thisStore.filterBy(function (record) {
                count++;
                return record.data.ID == v;
            });
            alert(count);
        }

But the count is always coming as 0.

My tree looks like this:

Ext.create('Ext.tree.Panel', {
    title: 'Simple Tree',
    width: 200,
    height: 150,
    store: store,
    rootVisible: false,
    renderTo: Ext.getBody(),
    plugins:[Ext.create('plugin.treefilter',{
        pluginId: 'treefilter',
        allowParentFolders: true
    })]
});

plugin:

Ext.define('Ext.ux.TreeFilter', {
    extend: 'Ext.AbstractPlugin',
    alias: 'plugin.treefilter',




    collapseOnClear: false,  // collapse all nodes when clearing/resetting the filter




    allowParentFolders: false, // allow nodes not designated as 'leaf' (and their child items) to  be matched by the filter




    init: function (tree) {
        var me = this;
        me.tree = tree;




        tree.filter = Ext.Function.bind(me.filter, me);
        tree.clearFilter = Ext.Function.bind(me.clearFilter, me);
        tree.filterBy = Ext.Function.bind(me.filterBy,me);
    },


    filter: function (value, property, re) {
        var me = this;
        if (Ext.isEmpty(value)) { // if the search field is empty
            me.clearFilter();
            return;
        }

        property = property || 'text';// property is optional - will be set to the 'text' propert of the  treeStore record by default
        re = re || new RegExp(value, "ig"); // the regExp could be modified to allow for case-sensitive, starts  with, etc.

        // iterate over all nodes in the tree in order to evalute them against the search criteria
        me.filterBy(function(node){
            return node.get(property).match(re);// if the node matches the search criteria and is a leaf (could be  modified to searh non-leaf nodes)
        });

    },

    filterBy: function (fn,scope){


        var me = this,
            tree = me.tree,
            matches = [], // array of nodes matching the search criteria
            root = tree.getRootNode(), // root node of the tree
            visibleNodes = [], // array of nodes matching the search criteria + each parent non-leaf  node up to root
            viewNode;


        if (!fn) { // if no fn defined
            me.clearFilter();
            return;
        }




        tree.expandAll(); // expand all nodes for the the following iterative routines



        //fn.call(scope || me, record)
        root.cascadeBy(function (node){
            if(fn.call(scope || me, node)){
                matches.push(node);// add the node to the matches array
            }
        });

        if (me.allowParentFolders === false) { // if me.allowParentFolders is false (default) then remove any  non-leaf nodes from the regex match
            Ext.each(matches, function (match) {
                if (match !== undefined) {
                    if (!match.isLeaf()) {
                        Ext.Array.remove(matches, match);
                    }
                }
            });
        }



        Ext.each(matches, function (item, i, arr) { // loop through all matching leaf nodes
            root.cascadeBy(function (node) { // find each parent node containing the node from the matches array
                if (node.contains(item) === true) {
                    visibleNodes.push(node); // if it's an ancestor of the evaluated node add it to the visibleNodes  array
                }
            });

/*   Commented out because this shows all children whether or not they pass the filter
            if (me.allowParentFolders === true && !item.isLeaf()) { // if me.allowParentFolders is true and the item is  a non-leaf item
                item.cascadeBy(function (node) { // iterate over its children and set them as visible
                    visibleNodes.push(node);
                });
            }
*/
            visibleNodes.push(item); // also add the evaluated node itself to the visibleNodes array
        });




        root.cascadeBy(function (node) { // finally loop to hide/show each node
            viewNode = Ext.fly(tree.getView().getNode(node)); // get the dom element assocaited with each node
            if (viewNode) { // the first one is undefined ? escape it with a conditional
                viewNode.setVisibilityMode(Ext.Element.DISPLAY); // set the visibility mode of the dom node to display (vs offsets)
                viewNode.setVisible(Ext.Array.contains(visibleNodes, node));
            }
        }); 
    },


    clearFilter: function () {
        var me = this,
            tree = this.tree,
            root = tree.getRootNode(),
            viewNode;




        if (me.collapseOnClear) {
            tree.collapseAll();
        } // collapse the tree nodes
        root.cascadeBy(function (node) { // final loop to hide/show each node
            viewNode = Ext.fly(tree.getView().getNode(node)); // get the dom element assocaited with each node
            if (viewNode) { // the first one is undefined ? escape it with a conditional and show  all nodes
                viewNode.show();
            }
        });
    }
});

Please suggest the changes I need to make to ensure I can filter a TreeStore.

Était-ce utile?

La solution

You have to implement something yourself... Here's a filterBy method that would work. Note that, contrarily to the regular store filter, this one doesn't keep a reference of the filtered out node (hence, no clearFilter method possible). If you need anything fancy, you'll have to adapt.

Fiddle here

var store = Ext.create('Ext.data.TreeStore', {
    root: {
        expanded: true,
        children: [
            { text: "detention", leaf: true },
            { text: "homework", expanded: true, children: [
                { text: "book report", leaf: true },
                { text: "algebra", leaf: true}
            ] },
            { text: "buy lottery tickets", leaf: true }
        ]
    }
});

var tree = Ext.create('Ext.tree.Panel', {
    title: 'Simple Tree',
    width: 200,
    height: 150,
    store: store,
    rootVisible: false,
    renderTo: Ext.getBody()

    /**
     * Filters the tree recursively with the given function.
     * 
     * @param {Function} fn
     * @param {Object} [scope]
     */
    ,filterBy: function(fn, scope) {
        scope = scope || this;

        function applyFilter(node) {
            var out = []; 
            Ext.each(node.childNodes, function(child) {
                if (fn.call(scope, child)) {
                    applyFilter(child);
                } else {
                    // we can't remove child right away, that would
                    // kill the loop
                    out.push(child);
                }
            });
            Ext.each(out, function(child) {
                // destroy, and suppressEvent
                node.removeChild(child, true, true);
            });
        }

        applyFilter(this.getRootNode());
    }
});

// example
tree.filterBy(function(record) {
    return record.get('text').indexOf('o') !== -1;
});
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top