jQuery - Magic Grid Filters using jQuery



Update: I've uploaded a demo page showing grid filters in action.  It can be found here.
Quite often there's a grid or two (or hundred) in a project.  One of the neat thing about jQuery is how simple it is to do some really amazing things, such as filtering grid content based on user input.

Take the following example: the above grid has several Employees listed, but the user only wants to see Michael Bolton's information.  With jQuery, it is possible to remove grid rows that don't match the user's selection, with just a few lines of code.  Here's how.

First, we create a view page listing the employees.  The key here is to decorate the table rows and cells with CSS classes so our jQuery function will search only where we want it to.


Code Snippet
  1. <table>
  2.         <thead>
  3.         <tr>
  4.             <th>Employee ID</th>
  5.             <th>Name</th>
  6.             <th>Age</th>
  7.             <th>Department</th>
  8.             <th>Status</th>
  9.         </tr>
  10.     </thead>
  11.  
  12.     <tbody>
  13.         @{
  14.             for (int i = 0; i < Model.Employees.Count; i++)
  15.             {
  16.                 <tr class="searchable">
  17.                     @Html.EditorFor(x => x.Employees[i])
  18.                 </tr>
  19.             }
  20.         }
  21.     </tbody>
  22. </table>


Notice the <tr> element in the table body gets the "searchable" class, while the <tr> element in the table header does not.  This ensures that only the content rows of the table will be searched / filtered, and the header row will not.

The Editor Template for the Employees object has the second piece of the puzzle:


Code Snippet
  1. @model MVC3GridFiltersjQuery.Models.Employee
  2.    
  3. <td>
  4.     <label>@Model.EmployeeId</label>
  5. </td>
  6.         
  7. <td>
  8.     @Html.TextBoxFor(x => x.Name, new { @class = "search-target" })
  9. </td>
  10.  
  11. <td>
  12.     @Html.TextBoxFor(x => x.Age, new { @class = "search-target" })
  13. </td>
  14.  
  15. <td>
  16.     @Html.DropDownListFor(x => x.DepartmentId,
  17.         new SelectList(ViewBag.Departments, "DepartmentId", "Description", Model.DepartmentId),
  18.         new { @class = "search-target" })
  19. </td>
  20.  
  21. <td>
  22.     <label class="search-target">@Model.Status</label>
  23. </td>


Each value in each cell that we want to be part of the filtering is marked with the class "search-target".  This ensures that only the values we wish to be targeted by the search are included in the filtering.  Note that we purposefully did not mark the EmployeeId label as a search-target.

Finally, the jQuery.  This is hooked to the keyup event on our Grid Filter textbox.  As the user types in that box, the function is run, and the following happens:

  1. Rows that have values matching the filter are shown
  2. The first cell that contains the value matched by the filter is highlighted
  3. All other rows are hidden
Code Snippet
  1. <script type="text/javascript">
  2.     $(function () {
  3.         $("#SearchTerm").keyup(function () {
  4.             //Remove previous highlighting
  5.             $(".found").removeClass('found');
  6.  
  7.             //get the search term
  8.             var terms = $(this).val().toLowerCase();
  9.  
  10.             if (!terms) {
  11.                 //Show all rows if there are no terms
  12.                 $(".searchable").show();
  13.             } else {
  14.  
  15.                 //Find all of the rows to search, hide those that don't match the terms, and show the rest
  16.                 $(".searchable").hide().filter(function () {
  17.                     var isFound = false;
  18.  
  19.                     //Only check cells that are marked as search-target
  20.                     $(this).find(".search-target").each(function () {
  21.  
  22.                         //If this is a select list, use the selected option's text()
  23.                         if ($(this[0]).is('option')) {
  24.                             searchText = $(this).find('option:selected').text();
  25.                         }
  26.                         //If this is a textbox, use the val()
  27.                         else if ($(this).is("input")) {
  28.                             searchText = $(this).val();
  29.                         }
  30.                         //For all other controls, use the text()
  31.                         else {
  32.                             searchText = $(this).text();
  33.                         }
  34.  
  35.                         //Check if the control's text contains the terms
  36.                         isFound = (searchText && searchText.toLowerCase().indexOf(terms) > -1);
  37.  
  38.                         if (isFound == true) {
  39.                             //Highlight the cell that matched the filter
  40.                             $(this).addClass('found');
  41.                             return false;
  42.                         }
  43.                         else {
  44.                             return true;
  45.                         }
  46.  
  47.                     });
  48.                     return isFound;
  49.                 }).show();
  50.             }
  51.         });
  52.     });
  53. </script>


That's it.  One quick jQuery function to allow filtering on any grid in your project.

Comments

Popular posts from this blog

SQL Reporting Services - Viewer broken in Non-IE Browsers: FIX

Dynamics AX 2012 - Visual Studio Team Services Custom Work Item Fields Break Version Control (Error TF237121)

Dynamics AX SysFileDeployment Framework - Deploy files automatically (using resources) to the client on login