5 Replies Latest reply on Jan 10, 2008 5:17 PM by peterrowe

    2 DataGerids and 2 dataproviders problem

    sjelauc
      Hi. I am a newbie in flex. I have a little bit more complex application, than example I am gonna show you, but in this simplified example the problem is the same.
      So Ihave 2 panels and 2 buttons in my application. Also I have 2 vars of type XML, defined in the <mx:Script> section.
      When user clicks on the first button, the Application creates the datagrid instance, sets the first dataprovider to it and then adds it to the panel one. When user clicks on the second button, the Application creates another datagrid instance, sets the second dataprovider to it and then adds it to the panel two. Here is my code:

      <mx:Application xmlns:mx=" http://www.adobe.com/2006/mxml" layout="absolute" xmlns:view="view.*" >

      <mx:Script>
      <![CDATA[
      import mx.controls.Alert;
      import mx.controls.DataGrid;

      [Bindable]
      private var dataProvider1:XML = <items>
      <item COL1="11111" COL2="22222" COL3="33333"/>
      <item COL1="11111" COL2="22222" COL3="33333"/>
      <item COL1="11111" COL2="22222" COL3="33333"/>
      </items>;
      [Bindable]
      private var dataProvider2:XML = <items>
      <item HEAD1="11111" HEAD2="22222" HEAD3="33333" HEAD4="44444"/>
      <item HEAD1="11111" HEAD2="22222" HEAD3="33333" HEAD4="44444"/>
      <item HEAD1="11111" HEAD2="22222" HEAD3="33333" HEAD4="44444"/>
      </items>

      private function handleClick1():void {

      var tableOne:DataGrid = new DataGrid();
      tableOne.sortableColumns = false;
      tableOne.dataProvider = dataProvider1.children();
      tableOne.name = "table";

      if(this.panelOne.getChildByName("table") != null) {
      this.panelOne.removeAllChildren();
      }

      this.panelOne.addChild(tableOne);

      }

      private function handleClick2():void {

      var tableTwo:DataGrid = new DataGrid();
      tableTwo.sortableColumns = false;
      tableTwo.dataProvider = dataProvider2.children();
      tableTwo.name = "table";

      if(this.panelTwo.getChildByName("table") != null) {
      this.panelTwo.removeAllChildren();
      }

      this.panelTwo.addChild(tableTwo);
      }

      ]]>
      </mx:Script>


      <mx:VBox id="tableBox">

      <mx:HBox>
      <mx:Panel id="panelOne"/>
      <mx:Panel id="panelTwo"/>
      </mx:HBox>

      <mx:ControlBar>
      <mx:Button id="buttonOne" label="Table One" click="handleClick1()"/>
      <mx:Button id="buttonTwo" label="Table Two" click="handleClick2()"/>
      </mx:ControlBar>
      </mx:VBox>

      </mx:Application>


      the problem, is: when I click the buttonOne first, the datagrid appears correct. Then, when I click buttonTwo, the second datagrid appears emty, with the same column name as in the datagrid one. And vise versa, if I click buttonTwo first - the data grid is ok, then on click buttonOne the datagrid is empty with the same column names as already created datagrid.
        • 1. Re: 2 DataGerids and 2 dataproviders problem
          sjelauc Level 1
          Nobody knows?
          • 2. Re: 2 DataGerids and 2 dataproviders problem
            dazweeja Level 1
            At first I thought you must be doing something wrong but now I really don't think so. This really looks to me like a bug and a pretty bad one at that. The strange thing is that the correct data is definitely being passed into the second datagrid - it's just not creating the datagrid properly. Flex likes to reuse components were possible for speed reasons but it can really stuff things up. I think the following simplified code highlights the same bug but I'm sorry that I don't have a solution:

            <mx:Application xmlns:mx=" http://www.adobe.com/2006/mxml" layout="absolute">
            <mx:Script>
            <![CDATA[
            [Bindable]
            private var items1:XML =
            <items>
            <item COL1="11111" COL2="22222" COL3="33333"/>
            <item COL1="11111" COL2="22222" COL3="33333"/>
            <item COL1="11111" COL2="22222" COL3="33333"/>
            </items>;

            [Bindable]
            public var items2:XML =
            <more_items>
            <another_item HEAD1="11111" HEAD2="22222" HEAD3="33333" HEAD4="44444"/>
            <another_item HEAD1="11111" HEAD2="22222" HEAD3="33333" HEAD4="44444"/>
            <another_item HEAD1="11111" HEAD2="22222" HEAD3="33333" HEAD4="44444"/>
            </more_items>;
            ]]>
            </mx:Script>
            <mx:HBox>
            <mx:Panel id="panelOne">
            <mx:DataGrid id="table1" dataProvider="{items1.children()}" />
            </mx:Panel>
            <mx:Panel id="panelTwo">
            <mx:DataGrid id="table2" dataProvider="{items2.children()}" change="trace(table2.selectedItem.toXMLString())" />
            </mx:Panel>
            </mx:HBox>
            </mx:Application>
            • 3. Re: 2 DataGerids and 2 dataproviders problem
              atta707 Level 2
              this has to be a bug. please log it at http://bugs.adobe.com/flex/
              • 4. Re: 2 DataGerids and 2 dataproviders problem
                dazweeja Level 1
                +1 for logging the bug.

                I guess the workaround is to create DataGridColumns with the properties you want for both DataGrids. 'headerText' and 'dataField' would be the 2 main properties you would look at. It would probably be easiest to do this in MXML and just toggle the 'visible' and 'includeInLayout' properties of the DataGrids with your clickHandler functions. Something like this:

                <mx:Application xmlns:mx=" http://www.adobe.com/2006/mxml" layout="absolute" xmlns:view="view.*" >
                <mx:Script>
                <![CDATA[
                import mx.controls.DataGrid;

                [Bindable]
                private var dataProvider1:XML = <items>
                <item COL1="11111" COL2="22222" COL3="33333"/>
                <item COL1="11111" COL2="22222" COL3="33333"/>
                <item COL1="11111" COL2="22222" COL3="33333"/>
                </items>;
                [Bindable]
                private var dataProvider2:XML = <items>
                <item HEAD1="11111" HEAD2="22222" HEAD3="33333" HEAD4="44444"/>
                <item HEAD1="11111" HEAD2="22222" HEAD3="33333" HEAD4="44444"/>
                <item HEAD1="11111" HEAD2="22222" HEAD3="33333" HEAD4="44444"/>
                </items>

                private function handleClick1():void {
                if(tableOne.visible) {
                tableOne.visible = false;
                tableOne.includeInLayout = false;
                } else {
                tableOne.visible = true;
                tableOne.includeInLayout = true;
                }
                }

                private function handleClick2():void {
                if(tableTwo.visible) {
                tableTwo.visible = false;
                tableTwo.includeInLayout = false;
                } else {
                tableTwo.visible = true;
                tableTwo.includeInLayout = true;
                }
                }

                ]]>
                </mx:Script>
                <mx:VBox id="tableBox">
                <mx:HBox>
                <mx:Panel id="panelOne">
                <mx:DataGrid id="tableOne" dataProvider="{dataProvider1.children()}" sortableColumns="false" visible="false" includeInLayout="false">
                <mx:columns>
                <mx:DataGridColumn dataField="@COL1"/>
                <mx:DataGridColumn dataField="@COL2"/>
                <mx:DataGridColumn dataField="@COL3"/>
                </mx:columns>
                </mx:DataGrid>
                </mx:Panel>
                <mx:Panel id="panelTwo">
                <mx:DataGrid id="tableTwo" dataProvider="{dataProvider2.children()}" sortableColumns="false" visible="false" includeInLayout="false">
                <mx:columns>
                <mx:DataGridColumn dataField="@HEAD1"/>
                <mx:DataGridColumn dataField="@HEAD2"/>
                <mx:DataGridColumn dataField="@HEAD3"/>
                <mx:DataGridColumn dataField="@HEAD4"/>
                </mx:columns>
                </mx:DataGrid>
                </mx:Panel>
                </mx:HBox>
                <mx:ControlBar>
                <mx:Button id="buttonOne" label="Table One" click="handleClick1()"/>
                <mx:Button id="buttonTwo" label="Table Two" click="handleClick2()"/>
                </mx:ControlBar>
                </mx:VBox>
                </mx:Application>

                Darren.
                • 5. Re: 2 DataGerids and 2 dataproviders problem
                  peterrowe
                  If you use an arrayCollection you will not see this problem:
                  import mx.collections.*;

                  private var DGArray1:Array = [
                  {COL1:'11111', COL2:'22222', COL3:'33333'},
                  {COL1:'11111', COL2:'22222', COL3:'33333'}];

                  [Bindable]
                  public var dataProvider1: ArrayCollection;


                  private var DGArray2:Array = [
                  {HEAD4:'44444', HEAD5:'55555', HEAD6:'66666'},
                  {HEAD4:'44444', HEAD5:'55555', HEAD6:'66666'}];

                  [Bindable]
                  public var dataProvider2: ArrayCollection;


                  public function initData():void {
                  dataProvider1 = new ArrayCollection(DGArray1);
                  dataProvider2 = new ArrayCollection(DGArray2);
                  }

                  call initialize="initData()" in the header