[Bindable] on a read-only getter is unnecessary and will be ignored.

Sometimes, when you build a Flex application, you encounter a compiler warning that says, “[Bindable] on a read-only getter is unnecessary and will be ignored.” If you’ve seen that message, and you’re curious what it means, hopefully I can explain it. In short, the compiler is telling you that it can’t actually make that property bindable because it has no way of determining when the property changes.

To understand that better, you should first know a little more about how binding works. Normally, when you make a getter/setter pair bindable, the compiler adds a little extra code for you. Behind the scenes, it dispatches PropertyChangeEvent.PROPERTY_CHANGE to tell the binding system that your property has changed. Basically, it converts your property functions from something like this:

private var _example:String = "I am the very model of a modern Flex developer";

[Bindable]
public function get example():String
{
    return this._example;
}
public function set example(value:String):void
{
    this._example = value;
}

to this:

private var _example:String = "I am the very model of a modern Flex developer";

[Bindable("propertyChange")]
public function get example():String
{
    return this._example;
}
public function set example(value:String):void
{
    this._example = value;
    this.dispatchEvent(new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE);
}

If you don’t have a setter, there’s nowhere for the compiler to act smart and determine that your property has changed. If you want a getter without a setter to be bindable, you need to specify an event to be fired when the value returned by the getter changes. Your code should look something like this:

private var _example:String = "I am the very model of a modern Flex developer";

[Bindable("exampleChange")]
public function get example():String
{
    return this._example;
}

Notice the inclusion of the event type in the metadata’s parentheses.

That’s only the first part, though. Next, you need to actually dispatch the exampleChange event from somewhere in your code. For example, let’s say that we change the _example variable when an URLLoader returns a result:

private function urlLoader_completeHandler(event:Event):void
{
    var loader:URLLoader = URLLoader(event.currentTarget);
    loader.removeEventListener(Event.COMPLETE, completeHandler);
    this._example = loader.data.toString();
    this.dispatchEvent(new Event("exampleChange"));
}

Any time you change _example, you need to dispatch the exampleChange event specified in the metadata so that the the binding system knows about what you did. If you set _example in many different places, you might consider making a private or protected setter that sets _example and dispatches that event, but that’s not required.

In summary, the compiler warning goes away when you specify an event type in the metadata. Simply specifying an event type won’t update bindings though, you also have to dispatch that event when the underlying variable changes. When the binding system receives your event, it knows to update any component to which your getter is bound.

One extra thing worth mentioning is that any property with Bindable metadata that has no event specified will dispatch the same generic propertyChange event. This means the binding system will have to work harder than needed because it could receive the same event for many different properties. It’s a good idea to a create custom event for each property to avoid this limitation. You can see in the Flex framework source code that Adobe has separate events for most, if not all, bindable properties they create.

About Josh Tynjala

Josh Tynjala is a frontend developer, open source contributor, bowler hat enthusiast, and karaoke addict. You might be familiar with his project, Feathers UI, an open source user interface library for Starling Framework that is included in the Adobe Gaming SDK.

Discussion

  1. Pingback: [Bindable] on a read-only getter is unnecessary and will be ignored. – Josh Talks Flash | Enigmatic Thought

  2. Josh McDonald

    Not only does using a custom event name per property improve performance, it makes it trivial to add some [Event] metadata to your class or MXML document, and then you can trigger off property changes easily using events, without using the MXML binding synax or going through BindingUtil.

  3. Tink

    I’m with Josh.

    Everything you mark bindable should have a custom event that’s fired when the property changes.

  4. seanos

    To get around this problem I created a setter, but set it private. From an external class this property is still ‘read-only’, but the event does get fired implicitly by the [bindable] private setter function

  5. Tim John

    @seanos I tried the method you suggested, having the getter as public and the setter as protected/private, but it seems that the setter’s namespace is overridden to public. As a result, the property isn’t read-only and I can change it from outside the class.

    Here’s a good example of how to truly bind to a read-only getter.