0
votes

I'm curious how others would tackle this:

Consider a DataGrid with every column using a Label subclass as its itemRenderer (for toolTip stuff or etc). In the first column I'd like to display a button inside each cell (for example a pencil icon which would enable editing of the cell text when clicked). The examples I've found either involve subclassing Button as the itemRenderer or adding the button via a new inline mxml itemRenderer...

Is there a way to do it that retains functionality of or subclasses the current itemRenderer? Thank you!

Here's my grid:

<mx:DataGrid id="dg_myGrid" width="100%" allowMultipleSelection="true">
      <mx:columns>
        <mx:DataGridColumn width="80" dataField="@currCode"
                           headerText="Current Code"
                           dataTipField="@codeDescription"
                           itemRenderer="com.foo.bar.components.LabelCustom"/>
        <mx:DataGridColumn width="80" dataField="@codeDescription
                           headerText="Description"
                           itemRenderer="com.foo.bar.components.LabelCustom"/>
       </mx:columns>
    </mx:DataGrid>

And here's the Label subclass being used as the dataGridColumn itemRenderer:

package com.foo.bar.components{
    public class LabelCustom extends Label{
        private function getToolTip():String{
            var dg:DataGrid = listData.owner as DataGrid;
            if(dg.columns[listData.columnIndex].dataTipField!=null){
                return data[dg.columns[listData.columnIndex].dataTipField]; 
            }else{
                return "";
            }
        }
        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
            var tip:String = getToolTip();
            if (tip != "") this.toolTip = tip;
            super.updateDisplayList(unscaledWidth, unscaledHeight);
        }
    }
}
1

1 Answers

0
votes

So typically you don't subclass a component in an item renderer instead you use composition to build / layout / manage the components instead. Like other components, the key is to manage the life cycle: createChildren(), commitProperties(), and updateDisplayList()

The reason why you do it this way is to avoid having the column directly size the internal components (ie you don't want a checkbox the same w/h as the column itself)

Here is an example that should give you an idea of the direction to head. To set properties of the itemRenderer you use a ClassFactory instance and set the properties as an associative object.

Class Factory Example:

private function get hiddenAccountRendererFactory():ClassFactory
{
    var cf:ClassFactory = new ClassFactory(CheckBoxItemRenderer);
        cf.properties = { dataField:'isHidden', expectedType:Account };
    return cf;
}

Item Renderer:

public class ActionItemRenderer extends MXAdvancedDataGridItemRenderer 
{

protected var newBtn:Button;
protected var copyBtn:Button;
protected var deleteBtn:Button;

private var _buttonWidth:Number;
private var _buttonHeight:Number;

private var _layout:HorizontalLayout;
private var _expectedType:Class;


public function ActionItemRenderer() 
{
    super();
}


public function get buttonWidth():Number { return _buttonWidth ||= 18; }

public function set buttonWidth(value:Number):void { _buttonWidth = value; }

public function get buttonHeight():Number { return _buttonHeight ||= 18; }

public function set buttonHeight(value:Number):void { _buttonHeight = value; }

override protected function createChildren():void 
{
    super.createChildren();

    newBtn = new Button();
    newBtn.width = buttonWidth;
    newBtn.height = buttonHeight;
    newBtn.addEventListener(MouseEvent.CLICK, onProxyClick);
    newBtn.toolTip = 'New';
    newBtn.setStyle('icon', AssetManager.newItem);

    ...         
    validateLayout();
    addElement(newBtn);
}