ISummaryCalculator, GroupingCollection2, and SummaryField2 with the Filter

clock January 13, 2011 10:46 by author Flexicious

Following up on the heels of an older blog post where we demonstrated how to filter out parent entities in hierarchical data when there are no children, here is an example that demonstrates how to update the summary totals that reflect the filter criteria.

To do this, we simply need to implement our own Summary Calculator. (Which is the CustomSummaryCalculator), and in the summary calculator, we check to see if the item is being filtered out before adding it to the summary.


CJ.mxml (3.93 kb)

CustomSummaryOperation.as (3.33 kb)



Custom Date Range

clock December 5, 2010 22:45 by author Flexicious

Another common question: How do I add Date Range Values that are not included in the available list.
By default, we ship with the following Date Range Values:

DATE_RANGE_LASTHOUR,
DATE_RANGE_THISHOUR,
DATE_RANGE_NEXTHOUR,
DATE_RANGE_YESTERDAY,
DATE_RANGE_TODAY,
DATE_RANGE_TOMORROW,
DATE_RANGE_LASTWEEK,
DATE_RANGE_THISWEEK,
DATE_RANGE_NEXTWEEK,
DATE_RANGE_LASTMONTH,
DATE_RANGE_THISMONTH,
DATE_RANGE_NEXTMONTH, 
DATE_RANGE_LASTQUARTER,
DATE_RANGE_THISQUARTER, 
DATE_RANGE_NEXTQUARTER,
DATE_RANGE_LASTYEAR,
DATE_RANGE_THISYEAR,
DATE_RANGE_NEXTYEAR,
DATE_RANGE_CUSTOM


But often, our clients need values that are not in this list. Rather than pre packaging all possible values in this list, attached is a project that defines how to introduce your own values in here. The process is simple - extend and override. This is a common theme in all Flexicious customization. This helps you in terms of receiveing updates to the library as well, because we are very careful about not introducing behavior modifying changes in existing codebase, nor do we remove API's that are documented.

Hope the attached project helps you in scenarios where you need to implement custom date ranges!

 

CustomDateRange.zip (15.03 kb)



The filterPageSortMode explained

clock June 28, 2010 04:52 by author Flexicious

 
Both the Flexicious basic and advanced datagrids expose a property, filterPageSortMode.


This is a key property to understand. There are two values for this property, “server” and “client”. Let us assume you are working on a Human Resource Management Application. You have a DataGrid that shows a list of Employees. You have a few hundred Employees to show. This can be easily accomplished by getting the list of employees from the server, and setting the data provider property of the ExtendedDataGrid to an ArrayCollection that contains this list of Employees. As you need, you enable filters, footers, paging, export, print, etc, and all is well and good. You will be up and running in no time with filterPageSortMode=client. The grid will take care of paging, filtering and cross page sorting for you. However, now consider a scenario where you have to display a time sheet search page. Each employee creates hundreds of timesheets each year, and multiply that by the number of employees, you are looking at thousands, even hundreds of thousands of records of data. Although it may be possible to load thousands of records in any Flex DataGrid (including ours) with no noticeable drag, this is not recommended, and often unnecessary. What we suggest in this scenario is you use the filterPageSortMode =”server”. What Flexicious does, in this setup, is it assumes that the current ArrayCollection is a part of a much larger recordset, and you are showing just the current page of data. So if there are 100,000 records in the database, and the pageSize is 50, Flexicious will show the 50 records, and provide paging UI for the user to navigate to any record in the resultset. At any point in time, no more than 50 records will be loaded on client memory. This setup, will require a little more effort in terms of configuration, but it will be considerably easier to do this with Flexicious as opposed to building it yourself, because the product is architected to cater to a scenario like this.

We provide complete examples on how to do this, including the backend code in Java and .Net.



Wierd behavior with edit enabled datagrids

clock June 26, 2010 08:33 by author Flexicious

Question:

In our Flexicious grids, a double-click usually opens a small popup form for editing the record.  We pass an object to that popup which is altered on edit/save and it appears to correctly update the grid with the new values when the popup is closed (because the object is being passed by reference).

What we’re noticing is that when the grid is sorted, occasionally (at least 50% of the time) the selected record actually moves by one or two indexes in the grid.  It’s not a huge issue, since the record is still updating correctly in the grid, but it’s a little weird.....

Answer:

