8 Replies Latest reply on Jun 3, 2010 2:50 PM by okayperson

    custom itemRenderer component based on cell value: error 1009

    okayperson Level 1

      I'm working on an item renderer for a dataGrid that has different states depending on the cell and row values.

      The cell value is a toggle (true or null), and sets whether content should be shown in the cell or not

      The row properties determine what is shown when the cell value is true.

      The dataGrid dataProvider is populated based on user id input.

       

      I created the itemRenderer as a custom actionscript component, closely following this example:

      360Flex Sample: Implementing IDropInListItemRenderer to create a reusable itemRenderer

      However, my component results in Error #1009 (Cannot access a property or method of a null object reference) when a user id is submitted.

       

      package components
      {
           import mx.containers.VBox;
           import mx.controls.*;     import mx.controls.dataGridClasses.DataGridListData;
           import mx.controls.listClasses.BaseListData;
           import mx.core.*;
      
           public class toggleCellRenderer extends VBox
           {
                public function ToggleCellRenderer()
                {super();}
      
                private var _listData:BaseListData;    
                     private var cellState:String;
                     private var cellIcon:Image;
                     private var imagePath:String;
                     private var imageHeight:int;
                     private var qty:String = data.qtyPerTime;
                     private var typ:String = data.type;
      
                public function get listData():BaseListData
                     {return _listData;}
              
                public function set listData(value:BaseListData):void
                     {_listData = value;}
                   
                override public function set data(value:Object):void {
                     super.data = value;
                     if (value != null)
                     //errors on next line: Error #1009: Cannot access a property or method of a null object reference.
                     {cellState = value[DataGridListData(_listData).dataField]}
                     }
      
                override protected function createChildren():void {
                     removeAllChildren();
                     if(cellState=='true'){
                          cellIcon = new Image();
                          addChild(cellIcon);
                     }
                     //there is another state here that adds another child...
                }
                //next overrides commitProperties()...
           }
      

       

      There are no errors if I don't use an itemRenderer--the cells correctly toggle between "true" and empty when clicked.

      I also tried a simple itemRenderer component that disregards the cell value and shows in image based off row data--this works fine without errors or crashing. But I need to tie it to the cell value!

       

      I have very limited experience programming, in Flex or any other language. Any help would be appreciated.

        • 1. Re: custom itemRenderer component based on cell value: error 1009
          Cyril Hanquez Level 3

          Do you really need the  _listData variable? try

           

           

          package components
          {
               import mx.containers.VBox;
               import mx.controls.*;     import mx.controls.dataGridClasses.DataGridListData;
               import mx.controls.listClasses.BaseListData;
               import mx.core.*;
          
               public class toggleCellRenderer extends VBox
               {
                    public function ToggleCellRenderer()
                    {super();}
             
                         private var cellState:String;
                         private var cellIcon:Image;
                         private var imagePath:String;
                         private var imageHeight:int;
                         private var qty:String = data.qtyPerTime;
                         private var typ:String = data.type;
          
                       
                    override public function set data(value:Object):void {
                         super.data = value;
                         if (value != null)
                         //errors on next line: Error #1009: Cannot access a property or method of a null object reference.
                         {cellState = value[DataGridListData(this.listData).dataField]}
                         }
          
                    override protected function createChildren():void {
                         removeAllChildren();
                         if(cellState=='true'){
                              cellIcon = new Image();
                              addChild(cellIcon);
                         }
                         //there is another state here that adds another child...
                    }
                    //next overrides commitProperties()...
               }
          
          
          1 person found this helpful
          • 2. Re: custom itemRenderer component based on cell value: error 1009
            okayperson Level 1

            Thank you. That took care of the error, but I don't think I'm getting to each column this way.  I don't really understand the details of custom components so I had to rely on code I could find. I may not need _listData, but the itemRenderer doesn't seem to be working with the code you suggested.

             

            It's not throwing any errors with the suggested coed, but it's also not adding any images (even though some cells are set to "true" in the user xml file). So I added an alert to check what data was getting passed:

             override public function set data(value:Object):void {
                 super.data = value;
                 if (value != null){
                 cellState = value[DataGridListData(this.listData)];
                 Alert.show(data.displayName + ": "+ DataGridListData(this.listData) + "=" + cellState, "Testing", Alert.OK)
                 }
            

             

            I'm only getting 4 alerts, one for each row (4 unique displayNames), with the other data being "null=null" for all rows. This makes me think I"m not getting each cell value like I need. But as I mentioned I am venturing far beyond my comfort zone.

             

            Any thoughts?

            • 3. Re: custom itemRenderer component based on cell value: error 1009
              Cyril Hanquez Level 3

              Can you post an extract of your xml file? I'm also thinking that maybe the value is not null but just empty so you could test if ( value != '') instead.

              • 4. Re: custom itemRenderer component based on cell value: error 1009
                okayperson Level 1

                I tried switching it to test  if ( value != "") to the same result---the alert is still only popping up once for each row, not for each cell.

                It also enters the createChildren() function once per row, but [if (cellState=="true")] is always evaluating as false.

                 

                I looked at the documentation again (see Accessing the listData property), and so I tried using the following for the set data, but it results in the same error 1009 as the earlier code when user xml data is loaded both testing for (value != "") and (value != null).

                super.data = value;
                if (value !="") cellState = DataGridListData(this.listData).dataField;
                

                The alert I set to appear when xml user data finishes loading doesn't come up at all, but it's my understanding alerts pop up after all other code is executed, and so the error is blocking the alert even though the user data is loaded.

                 

                 

                Here's the dataGrid portion of the xml file. I wasn't sure what else (if anything) would be useful

                mx:DataGrid id="dgSchedule" rowHeight="42" 
                     creationComplete = "{setCols()}" itemClick="scheduleClickEvent(event);">
                     <mx:columns>
                     
                          <mx:DataGridColumn headerText="Row Name" dataField="displayName" visible="true" />
                
                          <mx:DataGridColumn dataField="400am" width="24" itemRenderer="components.toggleCellRenderer"/>
                          <mx:DataGridColumn dataField="430am" width="24" itemRenderer="components.toggleCellRenderer"/>
                          //a whole bunch more columns
                
                     </mx:columns>
                </mx:DataGrid>
                
                • 5. Re: custom itemRenderer component based on cell value: error 1009
                  Cyril Hanquez Level 3

                  Try the following code:

                   

                  package components
                  {
                       import mx.containers.VBox;
                       import mx.controls.*;    
                       import mx.controls.dataGridClasses.DataGridListData;
                       import mx.controls.listClasses.BaseListData;
                       import mx.core.*;
                  
                       public class toggleCellRenderer extends VBox
                       {
                            public function ToggleCellRenderer()
                            {
                             super();
                            }
                  
                            private var _listData:BaseListData;    
                            private var cellState:Boolean;
                            private var cellIcon:Image;
                            private var imagePath:String;
                            private var imageHeight:int;
                            private var qty:String = data.qtyPerTime;
                            private var typ:String = data.type;
                  
                               
                            override public function set data(value:Object):void {
                                 cellState = false;
                                 if (value != null){
                                     super.data = value;
                                     if (value[DataGridListData(this.listData).dataField] == "true"){
                                         cellState = true;
                               }
                                 }
                            }
                  
                            override protected function createChildren():void {
                                 removeAllChildren();
                                 if(cellState){
                                      cellIcon = new Image();
                                      addChild(cellIcon);
                                 }
                                 //there is another state here that adds another child...
                            }
                            //next overrides commitProperties()...
                       }
                  

                   

                  I changed:

                  - the cellState to a boolean.

                  - the test on value before the super.data = value

                   

                  I assume that your dataFile contains true (the String) or nothing, that's it?

                  • 6. Re: custom itemRenderer component based on cell value: error 1009
                    okayperson Level 1

                    Your assumption that the xml file either loads with "true" or nothing  is right.

                     

                    After modifying the code to the following, I don't get the error, but it's still not reading the cell value correctly.

                    package components
                    {
                         import mx.containers.VBox;
                         import mx.controls.*;    
                         import mx.controls.dataGridClasses.DataGridListData;
                         import mx.controls.listClasses.BaseListData;
                         import mx.core.*;
                    
                         public class toggleCellRenderer extends VBox
                         {
                              public function ToggleCellRenderer()
                              {
                               super();
                              }
                    
                              private var _listData:BaseListData;    
                              private var cellState:Boolean;
                              private var cellIcon:Image;
                              private var imagePath:String;
                              private var imageHeight:int;
                              private var qty:String;
                              private var typ:String;
                    
                               public function get listData():BaseListData
                                   {
                                 return _listData;
                                   }   
                                    
                              override public function set data(value:Object):void {
                                   cellState = false;
                                   if (listData && listData is DataGridListData && DataGridListData(listData).dataField != null){
                                       super.data = value;
                                       if (value[DataGridListData(this.listData).dataField] == "true"){
                                           cellState = true;
                                 }
                                   }
                              }
                    
                              override protected function createChildren():void {
                                   removeAllChildren();
                                   if(cellState==true){
                                        cellIcon = new Image();
                                        addChild(cellIcon);
                                   }
                                   //there is another state here that adds another child...
                              }
                              //next overrides commitProperties()...
                         }
                    
                    

                    - didn't set the value of qty or typ in the variable declarations (error 1009 by this too--I removed this before but wanted to point out in case its useful)

                    - added back in the get listData() function so I could use the listData

                    - changed the null check

                     

                     

                    All cells are still returning cellState = false when some are set to true, even if I comment out [if (value[DataGridListData(this.listData).dataField] == "true")] and just have it look for non-null data. That shouldn't make a difference anyway, but it confirms that all cells are returning null value.

                     

                    Swapping out the first if statement in set data with different variables results in the following:

                    [if (listData != null)]  all cells return null (cellState=false for all)

                    both [if (value != null)] and  [if (DataGridListData != null)]  results in error 1009 on a line following the if, so I assume they return non-null values.

                     

                    All rows have data, just not all fields in all rows, so shouldn't listData be non-null?  Could it be that the xml file hasn't fully loaded before the itemRenderer kicks in?

                     

                    I also realized  I had removed the item renderer from many of the columns for testing, and since some columns are hidden by default only one column in the view was using the itemRenderer--hence the single alert per row I was worried about earlier.

                     

                    Thanks for your help so far.

                    • 7. Re: custom itemRenderer component based on cell value: error 1009
                      Cyril Hanquez Level 3

                      How are you loading those datas? Can you load the content of the xml file into an ArrayCollection and bin this arrayCollection to the Datagrid?

                       

                      Please post a sample of your data (not the code, the xml file is it(s not confidential).

                      • 8. Re: custom itemRenderer component based on cell value: error 1009
                        okayperson Level 1

                        The HTTPService result function loads the xml data to an array, and also sets that array as the data provider in the same function.

                         

                        Here's the setup of the xml file (I made the data generic & truncated the number of rows, but the format is the same): 099.xml

                        //user data -- sample user 099
                        <userRows>
                          <userRow id="the_first_rows_id">
                             <displayName>The first row's id</displayName>
                             <qtyPerTime>1</qtyPerTime>
                             <type>StandardType1</type>
                             <numTimes>3</numTimes>
                             <details>• first line of detail
                        • second line of detail</details>
                             <1130am>true</1130am>
                          </userRow>
                        
                          <userRow id="the_second_rows_id">
                             <displayName>The second row's id</displayName>
                             <qtyPerTime>3</qtyPerTime>
                             <type>StandardType2</type>
                             <numTimes>2</numTimes>
                             <details>• 1st line of detail
                        • 2nd line of detail, some of these wrap to several rows
                        • 3rd line of detail</details>
                             <800am>true</800am>
                             <500pm>true</500pm>               
                           </userRow>
                        <userRows>