Home > Flex 4 > Binding warnings when using Object in a List dataProvider

Binding warnings when using Object in a List dataProvider

If you have built a custom item renderer for a DataGroup or List you may have come across warnings in your Flash Builder console output similar to this:

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


This kind of warning typically happens when you are trying to bind to an object or property that isn’t defined as Bindable. I’ve seen this issue come up often when working with dataProviders that use <fx:Object />. For example, when running this application:

<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark">
 
    <s:List>
        <s:dataProvider>
            <s:ArrayList>
                <fx:Object firstName="Steve" lastName="Yzerman" />
                <fx:Object firstName="Joe" lastName="Sakic" />
            </s:ArrayList>
        </s:dataProvider>
        <s:itemRenderer>
            <fx:Component>
                <s:ItemRenderer>
                    <s:HGroup>
                        <s:Label text="{data.firstName}" />
                        <s:Label text="{data.lastName}" />
                    </s:HGroup>
                </s:ItemRenderer>
            </fx:Component>
        </s:itemRenderer>
    </s:List>
 
</s:Application>

The Flash Builder console outputs:

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

The issue is this custom inline renderer uses the { } binding syntax to bind to the value of data.firstName and data.lastName, but since the properties aren’t defined as bindable, changes to the data won’t get updated in the renderer (hence the warning).

There are two ways of changing your application to avoid these warnings.

1. Change your item renderer

Instead of binding the Label’s text property to the data you can override the set data method on the item renderer and update the Labels from there:

<s:ItemRenderer>
    <fx:Script>
        <![CDATA[
            override public function set data(value:Object):void {
                txtFirstName.text = value.firstName;
                txtLastName.text = value.lastName;
            }
        ]]>
    </fx:Script>
    <s:HGroup>
        <s:Label id="txtFirstName" />
        <s:Label id="txtLastName" />
    </s:HGroup>
</s:ItemRenderer>

If you aren’t comfortable overriding the set data method you might find it easier to listen for the dataChange event, for example:

<s:ItemRenderer dataChange="updateRenderer()">
    <fx:Script>
        <![CDATA[
            public function updateRenderer():void {
                txtFirstName.text = data.firstName;
                txtLastName.text = data.lastName;
            }
        ]]>
    </fx:Script>
    <s:HGroup>
        <s:Label id="txtFirstName" />
        <s:Label id="txtLastName" />
    </s:HGroup>
</s:ItemRenderer>

Note: You should never key off of the creationComplete event in a spark item renderer unless you are fully aware of the consequences of item renderer recycling. Listening for the dataChange event is recommended.

2. Change the objects in your dataProvider

If you would like to take full advantage of the Binding syntax in your renderer then the objects in your dataProvider must be bindable. You can do this by creating a custom data type and defining some bindable properties on it. For example create a file called HockeyPlayer.as:

package
{
    public class HockeyPlayer extends Object
    {
        [Bindable] public var firstName:String;
        [Bindable] public var lastName:String;
    }
}

And then using this data structure in the dataProvider:

<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:local="*">
 
    <s:List>
        <s:dataProvider>
            <s:ArrayList>
                <local:HockeyPlayer firstName="Joe" lastName="Sakic" />
                <local:HockeyPlayer firstName="Steve" lastName="Yzerman" />
            </s:ArrayList>
        </s:dataProvider>
        <s:itemRenderer>
            <fx:Component>
                <s:ItemRenderer>
                    <s:HGroup>
                        <s:Label id="txtFirstName" text="{data.firstName}" />
                        <s:Label id="txtLastName" text="{data.lastName}" />
                    </s:HGroup>
                </s:ItemRenderer>
            </fx:Component>
        </s:itemRenderer>
    </s:List>
 
</s:Application>

Note: This sample requires Flex SDK 4.0.0.11419 or higher. You can get the latest SDK builds from opensource.adobe.com.

  1. myIP
    December 11th, 2009 at 07:47 | #1

    Ah! Thanks for yer post. I have been looking for a solution on and off for months now, aye(:P).

  2. January 5th, 2010 at 13:09 | #2

    I was having this ‘problem’ also, but solutions you suggest didn’t work for me. Here’s what I came up with:

    PS. by the way, any idea how to validate my TextInput in this case? :P

  3. Steven Shongrunden
    January 7th, 2010 at 21:51 | #3

    @sasxa – Looks like WordPress swallowed up your code. If you want you can send me your code and I’ll take a look – steve at flexponential dot com

  4. johans
    February 14th, 2010 at 15:15 | #4

    I found using an ObjectProxy as described here works well:
    http://www.designovermatter.com/post.cfm/warning-unable-to-bind-to-property-somevar-on-object-object-class-is-not-an-ieventdispatcher

    I found this easier than overriding the setter.

  5. Steven Shongrunden
    February 14th, 2010 at 16:29 | #5

    @johans – Thanks for the link, I had not thought of that approach before.

    But this might not work as you would expect in spark. In general a spark ItemRenderer should never have logic waiting on the creationComplete event. This is because of item renderer recycling. If you do use the ObjectProxy approach you will still need to override the data setter (or handle the dataChange event) rather than having that logic in creationComplete.

    I’ve added an extra code snippet to option 1 above to demonstrate keying off of the dataChange event instead of overriding set data since some find that more convenient.

  6. Caspar Harmer
    May 14th, 2010 at 03:32 | #6

    Hi Steven,
    I think avoiding using an ObjectProxy is the way to go – I can verify that things don’t work too well when you use that technique in Spark. I had thought the fact that I was using an ArrayCollection as the dataProvider on my list meant that I wouldn’t need to over-ride the setter, but I forgot about the data object – it’s just generic. Thanks.

  7. Valdemar
    January 18th, 2011 at 03:27 | #7

    The ‘updateRenderer()’ option worked for me.
    Thank you.

  8. February 14th, 2011 at 16:54 | #8

    Good work, well done.

  9. Chris
    August 8th, 2011 at 02:10 | #9

    Thanks for this, updateRenderer() works fine for me too

  10. Dave
    October 27th, 2011 at 05:43 | #10

    updateRenderer() is a good clean option, worked for me. Thanks

  1. April 13th, 2010 at 14:48 | #1