Skip to content

Instantly share code, notes, and snippets.

@colinramsay
Created February 10, 2012 12:58
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save colinramsay/1789536 to your computer and use it in GitHub Desktop.
Save colinramsay/1789536 to your computer and use it in GitHub Desktop.
Add filtering to Ext JS 4's TreePanel (Ext.tree.Panel)
/**
* Add basic filtering to Ext.tree.Panel. Add as a mixin:
* mixins: {
* treeFilter: 'MyApp.lib.TreeFilter'
* }
*/
Ext.define('MyApp.lib.TreeFilter', {
filterByText: function(text) {
this.filterBy(text, 'text');
},
/**
* Filter the tree on a string, hiding all nodes expect those which match and their parents.
* @param The term to filter on.
* @param The field to filter on (i.e. 'text').
*/
filterBy: function(text, by) {
this.clearFilter();
var view = this.getView(),
me = this,
nodesAndParents = [];
// Find the nodes which match the search term, expand them.
// Then add them and their parents to nodesAndParents.
this.getRootNode().cascadeBy(function(tree, view){
var currNode = this;
if(currNode && currNode.data[by] && currNode.data[by].toString().toLowerCase().indexOf(text.toLowerCase()) > -1) {
me.expandPath(currNode.getPath());
while(currNode.parentNode) {
nodesAndParents.push(currNode.id);
currNode = currNode.parentNode;
}
}
}, null, [me, view]);
// Hide all of the nodes which aren't in nodesAndParents
this.getRootNode().cascadeBy(function(tree, view){
var uiNode = view.getNodeByRecord(this);
if(uiNode && !Ext.Array.contains(nodesAndParents, this.id)) {
Ext.get(uiNode).setDisplayed('none');
}
}, null, [me, view]);
},
clearFilter: function() {
var view = this.getView();
this.getRootNode().cascadeBy(function(tree, view){
var uiNode = view.getNodeByRecord(this);
if(uiNode) {
Ext.get(uiNode).setDisplayed('table-row');
}
}, null, [this, view]);
}
});
@shwetapro
Copy link

I am really very thankful to the person who provided above piece of code.
It really helped me a lot. Thanks again. :)

@lardern
Copy link

lardern commented Jun 5, 2013

Thanks very much! It's very useful!

@GauravVarshikar
Copy link

God bless you! You saved few of my hours. Working like a charm..

@sdanishevsky
Copy link

I'm really sorry for newbie question. But could you give an example of how to use your TreeFilter? Let's assume I have variable "tree" with reference to my Ext.tree.Panel and variable "text" with a string term to filter on. What's next?

@sdanishevsky
Copy link

So you call it like: tree.filterBy(text, "my field name"). But it works for me only if I add your class as the mixin in the following way: mixins: ['MyApp.lib.TreeFilter'].

@longsoft-dev
Copy link

Very nice work. One thing I would suggest is: line 34-37 should be improved using:
do {
nodesAndParents.push(currNode.id);
currNode = currNode.parentNode;
} while (currNode);

The problem with current version is that if you are displaying root node, after applying the filter it's gone because it was never saved in the nodesAndParents array. Of course this bug doesn't show if you don't display the root node.

@dlangh
Copy link

dlangh commented Nov 21, 2013

Thank you for this. Works perfectly!

I wanted to suggest an additional function that I added that might be of use:

searchBy: function(text, by) {
var result = [];
var view = this.getView(),
me = this;
this.getRootNode().cascadeBy(function(tree, view) {
var currNode = this;
if(currNode && currNode.data[by] && currNode.data[by].toString().toLowerCase().indexOf(text.toString().toLowerCase()) > -1) {
result.push(currNode);
}
}, null, [me, view]);
return result;
}

This function won't modify the tree view like filterBy does, but rather returns an array of matching nodes. I needed this because I needed to check if a node was already present when dragging an item into the tree. Your filterBy provided a great jumping off point to accomplish this. If no match is found, it just returns an empty array

@dlangh
Copy link

dlangh commented Nov 21, 2013

I discovered a bug in the code. Line 31, your calling text.toLowerCase(). this works if text is a string, but if it is a number it bombs, you can simply change to text.toString().toLowerCase() and it works.

Thanks again for saving me the time of writing this from scratch!

@violinnerzz
Copy link

This code breaks multi-select drag-drop.
If multiple selection is enabled (multiSelect : true), and the tree is filtered so that some items are hidden, and the user selects a range of items crossing over hidden items, the hidden items are still dragged and can magically re-appear on the drop target.

@guruprasadz
Copy link

Thanks !! I couldn't use this custom tree filter as a mixin but created panel function using same logic.

@xskook
Copy link

xskook commented Jun 7, 2015

Awesom!!! Thank..
It's very useful in ExtJS 5.1.1

@vishalzanzrukia
Copy link

Awesome work..! Thanks :) It's also working with ExtJS 6.0.0 👍

@daveaie
Copy link

daveaie commented Oct 20, 2016

hi, i use unigui , a lib for delphi, that use extjs 4.2.5.

Taking your approach to create filter, I get the goals of hiding nodes not respondig to filter (thanks to your work) , but when i collapse a brunch and re-expand , the tree is re-redered and the nodes are displyed again!

someone else have encoutered the same beaviour ?
or is a special case for my lib?

dave

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment