12 Replies Latest reply on Mar 4, 2010 12:55 PM by ehusar

    How to Cycle Through ArrayCollection?

    ehusar Level 1

      I have two datagrids and would like to move items from on datagrip and populate the other.  Here is a screen shot for a visual.

       

      Picture 1.png

      In the screenshot about I can add names/sex to the datagrid on the left by using the text entry and Add button.  I can select the check boxes for each name ros as well. What I want to do is move the check names in the datagrid on the left to the datagrid on the right.  4 max.  But if I only selected 2 name, two names would be added to the Racer 1 and Racer 2. Racer 3 and Race 4 would be left empty.  If I check new names and submitted them it would go into a new row on the left datagrid.

       

      What I can figure out is how to cycle through the left datagrid and find only the check rows.  Adding them to the right datagrid is easy enough as soon as I figure how to identify what is checked and what is not checked.

       

      Here is the datagrid on the right.

       

      <mx:DataGrid x="10" y="76" height="337" id="roster" editable="false" dataProvider="{rosterArray}">

      <mx:columns>

      <mx:DataGridColumn headerText="" width="30">

         <mx:itemRenderer>

            <mx:Component>

               <mx:CheckBox />

            </mx:Component>

         </mx:itemRenderer>

      </mx:DataGridColumn>

       

      <mx:DataGridColumn headerText="Name" dataField="name" width="200" editable="false" />

      <mx:DataGridColumn headerText="Sex" dataField="sex" width="40" editable="false" />

      <mx:DataGridColumn headerText="Time" dataField="time" width="45" editable="false" />

      </mx:columns>

      </mx:DataGrid>

       

       

      The function to add to my rosterArray (left datagrid) is below.

       

      private function rosterAdd():void

      {

           rosterArray.addItem({name:addName.text,sex:sexGroup.selectedValue.toString()});

           addName.text = ""; // empty the text entry field.

      }

       

      I guess I need to cycle through the datagrid and not the rosterArray since I don't have a place for the check marks in the rosterArray.

       

      Any help idetifying what rows are checked in the left data grid would be much appreciated.

       

      Thanks.

        • 1. Re: How to Cycle Through ArrayCollection?
          EWN-CMI Level 1

          I would use roster.selectedItem.name (manually set the checkbox.selected=true)  to build the datastructure and Bind that array to the raceGrid. Just keep a counter in your onClick function to figure out which race/racer it should be.  Good Luck.

          • 2. Re: How to Cycle Through ArrayCollection?
            ehusar Level 1

            Okay, let me see if I can make this simpler and get some suggestions. I can now cycle through the first datagrid but I can't seem to figure out how to tell is the checkbox is checked. I know what my issue is, there i actually  nothing in the rosterArray for the checkbox in the datagrid. I am not sure what to insert in there either.

             

            Here is the rosterArray..

             

            [Bindable]

            private var rosterArray:ArrayCollection = new ArrayCollection();

             

             

            Here the function to addItem. No entry for my checkbox, not sure what to add?...

             

            private function rosterAdd():void

            {

            rosterArray.addItem({name:addName.text,sex:sexGroup.selectedValue.toString()});

            addName.text = "";

            }

             

             

            Datagrid on left.... I updated the way I put the checkbox in the datagrid from my last post

             

            <mx:DataGrid allowMultipleSelection="true" change="foo.text = roster.selectedIndices.toString()" x="10" y="76" height="337" id="roster" editable="false" dataProvider="{rosterArray}">

            <mx:columns>

            <mx:DataGridColumn width="20"

               dataField="isOpen"

               headerText=""

               editable="true"

               textAlign="center"

               itemEditor="mx.controls.CheckBox"

               editorDataField="selected"

               itemRenderer="mx.controls.CheckBox"  />

             

            <mx:DataGridColumn headerText="Name" dataField="name" width="200" editable="false" />

            <mx:DataGridColumn headerText="Sex" dataField="sex" width="40" editable="false" />

            <mx:DataGridColumn headerText="Time" dataField="time" width="45" editable="false" />

            </mx:columns>

            </mx:DataGrid>

             

            Datagrid on right...

             

            <mx:DataGrid x="393" y="43" id="eventRace" dataProvider="{eventArray}" width="337" height="370">

            <mx:columns>

            <mx:DataGridColumn headerText="Racer 1" dataField="col1"/>

            <mx:DataGridColumn headerText="Racer 2" dataField="col2"/>

            <mx:DataGridColumn headerText="Racer 3" dataField="col3"/>

            <mx:DataGridColumn headerText="Racer 4" dataField="col4"/>

            </mx:columns>

            </mx:DataGrid>

             

            Function to cycle through datagrid and do something for at each row...

             

            Function to cycle through the first array.

             

                    public function addToRace():void

                    {

                    for each(var item:Object in rosterArray){

                           // here i need to detect if the checkbox is checked.

                      }

                    }

             

            • 3. Re: How to Cycle Through ArrayCollection?
              Karl_Sigiscar_1971 Level 3

              Why not use drag'n'drop between the two datagrids ? This is a built in feature in Flex. You can have single or multiple rows selected and then you don't need checkboxes or to care about the array collections.

              • 4. Re: How to Cycle Through ArrayCollection?
                EWN-CMI Level 1

                Hope this helps code just typed not tested. Might go back to the other checkBox declaration?  I would call a function on change of the roster dataGrid.  In that function, build the dataprovider for the raceGrid?

                 

                private var racer:int=0;

                private var race:int=0;

                 

                private function racerSelected(); {

                rosterGrid.selectedItem.ckBox.selected=true;  //not sure on syntax here but this should be close

                raceArray[race][racer]=rosterGrid.selectedItem.name;

                racer=racer+1;

                if (racer==4) {race=race+1;racer=0;};

                //you can add your text indicies stuff here too

                }

                 

                You could also check first to see if (!rosterGrid.selectedItem.ckBox.selected) then do the racer add, if it is selected remove the racer? (Could be difficult if racer can be in multiple races to find the right race, I may add another column or 2 to my racerGrid (visible="false") to help keep up with things.  Give everything an itemName.

                 

                Good Luck.

                1 person found this helpful
                • 5. Re: How to Cycle Through ArrayCollection?
                  ehusar Level 1

                  Okay, I see what you are doing there.  One question, is 'ckBox' the id or a checkbox?  The reason I ask is that with this code...

                   

                  <mx:DataGridColumn headerText="" width="30">

                     <mx:itemRenderer>

                        <mx:Component>

                           <mx:CheckBox />

                        </mx:Component>

                     </mx:itemRenderer>

                  </mx:DataGridColumn>

                   

                  ... you can't put an id on the CheckBox.

                   

                  But I guess that doesn't matter since the only thing that changes in the row is a the checkmark. So any change I would know it is checked. If they unchecked it I could just look in your raceArray for the name (assuming it is unique) and if it is there, remove it from your raceArray.

                   

                  I am not infront of my home computer to give this a go but I will as soon as I get home.

                   

                  Thanks! I will follow up later tonight after I give this a try.

                  • 6. Re: How to Cycle Through ArrayCollection?
                    ehusar Level 1

                    That is a great question Karl. One reason I did not look at the drag was usability.  This applicatoin is used on netbooks run in pubs and bars. The trackpad on those are not the best for dragging items around and dropping in a small area.  People do not always have a mouse connected to the netbooks.  Much eaier to use a checkbox and add a button to add them to the second data grid.

                     

                    But I don't think I have seen a drag/drop datagrid where only one field in the row is dragged over.  If you have seen one please post a link.

                     

                    Thanks!

                    • 7. Re: How to Cycle Through ArrayCollection?
                      EWN-CMI Level 1

                      Yes, you may not be able to id the checkBox through the renderer, I would probably add a columns visible="false" to the racerGrid to keep up with it if necessary and it is too much trouble to figure out the status of the checkBox.  You could store the race number & slot columns that the racer is scheduled for which would make it easier to remove him from a race.

                      • 8. Re: How to Cycle Through ArrayCollection?
                        ehusar Level 1

                        I have been sitting here thinking about this since I can't get to my code right now.  As long as I put a itemEditEnd on the datagrid I should be able to capture what row was checked. The checkbox is the only editable field.

                         

                        Like you suggested, add in a new field for the checkbox and set it to a 1 or 0 if it is checked or not. I will just update the arrayCollection that feeds the datagrid.  Then finally add a button to the UI and sends all the checked names in the arrayCollection to the second datagrid, limiting it to the first 4 checks.  I should be able to count the checked rows and not allow more than 4.

                         

                        In my head I have it so thanks to your suggestions.  I am heading home now so look for an update on progress later today. I will post and update and make sure you get the solution credit if it work.

                         

                        Thanks!

                        • 9. Re: How to Cycle Through ArrayCollection?
                          Gregory Lafrance Level 6

                          I'll have a complete, working solution for you soon.

                          • 11. Re: How to Cycle Through ArrayCollection?
                            Gregory Lafrance Level 6

                            This code is not production-level, but it should answer your question.

                             

                            If this post answers your question or helps, please mark it as such.


                            Greg Lafrance - Flex 2 and 3 ACE certified

                            www.ChikaraDev.com

                            Flex / AIR Development, Training, and Support Services

                            <?xml version="1.0" encoding="utf-8"?>
                            <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
                              <mx:Script>
                                <![CDATA[
                                  import mx.collections.ArrayCollection;
                                  
                                  [Bindable] private var rosterArray:ArrayCollection = new ArrayCollection();
                                  [Bindable] private var eventArray:ArrayCollection = new ArrayCollection();
                                  public var num:uint = 0;
                                  
                                  public function processRoster():void{
                                    eventArray = new ArrayCollection();
                                    var cnt:uint = 1;
                                    var race:Object = new Object();
                                    for each(var obj:Object in rosterArray){
                                      if(obj.selected){
                                        switch(cnt++){
                                          case 1:
                                            race["col1"] = obj.name;
                                            break;
                                          case 2:
                                            race["col2"] = obj.name;
                                            break;
                                          case 3:
                                            race["col3"] = obj.name;
                                            break;
                                          case 4:
                                            race["col4"] = obj.name;
                                            continue;
                                            break;
                                        }
                                      }
                                    }
                                    eventArray.addItem(race);          
                                  }
                                  
                                  private function addParticipant():void{
                                    rosterArray.addItem({selected: false, name: participant.text, sex: gender.selectedValue, time: null});
                                    participant.text = "";
                                    male.selected = true;
                                  }
                                  
                                  private function removeSelected(evt:MouseEvent):void{
                                    
                                  }
                                ]]>
                              </mx:Script>
                              <mx:RadioButtonGroup id="gender"/>
                              <mx:Panel layout="horizontal" backgroundColor="0xFFFFFF" 
                                borderColor="0x663300" title="Events" color="0xFFFFFF"
                                horizontalGap="50">
                                <mx:VBox horizontalAlign="right" color="0x000000" paddingBottom="10"
                                  paddingLeft="10" paddingRight="10" paddingTop="10">
                                  <mx:Label text="Event Roster" fontWeight="bold" fontSize="14"
                                    width="100%" textAlign="left"/>
                                  <mx:HBox width="{roster.width}">
                                    <mx:TextInput id="participant" width="100%"/>
                                    <mx:RadioButton id="male" label="M" groupName="gender" selected="true"/>
                                    <mx:RadioButton id="female" label="F" groupName="gender"/>
                                    <mx:Button label="Add" click="addParticipant()"/>
                                  </mx:HBox>
                                  <mx:DataGrid x="10" y="76" height="337" id="roster" editable="false" dataProvider="{rosterArray}">
                                    <mx:columns>
                                      <mx:DataGridColumn headerText="" width="30">
                                        <mx:itemRenderer>
                                          <mx:Component>
                                            <mx:Canvas>
                                              <mx:CheckBox id="ckbx" selectedField="selected" change="onChange(event);" 
                                                label="" horizontalCenter="0">
                                                <mx:Script>
                                                  <![CDATA[
                                                    import mx.controls.Alert;
                                                    private function onChange(evt:Event):void {
                                                      if(Boolean(data.selected) == false && outerDocument.num < 4){
                                                        outerDocument.num++;
                                                        data.selected = !data.selected;
                                                        outerDocument.processRoster();
                                                      }else if(Boolean(data.selected) == true){
                                                        outerDocument.num--;
                                                        data.selected = !data.selected;
                                                        outerDocument.processRoster();
                                                      }else{                            
                                                        mx.controls.Alert.show("Maximum of 4 participants can be selected.");
                                                        ckbx.selected = false;
                                                      }
                                                    }
                                                  ]]>
                                                </mx:Script>
                                              </mx:CheckBox>
                                            </mx:Canvas>
                                          </mx:Component> 
                                        </mx:itemRenderer>
                                      </mx:DataGridColumn>
                                      <mx:DataGridColumn headerText="Name" dataField="name" width="200" editable="false" />
                                      <mx:DataGridColumn headerText="Sex" dataField="sex" width="40" editable="false" />
                                      <mx:DataGridColumn headerText="Time" dataField="time" width="45" editable="false" />
                                    </mx:columns>
                                  </mx:DataGrid>
                                  <mx:Button label="Remove Selected" fontSize="14" click="removeSelected(event)"/>
                                </mx:VBox>  
                                <mx:VBox horizontalAlign="right" color="0x000000" paddingBottom="10"
                                  paddingLeft="10" paddingRight="10" paddingTop="10">
                                  <mx:Label text="Races" fontWeight="bold" fontSize="14"
                                    width="100%" textAlign="left"/>
                                  <mx:DataGrid x="393" y="43" id="eventRace" dataProvider="{eventArray}" width="337" height="365">
                                    <mx:columns>
                                      <mx:DataGridColumn headerText="Racer 1" dataField="col1"/>
                                      <mx:DataGridColumn headerText="Racer 2" dataField="col2"/>
                                      <mx:DataGridColumn headerText="Racer 3" dataField="col3"/>
                                      <mx:DataGridColumn headerText="Racer 4" dataField="col4"/>
                                    </mx:columns>
                                  </mx:DataGrid>
                                  <mx:Button label="Remove Selected" fontSize="14" click="removeSelected(event)"/>
                                </mx:VBox>
                              </mx:Panel>
                            </mx:Application>
                            
                            • 12. Re: How to Cycle Through ArrayCollection?
                              ehusar Level 1

                              Greg, that is just about perfect. I REALLY appreciate posting the code. This really helped!  I only made a few changes.  In the processRoster function I removed the event array out and used one I already had. This allows me now to add multipe races instead of overwriting the same first row of the eventRace datagrid. Now I can have more than one race in the rigth datagred.  I also added a Create Race button that calls the processRoster instead of that happening on each click of the checkbox. Here is a movie of what I am working on to show it in action.