Showing posts with label DataGrid. Show all posts
Showing posts with label DataGrid. Show all posts

Wednesday, February 20, 2008

Alternate row color in DataGrid per DataGridColumn

The idea came from a flexcoders post here. After attempting the previous example of row background colors in ADG I thought it should be easy to achive this which resulted in this post.

I extended the DGColumn and added a "alternatingItemColors" style it so that it would be possible to set it per column.

I extended the DGItemRenderer and used the background and backgroundColor properties to set the items background color. I added logic in a overridden validateNow function to pick up the color from the alternatingItemColors color array.

The drawback of this approach is that the selection feedback gets almost hidden by the background coloring which would not be the case if the drawRowBackground function is overridden.

The result :

The source is available here.

Auto generating DataGrid columns for XML data

When we have dynamic XML data as follows

<employees>

<employee>

<name>Christina Coenraets</name>

<phone>555-219-2270</phone>

<email>ccoenraets@fictitious.com</email>

<active>true</active>

</employee>

<employee>

<name>Louis Freligh</name>

<phone>555-219-2100</phone>

<email>lfreligh@fictitious.com</email>

<active>true</active>

</employee>

</employees>

or in the form of attributes

<employees>

<employee name="Christina Coenraets"

phone="555-219-2270"

email="ccoenraets@fictitious.com"

active="true" />

<employee name="Louis Freligh"

phone="555-219-2100"

email="lfreligh@fictitious.com"

active="true" />

</employees>

and feed into DG or ADG it won't create columns auto-magically as it does for Object data type. This may be because it is difficult to decide whether you want to display the child nodes as columns or attributes of nodes. And may be it was not appropriate to clutter the API with one more flag to do this.

I wrote the following code to get this working.

private function generateCols(input:XMLList, 
 useAttributes:Boolean = false):Array
{
 var e1:XML = input[0];
 var columns:Array = [];
 var children:XMLList ;
 if (useAttributes)
    children = e1.attributes();
 else
    children = e1.children();
 for each(var child:XML in children)
 {
    var col:DataGridColumn = new DataGridColumn();
    col.dataField = useAttributes ? "@" + child.name() : child.name();
    
    var fieldName:String = child.name();
    col.headerText = fieldName.charAt(0).toUpperCase() + fieldName.substr(1);
    columns.push(col);
 }
 return columns;
}

The source is available here

The thread related to this post is here

Tuesday, January 22, 2008

Extending DGColumn and ADGColumn to handle nested data fields.

I have seen numerous questions regarding how to specify DataGridColumn.dataField when the data is nested (object or XML). Developers attempt to use "datafield1.datafield2.datafield3" to find out that it doesn't work !

The data might look like this :

<mx:XMLList id="testData" xmlns="">

<root>

<item>

<childItem>

<name>India Flex group</name>

<mail>indiafx@gmail.com</mail>

</childItem>

<location>India</location>

</item>

<item>

<childItem>

<name>Singapore Flex group</name>

<mail>singaporefx@gmail.com</mail>

</childItem>

<location>Singapore</location>

</item>

<item>

<childItem>

<name>Sreenivas</name>

<mail>sreenivas.ramaswamy@gmail.com</mail>

</childItem>

<location>Bangalore</location>

</item>

</root>

</mx:XMLList>

The answer has always (most of the time?) been to use DataGrid.labelFunction. I dislike the solution because it requires the developer to do this again and again for every column and every usage. I find it easier to extend the DataGridColumn and override the itemToLabel function to do the needful.

The usage is simple. The Nested and ordinary columns can be mixed or only nested columns can be used as the logic kicks in only when "." is present in dataField value.

<mx:AdvancedDataGrid dataProvider="{testData.item}">

<mx:columns>

<local:AdvancedDataGridColumnNested dataField="childItem.name" headerText="Name" width="150"/>

<local:AdvancedDataGridColumnNested dataField="childItem.mail" headerText="email" width="100"/>

<mx:AdvancedDataGridColumn dataField="location" headerText="Location" />

</mx:columns>

</mx:AdvancedDataGrid>

<mx:DataGrid dataProvider="{testData.item}">

<mx:columns>

<local:DataGridColumnNested dataField="childItem.name" headerText="Name" width="150"/>

<local:DataGridColumnNested dataField="childItem.mail" headerText="email" width="100"/>

<mx:DataGridColumn dataField="location" headerText="Location" />

</mx:columns>

</mx:DataGrid>

The result looks like this:

The data can be nested to any level not just two. The same logic takes care of everything!

Here are the source files for DataGridColumnNested and ADGColumnNested and test app.

Thursday, November 29, 2007

Use ArrayCollection available in HTTPService result with caution

Please refer to this and this bug report .

Both of them speak about data editing/update not getting propagated properly through a ArrayCollection. The samples are using the ArrayCollection available from the HTTPService result directly. The HTTPService is creating the ArrayCollection first and then updating its source Array with items. The Array object doesn't dispatch any events when it is updated with new items. Due to this ArrayCollection has no way of adding event listeners for property changes to the items added later on. Hence the changes are detected only for the items present at the time of creation of ArrayCollection which happens to be 2 items.

If one desire to use the HTTP result as dataProvider and expects data updates to get properly propagated they need to create a new ArrayCollection using the source of the default ArrayCollection present in the HTTP result.

data_provider = new ArrayCollection(ArrayCollection(srv.lastResult.data.result).source);

where srv is the HTTPService. If data_provider is already a ArrayCollection then we can just modify the source as follows

data_provider.source = ArrayCollection(srv.lastResult.data.result).source;

This bug exists in Flex 2 and may not be fixed in Flex 3 as the current bug status is deffered! The source is available here and data getting loaded here.

Friday, November 9, 2007

Smart column width based on data displayed (Part One: No code yet)

From the poll conducted I find that many users want Smart column width based on data displayed in DG/ADG.

I hope people requesting this feature know that it is a CPU intensive process to go over all the items in the dataProvider to find out maximum width required for all the columns. If the number of visible columns is more it would take even more time to compute the values and layout the columns.

If a labelFunction is being used at DG or DGColumn level and custom styles have been used on a column for fontSize for example, it complicates the computation even more.

When the data is being paged from a server it is not possible to compute the smart width at all without requesting all the data from the server, which is never desirable.

Keeping these things in mind I feel it makes sense to have a flag on individaul DGcolumn (apart from one on the DG itself) to control the computation of smart width. If the flag is true width is computed and false would use the normal way of determining the column width.

Thoughts?