Hello. I have a new blog.

I've moved this blog to the following URL Kerkness.ca. Thank you for visiting, please update your bookmarks.

Thursday, April 17, 2008

warning: unable to bind to property 'XX' on class 'Object' (class is not an IEventDispatcher)

When working with data pulled in from an HTTPService in Flex you may find that at run time your application spits out a bunch of warnings that it is unable to bind to a property.

If you want to prevent these warnings from occuring you should process your the data for your in actionscript instead of MXML.

Change this ...

<mx:Label text="{myresults.dynamiclabel}"/>
To this ... ( calling the function init() with the creationComplete event )
<mx:Script>
[Bindable] private var dynamiclabel:String;
private function init():void
{
this.dynamiclabel = myresults.dynamiclabel;
}
</mx:Script>
<mx:Label text="{this.dynamiclabel}"/>
I know this approach requires a little bit more code and the first approach works, but this way it doesn't result in any warnings. I'll make the assumption that no run-time warnings means more compliant code.

Another approach to solving the problem is by wrapping Arrays in ArrayCollection and Objects in ObjectProxy wrappers. I got the following example from here.
function resultHandler(result:Array)
{
for(var i:String in result)
{result[i] = new ObjectProxy(result[i]);}
targetArrayCollection = new ArrayCollection(result);
}
What about using ItemRenderer(s)?

If you are combining the use of an ItemRenderer and data from an HTTPService in your application you may find that neither of the above solutions fully work. What you really need is a modification of the first solution. Collecting your data in response to the creationComplete event will only collect data when the itemRenderer is first created. The event is not called when dynamically change the dataProvider. An approach to solving this scenario is the create a ChangeWatcher in the ItemRenderer to respond to changes to the data property of said ItemRenderer.

<mx:Script>
import mx.binding.utils.ChangeWatcher;
import mx.events.PropertyChangeEvent;

private var dataWatcher:ChangeWatcher;

[Bindable] private var dynamiclabel:String;

// ** Call this function from creationComplete event **
private function init():void
{
this.dataWatcher = ChangeWatcher.watch( this, 'data', dataChangeHandler );
this.dataChangeHandler();
}

private function dataChangeHandler(event:Event=null):void
{
this.dynamiclabel = data.dynamiclabel;
}
</mx:Script>
<mx:Label text="{this.dynamiclabel}"/>

7 comments:

  1. Thank you for posting this. I'm new to flex and resources like your blog are always helpful. Keep up the good work.

    ReplyDelete
  2. @jake

    Thank you for the comments. It helps me to post things because then I have some documentation to fall back on and I don't forget how something is done.

    ReplyDelete
  3. Thanks, good and useful information!

    Cyril

    ReplyDelete
  4. Thanks for posting this - specifically the bit about item renderers. I had exactly this issue (needed to format a date/time and change the color based on the value) and your example showed me the way.

    - Greg

    ReplyDelete
  5. So, what happens if your objects are quite complex, and they have nested objects inside of them (say a Company-type contact person has Person-type contact persons and the contact persons also have multiple emails and phonenumbers)?

    Is this still a good sollution if i'm using multiple repeaters and custom-component itemrenderers inside those repeaters and also need to have an option to dynamically add to those repeaters (and nested repeaters)?

    I can see the code growing so much that i just want to leave the warnings right were they are...

    ReplyDelete
  6. @Anonymous,

    Thanks for the comment. I think you'll run into lots of potential issues with itemrenderers which have repeaters and more itemrenderers inside them.

    The best approach for a complex itemrenderer is to create an ActionScript component that extends UIComponent and implements IListItemRenderer. With this approach you have a lot more finite control over how data is handled when it changes.

    An important thing to remember about itemrenderers is that one isn't created for every item in your dataProvider. ItemRenderers are only created for visible items and data is moved through the item renderers as you scroll or browse through your data.

    I'll make a post showing the basic creation of an ItemRenderer in Actionscript

    ReplyDelete
  7. I'll have to look into that. Useful information.
    Thank you!

    ReplyDelete

Thank you for the comments.