Search code examples
actionscript-3flash-cs4flash-v3-components

Datagrid Cell render with custom component


A few hours ago I've asked how to create a custom component (textInput and label component and created a Component Definition) and with your answers I can do that now.

Problem 2: I'd like to use that component in a datagrid column so that the user can type a value in the textInput which will in turn update the underlying dataprovider. I know I should use a cellrenderer like I've done with a checkbox column (also with help on the Net), but at this stage I'm only pulling my hair out. Please help.


Solution

  • This might look messy as it's a modified example.

    Make sure you have the DataGrid, Label and TextInput components in the library of the fla you want to try this:

    // Import the required component classes.
    import fl.controls.DataGrid;
    import fl.controls.dataGridClasses.DataGridColumn;
    import fl.data.DataProvider;
    //get some data ready, notice data and label
    var dp:DataProvider = new DataProvider();
    for(var i:int = 0 ; i < 7; i++)
        dp.addItem({data:'input '+(i+1),label:'label '+(i+1), title:"item " + (i+1)});
    var dataCol:DataGridColumn = new DataGridColumn("data");
    dataCol.cellRenderer = CustomCell;
    var titleCol:DataGridColumn = new DataGridColumn("title");
    
    var myDataGrid:DataGrid = new DataGrid();
    myDataGrid.addColumn(dataCol);
    myDataGrid.addColumn(titleCol);
    myDataGrid.dataProvider = dp;
    myDataGrid.rowHeight = 64;
    myDataGrid.width = 500;
    myDataGrid.rowCount = dp.length - 1;
    myDataGrid.move(10, 10);
    myDataGrid.editable = true;
    addChild(myDataGrid);
    

    And the CustomCell class looks like this:

    package {
        // Import the required component classes.
        import fl.controls.listClasses.ICellRenderer;
        import fl.controls.listClasses.ListData;
        import fl.controls.Label;
        import fl.controls.TextInput;
        import fl.core.InvalidationType;
        import fl.core.UIComponent;
        import fl.data.DataProvider;
        import flash.display.Sprite;
        import flash.events.Event;
    
        public class CustomCell extends UIComponent implements ICellRenderer {
            protected var _data:Object;
            protected var _listData:ListData;
            protected var _selected:Boolean;
            //the custom components
            private var labelComponent:Label;
            private var inputComponent:TextInput;
            /**
             * Constructor.
             */
            public function CustomCell():void {
                super();
                init();
            }
            /**
             * Draws the Label and TextInput components
             */
            private function init():void{
                labelComponent = new Label();
                labelComponent.autoSize = 'right';
                inputComponent = new TextInput();
                inputComponent.editable = true;
    
                addChild(labelComponent);
                addChild(inputComponent);
                inputComponent.x = labelComponent.width + 5;//5 pixels distance between components
                inputComponent.drawFocus(true);
            }
    
            public function get data():Object {
                return _data;
            }
            /** 
             * @private (setter)
             */
            public function set data(value:Object):void {
                _data = value;
                //there's label data, update the label
                if(_data.label) labelComponent.text = _data.label;
                //there's data for the input, update that too
                if(_data.data) inputComponent.text = _data.data;
            }
    
            public function get listData():ListData {
                return _listData;
            }
            public function set listData(value:ListData):void {
                _listData = value;
                invalidate(InvalidationType.DATA);
                invalidate(InvalidationType.STATE);
            }
            public function get selected():Boolean {
                return _selected;
            }
            public function set selected(value:Boolean):void {
                _selected = value;
                invalidate(InvalidationType.STATE);
            }
            public function setMouseState(state:String):void {
            }
    
        }
    }
    

    The code mostly comes from this devnet article.

    It works ok, as in, it's editable.

    Solution is be a component class(a class extending fl.core.UIComponent), implementing the ICellRender interface so it can be set as a renderer, and containing the Label and TextInput components. Also data will be mapped to TextInput.text, so it can be easily edited.

    If DataGrid is a bit bloated, and you want to use the Component Definition or something simpler. I guess you can hack together a solution using a List and setting a custom cellRenderer using styles. I'm guessing custom clips are used as a cell renderer in the Plugins list on the tweenlite page.

    HTH, George