jQuery Grid’s GroupBy. Just add a little JavaScript or ASP.NET MVC to taste!

Damyan Petev / Friday, February 10, 2012

Have you met the igGrid? It is part of Infragistics’ NetAdvantage for jQuery product, built on top jQuery UI and is pretty much the best way to bring HTML tables and data to life! Now while this amazing widget is sporting some serious speed, that performance is only as good as the speed the user can assimilate it and it’s no news the normal human being (read: your users) won't read a thousand records in the milliseconds it will take the grid to load them. This is probably the main reason to use this grid nonetheless –  a big gain also comes not from the “being able” side of displaying data but from the “HOW” – the user is constantly presented with ways to navigate and narrow down data more easily which in terms makes us humans that much more efficient and faster at digesting huge chunks of data. One thing that is very natural in terms of usage is grouping – finding the connection that can divide the information in smaller, more manageable logical groups. We’ve been over so many of the new features from the last release yet still have things to be excited to share, because 11.2 brought exactly that kind of functionality.

Groups: The (drag and drop) way to user satisfaction

This Outlook style feature creates a “group by” area on top of the grid that allows users to drag and drop column headers to… well, group by. Besides all the property names making what this does crystal clear for developers, the drag and drop action is another thing that assures natural user interaction. There are also those that will be familiar or even used to it, making it even more desirable. When a column is dropped in that area, unique values for that column are taken and a row group is created for all entries that have the same value. The column header also remains in that area to indicate grouping is active. These columns’ values become primary (displayed as type of header for each group) and the groups themselves can be collapsed and expanded. Of course everything is well arranged – the groups are sorted based on the “primary” values and the rows inside them are sorted as well.

So step 1:

Using the GroupBy feature in NetAdvantage for jQuery Grid

And there really isn’t a step 2. The results are already in place:

GroupBy feature in NetAdvantage for jQuery Grid

As you can see a very simple action produces overwhelming results. Groups have nicely visible –/+ icons to collapse and expand respectively and the header in the ‘GroupBy’ area indicates with an arrow the sorting applied and has a cross on mouseover – one click away from restoring the original state by removing the group criteria. Everything happens seamlessly - the user can narrow down the records even further by applying more grouping criteria and removing them just as easily with one click and with no regard on their order. And speaking of order, this is how the jQuery grid looks when this is done:

Nested groups. GroupBy feature in NetAdvantage for jQuery Grid

The top area will arrange the headers and the results will be nested based on their order and you can see you can define the sorting for each column.

How do you get this awesome feature?

First off as with all jQuery projects it starts with adding the required resources and script files. This time I will skip that part and present the NetAdvantage for jQuery Deployment Guide where you can find instructions on how to add all the required files to your project.

Once you have that done you would need to present your data in a form the igGrid can read, which by the way is not hard to do at all as it supports most major formats to begin with. Also the widget will willingly transform an already present HTML table with its data (Our help topics on how to bind the jQuery grid to HTML table). Enabling the ‘GroupBy’ feature is just as easy as with any other grid’s feature:

Your page should have a HTML table element to become the container..

  1. <table id="grid1"></table>

.. and if you have the proper script files loaded you will be able to instantiate the igGrid widget:

  1. $('#grid1').igGrid({
  2.     autoGenerateColumns: true,
  3.         //------
  4.         features: { name: 'GroupBy' },
  5.         //------
  6.         dataSource: adventureWorks,
  7.         primaryKey : "ProductID"
  8.     });
  9. });

And this is how it looks like using the ASP.NET MVC helper with Razor syntax where the container HTML element can be omitted :

  1. @( Html.Infragistics()
  2.         .Grid(Model)
  3.         //------
  4.         .Features(feature => feature.GroupBy())
  5.         //------
  6.         .AutoGenerateColumns(true)
  7.         .PrimaryKey("ProductID")
  8.         .DataBind()
  9.         .Render()
  10. )

A closer look

Setting up features

The Group By feature is in fact implemented and supported by its own widget and it supports quite a few options too! You can define local or remote mode, provide settings on per-column basis through the ColumnSettings. There you can allow grouping as a whole or provide summary. Say you want to have a column as group by criterion from the start and you can do that by setting that column’s IsGroupBy property to true :

  1. //...
  2. features: [
  3.     {
  4.         name: 'GroupBy',
  5.         columnSettings: [
  6.             {
  7.                 columnKey: "SafetyStockLevel",
  8.                 isGroupBy: true
  9.             }]
  10.     }
  11. ],
  12. //...

And in Razor:

  1. //...
  2.     .Features(feature =>
  3.     {
  4.         feature.GroupBy().ColumnSettings(groupedGolumn =>
  5.         {
  6.             groupedGolumn.ColumnSetting().ColumnKey("ProductID").IsGroupBy(true);
  7.         });
  8.     })
  9. //...

You can address columns by Key and Index as seen above.

