Archive for May, 2008

itemEditors – Part 1

inline itemEditors

I recently completed a series on itemRenderers – customizations to list controls which format the display of the list contents. Displaying and rendering content is very cool and with Flex you can do nearly anything you can imagine.

This new series covers itemEditors – a way to allow data to be changed directly inside of a list control. This first article covers inline itemEditors which are very simple, though quite useful, components you write directly inside your MXML files. The other articles in the series will cover more complex editing, validation, events, and using itemRenderers as itemEditors.

The source code to this article is available by downloading it here.

TextInput Editor

It is nice to edit directly in the list controls. You can imagine a DataGrid of warehouse inventory where you can adjust the content right in the grid without needing a special pop-up. The list controls have a built in editor – a TextInput control – which appears whenever the user clicks the mouse in an editable area, either a row (for a List), a branch (for a Tree), or a cell (for a DataGrid). All you need to do is set the list control’s editable property to true. For a DataGrid you can exclude a column from being edited by setting the DataGridColumn’s editable property to false.

Before editing a cell
After clicking on a cell, the editor opens and the content is ready for editing.

itemEditors differ from itemRenderers in that only one instance of the itemEditor is seen – just on the cell being edited. The itemEditor is not seen until the cell to be edited receives input focus. Then the itemRenderer is hidden and the itemEditor is moved to that position, sized to fit the area, and given the data for the record. When editing is finished (by moving focus to another location), the list control copies the new value from the editor to the dataProvider record.

Using the image above as an example, when the user clicks in a cell of the "Part #" column, the dataProvider[row][dataField] value is given to the text property of the itemEditor (TextInput) control. When editing is finished, the text property value from the itemEditor (TextInput) control is copied to the dataProvider[row][dataField]. The dataProvider, being a collection, dispatches an event in response to the update.

While the default TextInput control makes a fine editor, it really only works for the most simple of cases. It works fine for String values, for example, such as a book title, author name, or product number. If you need more control or want to validate the user’s input, then you need to take matter into your own hands.

Flex Controls as itemEditors

Here is how you make an itemEditor which only accepts numeric values:

	<mx:DataGrid x="46" y="270" editable="true" dataProvider="{employeeDB}">
<mx:columns>
<mx:DataGridColumn headerText="Name" dataField="name"/>
<mx:DataGridColumn headerText="Position" dataField="position"/>
<mx:DataGridColumn headerText="Age" dataField="age">
	<mx:itemEditor>
<mx:Component>
<mx:TextInput restrict="0-9" maxChars="3" />
</mx:Component>
</mx:itemEditor> 
</mx:DataGridColumn>
</mx:columns>
</mx:DataGrid>

A very common control to use for an itemEditor is the CheckBox. This is very useful for editing Boolean values. Here is an example of using the CheckBox to edit the values for an "In Stock" column of an inventory program:

<mx:DataGrid x="531" y="273" editable="true" dataProvider="{inventoryDB}">
<mx:columns>
<mx:DataGridColumn headerText="Product" dataField="product"/>
<mx:DataGridColumn headerText="Part #" dataField="part"/>
	<mx:DataGridColumn headerText="In Stock?" dataField="inStock"
labelFunction="inStockLabeler"
itemEditor="mx.controls.CheckBox" editorDataField="selected" /> 
<mx:DataGridColumn headerText="Quantity" dataField="quantity"/>
</mx:columns>
</mx:DataGrid>

In this example the content of the cells in this column are rendered using a labelFunction (inStockLabeler) which could display anything such as "Yes", "No", "In Stock", or "Out of Stock". The itemEditor property is set to the mx.controls.CheckBox class. And there is another, equally important, property set on the DataGridColumn: editorDataField. This field indicates the property of the itemEditor class to use to fetch the value when editing is finished. In this case it is the CheckBox’s selected property. When editing is finished, the DataGrid will use the CheckBox’s selected property to replace the inStock property in the data record.

You may wonder why the example with the TextInput did not supply the editorDataField property. That is because the default value for editorDataField is "text" which just happens to be name of the property on the TextInput control holding the value.

You can use this same technique with a number of Flex controls. Here is one for an order quantity column using NumericStepper:

	<mx:DataGrid x="531" y="82" editable="true" dataProvider="{inventoryDB}">
<mx:columns>
<mx:DataGridColumn headerText="Product" dataField="product"/>
<mx:DataGridColumn headerText="Part #" dataField="part"/>
<mx:DataGridColumn headerText="In Stock?" dataField="inStock"/>
	<mx:DataGridColumn headerText="Quantity" dataField="quantity"
itemEditor="mx.controls.NumericStepper" editorDataField="value"/> 
</mx:columns>
</mx:DataGrid>

Notice the editorDataField is "value" – the property of the NumericStepper which holds the current value of the control. Make sure you use the fully-qualified class name for the itemEditor property.

Complex Editor

Now suppose you want to do something a little more complex that doesn’t have a ready-made Flex control available. Here is one which allows a credit card number to be entered using 4 separate 4-digit fields:

	<mx:DataGrid x="46" y="463" editable="true" dataProvider="{accountDB}" width="302">
<mx:columns>
<mx:DataGridColumn headerText="Account" dataField="account" width="100"/>
<mx:DataGridColumn headerText="Credit Card" dataField="ccard" editorDataField="value">
<mx:itemEditor>
<mx:Component>
<mx:HBox>
<mx:Script>
<![CDATA[
public function get value() : String
{
return part1.text+part2.text+part3.text+part4.text;
}
override public function set data(value:Object):void
{
super.data = value;
part1.text = value.ccard.substr(0,4);
part2.text = value.ccard.substr(4,4);
part3.text = value.ccard.substr(8,4);
part4.text = value.ccard.substr(12,4);
}
]]>
</mx:Script>
<mx:TextInput id="part1" maxChars="4" restrict="[0-9]" width="40" />
<mx:TextInput id="part2" maxChars="4" restrict="[0-9]" width="40" />
<mx:TextInput id="part3" maxChars="4" restrict="[0-9]" width="40" />
<mx:TextInput id="part4" maxChars="4" restrict="[0-9]" width="40" />
</mx:HBox>
</mx:Component>
</mx:itemEditor>
</mx:DataGridColumn>
</mx:columns>
</mx:DataGrid>

This inline itemEditor follows the same rules as other itemEditors and names the editorDataField as "value". The component chosen for the itemEditor is the HBox – which does not have a "value" property. To make this itemEditor work, a getter function named value is created to return the concatenation of the 4 input fields. Now when editing for the cell completes, the DataGrid can call upon the value property of the itemEditor and it will receive the combined fields.

You can also see that I have overridden the data setter function. In that function I split up the credit card number among the four TextInput fields. This is the technique you use to display the data to be edited. The editorDataField is the property used to retrieve the new value.

Conclusion

In this article you’ve seen how to create an inline itemEditor – from simply naming a class to creating a complex class right within the MXML tags. By naming the property of the editor class which contains the final editor value, the DataGrid can retreive the value from the editor instance and replace the current value in the data.

The next article covers more complex itemEditors and editing events.

Registration Open for MAX 2008

MAX 2008 will be held in San Francisco this year and is now ready for you to register.

Each year MAX has gotten bigger and better. If you haven’t attended MAX, make this year your first. MAX is a great place to network and to see the new things coming from Adobe and other companies. MAX is also the place to meet the Adobe staff and there are always plenty of Adobe people on hand.

Following this link and make your reservation: http://max.adobe.com/blog/

Hope to see you at MAX!

Ruth G. Chamberlain

In memoriam…

Ruth Chamberlain

Early in the morning of April 28, 2008, my mother, Ruth Chamberlain, passed away. She was 89 years old and suffered from emphysema.

My mother often worked two jobs while I was growing up and it was while she was working that she was most happy. She managed to work until she was 86 and was, at the time, the oldest employee of A.C. Moore. I think I take after her in that respect.

I am not writing this article for your sympathy, but to be another voice and to challenge you and remind you of the effects of smoking. You see, my mother smoked most of her adult life. She quit smoking in her 60s, but still, 20 years later, it caught up with her.

She spent her last years in a nursing home because of her breathing. She had to be on oxygen all of the time and took medication several times a day. Toward the end her breathing became more and more difficult until she couldn’t do it any longer.

If you smoke – STOP NOW. For yourself, for those you love and who love you. STOP NOW for your friends and co-workers. STOP NOW for your pets too.

My mother was fond of St. Jude’s Children’s Hospital. If you care to make a donation I know they would love it.

Thanks to my mom for raising me and giving me the opportunity to work and do what I love to do best.

Return to Normal

Our blogging server is back and my blog, along with a bushel of others, have been restored.

Now I can work on my back-log of articles.