6 Replies Latest reply on Jun 22, 2009 7:13 AM by rtalton

    Using data contained in an event.

    markFuqua

      I am trying to understand how to use data from an event to set the selectedIndex of a comboBox.  If I hardcode the number 4 as it is in the example A below, the fuction sets the selectedIndex correctly.  When I run the debugger, the data (4) is under event.itemRenderer.data.ConstructionPhase.  However, if I try example B or C, Flex builder gives an error....example D gives no error in flex builder but then does when run.  Help please, how do i get the value out of the event for use in the function?

       

      Example A (this works, but can't very well hardcode the value!!):

       

      private function fillInForm(event:Event):void {
                      openAddForm();
                      addEditItem.label = "Edit";
                      for (var i:int = 0; i < ConstructionPh.dataProvider.length; i++) {

       

                       if (ConstructionPh.dataProvider[i].ConstructionPhaseId == 4) {

       

                        ConstructionPh.selectedIndex = i;
                      break;
                   }

       

                  }
              }

       

      Example B (Error message in flexbuilder ="1119: Access of possibly undefined property itemRenderer through a reference with static type flash.events.Event")

       

      private function fillInForm(event:Event):void {
                      openAddForm();
                      addEditItem.label = "Edit";
                      for (var i:int = 0; i < ConstructionPh.dataProvider.length; i++) {

       

                       if (ConstructionPh.dataProvider[i].ConstructionPhaseId == event.itemRenderer.data.ConstructionPhase) {

       

                        ConstructionPh.selectedIndex = i;
                      break;
                   }

       

                  }
              }

       

      Example C (Error message in flexbuilder ="1120: Access of undefined property itemRenderer")

       

      private function fillInForm(event:Event):void {
                       openAddForm();
                       addEditItem.label = "Edit";
                       for (var i:int = 0; i < ConstructionPh.dataProvider.length; i++) {

       

                       if (ConstructionPh.dataProvider[i].ConstructionPhaseId == itemRenderer.data.ConstructionPhase) {

       

                        ConstructionPh.selectedIndex = i;
                       break;
                    }

       

                  }
               }

       

      Example D (no error message in flexbuilder, but the following when run...Type Error:Error #1009: Cannot access a property or method of a null object reference)

       

      private function fillInForm(event:Event):void {
                       openAddForm();
                       addEditItem.label = "Edit";
                       for (var i:int = 0; i < ConstructionPh.dataProvider.length; i++) {

       

                       if (ConstructionPh.dataProvider[i].ConstructionPhaseId == data.ConstructionPhase) {

       

                        ConstructionPh.selectedIndex = i;
                       break;
                    }

       

                  }
               }

       

      How do i get the value out of the event?  When I run the debugger with a line break at the start of the function, it is under event.itemRenderer.data.ConstructionPhase...how do i reference it?????

       

      Thanks a lot,

       

      Mark

        • 1. Re: Using data contained in an event.
          rtalton Level 4

          You shouldn't attempt accessing data through an itemRenderer.

          Where is this function: fillInForm(event:Event) being called from; what kind of component is throwing the Event? Does this component share the same dataprovider as the combo box? Do you have a sample of the dataprovider?

          • 2. Re: Using data contained in an event.
            markFuqua Level 1

            thanks for the reply.  The event is coming from a datagrid item click.  The datagrid has a VO that has the data i need to set the selectedIndex for four comboBoxes.  All the comboBoxes are already populated and when the user clicks on a row of the data grid, I want to set the textFields (easy...got that one) and the combo boxes to the values in that row.  Please excuse some of the slop...this is my first app.  Below is the entire thing.  Right now, setting the value of the comboBoxes for the edit function is really hanging me up.  The event has the data i want...just can't figure out how to access it.

             

            thanks

             

             

            <?xml version="1.0" encoding="utf-8"?>
            <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
                layout="vertical" applicationComplete="init()">
                <mx:Label text="Database of Estimate Items" fontSize="18">
                   
                </mx:Label>
               
                <mx:Script>
                <![CDATA[
                    import mx.rpc.events.ResultEvent;
                    import mx.collections.ArrayCollection;
            //the following vars are for remote object tags below
                    [Bindable]
                    private var acEstimatesFixedItems:ArrayCollection;
                    [Bindable]
                    private var acJobType:ArrayCollection;
                    [Bindable]
                    private var acConstructionPhases:ArrayCollection;
                    [Bindable]
                    private var acItemType:ArrayCollection;
                    [Bindable]
                    private var acDefaultUnitType:ArrayCollection;
                   
                    private var EstimateItem:EstimatesFixedItems;
               
                   
            //at start-up populates the datagrid and the four comboboxes
                private function init():void
                {
                    EstimatesFixedItemsGateway.getAll();
                    JobEstTypeGateway.getAll();
                    ContructionPhasesGateway.getAll();
                    ItemTypeGateway.getAll();
                    DefaultUnitTypeGateway.getAll();
                }
                   
                           
            //the following functions are for handling the result events from remote objects
                    private function resultHandler(event:ResultEvent):void
                    {
                        acEstimatesFixedItems = new ArrayCollection(
                        event.result as Array)
                    }
                    private function jobTypeResultHandler(event:ResultEvent):void
                    {
                        acJobType = new ArrayCollection(
                        event.result as Array)
                    }
                    public function ConstructionPhasesResultHandler(event:ResultEvent):void
                    {
                        acConstructionPhases = new ArrayCollection(
                        event.result as Array)
                    }
                   
                    private function ItemTypeResultHandler(event:ResultEvent):void
                    {
                        acItemType = new ArrayCollection(
                        event.result as Array)
                    }
                   
                    private function DefaultUnitTypeResultHandler(event:ResultEvent):void
                    {
                        acDefaultUnitType = new ArrayCollection(
                        event.result as Array)
                    }
                   
                    private function openAddForm():void
                    {
                        AddForm.height = 250;
                        AddForm.width = 700;
                    }
                   
            //called when item clicked in datagrid       
                //    private function editItemInsertHandler():void
                    //{
                        //openAddForm();
                        //addEditItem.label = "Edit";
                        //ConstructionPh.selectedItem.ConstructionPhaseId = dg.selectedItem.ConstructionPhase;
                       
                        //ConstructionPh.selectedItem = dg.selectedItem.ConstructionPhase;
                       
                        //ItemName.text = dg.selectedItem.ItemName;
                //    }
                    private function fillInForm(event:Event):void {
                            openAddForm();
                            addEditItem.label = "Edit";
                            for (var i:int = 0; i < ConstructionPh.dataProvider.length; i++) {

             

                             if (ConstructionPh.dataProvider[i].ConstructionPhaseId == data.ConstructionPhase) {

             

                              ConstructionPh.selectedIndex = i;
                            break;
                         }

             

                        }
                    }
                   
                    private function addEditItemInsertHandler():void
                    {
                        var dataEstimateFixedItem:EstimatesFixedItems = new EstimatesFixedItems();
                           
                           
                           
                            dataEstimateFixedItem.ConstructionPhase = ConstructionPh.selectedItem.ConstructionPhaseId;
                            dataEstimateFixedItem.JobEstimateType = JobEstimateType.selectedItem.JobTypeId;
                            dataEstimateFixedItem.ItemType = ItemType.selectedItem.ItemTypeId;
                            dataEstimateFixedItem.DefaultUnitType = DefaultUnitType.selectedItem.DefaultUnitTypeId;
                            dataEstimateFixedItem.ItemName = ItemName.text;
                            dataEstimateFixedItem.ItemDescription= ItemDescription.text;
                            //dataEstimateFixedItem.PricePerUnit = PricePerUnit.text;
                           
                   
                        EstimatesFixedItemsGateway.save(dataEstimateFixedItem);
                        AddForm.height = 5;
                       
                       
                    }
                    private function addEditItemResultHandler():void
                    {
                       
                    }
                   
                   
                           
                ]]>
            </mx:Script>

             

            <mx:RemoteObject id="JobEstTypeGateway" destination="ColdFusion"
                source="Estimate.cfcs.JobEstTypeGateway"   showBusyCursor="true">
                <mx:method name="getAll" result="jobTypeResultHandler(event)"/>
                <mx:method name="save" result="addEditItemResultHandler()"/>

             

            </mx:RemoteObject>
            <mx:RemoteObject id="ContructionPhasesGateway" destination="ColdFusion"
                 source="Estimate.cfcs.ConstructionPhasesGateway" result="ConstructionPhasesResultHandler(event)"
                  showBusyCursor="true"/>
            <mx:RemoteObject id="EstimatesFixedItemsGateway" destination="ColdFusion"
                  source="Estimate.cfcs.EstimatesFixedItemsGateway" result="resultHandler(event)"
                    showBusyCursor="true"/>
            <mx:RemoteObject id="ItemTypeGateway" destination="ColdFusion"
                     source="Estimate.cfcs.ItemTypeGateway" result="ItemTypeResultHandler(event)"
                      showBusyCursor="true"/>
            <mx:RemoteObject id="DefaultUnitTypeGateway" destination="ColdFusion"
                     source="Estimate.cfcs.DefaultUnitTypeGateway" result="DefaultUnitTypeResultHandler(event)"
                      showBusyCursor="true"/>
               
            <mx:Panel>

             

            <mx:Panel title="To Edit or delete an item, double click that item." height="75%" width="100%"
                    paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10">
            <mx:HBox>
                <mx:Button id="addEdit" click="openAddForm()" label="Add New Item to Database"/>
                <mx:Button id="refresh" click="openAddForm()" label="Refresh Database View"/>
            </mx:HBox>
            </mx:Panel>

             

            <mx:Form  id="AddForm"  height="10">
                <mx:FormHeading id="addFormLabel" label="Add New Item to Database."/>
                    <mx:HBox>
                        <mx:FormItem label="Job Type">
                             <mx:ComboBox id="JobEstimateType" dataProvider="{acJobType}" labelField="JobType"/>
                        </mx:FormItem>
                        <mx:FormItem label="Job Phase">
                            <mx:ComboBox id="ConstructionPh"  dataProvider="{acConstructionPhases}" labelField="ConstructionPhaseDes"/>
                        </mx:FormItem>
                    </mx:HBox>
                    <mx:HBox>
                        <mx:FormItem label="Item Type">
                            <mx:ComboBox id="ItemType" dataProvider="{acItemType}"  labelField="ItemTypeDes"/>
                        </mx:FormItem>
                        <mx:FormItem label="Default Unit Type">
                            <mx:ComboBox id="DefaultUnitType"  dataProvider="{acDefaultUnitType}" labelField="DefaultUnitTypeDes"/>
                        </mx:FormItem>
                    </mx:HBox>
                    <mx:HBox>
                        <mx:FormItem label="Item Title">
                            <mx:TextInput id="ItemName"/>                     
                        </mx:FormItem>
                        <mx:FormItem label="Description">
                            <mx:TextArea id="ItemDescription"/>
                        </mx:FormItem>
                    </mx:HBox>
                    <mx:FormItem label="Price Per Unit">
                        <mx:TextInput id="PricePerUnit" width="40"/>
                    </mx:FormItem>
                    <mx:FormItem>
                        <mx:Button id="addEditItem" label="add" click="addEditItemInsertHandler()"/>
                    </mx:FormItem>
               
               
            </mx:Form>

             

             

             

            <mx:DataGrid id="dg" dataProvider="{acEstimatesFixedItems}" variableRowHeight="true"
                 itemClick="fillInForm(event)">
                <mx:columns>
                    <mx:DataGridColumn headerText="Job Type" dataField="JobType"/>
                    <mx:DataGridColumn headerText="Job Phase" dataField="ConstructionPhaseDes"/>
                    <mx:DataGridColumn headerText="Item Type" dataField="ItemTypeDes"/>
                     <mx:DataGridColumn headerText="Item Name" dataField="ItemName" />
                     <mx:DataGridColumn headerText="Description" width="200" wordWrap="true"
                          dataField="ItemDescription" />
                       <mx:DataGridColumn headerText="Unit" dataField="DefaultUnitTypeDes" width="50"/>
                       <mx:DataGridColumn headerText="Price" dataField="PricePerUnit" width="50"/>
                  </mx:columns>

             

            </mx:DataGrid>
                
            </mx:Panel>

             

             

             

            </mx:Application>

            • 3. Re: Using data contained in an event.
              rtalton Level 4

              Cool. From what I can see, you need to find a record in the ComboBox based on a

              shared value in the DataGrid record. So in a nutshell, you're screwed.

               

              No, no, just kidding! It's Friday and I'm looking forward to the weekend. And you

              will be too, after you see the solution to your problem!

               

              Answer: Search through your ComboBox's data provider for the value in the

              DataGrid's selectedItem. Then set the ComboBox's selectedItem accordingly.

              So the trick is to then assign an OBJECT from the dataprovider to the ComboBox's

              selectedItem property. Voila! Don't bother with the selectedIndex, and no looping

              needed.

               

              Oh, and another thing: when working with the DataGrid, you want to use the

              ListEvent, not the plain ol' Event you were using. The ListEvent contains the

              selectedItem object from the data provider; just what we need for this method.

               

              Oh, what? Not clear enough? OK. Let's get this party started...


              There are two things you have to remember to accomplish this:
              1) To search an Array Collection, you must create a Cursor. Just like a database.
              2) The Array Collection must be sorted before searching it. Required!

               

              OK, here's an example I want you to try. Not knowing what your data looks like, I

              had to fake it, so please excuse my laughable attempts at creating typical data

              that might be used in your industry.

               

              Notes:
              a) Sorting and searching does take time on large datasets. But so does looping,

              which is what you were doing.

              b) You should return the ComboBox to its "unsorted" state after sorting and

              searching on the desired field, otherwise the user will see a different sort

              order whenever she opens it.

               

              This example accomplishes all of the above. Enjoy!
              //***************************************************
              <?xml version="1.0" encoding="utf-8"?>
              <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
              <mx:Script>
                  <![CDATA[
                      import mx.events.ListEvent;
                      import mx.collections.ArrayCollection;       
                      import mx.collections.SortField;
                      import mx.collections.Sort;
                      import mx.collections.IViewCursor;
                     
                      //Data provider for the ComboBox:       
                      [Bindable]
                      public var acConstructionPhases:ArrayCollection = new ArrayCollection([
                      {label:"In Progress", data:"1", idx:0},
                      {label:"Delayed", data:"2", idx:1},
                      {label:"On Track", data:"3", idx:2},
                      {label:"Cancelled", data:"4", idx:3},
                      {label:"Completed", data:"5", idx:4},
                      {label:"Billed", data:"6", idx:5},
                      ]);
                     
                      //Data provider for the DataGrid:
                      [Bindable]
                      public var acEstimatesFixedItems:ArrayCollection = new ArrayCollection([
                      {JobType:"Kitchen remodel", ConstructionPhaseDes:"1"},
                      {JobType:"Bathroom remodel", ConstructionPhaseDes:"4"},
                      {JobType:"Garage demolition", ConstructionPhaseDes:"5"},
                      {JobType:"Landscaping", ConstructionPhaseDes:"2"},
                      {JobType:"Roof replacement", ConstructionPhaseDes:"6"},
                      ]);
                             
                      private var cursor:IViewCursor;
                      public var sortConstPhaseData:String;//Used to determine the sort field
                             
                      //These function sort the ComboBox data provider.
                      //Nore that the data provider uses the 'idx' field for one of the sorts.
                      //This allows me to get it back to the "natural", "unsorted" order
                      //that I want the values to appear in the ComboBox.
                      public function sortacConstructionPhases():void{
                          //Sort on the 'data' field.
                          var sortAC:Sort = new Sort();
                          sortAC.fields = [new SortField('data')];
                          acConstructionPhases.sort = sortAC;
                          acConstructionPhases.refresh();
                          //This var stores what field we sorted on:
                          sortConstPhaseData = 'data';
                      }
                      public function unsortacConstructionPhases():void{
                          //Sort on the 'idx' field.  DEFAULT.
                          var sortAC:Sort = new Sort();
                          sortAC.fields = [new SortField('idx')];
                          acConstructionPhases.sort = sortAC;
                          acConstructionPhases.refresh();
                          //This var stores what field we sorted on:
                          sortConstPhaseData = 'idx';
                      }       
                      public function syncComboBoxToDataGrid(event:ListEvent):void{
                          //Called by click on a DataGrid row.
                          //First, sort the ComboBox array (must be done prior to cursor

              search):
                          if (sortConstPhaseData != 'data'){
                              sortacConstructionPhases();
                          }
                          //get the currently selected item's ConstructionPhaseDes value:
                          var phaseDes:String = event.target.selectedItem.ConstructionPhaseDes;
                          //Put that into an Object:
                          var ConstructionPhSearchObject:Object = {data:phaseDes};
                          //Create a search cursor on the ComboBox's DataProvider:
                          cursor = acConstructionPhases.createCursor();
                          //Search for the Object within the ComboBox's DataProvider:
                          var phaseFound:Boolean =

              cursor.findFirst(ConstructionPhSearchObject);
                          if (phaseFound){//If the value was found...
                              //Found; assign the found object data to the ConstructionPh

              ComboBox.
                              //This will assure the displayed value matches the selected data.
                              var constructionPhFoundObject:Object = cursor.current;
                              ConstructionPh.selectedItem = constructionPhFoundObject;
                          }
                          //Now, return the ComboBox to its 'unsorted', initial state:
                          unsortacConstructionPhases();
                                  
                      }      
                      private function setComboBoxIndex(event:ListEvent):void{
                          ConstructionPh.selectedItem = event.target.selectedItem;
                          trace();
                      }
                  ]]>
              </mx:Script>   
                      <mx:ComboBox id="ConstructionPh"
                         dataProvider="{acConstructionPhases}"
                         labelField="label"
                         prompt="select one..."
                         width="244"
                         dropdownWidth="200"
                         fontWeight="normal"
                         x="158" y="50">
                          </mx:ComboBox>
                     
                      <mx:DataGrid dataProvider="{acEstimatesFixedItems}" x="58" y="137"

              width="396"
                          itemClick="syncComboBoxToDataGrid(event)" >
                      </mx:DataGrid>
              </mx:Application>

              //***************************************************

              • 4. Re: Using data contained in an event.
                markFuqua Level 1

                Looking at your answer gives me great hope...however, I just got the message and it is 9:30 on Friday night...I've had three beers and my brain is even more foggy than usual.  I'll look tomorrow...thank you very, very, very much.

                • 5. Re: Using data contained in an event.
                  markFuqua Level 1

                  Don't know if it was the right way or a hack, but it worked!  Used the info you gave me...changing the event type and using event.target.selectedItem...but I couldn't figure out some of the rest of what you suggested, so I just created four functions to loop the four different combo boxes like so (the first function just call the others):

                   

                   

                  //This function fills in the edit form...uses four function below for comboboxes
                          private function fillInForm(event:ListEvent):void {
                                  openAddForm();
                                  addEditItem.label = "Edit";
                                  public var editId:Number = event.target.selectedItem.EstFixedItems;
                                  setIndexConstructionPhase(event);
                                  setIndexDefaultUnitType(event);
                                  setIndexItemType(event);
                                  setIndexJobType(event);
                                  ItemName.text = event.target.selectedItem.ItemName;
                                  ItemDescription.text = event.target.selectedItem.ItemDescription;
                                  PricePerUnit.text = event.target.selectedItem.PricePerUnit;
                                  addFormLabel.label = "Edit an Existing Item";
                          }
                         
                      //The following functions set the selectedIndex for the comboBoxes for edit operation
                     
                          private function setIndexConstructionPhase(event:ListEvent):void{
                                  //Get correct selected index for constructionPhase comboBox
                                  var phaseDes:int = event.target.selectedItem.ConstructionPhase;
                                  for (var i:int = 0; i < ConstructionPh.dataProvider.length; i++) {
                                       if (ConstructionPh.dataProvider[i].ConstructionPhaseId == phaseDes) {
                                            ConstructionPh.selectedIndex = i;
                                          break;
                                       }
                                  }
                              }
                         
                          private function setIndexDefaultUnitType(event:ListEvent):void{
                                  //Get correct selectedIndex for defaultUnitType
                                  var defaultUnit:int = event.target.selectedItem.DefaultUnitType;
                                  for (var i:int = 0; i < DefaultUnitType.dataProvider.length; i++) {
                                       if (DefaultUnitType.dataProvider[i].DefaultUnitTypeId == defaultUnit) {
                                            DefaultUnitType.selectedIndex = i;
                                          break;
                                       }
                                  }
                              }
                         
                          private function setIndexItemType(event:ListEvent):void{
                                  //Get correct selectedIndex for defaultUnitType
                                  var itemType:Number = event.target.selectedItem.ItemType;
                                  for (var i:int = 0; i < DefaultUnitType.dataProvider.length; i++) {
                                       if (ItemType.dataProvider[i].ItemTypeId == itemType) {
                                            ItemType.selectedIndex = i;
                                          break;
                                       }
                                  }
                              }
                          private function setIndexJobType(event:ListEvent):void{
                              //Get correct selectedIndex for JobType
                              var jobType:Number = event.target.selectedItem.JobEstimateType;
                              for (var i:int = 0; i < JobEstimateType.dataProvider.length; i++) {
                                  if (JobEstimateType.dataProvider[i].JobTypeId == jobType) {
                                      JobEstimateType.selectedIndex = i;
                                      break;
                                  }
                              }
                          }

                   

                  Thanks a bunch for the help!

                   

                  Mark

                  • 6. Re: Using data contained in an event.
                    rtalton Level 4

                    Great, you got it! No, I wouldn't call this a hack. It works well.

                    You're setting the selectedIndex prop of the ComboBox by looking at the ListEvent to get the selectedItem of the DataGrid; this is waaaay better than accessing the itemRenderer, as the first version of your code did. You saved yourself a lot of possible heartache in the future with the ever-changing itemRenderers. Using your method, you technically don't even need to access the event object for this property-you could just look directly at the dataGrid itself for it (myDataGrid.selectedItem).

                    Three things:

                    1) Take a look into the Cursor function of the ArrayCollection. You will eventually need to use this method, as opposed to sorting, and it provides much more flexibility than looping does.

                    2) The Sort function is another goodie when you need to change things in the view.

                    3) Stop working on Sundays! hah!

                     

                    Great work!