Click here to Skip to main content
Click here to Skip to main content

Filter a Flex DataGrid using an intuitive filter text bar with expressions being parsed

, 19 Oct 2009
Rate this:
Please Sign up or sign in to vote.
Allow users to type in filter criteria in an input text box to filter a Flex DataGrid or AdvancedDataGrid.

Introduction

The existing filtering methods used with the Flex DataGrids seem to be very UI intensive. In this implementation, a simple "search style" filtering is made available. I believe this provides a more intuitive filtering functionality, and as I saw in the implementation, extending the filtering capabilities is quite easy. At the same time, it allows the UI designer to be more creative in providing options and feedback to the user.

Using the Demo

The demo is provided as an SWF file. You need to have Flash Player 9 installed for your browser. Then you can drop in the SWF file into a browser window and test it.

To start using the application, you can just start typing in the filter text box. Type 'mi' or '12' and see what happens.

Or to do a column specific search, type '(name . yo)' or '(name ^ j)' or '(name ~$ s)' or '(phone !. 21)' ... and well, keep going.

Using the Demo Continued ...

In the current implementation, I have provided two modes. If the search text starts with anything other than a (, then the filtering method used is a simple filtering which looks for the given text in any of the columns. If the first character is a (, then in the current implementation, it defaults to the columnar search mode.

When you start typing an open bracket, (, the current implementation will guide you, via ToolTips, to enter the remaining filter text.

The operators that can be used are customizable in code. When you reuse this code, you can choose what your likely operators are. I have used the following:

  • >, <, =, != are used as normally used - greater than, less than, equal to, not equal to, respectively. The ! is used to indicate all inverses or NOT-ing. These are string comparisons.
  • ., !. are used as 'contains' and 'does not contain' operators.
  • ^, $ are used as the 'begins with' and 'ends with' operators, respectively. Each of them can be 'NOT'-ed, i.e., !^ is 'does not begin with' and !$ is 'does not end with'.
  • ~ is for case sensitive filtering. E.g., between (Name ~^ Ben) and (Name ^ Ben), the first is a case sensitive search and the second is case insensitive.

In addition, I intend to use these characters too, but I'm yet to code them. (This will require a little more thinking Smile | :) ).

  • # for numeric comparison. E.g., between (Name #> 025) and (Name > 025), the first does a numeric comparison and the second does a text comparison. (I've written this for now and seems to work, but I don't really know why. It's probably due to some quirk in ActionScript that I do not know of. It is defaulting to some behavior, I don't know what it is, so should either find out why it works or make it work in a known way.)

Note: At this point, the Regular Expression for matching the operators is hard-coded, and if you are adding a different set of operators, this needs to be changed in the case OPERATOR: area within ColumnOperatorValueParser.as.

Using the Code

The code is quite simple and there doesn't appear to be any reason to copy paste parts of it here. However, a flow of activity explanation would be useful. At a high level, the relevant part of the code has this flow:

  1. Create a new parser with the allowed set of column names, which can be obtained from the datagrid itself and the allowed set of operators, which you can choose. During parsing, when a potential column on an operator token is found, it is compared against the available list of allowed values.
  2. Wait for user to type something.
  3. Parse the changed input text (or expression).
    1. If an invalid expression is encountered, catch that event (INVALID_EXPRESSION, EMPTY_STRING) and display a useful comment/feedback to the user.
    2. If a proper expression is provided, you can obtain a list of the parsed expressions in a tuple like this: [column_name, operator, search_value]. The class that represents this is ColumnOperatorValueTriplet.
  4. When a proper expression is encountered, the parser ColumnOperatorValueParser raises a FilterStringEvent of type PARSING_COMPLETE.
    1. When a proper list of parsed expressions is available, the data can be filtered by using the normal filterFunction and <data id>.refresh() calls.
    2. Typically, you can do a switch() on the ColumnOperatorValueTriplet operator and perform a comparison operation to suit the type of data using the column_name and search_value fields in ColumnOperatorValueTriplet.

Points of Interest

The Parsing Algorithm

The parsing algorithm that I've put together is quite elementary. A typical expression statement is expected to be of this form:

((EOL) | (BEGIN_CHAR & COLUMN_NAME & OPERATOR & SEARCH_VALUE & (SEPARATOR_CHAR | EOL)))

For example: (firstname = ben)(age > 25)

Some notable points:

  • Firstly, the disclaimer, I don't think the parsing algorithm is working perfectly. Smile | :) This is the first time I'm coding in ActionScript and Flex where the code is not a variation of something copied from the net and modified to check something, and I've not quite figured out how to even debug properly in FlexBuilder!! Imagine. Well, anyways, long story short, it works for now, and I'd be happy to incorporate feedback to make it better.
  • Now that having been said, here is what would be good for you to know ...

  • There is a NextExpectedTokenList which contains the list of possible next tokens. This has to be an ordered list. If the token type that is first in the list is not encountered, only then is the next one checked for.
  • The token to be checked next is maintained in NextExpectedToken.
  • At certain points, where the | symbol is, one of many possibilities exist for the next field - this will result in more than one entry in NextExpectedTokenList. If none of them are encountered, then there is an error in the input string.
  • For the remaining where the & symbol is, only one possibility exists, and if it is not encountered, then there is an error in the input string.
  • When a particular token is expected, a Regular Expression matching is done. Column names typically start with an alphabet and can contain alphanumerics and the underscore. The operator has to be one in the given list; the Regular Expression for this is currently hard-coded to use some of the known characters. The search value can be anything but a close parenthesis.
  • When a proper token is encountered, the parsedExpressions array containing a list of ColumnOperatorValueTriplet items is created.
    • when a COLUMN_NAME is encountered, a new ColumnOperatorValueTriplet item is created.
    • when an OPERATOR is encountered, the operator is added to the last ColumnOperatorValueTriplet that was added.
    • when a SEARCH_VALUE is encountered, the value is added to the last ColumnOperatorValueTriplet that was added.
  • When the expected tokens are not encountered or the input string is empty, appropriate FilterStringEvent events are raised.
  • When the parsing ends without error, a PARSING_COMPLETE FilterStringEvent is raised.
  • The application handles the events and performs whatever actions it thinks fit. Ideally, filtering needs to be done in the front end only on PARSING_COMPLETE. On anything else, it is enough to provide some feedback, allowing the user to correct the input string.

FilterFunction Implementations

I have done two filter function implementations to provide an example and a ready set for anybody reusing this code. These are available as static functions within ColumnOperatorValueParser. These may be reused and/or modified as you might require for your application.

  • simpleFilterData: this checks for the input string in any of the columns in the given data. The check done is 'contains'.
  • columnarFilterData: this uses the parsed expressions to do a comparison based on some defined operators.

User Feedback on Events for Entering Expressions

In the current implementation, the events are used to provide appropriate feedback to the user. This will allow the user a smaller learning curve and also provide good information on what is expected.

TODOs and Future Directions

  • / for date comparison. E.g., between (Name /> 10/5/2009) and (Name > 10/5/2009), the first does a date comparison and the second does a text comparison. This is not implemented yet!
  • When entering in the search bar, there could be suggestions given - via autocomplete, or through popup combo boxes with the possible entries.
  • Provide a user to 'filter by this cell' - a user would choose a cell (say right click and choose) and then the entry will automatically be put into the filter bar. This can also be done on drag and drop of a cell to the filter bar.
  • When providing the search values in the expression, currently all characters except the right parentheses, ), are acceptable. However, there is a way to do validation in the search value - for example, if the data type of the column is a number, then only numbers need be allowed. Similarly for dates, email addresses, zip code, phone numbers, etc., if required.

History

  • 19th October 2009 - Current version is the first.

License

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

About the Author

SathishVJ

France France
~/sathishvj

Comments and Discussions

 
QuestionUsing Script with Database Pinmemberkyron green11-Aug-10 11:44 

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
Web03 | 2.8.140709.1 | Last Updated 19 Oct 2009
Article Copyright 2009 by SathishVJ
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid