Skip to content
September 22, 2008 / Shrikant Patil

Creating a component which can be used as Renderer and Editor

Flex provides a mechanism that we can use a itemRenderer as ItemEditor as well, by setting the rendererIsEditor property of the data Grid, list etc components. We can use any of built-in component
which implement IDropInListItemRenderer interface as ItemRenderer as well as ItemEditor. Suppose if we want to create our custom/ own component which can be used as Itemrenderer and Itemeditor, then we need to work little bit. In this post we are going to create a custom component which can be used as item renderer and item editor.

The components which are used as rendererIsEditor property of list, Datagrid etc components uses two states. one which is used to show the data (renderer view) and another state which is used to allow editing of the data (editor View). The base state of the component is renderer view. once the component receives double click event it changes its state to editor state allowing to edit data, and registers for FocusOut Lister.
Here is quick review of the both states:
Base View  – Renderer View:
a) Registers a listener for double click event.
b) use a component like text, label etc to display data.
Once renderer State get the double click event, it changes its state to Editor View.
Editor View:
a) Registers a listener for FocusOut event.
b) Uses a component to edit the data. While value of the component changes it dispatches ITEM_EDIT_END event, so that updated data get assigned to the data provider.   Once editor state receives Focus out event, it changes its state back to renderer state. This is what base idea behind the component.

Lets check some steps to create the component:
1) Component must implement mx.controls.listClasses.IDropInListItemRenderer.
2) Component must set to doubleClickEnabled=true.
3) Component must override public setter and getter of ‘data’ property.
4) Component must include public setter/getter for ‘listData’ property.
5) When component is in ‘renderer’ state, it may register for MouseEvent.DOUBLE_CLICK event listener.
6) When component is in ‘Editor’ state, it may register for FocusEvent.FOCUS_OUT event listener.
7) The component used in Editor State, should dispatch DataGridEvent.ITEM_EDIT_END event on change in value.

So, Here is a custom RateRenderer component used to display/Edit rate value.


<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="100"
 doubleClickEnabled="true" currentState="showRenderer"
 implements="mx.controls.listClasses.IDropInListItemRenderer">
 <mx:Script>
     <!&#91;CDATA&#91;
         import mx.events.DataGridEvent;
         import mx.controls.listClasses.BaseListData;

         //declear variables to hold listData and data objects.
         private var _listData:BaseListData;
         private var _data:Object = new Object();

         //override public setter for data property
         override public function set data(value:Object):void{
             _data = value;
             //check property weather is that null
             if(_data.rate != null){
                 //add listener  to listen for double click
                 addEventListener(MouseEvent.DOUBLE_CLICK, beginToEdit);
             }
         }

         //override publi getter for data property
         override public function get data():Object{
             return _data;
         }

         //double click listener
         private function beginToEdit(e:MouseEvent):void{
             //check for the currentstate of the compoent
             if(currentState == 'showRenderer'){
                 //change state to editor
                 currentState = 'showEditor';
                 //add listener to Focus out to end editing
                 addEventListener(FocusEvent.FOCUS_OUT, quitFromEdit);
             }
         }

         //focus out listener
         private function quitFromEdit(e:FocusEvent):void{
             //reset the current state to renderer state
             currentState = 'showRenderer';
         }

         //IDropInListItemRenderer implementation of get listData
         &#91;Bindable("dataChange")&#93;
         public function get listData():BaseListData{
             return _listData;
         }
         //IDropInListItemRenderer implementation of set listData
         public function set listData(value:BaseListData):void{
             _listData = value;
         }

         //value update function
         private function updateData():void{
             //On edit complete assign updated component value back to _data property
             _data.rate = stepper.value;
             //dispatch datagrid - itemEditEnd event so that new value updated on dataprovider
             dispatchEvent(new DataGridEvent(DataGridEvent.ITEM_EDIT_END,true, false,_listData.columnIndex,'rate',_listData.rowIndex));
         }
     &#93;&#93;>
 </mx:Script>
 <mx:states>
     <mx:State name="showEditor">
         <mx:AddChild>
             <mx:NumericStepper id="stepper" addedToStage="stepper.value = _data.rate"
              change="updateData()"/>
         </mx:AddChild>
     </mx:State>
     <mx:State name="showRenderer">
         <mx:AddChild>
             <mx:Text id="txt" addedToStage="txt.text = _data.rate"/>
         </mx:AddChild>
     </mx:State>
 </mx:states>
</mx:Canvas>

Once we have done with the component, we can use it for rendererIsEditor property of DataGrid or List component. Here i am showing how to use the above RateRenderer in datagrid.


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
xmlns:com="*" xmlns:flexScript="flexScript.*">
<mx:Script>
    <!&#91;CDATA&#91;
        import mx.collections.ArrayCollection;

        private var ary:ArrayCollection = new ArrayCollection(&#91;
        {Article:"The legand",  rate:1},
        {Article:"War on Plaet", rate:3},
        {Article:"Predication",  rate:4}
        &#93;);

    &#93;&#93;>
</mx:Script>
<mx:DataGrid dataProvider="{ary}" width="450" id="dg">
        <mx:columns>
            <mx:DataGridColumn dataField="Article"/>
            <mx:DataGridColumn itemRenderer="flexScript.RateRenderer"
            editable="true" rendererIsEditor="true"/>
        </mx:columns>
    </mx:DataGrid>
</mx:Application>

Advertisements

One Comment

Leave a Comment

Trackbacks

  1. Anonymous

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: