We have had a few requests to explain in detail the process for creating a new Fitler Control.
First, a little background. Filter Controls are objects that show up in the Filter Row for the Flexicious Classic and Advanced DataGrid controls. There are seven built in Filter Controls as follows:
That said, Flexicious exposes, a robust mechanism in which you can create and plugin your own filter controls. We actually provide an example of this, in the SalaryRangeSlider.mxml. There are a few steps involved in creating a filter control.
Step1: Choose the appropriate IFilterControl Interface OR extend an existing FilterControl.
Filter Controls in most cases, need to implement a derivative of the IFilterControl interface (See the end of this article if none of the below interfaces apply to your scenario). This gives you the following options:
Now consider what you wish you filter control to behave like. Are you going to be executing Text based search? Then your best best is ITextFilterControl (Or extending TextInput). Are you performing Date Range Searches? Then you want the IRangeFilterControl. Do you need complete control over the FilterExpression that gets generated? Then you need the Dynamic Filter Control. Do you need even more control and have a requirement to build in custom logic in your filter control? Then you can use the ICustomMatchFilterControl (which is new to Flexicious 1.5). Our sample code includes examples for each of these. For the purpose of this entry, since we are discussing the SalaryRangeSlider, we need to search a range of Salaries for our list of employees, so we pick the IRangeSlider to implement, and extend the HSlider component that is available with the Flex SDK. This is accomplished using the following line of code at the opening of the markup:
<mx:HSlider .... implements="com.flexicious.controls.interfaces.filters.IRangeFilterControl" .... />
Now, there are a bunch of properties and methods that the IFilterControl comes along with. Most of these, are already implemented for you, all you have to is to include the FilterInclude.as file that is provided to you in the sample download. This is accomplished using the following line of code (Your path may be different on basis of where you have placed the FilterInclude.as file):
<mx:Script source="../../includes/FilterInclude.as" />
Dispatch the appropriate event: The Flexicious DataGrid is setup so that the filter control should dispatch an event (which is configurable) that the datagrid listens for, and when this event is dispatched, a filter is run. By default, this event is the "change" event. For controls that implement IDelayedChange, it is the delayed change event. So, this is something you need to keep in mind while implementing your own filter control. The change event being dispatched by default will trigger the filter. You can control this via setting the filterTriggerEvent on the column, if you want a specific event to trigger the filter. In our scenario, we dont need to worry about this, because we are extending a slider. This control already dispatches a change event when the user changes the value of the slider thumb.
Implement the Filter Interface methods: There are a few methods that we need to implement based on which filter interface we are implementing: In this scenario, since we are implementing IRangeFilterControl, we need to provide searchRangeStart and searchRangeEnd. This is then used by the filter logic to build a BETWEEN expression. If either searchRangeEnd or searchRangeStart is empty, the entire filter expression for this control is ignored. The other important methods are: setValue, getValue and clear. These methods are called by our API, when we rebuild the filter row in response to a refresh of the layout. So we call getValue, store it temporarily, destroy the filter component, create a new one, and then call setValue with the previously persisted filter Value. It is the responsibility of the filter control, to restore its state, from information it we give it in setFilterValue (which it gave us in getFilterValue). For sample implementation, look at the Salary Range Slider,
public function getValue():Object
public function setValue(val:Object):void
public function clear ():void
Using the Filter Control : Once we have a filter control implemented, its just a matter of setting its name (along with the package) in the filterRenderer property of the ExtendedDataGridColumn or ExtendedAdvancedDataGridColumn.
<columns:ExtendedDataGridColumn .... filterRenderer="com.sample.examples.support.SalaryRangeSlider"..../>
All of that said, there may be scenarios where you need to massage the value of the filter before processing it, or you may need to apply your own filtering logic to the filter control. There are ways to do this:
1) Implement IConverterControl: This interface is used, when you need to process the value of the item being compared. For example. A database sends down date columns as Strings. You have a DateComboBox as a filter. By default, the filter mechanism will try to compare two dates against a string. To combat this situation, you implement IConverterControl, and in the convert method, convert the string to a Date. We do this in the sample, look at MyDateComboBox.as (The code is commented, but its there).
2) Implement ICustomMatchFilterControl : This is new to Flexicious 1.5, but basically lets you completely encapsulate the logic for performing a filter. Please note, only use a FilterControl that implements this interface in filterPageSortMode=client.
One more caveat:
Flexicious 1.5 will have focus and tab enabled filter controls. This means that if your filter class does not implement IFocusManagerComponent, you will need to do it manually, otherwise we'll just tab over you. If it is a container control that encapsulates a IFocusManagerComponent control, then you will need to set focus contained control when you receieve focus. See DynamicFilterControl.mxml, where we implement the following methods:
public override function setActualSize(w:Number, h:Number)
public override function setFocus()
public override function drawFocus(isFocused:Boolean)
As always, unique requirements often demand unique resolutions, so please feel free to reach out with your questions, we're happy to help!