This behaviour is a byproduct of using the filterFunction along with sort on. In filterPageSortMode=client, flexicious leverages the fiterFunction property of Adobe's ICollectionView. When you turn this on, the grid refreshes on each update to any object within the dataprovider. The post below summarizes this issue very well:

http://tomek.me/disable-sort-on-datagrid-edit-update/

Attached, is a file that demonstrates this same issue with the Adobe DataGrid, and a way to bypass it.
In short - you could either disable Auto Update, or use the modified ArrayCollection. If you disable autoupdate, you may have to manually call processFilter on the grid, which will refresh the grid UI for you.

 

 

FlexiciousSandbox.mxml (4.43 kb)



Change the Display labels of the Date Combo Box, Date Format/Range on the picker

clock June 12, 2010 19:21 by author Flexicious


Question1: I’m very impressed and pleased with the product. I’m using the DateComboBox and wondering if there’s a way to disabled certain date on the CustomDatePicker if the user chooses to pick a custom date range. As of now, the user can pick any start date and end date. I’d like to have the option of limit it to only the current year. Is it possible?

Question2: How do I change the display labels of the Date Combo Box?

Question3: How do I change the "All" text that shows up in the Filter ComboBoxes.

Question4: My backend sends down dates as strings. How can I get the date combobox to filter correctly?

Answer: You will need to extend the DateComboBox for both of the above.

For #1 and #2, you would associate your column with your custom date combobox like below:

<columns:ExtendedDataGridColumn filterRenderer="MyDateComboBox" />

For #1, in your custom date combbox you would do the following (This code is included in the sample):

    public class MyDateComboBox extends DateComboBox
    {
        public override function get  popup():Object
        {
            if(!_popup)_popup=new MyDatePicker();
                return _popup;
        }

For #2, in your custom date combbox you would do the following:
 


public class MyDateComboBox extends DateComboBox
{

    public override function set dateRangeOptions(val:Array):void

    {

   
    var coll:ArrayCollection=new ArrayCollection();

    for each(var dateRange:String in val)
       coll.addItem({"label":YOUR_LABEL,"data":dateRange});

    dataProvider = coll;

    coll.refresh();

    }

}

 

For #3: <mx:Application preinitialize="application1_preinitializeHandler(event)">
protected function application1_preinitializeHandler(event:FlexEvent):void
{
    Filter.ALL_ITEM="todos";
}


For #4: There are a couple of options, first is to use a ICustomMatchFilterControl. This will basically give you control over the filter matching operation. There is another blog post that describes how to do this. The other option, and this one was specifically designed for this case is to implement a IConverterControl. The file below demonstrates how to do this:

 

custom filter.txt (2.39 kb)

 

MyDatePicker.mxml (2.26 kb)

MyDateComboBox.as (2.34 kb)



Persisting Preferences on the Server

clock May 31, 2010 11:48 by author Flexicious

Flexicious has a robust persistence preference mechanism that "just works" out of the box, but the preferences are stored on the client machine in the form of Shared Objects by default. This enables the preference persistence mechanism to work without any additional coding on the part of the developers utilizing the library. While this may be sufficient for most people, this will not work in scenarios when the same user uses multiple machines to access your application, or if multiple users access the application using the same machine. For this, you will need to store preferences in the backend, and this post aims to show you how this is done. Attached are 2 files that will help you understand both the server and client side of this equation.

This entry will discuss at a high level the code in these two files:

1) preferencesFlex.mxml:  A sample file, that shows the Flex code require to enable server based persistence of preferences:

Please note the declaration of the grid - we wire up 3 events, loadPreferences, persistPreferences, and clearPreferences. Each of these events call a service method, which we will talk about in a bit. But the idea is simple, on persistPreferences, we send up the preferences xml, the name of the grid, and in your service method, you figure out who the logged in user is (on basis of your security implementation) and store a record in the database with UserID, gridName, and preferenceXML (Make this a large text field (nvarchar(max) in SQL Server Lingo), it could get pretty verbose). the loadPreferences will call your service method to load the preferences you persisted, and set the grids preferences property. Once you set the property, the grid will parse everything and get back to the state it was when the preferences were stored. And then the final method is the clearPreferences, which will basically just wipe out the preferences that were previously stored. Sound like a lot, but really pretty straight forward.

    <grids:ExtendedDataGrid id="dgEmployees" enablePreferencePersistence="true"
        preferencePersistenceMode="server"...... loadPreferences="onLoadPreferences()" persistPreferences="onPersistPreferences()"
        clearPreferences="onClearPreferences()">

           //Called when the grid needs preferences (on creation complete)
            private function onLoadPreferences():void{
                callMethod("GetSavedPreferences",{gridName:dgEmployees.preferencePersistenceKey},onLoadPreferenceResult);
            }
            //Callback when the preference data is loaded from the server.
            private function onLoadPreferenceResult(event:ResultEvent):void{
                if(event.result.toString().length>0)
                dgEmployees.preferences=event.result.toString();
            }
            //Called when the user clicks on "save preferences" in the preferences dialog box
            private function onPersistPreferences():void{
                callMethod("PersistPreferences",{gridName:dgEmployees.preferencePersistenceKey,prefXml:dgEmployees.preferences},onPersistPreferencesResult);
            }
            //Callback when the preference data is persisted on the server
            private function onPersistPreferencesResult(response:ResultEvent):void{
                processResult(response);
            }
            //Called when the user clicks on "clear preferences" in the preferences dialog box
            private function onClearPreferences():void{
                callMethod("ClearPreferences",{gridName:dgEmployees.preferencePersistenceKey},onClearPreferencesResult);
            }
            //Callback when the preference data is cleared on the server
            private function onClearPreferencesResult(response:ResultEvent):void{
                processResult(response);
            }
            //here we just call server methods using http services, but you could
            //use remoting or web services, or whatever
            private function callMethod(methodName:String, parameters:Object, callBack:Function):void{...}


