17 Replies Latest reply on May 3, 2011 9:57 AM by Flex harUI

    Two-way data binding on custom component

    eprevot123 Level 2

      Hi, maybe there already is a post for this question but the search engine seems to be broken...

       

      I found many many examples for two-way data binding on a text component, but I want to use it on a custom component.

      For exampel I want to do :

       

      <myPackage:MyComponent myLabel="@{myModel}"/>

       

      MyComponent is a Group that contains a Label, among other things.

      That Label displays the String in var myLabel.

      A click in MyComponent calculates a new value for myLabel.

      So I want the Label to display this new vaue AND the original myModel to get the new value too (thanks to the @).

       

      Is this possible ? Do I have to add some Binding tag with a special event name, on myLabel var ?

        • 1. Re: Two-way data binding on custom component
          Tanu Jain Level 2

          Both 'myModel' and 'myLabel' variable in your MyComponent must be declared Bindable in order to two-way binding to work.

           

          --

          Tanu

          • 2. Re: Two-way data binding on custom component
            eprevot123 Level 2

            I had declared both myLabel and myModel as [Bindable] but it didn't not work.

             

            When I look at spark TextArea, I see the set text method has these tags :

            [Bindable("change")]
            [Bindable("textChanged")]

            and set text method dispatches "textChanged" event.

             

            That's why I wonder if there is something more to do than just ading a simple [Bindable] to the 2 variables ?

            • 3. Re: Two-way data binding on custom component
              Karl_Sigiscar_1971 Level 3

              Have a setter on the property you are trying to bind to and put a breakpoint in there to see if

              the value changes. If it does, check in the event that newValue is different than oldValue. If not, data binding

              will not trigger.

               

              First try one way data binding. When it works, try two way data binding.

               

              For data binding to work, Flex uses the PropertyChangeEvent by default if you don't specify your own. It is true for both one way and two way data binding. Specifying your own event optimizes data binding.

              1 person found this helpful
              • 4. Re: Two-way data binding on custom component
                eprevot123 Level 2

                Ok the problem does not seem to come from two way data binding.

                In my real application, myModel is a XML and the click on MyComponent changes a grand child of myModel. It seems that myModel does not see the change. Event if I do myModel = calculateMethod(); the binding is not triggered.

                BUT if I dispatch a PropertyChangeEvent after having modified myModel grand child, then the binding is ok. Actually I don't event need the @, the XML model is changed.

                I don't really get it ...

                • 5. Re: Two-way data binding on custom component
                  Zolotoj Level 3

                  Try this for custom component's getter:

                  [Bindable(event="Change")]
                  public function get gettername():String
                  {
                       return _something;
                  }

                   

                  change listener:

                  private function changeHandler(event:Event):void
                          {                       
                                 ....

                                 .....

                                // we cannot dispath parameter "event" because of
                                // Error #2094: Event dispatch recursion overflow

                                dispatchEvent(new Event("Change"));
                             
                          }  

                  • 6. Re: Two-way data binding on custom component
                    Karl_Sigiscar_1971 Level 3

                    What you say here is very interesting:

                     

                    >>> the click on MyComponent changes a grand child of myModel. It seems that myModel does not see the change BUT if I dispatch a PropertyChangeEvent after having modified myModel grand child, then the binding is ok

                     

                    Because this is exactly what they say in the book Enterprise Development with Flex:

                     

                    "Imagine a collection of objects with complex structure, with class variables of nonprimitive
                    data types—for example, a collection of Employee objects in which each
                    object has a variable of type WorkHistory, which is a class with its own properties.
                    If a variable declared in the WorkHistory class gets modified, the collection of
                    Employee objects won’t know about this change unless you explicitly dispatch the
                    propertyChange event."

                     

                    So, I think that dispatching a PropertyChangeEvent after having modified myModel grand child, as you did, is the right thing to do.

                    • 7. Re: Two-way data binding on custom component
                      eprevot123 Level 2

                      I understand a little better what is going on.

                      When calculateMethod() changes the XML model, it changes the reference I gave, so it changes directly myModel, I don't need to add any Bindable tag on myModel.

                      But if I bind a component on myModel to represent the XML information, the binding will not trigger when grand child changes. Then I need to dispatch myself a propertyChangeEvent when the grand child changes.

                      That's right ?

                       

                      I didn't think XML was "a collection of objects with complex structure, with class variables of nonprimitive data types". The example they give is a collection of Custom class that contains itself Custom class. Here it's just XML, a core Actionscript class...

                      • 8. Re: Two-way data binding on custom component
                        Karl_Sigiscar_1971 Level 3

                        That's right !

                         

                        >> I didn't think XML was "a  collection of objects with complex structure, with class variables of  nonprimitive data types".

                         

                        Conceptually, it's the same thing. You can think of the top XML nodes as Employee objects and the children nodes as WorkHistory objects. And you can think of the grand children nodes as WorkHistory properties.

                        • 9. Re: Binding on a XML
                          eprevot123 Level 2

                          So if I want to use a XML as model, I can't really use data binding, I have to dispatch events by myself when I know that the XML has changed...

                           

                          I have components like this :

                          <comp:ParentComponent>

                               <comp:Component1>

                               <comp:Component2>

                               ...

                               <comp:ComponentN>

                           

                          all Components are bound on the same XML and represent son or grandson of this XML. A click in one of those Component can change several nodes of the XML model, those changes should be visible in the other Components. So Componenti dispaches a propertyChangeEvent, so that it updates itself, but its brothers Components don't receive it.

                          What solution do you suggest ?

                          • 10. Re: Binding on a XML
                            Karl_Sigiscar_1971 Level 3

                            The best approach is to use DTOs (Data Transfer Objects) with the [Bindable] and [RemoteClass] metadata tags.

                             

                            XML is good for configuration files and to transmit data to the LCDS server for PDF generation, but I wouldn't use it to get data from a server (parsing XML and creating objects from that is too slow) nor to represent the data model on the client.

                            • 11. Re: Binding on a XML
                              eprevot123 Level 2

                              I don't get the model from a server. It's an Air application and I get information from a XML file in the storage directory. I read the XML file so it's simpler for me to keep my model as XML.

                              • 12. Re: Two-way data binding on custom component
                                Flex harUI Adobe Employee

                                You can bind to XML.

                                • 13. Re: Two-way data binding on custom component
                                  eprevot123 Level 2

                                  That would be great. So tell me what I don't understand.

                                   

                                  Let's say I have a component with a "contact" property that is an XML :

                                  <contact>

                                       <address>

                                            <country>France</country>

                                            <city>Paris</city>

                                       </address>

                                       <name> ...

                                   

                                  Now this component contains 2 components that take contact XML, and the node you want to represent :

                                  <comp:MyComp myContact="{contact}" info="country"/>

                                  <comp:MyComp myContact="{contact}" info="city"/>

                                   

                                  The first MyComp represents contact.address.country, the second MyComp represents contact.adress.city.

                                  For example, a click in MyComp representing country, will do :

                                  myContact.address.country[0] = "Spain";

                                  myContact.address.city[0] = "Madrid";

                                   

                                  myContact property is Bindable, and the model "contact" is changed in the parent component. But the first MyComp does not display Spain but still France, unless I dispatch a PropertyChangeEvent. Then Spain is displayed on first MyComp but I still have Paris in the second MyComp.

                                   

                                  Edit : I use bindable function. MyComp is like this :

                                   

                                            [Bindable]
                                            public var myContact:XML;

                                   

                                            public function getInfo(myContact:XML):String
                                            {
                                                return myContact.address.elements(info);
                                            }
                                          ]]>
                                      </fx:Script>
                                     
                                      <s:Label text="{getInfo(myContact)}"/>

                                   

                                  Message was edited by: eprevot123

                                  • 14. Re: Two-way data binding on custom component
                                    Flex harUI Adobe Employee

                                    How is MyComp wired up to display myContact in its UI widgets?

                                     

                                    If you did:

                                        <mx:Label text="{myContact[info]}" />

                                     

                                    That might not work and you should have gotten warnings in the console.

                                     

                                    If you did:

                                     

                                        <mx:Label text="{XML(myContact)[info]}" />

                                     

                                    That should work.  The compiler should generate different binding code to

                                    watch the XML for changes.

                                    • 15. Re: Two-way data binding on custom component
                                      eprevot123 Level 2

                                      I edited the post to show how MyComp displays myContact.

                                       

                                      If I use "direct binding", then it works :

                                      <s:Label text="{myContact.address.elements(info)} />

                                       

                                      But when I use function with bindable property as argument (see previous post), the function is not triggered and so label stay the same.

                                      • 16. Re: Binding on XML
                                        eprevot123 Level 2

                                        So, do you see any mistake in the way I use bindable function ?

                                        If I use String instead of XML it works. But when I use XML as bindable argument of a function to inject new value to the view when XML changes, that does not work.

                                        • 17. Re: Two-way data binding on custom component
                                          Flex harUI Adobe Employee

                                          I'm not sure that binding to functions will watch changes deep in an XML

                                          structure.  Binding to properties in XML should work though.