10 Replies Latest reply on Jan 2, 2007 7:37 AM by dimival

    Possible Custom Components Bug

    dimival Level 1
      I think i found a bug when using custom components. I have a custom TabNavigator whose child containers are also custom components. When doing this, i can't set some properties on the custom containers, it fails.
      Here's an example of how to do it:

      1. Create a custom TabNavigator like this: (in this example i will call it TabN)
      <?xml version="1.0" encoding="utf-8"?>
      <mx:TabNavigator xmlns:mx=" http://www.adobe.com/2006/mxml">
      </mx:TabNavigator>

      As you can see, there's nothing weird with this one, just a custom bar

      2. Create a custom Container like this: (in this example named reportGrid)
      <mx:HBox xmlns:mx=" http://www.adobe.com/2006/mxml"
      <mx:DataGrid id="telefonosDG" dataProvider="{dataGridList}" width="100%"/>
      <mx:Script>
      <![CDATA[
      import mx.collections.ArrayCollection;

      [Bindable]
      public var dataGridList: ArrayCollection;
      ]]>
      </mx:Script>
      </mx:HBox>

      As you can see it only has a dataGrid whose dataProvider is binded to an arrayCollection.

      3. In your application do this:
      <mx:Application xmlns:mx=" http://www.adobe.com/2006/mxml"
      xmlns:custom="custom.*"
      creationComplete="inicializar()" width="100%" height="100%" layout="absolute">

      <mx:ArrayCollection id="testList"/>
      <custom:TabN width="100%">
      <custom:reportGrid id="telefonos" dataGridList="{testList}" width="100%" height="100%"/>
      </custom:TabN>

      <mx:Script>
      <![CDATA[
      private function inicializar() : void
      {
      var prod1:Object = {};
      var prod2:Object = {};
      prod1.Qty = 1;
      prod1.Index = 1;
      prod2.Qty = 2;
      prod2.Index = 2;
      testList.addItem(prod1);
      testList.addItem(prod2);
      }
      ]]>
      </mx:Script>
      </mx:Application>


      In theory, when you modify the testList those changes should appear in the DataGrid, but it fails, the DataGrid remains empty.

      Now instead of using the custom TabNavigator (TabN) use a normal <mx:TabNavigator> component and see what happens, it works perfectly fine, the DataGrid is filled with the two elements that i added.

      SO, What's the deal here???? Is this a bug?
        • 1. Re: Possible Custom Components Bug
          FlightGuy Level 1
          My guess is this: the fact that the dataGridList is marked [Bindable] means it will dispatch an event when the value of dataGridList changes. The only time the value of dataGridList changes is when you assign a new ArrayCollection to the property, not when you change the contents of the existing ArrayCollection.

          You probably need to listen on the ArrayCollection for whatever event it dispatches when its content changes. I would expect that DataGrid is already doing that, but try adding your own listener and see if (and when it's firing). I doubt it's a bug - more likely to be a timing difference of some sort.
          • 2. Re: Possible Custom Components Bug
            dimival Level 1
            But why does it work when you use the normal TabNavigator component? I am guessing that you didn't test the example. If you use custom TabNavigator it fails, but if you use the normal one it works, so i don't think it has anything to do with what you said since the rest of the code is the same, it only changes from <custom:TabN> to <mx:TabNavigator>, nothing related to the arrayCollection changes.
            • 3. Re: Possible Custom Components Bug
              FlightGuy Level 1
              You're right - there is something wrong. There should be no change in behavior when replacing a class with a subclass that doesn't override anything. The same happens with even a simple container like VBox.

              I note that the problem lies in flex's failure to assign the testList to the reportGrid in the first place. I replaced the public var with accessor functions and put trace commands into them. The setter for testList is not invoked at all. You'll see that if you actually set telefonos.dataGridList=testList in your script that everything works fine.

              This failure to assign the property set in MXML happens with any property that has a bound value (one that uses {} notation). I tried adding a simple String property (with accessors) to you reportGrid. If I set its value to a simple string like "hello" from the MXML, it gets called correctly. If, however, I set the value to "{'hello'}", it never gets called at all.
              • 4. Re: Possible Custom Components Bug
                FlightGuy Level 1
                Your example can be reduced to a very simple one:

                MXMLVBox.mxml:
                <mx:VBox xmlns:mx="..."/>

                MXMLComponent.mxml:
                <mx:Box xmlns:mx="...">
                <mx:Script>
                <![CDATA[
                public function get testValue():String{
                return "hi";
                }
                public function set testValue(value:String):void{
                trace('setting test value');
                }
                ]]>
                </mx:Script>
                </mx:Box>


                And the application:
                <mx:Application xmlns:mx="..."
                width="100%" height="100%" layout="absolute" xmlns:local="*">
                <local:MXMLVBox width="100%">
                <local:MXMLComponent testValue="{'hello'}"/>
                </local:MXMLVBox>
                </mx:Application>


                You'll see that the trace never happens. However, if you replace either the container or the component with an AS equivalent like this:

                ASVBox.as
                package
                {
                import mx.containers.VBox;
                public class ExtendedVBox extends VBox {}
                }


                ASComponent.as
                package
                {
                import mx.containers.Box;
                public class SimpleMXMLComponent extends Box
                {
                public function get testValue():String{
                return "hi";
                }
                public function set testValue(value:String):void{
                trace("set testValue");
                }
                }
                }


                ...All works fine and you can see the setter being called. Hopefully these test cases will help someone with access to that source to solve the problem.

                Tim
                • 5. Re: Possible Custom Components Bug
                  dimival Level 1
                  Let me see if i got it right, you are saying that i should change my mxml components to as classes and that way it works?
                  Well if that's true i guess that would be a workaround, on the other hand this sucks :P because building a screen using just code is not the best way to do it, that's why we have mxml for.

                  Can anyone from Adobe please confirm if this is a bug or not? and any other possible workarounds

                  Thanks
                  • 6. Possible Custom Components Bug
                    chris.huston.t10 Level 3
                    The problem you are having is one of variable scope. Because custom components are limited in scope and do not have the same application level scope as regular components, you need to change how you bind your data. There are two ways to do this. The first way is just to change your binding to this:
                    dataGridList="{parentDocument.testList}"

                    The second way would be to assign the testList binding through your initialize function:

                    private function inicializar() : void
                    {
                    var prod1:Object = {};
                    var prod2:Object = {};
                    prod1.Qty = 1;
                    prod1.Index = 1;
                    prod2.Qty = 2;
                    prod2.Index = 2;
                    testList.addItem(prod1);
                    testList.addItem(prod2);
                    telefonos.dataGridList = testList; //Bind data to the dataGrid in the custom component.
                    }

                    I tested both of these methods and they worked. I added the below function to check on the data binding:

                    private function add_prod():void {
                    var prod:Object = {};
                    prod.Qty = testList.length + 1;
                    prod.Index = testList.length + 1;
                    testList.addItem(prod);
                    }

                    So, you can use mxml custom components but just need to be careful of the variable scope.

                    Vygo
                    • 7. Re: Possible Custom Components Bug
                      FlightGuy Level 1
                      I agree that this stops the problem from being visible - I still argue it's a bug. First, why should a custom class have a different scope from a builtin class used in exactly the same place. Second, why the different behavior when either of the classes is described in AS rather than MXML? Third, the scope of the {} has to be local to where it's used - it's whole purpose is to allow you to bind values from the current scope.

                      I'm not disagreeing that it is showing this behavior - I'm arguing that it shouldn't.

                      Perhaps dimival could be so kind as to log this as a bug, failing any feedback from Adobe.

                      Thanks,
                      Tim
                      • 8. Re: Possible Custom Components Bug
                        dimival Level 1
                        Wanna hear something funny?

                        A friend of mine is using the beta release of Flex 2.0.1 and he tried to do this and it worked, so yes, it looks like it was a bug and that it was corrected for the next updater release so i guess we should only wait for it to be released (sometime in january).

                        Anyways, thank you guys for taking the time to try this.
                        • 9. Re: Possible Custom Components Bug
                          FlightGuy Level 1
                          I'm using 2.0.143459 and I do get it. I'm not aware of a newer release, but I will say the Adobe site is pretty secretive about what the latest release is. I wouldn't know if there were a new release. Perhaps just because there haven't been any?

                          Does anybody know if flex actually has an Eclipse update site (Eclipse has a protocol for checking for and downloading updates to all your plugins).
                          • 10. Possible Custom Components Bug
                            dimival Level 1
                            My friend is using version 2.0.154976 and on that one the bug was corrected