Flexicious 1.4 Released!

clock May 31, 2010 13:12 by author Flexicious

Happy to announce that Flexicious 1.4 is now official.

Please check out http://www.flexicious.com/Home/Updates for a list of features that are included!

A few of our early adopter customers have already been using the library for sometime, and no major issues reported.

If you are an existing subscription customer, please send a message to the info address for an update. Please ensure you mention your company name, purchase date, and the version of the SDK (Flex 3 or 4)!

And follow us on twitter to be notified when we release new versions!

NOTE: This time around there were a few minor changes to the client section of the code (in addition to what is in the library), This is code that is provided as a Sample, but we realize a lot of our customers are using this code as is. So you may need to update these files to ensure you get everything:

The files are:
SettingsPopup.mxml (Fixed issues with Checkbox List)
SaveSettingsPopup.mxml (Added Print Settings checkbox)
support/print/*(Added persistence support, resizable columns, header parameters, etc.)
SalaryRangeSlider.mxml (Fixed persistence/rebuild)
CustomPagerControl.mxml (Fixed alignment issues)

 

 

 



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();



Pre Select checkboxes and row formatting

clock May 21, 2010 09:05 by author Flexicious

1.  Is it possible, on loading data, to check some row of the “check” column

-> Use grid.selectedKeys.add(key). Once you do this, please ensure to reset the data provider, as shown in the attached example.

2.       Is it possible, on loading data, set row background color, not alternating, but based on change of code
-> Use the styleFunction (see example 2). Please note, this is only supported for the Advanced DataGrid.

FlexiciousFooterTest.mxml (1.46 kb)



Preference Persistence

clock May 21, 2010 09:02 by author Flexicious

When you save preferences, where are the preferences persisted to??
A: See the docs for preferencePersistenceMode
String value "server" or "client". When this property is set to client(default), the grid uses a shared object on the client to store preference settings. When it is set to server, the grid fires an event, preferencesChanged, which contains a XML string representation of the preference values. This can then be persisted on the backend, tied to a specific user id.

While you are at it, also review
preferencePersistenceKey:
String value that uniquely identifies this grid across the application. If you have multiple grids' with enablePreferencePersistence, and they happen to share the same value for the id field, e.g. id="grid1" they might overwrite each others' preferences. To combat this situation, we provide a property, which defaults to the id of the grid, but you can override to provide a globally unique key.



Image to the Report header

clock May 21, 2010 08:30 by author Flexicious

Question:  How do I add images to the Report header?

Answer:  The image tag needs to be embedded for example:
<mx:Image source="@Embed('../assets/images/YourImageFile.png')"/>



Access the filter expressions

clock May 21, 2010 08:13 by author Flexicious

Q:

Your component is great.  Easy to use and very powerful.

Can you tell me how I can access the filter expressions from within a component that contains one of your extended datagrids?  I simply want to get the filter expressions that have been entered and use them for another purpose.

Thank-you.

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

Depending on what you want to do, there are multiple ways. Look at example 5 on the demo
http://www.flexicious.com/Home/Demo, here in the filterPageSortEvent,

function onFilterPageSortChange(event:FilterPageSortChangeEvent): void 
event.filter.arguments will contain all the arguments.

 

In the next release, we will have a public function that will fit the bill:
grid.getFilterArguments, but for now, if you really need it, you could extend the grid, and have the following function in the extended grid:

public function getFilterArguments():ArrayCollection
{
  var filterArgs:ArrayCollection=new  ArrayCollection();
   for each(var row:DataGridFilterRow in filterRows){
     for each(var arg:Object in row.getFilterArguments()){
      filterArgs.addItem(arg);
    }
  }
  return filterArgs;
}



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.


Errror : Instantiation attempted on a non-constructor.

clock May 21, 2010 07:50 by author Flexicious
Q:
=========================================================
I copied in the attached shopping cart and when I click on it I get:
TypeError: Error #1007: Instantiation attempted on a non-constructor.
at mx.controls::AdvancedDataGridBaseEx/getSeparator()[E:\dev\4.0.0\frameworks\projects\datavisualization\src\mx\controls\AdvancedDataGridBaseEx.as:4618]
at mx.controls::AdvancedDataGridBaseEx/createHeaderSeparators()[E:\dev\4.0.0\frameworks\projects\datavisualization\src\mx\controls\AdvancedDataGridBaseEx.as:4660]
at mx.controls::AdvancedDataGrid/createHeaderSeparators()[E:\dev\4.0.0\frameworks\projects\datavisualization\src\mx\controls\AdvancedDataGrid.as:2428]
at mx.controls::AdvancedDataGridBaseEx/drawSeparators()[E:\dev\4.0.0\frameworks\projects\datavisualization\src\mx\controls\AdvancedDataGridBaseEx.as:4574]
at mx.controls::AdvancedDataGridBaseEx/updateDisplayList()[E:\dev\4.0.0\frameworks\projects\datavisualization\src\mx\controls\AdvancedDataGridBaseEx.as:2119]
at mx.controls::AdvancedDataGrid/updateDisplayList()[E:\dev\4.0.0\frameworks\projects\datavisualization\src\mx\controls\AdvancedDataGrid.as:2899]
at mx.controls.listClasses::AdvancedListBase/validateDisplayList()[E:\dev\4.0.0\frameworks\projects\datavisualization\src\mx\controls\listClasses\AdvancedListBase.as:3468]
at mx.managers::LayoutManager/validateDisplayList()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:663]
at mx.managers::LayoutManager/doPhasedInstantiation()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:718]
at mx.managers::LayoutManager/doPhasedInstantiationCallback()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:1072]
 
=========================================================
 
We had this error a long time ago and it turned out to be a corrupt sdk install.
http://kb2.adobe.com/cps/403/kb403121.html
 
Depending on the sdk you have, one of the following suggestions should address
the issue
1) If you are on Flex 3. ensure that you have the latest 3.5 sdk (along with the datavisualization sdk)

2) If you are on Flex 4, ensure you have the latest sdk, and we have sent you the library specifically for Flex 4. 
3) Include the attached Style.css, (depending on what
build of the Flex sdk you have, you may have to update the namespace declaration
from @namespace mx "library://ns.adobe.com/flex/mx"; to @namespace mx
"library://ns.adobe.com/flex/halo";

Style1.css (8.92 kb)