I originally posted this on the Sencha forums here but didn't get any responses (other than my own answer, which I will post soon), so I am going to repost it here and see if I get anymore help.
I've been racking my brain on how to filter a TreeStore in 4.0.7. I've tried the following:
The model
Ext.define('model', {
extend: 'Ext.data.Model',
fields: [
{name: 'text', type: 'string'},
{name: 'leaf', type: 'bool'},
{name: 'expanded', type: 'bool'},
{name: 'id', type: 'string'}
],
hasMany: {model: 'model', name: 'children'}
});
The store
Ext.define('myStore', {
extend: 'Ext.data.TreeStore',
model: 'model',
storeId: 'treestore',
root: {
text: 'root',
children: [{
text: 'leaf1',
id: 'leaf1',
children: [{
text: 'child1',
id: 'child1',
leaf: true
},{
text: 'child2',
id: 'child2',
leaf: true
}]
},{
text: 'leaf2',
id: 'leaf2',
leaf: true
}]
},
proxy: {
type: 'memory',
reader: {
type: 'json'
}
}
});
The tree
var myTree = Ext.create('Ext.tree.Panel', {
id: 'myTree',
selType: 'cellmodel',
selModel: Ext.create('Ext.selection.CellModel', {mode: 'MULTI'}),
rootVisible: false,
store: Ext.create('myStore'),
width: 300
});
The filter
var filter = Ext.create('Ext.util.Filter', {
filterFn: function(item) {
return item.data.text == 'leaf1';
}
});
So I think my problem is... I don't know how to use this filter due to TreeStore not actually inheriting any type of filter functions like a normal store. I've tried:
myTree.store.filters.add(filter);
myTree.store.filters.filter(filter); // This seems to work
// I can get into the filterFn when debugging, but I think item is the "this" of my filter object.
Normally, if I have a grid and I create a filter like above, I can just do myTree.store.filter(filter)
and it'll grab each row's item/filter on what I return... but I'm thinking because TreeStore doesn't inherit a filtering function, that's not being passed in.
If someone could provide some clarity as to what I'm doing wrong or any insight on how to set up a filter function/my thinking process, please go ahead. I'd appreciate any help.
I was looking for a way to filter a treestore so that if a filterBy function returned true for any node, I wanted to display the complete node hierarchy of that node including all the parent nodes, grand parent node, etc and child nodes, grand child node, etc. I modified it from the other solutions provided in this question. This solutions works recursively so the treestore can be of any size.
So it works with just like a regular store filterBy call.
The above override is great, and it solves some of my problems, however, I found a bug that is hard to find with the above code. After spending half a day, I figured out we need to use slice() to copy the array otherwise some nodes get deleted.
This is the answer that I came up with... it's not ideal, so I'm hoping someone can provide a better, more generic approach. Why? Well, if my tree had a parent that had a child that had a child, I'd like to filter on those, but my solution only goes one child deep.
Thanks to this thread, I figured some things out. The only problem with this thread is that it made filtering flat... so child nodes wouldn't appear under their parent nodes. I modified their implementation and came up with this (it only goes 1 child deep, so it wouldn't work if you have a parent that contains a child that has a child):
TreeStore
So this works when I do something like this (using my tree in the first post):
This code will return every record that doesn't have a child1 id, so under leaf1, it will only have child2 as the node. I can also clear the filter by doing
Ext.getCmp('myTree').store.clearFilter()
.Now, I realize I just answered my own question, but like I posted above, I'd really like critiquing/advice on what I can make more efficient and generic. If anyone has any tips, I'd love to hear them! Also, if you need help getting this code up and running, let me know.
Sha, I also tried filters, but no luck. Have a look at this thread.
I was able to do some basic filtering using onbeforeappend event. While not as well structured as the above solutions, this provides an easy and straight forward way to apply basic filtering without the need to override base class methods or use external plugins.
I implemented my filtering in the store itself. In more advanced scenarios this can be done in controller too.
Thanks for catching that other one, I fixed up the answer to include the more dynamic treestore filter override that I included below to answer your Q.
It is working fine in 4.1b2, I know there were some changes to the treestore between 4.07 and 4.1 but I think 4.07 still had the tree objects I am using here.
Here's the override:
It uses the
store.tree.nodeHash
object to iterate through all nodes against the filters rather than just the first child. It will accept a filter as a function or property/value pair. I suppose the clearFilter method could be worked over though to prevent another ajax call.