Click here to Skip to main content
Click here to Skip to main content
Go to top

JavaScript Filtering with JSON and Filter Management

, 16 Sep 2010
Rate this:
Please Sign up or sign in to vote.
Part 1 of creating a dynamical filtering mechanism in C#
xFilter.jpg

Introduction

This article will explain a simple client-side filtering framework that can be implemented in any page to obtain easy-to-use filters.

Background

I was looking for some controls that could help me create my application. The control which suited me the most was jqGrid - a jQuery plugin. jqGrid displays a JSON data source in tabular format, along with filtering and sorting. For this, we must define a columns model (see example) - in JSON format of course:

colModel:[
   	{name:'id',index:'id', width:60, sorttype:"int"},
   	{name:'name',index:'name', width:100, editable:true},
   	{name:'note',index:'note', width:150, sortable:false}		
  ]

Using the Code

Unfortunately, the filtering capability of the jqGrid is not as complex as I need. A filter is a JSON object with the following format type:

{ "groupOp": "and",
      "rules": [
        { "field": "name", "op": "eq", "data": "Romania" }, 
        { "field": "id", "op": "le", "data": "1"}
      ]
}

It's basically a set of rules grouped together using a logical operator: "OR" or "AND". For a simple search, this filter can be enough, but anything more complex requires a tree of such groups. So let's add an array of groups to this structure. Now we have the tree structure that we need and still maintain the support for normal jqGrid filters. Suppose we would need a filter like this:

(name == "John" AND age > 30) OR (name == "Doe" AND age < 30) OR name == "Joe"

Note first that between groups and also between groups and rules, we must have the same logical operator, otherwise we will have to isolate them in a subgroup. The above formula will map into:

{ "groupOp": "or",
      "groups": [
		{ "groupOp": "AND", 
		  "rules": [
		      { "field": "name", "op": "eq", "data": "John" },
			  { "field": "age", "op": "gt", "data": "30" }
		  ]
		},
		{ "groupOp": "AND", 
		  "rules": [
		      { "field": "name", "op": "eq", "data": "Doe" },
			  { "field": "age", "op": "lt", "data": "30" }
		  ]
		}
	  ]
      "rules": [{ "field": "name", "op": "eq", "data": "Joe" }]
}

As I said, we have two types of operators: group operators and rule operators. The only group operators are "OR" and "AND". As rule operators, we have: eq (equal to), us (different to), lt (lower than), etc. as well as string operators: cn (contains), sw (starts with), etc. The above can be easily converted into a syntax closer to the JavaScript, by using functions:

(eq(item.name, "John") && gt(item.age, "30")) || 
	(eq(item.name, "Doe") && lt(item.age, "30")) || eq(item.name, "Joe")

Note that all entity fields have are prefixed with "item.". Let's define the necessary JavaScript functions:

function eq(d1, d2) { return d1 == d2; }
function lt(d1, d2) { return d1 < d2; }
function gt(d1, d2) { return d1 > d2; }

Now we can loop through a JSON object and evaluate the above formula.

var jsonItems = [
	{"name": "John", "age": "18"},
	{"name": "Amanda", "age": "21"},
	{"name": "Dave", "age": "31"}
];

var expression = '(eq(item.name, "John") && gt(item.age, "30")) || 
	(eq(item.name, "Doe") && lt(item.age, "30")) || eq(item.name, "Joe")';

var newJsonItems = [];
for(var index = 0; index < jsonItems.length; index++){
	var item = jsonItems[index]; // define the item that will be evaluated
	if(eval(expression) == true){
		newJsonItems.push(item);
	}
}

So far we have logic, but we need a web user interface to cofigure the filter. Luckily I wrote a JS class that does this: xFilter (see attachment). To use it, you only need to provide the DOM parent element and columns model.

var colModel = [
	{ "name": "id"},// we only need this field, jqGrid requires the rest
	{ "name": "name"},
	{ "name": "note"}
];
var items = [
	{ "name": "Romania", "id": "1", "note": "ro" },
	{ "name": "Franta", "id": "2", "note": "fr"},
	{ "name": "Anglia", "id": "3", "note": "uk"},
	{ "name": "Italia", "id": "4", "note": "it" },
	{ "name": "Germania", "id": "5", "note": "ge" }
];
	
var f = new xFilter(document.getElementById("fil"),
{
	columns: colModel,
	onchange: function() {
		document.getElementById("message").innerHTML =	
			this.toUserFriendlyString();

		var resItems = f.Apply(items);
		var s = "";
		for (var i = 0; i < resItems.length; i++) {
			s += "," + resItems[i].name;
		}
		document.getElementById("message").innerHTML = s;
	}
});

As you can see, the class has the "onchange" event that is triggered whenever a change to the filter occurs. Of course, one can use the method "Apply" - whose logic is presented above - to filter a JSON object.

Conclusion

Hope you enjoyed this. The next article will take this model on the server side (C#), where the filters we've created will become expression trees that can be used with LINQ implementations.

Link

Part 2 of creating a dynamical filtering mechanism in C#

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

strofo
Engineer
Romania Romania
No Biography provided

Comments and Discussions

 
QuestionGreat! [modified] PinmemberMember 765759626-Aug-13 10:33 
GeneralMy vote of 5 Pinmembermanoj kumar choubey9-Aug-12 21:22 
GeneralMy vote of 5 Pinmembermanoj kumar choubey3-Feb-12 1:09 
GeneralMy vote of 5 PinmemberJohanJAM13-Jan-11 16:18 
QuestionIs this implementable in jqGrid? PinmemberJohanJAM13-Jan-11 16:16 
AnswerRe: Is this implementable in jqGrid? Pinmemberstrofo4-Mar-11 9:04 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140905.1 | Last Updated 16 Sep 2010
Article Copyright 2010 by strofo
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid