/** | |
* 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]); | |
} | |
}); |
Thanks very much! It's very useful!
God bless you! You saved few of my hours. Working like a charm..
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?
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'].
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.
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
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!
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.
Thanks !! I couldn't use this custom tree filter as a mixin but created panel function using same logic.
Awesom!!! Thank..
It's very useful in ExtJS 5.1.1
Awesome work..! Thanks :) It's also working with ExtJS 6.0.0 👍
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
I am really very thankful to the person who provided above piece of code.
It really helped me a lot. Thanks again. :)