7 Replies Latest reply on Mar 28, 2011 9:29 PM by Flex harUI

    Flex datagrid custom itemEditor - not returning data

    newbie_dev

      Hi,

       

      I am new to flex and this is a basic "How to" question.

       

      I want to  write custom item editors and renderers for a datagrid column.

       

      I am facing two problems here

       

      1) override public function get data() : Object is not working. however, if the type of the column is just text then override public function get text():String is working. Specifying editorDataField in the datagrid column definition is working for some types ex:Strings, Numbers

       

      2) Nothing is working for slightly more complex types like an Image. even editorDataField is not working. Somewhere between the user editing the data (in the case of an image, edit = browse, select & load an image) and grid asking for data at itemEditEnd, the entire data loaded by the user is disappearing and it is returning null or some default value I'd set it to in override public function set data().

       

      I am aware that datagrid reuses both editors and renderers but I dono how the data user has set is getting lost while the focus is on the same cell

      I have tried to use getter setter for this custom data field mentioned in editorDataField but when I do so, nothing works.. it fails even for string type

       

      It should be a simple thing to do and I am sure I am making some silly mistake .. please help me out. It has driven me nuts since today morning..

       

      any pointers would be really appreciated.

        • 1. Re: Flex datagrid custom itemEditor - not returning data
          Flex harUI Adobe Employee

          The field specified by editorDataField is read and put into the property in

          the data item specified by the column's dataField.

           

          Let's say you have one item in the dataProvider

           

              dg.dataProvider = [ ];

           

          And two columns:

           

              dg.columns = [ new DataGridColumn("firstName"), new

          DataGridColmn("lastName") ];

           

          If you click on the lastName column, an editor is created and assigned the

          entire data item

           

              itemEditorInstance.data = dg.dataProvider[0]; //

           

          The editor can use the listData to see what column is being edited, or use

          the label, or be bound to the lastName property, and should show "Harui" and

          let it be edited.

           

          When done, because you are editing row 0, column 1, the column's default

          editorDataField is text, then the following will happen:

           

              dg.dataProvider[0][dg.columns[1].dataField] =

          itemEditorInstance[dg.columns[1].editorDataField]

           

          That is equivalent to:

           

              dg.dataProvider[0]["lastName"] = itemEditorInstance["text"];

           

          For complex renderers, make sure the property is properly implemented on the

          outer component.

           

          There's a good chance the forum will screw up most of the formatting in this

          message.

          • 2. Re: Flex datagrid custom itemEditor - not returning data
            newbie_dev Level 1

            Hi,

             

            thanks for the info. This is the understanding that I had after reading livedocs about item renderers.

             

            I have given the correct editorDataField and dataField. But it isnt working..I am not sure what you mean by For complex renderers, make sure the property is properly implemented on the outer component.

             

             

            The weird part is specifying editorDataField works for String and not for an image.  I am pasting some of code (highlighting relevant parts) below.. please have a look and tell me what I am missing.

             

            Datagrid :

            <mx:DataGrid id="dg" editable="true" rowHeight="100" width="861" x="10" y="10" height="498"
                             dataProvider="{this.slideArray}">
                    <mx:columns>
                        <mx:DataGridColumn headerText="Text" width="100"
                                           resizable="true" sortable="false"
                                           itemRenderer = "mx.controls.Label"
                                           itemEditor="editors.TextEditor"
                                           dataField="text" editorDataField="myData"/>


                        <mx:DataGridColumn headerText="Image" width="600" resizable="true" sortable="false"
                                           itemRenderer="mx.controls.Image"
                                           itemEditor="editors.ImageEditor"
                                           dataField="image" editorDataField="myData"/>           
                    </mx:columns>
                </mx:DataGrid>

             

            Text editor :

            <?xml version="1.0" encoding="utf-8"?>
            <s:MXDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
                                      xmlns:s="library://ns.adobe.com/flex/spark"
                                      xmlns:mx="library://ns.adobe.com/flex/mx"
                                      focusEnabled="true"
                                      initialize="initEditor()">

             

                <mx:TextInput id="edit" width="{this.width}" height="{this.height}"/>
               
                <fx:Script>
                    <![CDATA[
                        import domain.Slide;  // has two properties : public  var text : String and public var image : mx.controls.Image;
                       
                        override public function set data(value:Object):void{
                            super.data = value;
                            this.edit.text = (value as Slide).text;
                        }

                       
                        public var myData : String; // editor data field
                       
                        import mx.binding.utils.BindingUtils;
                       
                        private function initEditor():void{
                            BindingUtils.bindProperty(this,"myData", this.edit, "text");
                        }
                    ]]>
                </fx:Script>
            </s:MXDataGridItemRenderer>

             

            ImageEditor :

            <?xml version="1.0" encoding="utf-8"?>
            <s:MXDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
                                      xmlns:s="library://ns.adobe.com/flex/spark"
                                      xmlns:mx="library://ns.adobe.com/flex/mx"
                                      width="100%" height="100%"
                                      focusEnabled="true" contentBackgroundColor="#F1B4B4">

                <mx:Image id="img" x="0" y="0" width="200" height="200" />

             

                <s:Button label="Click to Add Image" id="addImageButton" click="addImageButton_clickHandler(event)"
                          x="0" y="{this.height - addImageButton.height}"/>
               
                <fx:Script>
                    <![CDATA[
                        import domain.Slide;
                       
                        public var myData : Image; //editor data field
                       
                        override public function set data(value:Object):void{
                            super.data = value;
                            if( (value as Slide).image != null) this.img.source = (value as Slide).image.source;
                        }

                       
                        protected function addImageButton_clickHandler(event:MouseEvent):void
                        {
                            // select image from file system
                            var imgFilter : FileFilter = new FileFilter("Images","*.jpg;*.png;*.gif");
                            var fileRef : FileReference = new FileReference();
                           
                            fileRef.addEventListener(Event.SELECT, fileSelectHandler);
                            fileRef.addEventListener(Event.OPEN, fileOpenHandler);
                            fileRef.addEventListener(Event.CANCEL, fileCancelHandler);
                           
                            fileRef.browse([imgFilter]);
                           
                            function fileRefSelectListenerUp(e:Event):void{}
                        }
                       
                        private function fileSelectHandler(event : Event):void{
                            var fileRef : FileReference = event.target as FileReference;
                            fileRef.addEventListener(Event.COMPLETE, fileLoadHandler);
                            fileRef.load();
                        }
                       
                        private function fileLoadHandler(event : Event) : void{
                            var fileRef : FileReference = event.target as FileReference;
                           
                            this.myData = new Image;
                            this.myData.name = fileRef.name;
                            this.myData.source = fileRef.data;
                            this.img.source = fileRef.data;

                        }
                       
                        private function fileOpenHandler(event : Event):void{}           
                        private function fileCancelHandler(event : Event):void{}
                       
                       
                       
                    ]]>
                </fx:Script>
               
            </s:MXDataGridItemRenderer>

            • 3. Re: Flex datagrid custom itemEditor - not returning data
              Flex harUI Adobe Employee

              MyData is of type Image which is a UI component.  I doubt that your data

              structure contains references to UI components.  What does it really want?

              The name of a file?  The bitmapData?

              • 4. Re: Flex datagrid custom itemEditor - not returning data
                newbie_dev Level 1

                By data structure you mean Slide? It has a property called image which  is of type mx.controls.Image. It is not a very good option to use a UI  component to hold data but I need a lot of info about an image file -  the bitmap data, filename, creation - modification date and so on.

                 

                I tried to send just the name or just the bitmap data .. but those dint work either.

                 

                While  debugging, I saw that after selecting the  required file, doPhasedInstantiationCallBack method of LayoutManager is invoked.  This happens irrespective of what data (filename, bitmapdata etc) that I  choose.

                 

                Following is the sequence of methods invoked.

                1. file browse, file load & file load complete handler - break points set by me.
                2. Here I load the necessary info from the filereference to my editor's properties
                  1. Immediately after the load complete handler, this doPhasedInstantiationCallBack method is invoked.

                  I am unable to understand why it is being called.

                   

                  a similar thing happened when I tried to get just the filename and not the entire image file bitmap data. callLaterDispatcher is called after load handler.

                   

                  In this image editor, I replaced the image UI component (placed before the button in mxml) in the ImageEditor to TextInput.

                   

                  1. The text of this TextInput component is set to the filename in the load complete handler.
                  2. Here while debugging I saw that the filename is being put correctly into the text property and
                  3. after handler returns the applicaiton is running
                  4. immediately after the I switch to the web browser i.e; focus returns to the application running in flash player (in web browser) callLaterDispatcher method of UIComponent is invoked for this TextInput component.
                  5. And here, the event type is "render" and target is "flash.display.stage" and the text field has lost the filename updated in the handler!!!!!
                  6. This method keeps getting invoked everytime I switch focus to the flash player. I mean when the debugger breaks at this method, I step over all the statements (F6) and at the end of method the debugger shows the application is running. And I switch to the applicaiton in browser and debugger hits this method again and this goes on till I hit resume (F8) instead of stepping over.


                  Now, I have absolutely now idea as to why this should happen only after a file browse. It doesnt seem to happen if I type something into the text input and change its text field by typing. But if the text field does change in the load handler, this callLaterDispatcher comes in and all the updates made are lost.

                  • 5. Re: Flex datagrid custom itemEditor - not returning data
                    Flex harUI Adobe Employee

                    I would suggest that you simply implement the fields you need instead of

                    using mx:Image to hold data values.

                     

                    Please provide the data structure you are using the in the dataProvider.

                     

                    It appears that it has a text property, which is probably a String, but you

                    are using myData as the editorDataField which is not a String.  Remember,

                    the assignment is going to look like:

                     

                       dg.dataProvider[0]["text"] = itemEditorInstance["myData"];

                     

                    If you assign the wrong thing to your dataProvider item, then when the

                    renderer tries to display the new value of text, it probably won't.

                     

                    -Alex

                    • 6. Re: Flex datagrid custom itemEditor - not returning data
                      newbie_dev Level 1

                      okie I shall try as you suggest and will post the entire project.. oh btw, how do I send an attachment? I want to zip the entire project and send.. it'll be better than pasting parts of code I think are relevant.

                      • 7. Re: Flex datagrid custom itemEditor - not returning data
                        Flex harUI Adobe Employee

                        Do not post the entire project.  I will not have time to look at it.  Reduce

                        it down to 20 lines we can cut, paste and run.   That will eliminate

                        side-effects.