LIDOR SYSTEMS

Advanced User Interface Controls and Components

Filtering in AngularJS TreeView

Created: 16 July 2015

When we have large tree structure containing thousands of items, it may be hard to find all items that we are looking for. For this purpose, it is better if we could filter the hierarchy so that only those items that match our criteria are displayed.

IntegralUI TreeView directive for AngularJS includes an option to filter the tree hierarchy using multiple different conditions in and/or combinations. There are many string and numeric operators to choose from, or you can create your own custom filter operations.

TreeView directive is part of IntegralUI Studio for Web
a suite of UI Components for development of web apps



Similar: TreeView Component for Angular 2

Built-in Filter Operations

As it is presented in above demo, we are using string operations to filter our TreeView. In case of this example, three conditions are allowed in different combinations using AND/OR operators. Using more conditions is possible, but to keep this example simple, we will stick to just to three conditions.

Initially, TreeView is not filtered, which can also be shown by pressing the Reset button. There are three drop-down lists that contain all available string conditions:

  • equals - determines whether item text matches exactly with provided value
  • does not equal - determines whether item text does not matches exactly with provided value
  • begins with - determines whether item text begins with provided value
  • does not begin with - determines whether item text does not begins with provided value
  • ends with - determines whether item text ends with provided value
  • does not end with - determines whether item text does not end with provided value
  • contains - determines whether item text contains the provided value
  • does not contain - determines whether item text does not contain the provided value

Note These conditions are part of IntegralUI FIlter service, which is an AngularJS service, which includes all necessary methods to create filter operations. There are also numeric conditions and other kinds of filters, which we are not going to cover in this article.

If item value field is not set, then item's text is used in filtering, to match the provided value. In other cases where you have custom items with custom values, you may need to use different conditions.

To filter items, we can select one or multiple conditions. For each condition, we also must set the matching value against which items are compared. The value is case-sensitive, so we need to consider this during filtering.

For example, let say we want to show only items that ends with 'ts' or ends with 'es' and that does not contain the 'a' character. By selecting these conditions and clicking on Apply Filter button, teh TreeView will show only those items that match those conditions.

Behind the scene, the code looks like this:

angular

.module("appModule", ["integralui"])

.controller("appCtrl", ["$scope", "IntegralUITreeViewService", "$timeout", function($scope, $treeService, $timeout){

$scope.treeName = "treeSample";

$scope.items = [];

 

$scope.filterOptions = [ '', 'equals', 'does not equal', 'begins with', 'does not begin with', 'ends with', 'does not end with', 'contains', 'does not contain' ];

$scope.filterValues = [ '', '', '' ];

$scope.selOptions = [

$scope.filterOptions[0],

$scope.filterOptions[0],

$scope.filterOptions[0]

];

 

$scope.combinations = [ 'Or', 'Or' ];

 

var getOperation = function(option){

var index = $scope.filterOptions.indexOf(option);

switch (index){

case 1: //equals

return '=';

 

case 2: //does not equal

return '!=';

 

case 3: //begins with

return '->';

 

case 4: //does not begin with

return '->';

 

case 5: //ends with

return '<-';

 

case 6: //does not end with

return '<-';

 

case 7: //contains

return '[]';

 

case 8: //does not contain

return '[]';

}

 

return '';

}

 

var getFormula = function(conditions){

var formula = '';

 

var firstCombination = $scope.combinations[0];

var secondCombination = $scope.combinations[1];

if (conditions.length == 2 && $scope.selOptions[0] == '')

firstCombination = $scope.combinations[1];

 

var firstSymbol = conditions[0].negative ? '!a' : 'a';

var secondSymbol = conditions[1].negative ? '!b' : 'b';

 

if (firstCombination == 'And')

formula = '(' + firstSymbol + ' & ' + secondSymbol + ')';

else

formula = '(' + firstSymbol + ' | ' + secondSymbol + ')';

 

if (conditions.length == 3){

var thirdSymbol = conditions[2].negative ? '!c' : 'c';

 

if (secondCombination == 'And')

formula += ' & ' + thirdSymbol;

else

formula += ' | ' + thirdSymbol;

}

 

return formula;

}

}]);

<!DOCTYPE html>

<html>

<head>

<link rel="stylesheet" href="css/integralui.css" />

<link rel="stylesheet" href="css/integralui.checkbox.css" />

<link rel="stylesheet" href="css/integralui.treeview.css" />

<link rel="stylesheet" href="css/themes/theme-flat-blue.css" />

<script type="text/javascript" src="external/angular.min.js"></script>

<script type="text/javascript" src="js/angular.integralui.min.js"></script>

<script type="text/javascript" src="js/angular.integralui.lists.min.js"></script>

<script type="text/javascript" src="js/angular.integralui.checkbox.min.js"></script>

<script type="text/javascript" src="js/angular.integralui.treeview.min.js"></script>

</head>

<body>

<div ng-app="appModule" ng-controller="appCtrl">

<iui-treeview name="{{treeName}}" items="items" show-check-boxes="true" item-checked-changed="onItemCheckedChanged(e)"></iui-treeview>

<div>

<label>Show items where: </label>

<div class="inline-block" style="margin-top:15px">

<select ng-model="selOptions[0]" ng-options="option for option in filterOptions"></select><input ng-model="filterValues[0]" type="text" style="width:125px"/>

</div>

<div class="inline-block" style="width:125px;margin:5px 15px">

<label class="inline-radio"><input type="radio" ng-model="combinations[0]" value="And" />And</label><label class="inline-radio"><input type="radio" ng-model="combinations[0]" value="Or" />Or</label>

</div>

<div class="inline-block">

<select ng-model="selOptions[1]" ng-options="option for option in filterOptions"></select><input ng-model="filterValues[1]" type="text" style="width:125px"/>

</div>

<div class="inline-block" style="width:125px;margin:5px 15px" align="center">

<label class="inline-radio"><input type="radio" ng-model="combinations[1]" value="And" />And</label><label class="inline-radio"><input type="radio" ng-model="combinations[1]" value="Or" />Or</label>

</div>

<div class="inline-block">

<select ng-model="selOptions[2]" ng-options="option for option in filterOptions"></select><input ng-model="filterValues[2]" type="text" style="width:125px"/>

</div>

 

<div class="inline-block" style="margin-top:25px;text-align:center;width:300px;">

<button ng-click="apply()">Apply Filter</button>

<button ng-click="reset()">Reset</button><br/><br/><br/>

<button ng-click="applyCustomFilter()" style="width:210px">Show Only Checked Items</button>

</div>

</div>

</div>

</body>

</html>

select

{

margin-right: 15px;

width: 150px;

}

.inline-radio

{

margin-right: 15px;

}

button

{

display: inline-block;

margin: 5px;

width: 100px;

height: 22px;

}

.inline-block

{

display: inline-block;

margin: 3px 0;

}

The getOperation function returns an operation symbol depending on which option is selected from drop-down list. When multiple options are selected, we need to create a formula by which conditions are combined. For this purpose getFormula function is used.

$scope.apply = function(){

var filterConditions = [];

for (var i = 0; i < 3; i++){

if ($scope.selOptions[i] != '' && $scope.filterValues[i] != ''){

var currentOperation = getOperation($scope.selOptions[i]);

 

filterConditions.push({

value: $scope.filterValues[i],

operation: currentOperation,

negative: $scope.filterOptions.indexOf($scope.selOptions[i]) % 2 == 0

});

}

}

 

if (filterConditions.length > 0){

var params = {}

 

if (filterConditions.length == 1){

params.conditions = filterConditions[0];

}

else {

params.conditions = filterConditions;

params.formula = getFormula(filterConditions);

}

 

$treeService.filter($scope.treeName, params);

}

else

$scope.reset();

}

 

$scope.reset = function(){

$treeService.filter($scope.treeName);

}

Next, when Apply Filter button is clicked, the apply function is called which creates filtering parameters using selected conditions and combinations. Then this parameters are added as argument to the filter method, which will process the filtering of the TreeView content.

At the end, if we are not happy with the result, we can press the Reset button, which also calls the filter method, but now without parameters. This will bring back the original content to the TreeView, showing all items.

Custom Filter Operations

Although the basic filtering operations are used in most cases, there may be some case where we need to create our own custom filter. This option is supported; we only need to provide a comparer function, which will be executed instead on the built-in functions.

In our example, we are going to create a filter that will show only checked items. For this purpose, we will use the value of item's checked field. In our comparer function instead of setting conditions (like in previous case), we are going to set only the callback function:

$scope.applyCustomFilter = function(){

var params = {

callback: function(value, item){

return item.checked;

}

}

 

$treeService.filter($scope.treeName, params);

}

In this function, the value argument is the item's value field. In our case, we will use item's checked field that determines whether the item is checked or not. By checking whether this value equals true, the item will pass the filter conditions and it is displayed in the TreeView. Other items that are not checked are excluded from the TreeView. You can also use any custom field applied to the item object, depending on the requirements of your app.

Note If root item does not pass the filter matching conditions, it is excluded from the TreeView along with all child items. Also, worth to mention here is that original tree structure in our app controller is not modified, the TreeView creates a temporary tree list of all items that pass the filtering conditions.

This sample with complete source code is available as part of the IntegralUI Studio for Web product package.

Did you Like this Article?


Enter your e-mail address below and you will receive latest articles as well as news on upcoming events and special offers.