Furthermore, you can provide you own text template for the grouped row – if you scroll up a bit you’ll notice the default is along the lines of  "${key}: ${val} (${count})" (this is all following the jQuery templating guidelines). You can alter that template, using the key, value and count to form a new message or disregard them as a whole. Lets take the example from above where by default data is grouped by ‘SafetyStockLevel’ and assume we have a goal to make the group row a bit more informative and interactive. Let’s do that by adding an link <a> tag ( Yes we can!) without a link but with just a title. What this would give you is a nice mouse hover effect and a tooltip and looks like so:

  1. //--insude features under GroupBy:
  2. groupedRowTextTemplate: " Products with <a title=\"Extra stock that is maintained to mitigate risk of stockouts.\"> Safety level </a> of ${val} (Count: ${count})"

While this fits a very specific scenario where only one row is ever meant to be a GroupBy criterion I believe that’s the whole point of having a bunch of settings. Also the result is very pleasing:

Group row text template in NetAdvantage for jQuery Grid

And then you have a bunch of visual-tweaking features like choosing to have initial expand of groups or not, defining a message in the area inviting the user to drag, the tooltips for collapse/expand/remove, toying with the opacity of the transparent header users see while dragging and even hiding the Group By area. Since we started with our very specific scenario lets remove the GroupBy area on the top as we have defined default Column to use with and group row template just for it and we don’t want to allow more groupings. This can be done with the groupByAreaVisibility property that is actually not bool – it can set the area to be rendered above the grid (‘top’), below it ‘bottom’) or not to be rendered at all (‘hidden’), which is exactly what we are after and it is as simple as it gets:

  1. //--insude features under GroupBy:
  2. groupByAreaVisibility: "hidden"

The same effecting without taking such drastic measures can be accomplished by disabling the GroupBy feature for columns you choose like so:

  1. features: [
  2.         {
  3.             name: 'GroupBy',
  4.             columnSettings: [
  5.                 {
  6.                     columnKey: "SafetyStockLevel",
  7.                     isGroupBy: true
  8.                 },
  9.                 {
  10.                     columnKey: "ProductID",
  11.                     allowGrouping: false
  12.                 }],
  13.                 // the rest of the options are omitted

What this would do is just deny the user the ability to drag the Products ID column essentially disabling the feature for that column and any other you set that property to false.

Summaries

You can define summary within the Column settings and when it is used as GroupBy criteria the group row will contain the default template (or your own) as well as the summary. In the case of summaries you can choose from a range of already available functions. As you would expect those include average(avg), minimum and maximum (min/max), count and like in the example below – sum:

  1. //--inside features under GroupBy:
  2. columnSettings: [
  3.     {
  4.         columnKey: "SafetyStockLevel",
  5.         isGroupBy: true,
  6.         summaries: [{
  7.                         summaryFunction: 'sum', text: ' total:'
  8.                    }]
  9.     },
  10.     //...

Events

There are two GroupBy-specific events and they are both connected with a change in the grouped columns – one firing during the change (“-ing”) and one when it’s done (“-ed”). You have access to a wide arrange of properties (and the grid itself) and most importantly the ‘-ing’ event is cancellable so you can stop an action before it has occurred. Here’s an example how you can cancel the adding of columns for grouping other than the Safety Stock Level:

  1. //bind the GroupBy columns changing event and deny other columns to be used
  2.  $("#grid1").live("iggridgroupbygroupedcolumnschanging", function (event, args) {
  3.    if (args.key != "SafetyStockLevel")
  4.    {
  5.       return false;
  6.    }
  7. });

The utility the events can provide goes a long way - except the key (which is the currently involved in the event column's name) the arguments give you access to the grid itself and its properties, a special array containing all the grouped columns (again with their properties) and the event as expected will provide a ton of useful information such as mouse and keys state and so forth. There really are so many ways you can take advantage of all that once you set your goals.

Make it your own

Apart from functionality personalization with properties, when in need for something to really fit your needs there is the option to create your own grouping logic (functions) and apply it to a column. This function should accept column setting, the first and the second value to compare and should return boolean(bool), like this very basic example:

  1. //inside GroupBy's Column setting:
  2. {
  3.     columnKey: "Name",
  4.     groupComparerFunction: function (columnSetting, val1, val2)
  5.     {
  6.         return (val1 === val2);
  7.     }
  8. }

But while simple, this is the basic functionality of the feature anyway – grouping entries with same values. And there are pretty much no limits how grouping in your grid would be done with this. You can also go that extra mile in making the feature a custom solution – if the available summary functions are not enough - define you own! There are quite a few amazing customization examples in our Samples and I encourage you to go have a look whether you seek guidance or inspiration.

As with all NetAdvantage for jQuery widgets igGrid is customization-friendly and will work well with jQuery UI’s ThemeRoller which means a ton of customization that becomes available right out of the box and again you can refer to the deployment guide linked above or visit the igGrid Styling and Theming help topic and you can find elaborate list of classes applied for theming purposes in the GroupBy’s Infragistics NetAdvantage jQuery API Reference.

Conclusion

The NetAdvantage for jQuery Grid’s GroupBy feature provides natural-feeling functionality and experience with added great benefits in terms of narrowing down data. It offers plenty of settings and it is definitely no surprise it is a separate widget. It’s easy to use and easy to modify in a ways that would go a long way in serving your end-users better. To get your hands on a grid demo and see that for yourself head to our online Samples or download the project for this post that includes most of the features discussed so far.