2) The Backend Service Code (This is C#, but Java/PHP/Anything would perform similar actions):

We are basically implementing the code to tie the passed in preferences to the IP address of the end user, but in your case, you could tie it to a session specific user ID.


        /// <summary>
        /// Returns previously saved preferences for the provided
        /// Grid Name. This name corresponds to the preferencePersistenceKey
        /// from Flex
        /// </summary>
        /// <param name="gridName">The Grid To get preferences for</param>
        /// <returns>The persisted preference values</returns>
        public ActionResult GetSavedPreferences(string gridName){...}

        /// <summary>
        /// Persists the preferences for the provided grid name
        /// </summary>
        /// <param name="gridName">Grid to persist the preferences for</param>
        /// <param name="prefXml">The preferences to persist</param>
        /// <returns>Success code.</returns>
        [ValidateInput(false)]
        public ActionResult PersistPreferences(string gridName, string prefXml)
       
        /// <summary>
        /// Clears previously saved preferences for the provided
        /// Grid Name. This name corresponds to the preferencePersistenceKey
        /// from Flex
        /// </summary>
        /// <param name="gridName">The Grid To clear preferences for</param>
        /// <returns>The persisted preference values</returns>
        public ActionResult ClearPreferences(string gridName)
           
We hope this explanation and the attached files should get you started in the right direction, but please feel free to reach out to us at the info address if you need any additional help!

preferencesFlex.txt (5.79 kb)

preferencesBackend.txt (3.20 kb)



Detached Filters

clock May 26, 2010 06:27 by author Flexicious

Question: In example # 5, Detached Filters, when you have filter controls that are outside the grid, you have to seperately manage the filter criteria entered in such controls. Why is this needed when I’m using controls outside the grid for filtering, but not when I use column header filtering?

Answer: The DataGrid internally contains a FilterRow object, which is a Flexicious Filter and DataBinding container. For details on this, review http://blog.flexicious.com/post/Custom-Filter-Control.aspx. Basically the idea is that all the Flexicious controls register themselves with the first Flexicious container in their hierarchy. These containers can then call methods on the controls. For the filtering mechanism, this means they can call the getFilterValue and setFilterValue methods on each of the Flexicious controls that have registered with them. Since the control is placed outside the grid, it does not register itself with the Grid's filter row, rather it registers itself with its own container. The grid itself is oblivious to the controls and containers that are outside of its own hierarchy. This is why you have to explicitly let the filtering mechanism of the grid know, that in addition to the filters within the grid, there are filters outside, that will affect the resulting filter to create a combination filter. We demonstrate how to do this in Example 5, Flexicious UI.

One of the driving factors behind this implementation is the loose coupling of the Grid UI and the Filter Control UI. All of the communication is handled via events. The Filter Controls fire a change event, the FilterContainer listens for it, aggregates all filter control values in its hierarchy, fires a change event, the grid listens for it, fires a filterPageSortChangeEvent, which in this case we listen into and append additional filter criteria, and process the resultant filter. A setup like this gives you more control over the UX, for example, you can have multiple Flexicious grids visible, and have additonal detached filters for each of them, or even share the same set of detached filters for multiple grids

 



Prepopulating the filters

clock May 24, 2010 02:01 by author Flexicious

Suppose you want to set predefined values for your filters- you can always use the setFilterValue and getFilterValue methods, passing in the dataField of the column name that you wish to set the filterValue for. Also, see example 8, the first grid always loads up with default filter values. This is how its done:


                grid1.setFilterValue("employeeId","1",false);

//The first parameter is the dataField of the column of the filter you want to set the value on
//The second parameter is the value. The type of this object depends on the filter control that you are targeting. The type has to match its "setValue".
//The third parameter is basically a flag that tells the grid whether to run the filter instantly.

                grid1.setFilterValue("department",new ArrayCollection(["IT"]),false);
                grid1.validateNow(); //Since we delay instantiate the Multi select, we need to do this for the
                //grid to pickup that there is a filter in that value.
                grid1.processFilter();



Not Printable/Exportable Columns, Defaults on print options, echoPDF

clock May 21, 2010 08:01 by author Flexicious

1. Is there a way to set a column in the grid as not printable? For example my Edit and Delete image columns.
-> Yes, use the excludeFromPrint and excludeFromExport on the column
===============================================================
2. Is there a way to set the defaults for your print options? Like for example I want it to default to "Landscape".
-> Not in this version, but the upcoming version will have this, in addition to being able to persist the print preferences.

http://blog.flexicious.com/post/New-features-coming!!!.aspx

===============================================================
3. Can you help me figure out your echoPDF (and getting rid of your titles that show up on the pdf etc...)
-> This is completely customizable. The tiles show up because they are provided as a place holder in the following files:
MyPageFooter,. MyPageHeader, MyReportFooter and MyReportHeader. (The names of these files dont matter either, they can be whatever you set them to be in
MyPrintOptions, and the name of MyPrintOptions does not matter either, it can be whatever you call in your PrintController.print(grid, SomePrintOptions.create()).
The idea is that all of these files are provided so you can completely customize the behavior of the functionality, but it works out of the box with no changes.)
Feel free to modify any file that starts with the "My" Prefix.
In regards to the echo pdf, please review this:

Also, in our sample code, we demonstrate how the Export can be customized, by plugging in a completely new Exporter, MyDocExporter to the list of exporters.


The Custom Pager Control

clock May 18, 2010 04:52 by author Flexicious

Question:

I have found the examples provided to be very helpful but I seem to be a little confused by the operation of CustomPagerControl.mxml.

ExtendedAdvancedDataGrid.enablePaging is the flag  to activate ExtendedAdvancedDataGrid.pagerRenderer but CustomPagercontrol.mxml contains an HBox(paging controls) that has a dependency on ExtendedAdvancedDataGrid.enablePaging.  If the renderer is not enabled (enablePaging=false), why would the HBox need to be disabled (not visible, not in the layout)?  Conversely, if the renderer is enabled, why would the HBox need to also be enabled?  And finally, how would you enable the renderer and not enable the HBox (hide the paging controls)?

===============================================================

The CustomPagerControl is something we provide, as an example of how you can completely customize the Pager Control. Back in the day when it was introduced, it used to have just the paging buttons. But most of our clients have added all sorts of functionality to it, and made it like the "toolbar" of the Flexicious Grid. Taking a cue from what our clients were doing with it, we updated the sample control to be the "toolbar" that most of our clients wanted anyway. So in essence, you could easily have a grid, with no paging enabled, but still want the pager bar (because it has all the other buttons). In order to not break any API's, we added a new property, "forcePager" which will show the pager bar regardless of the enablePaging flag.

While you are at it, do check out the "displayOrder" property - you can control in what order you want the different sections of the grid (header, footer, pager, filter) to show!


http://www.flexicious.com/resources/docs/com/flexicious/grids/ExtendedAdvancedDataGrid.html#forcePagerRow

http://www.flexicious.com/resources/docs/com/flexicious/grids/ExtendedAdvancedDataGrid.html#displayOrder