HowToUseCairngormObserver

### Cairngorm 3 - [ Home ][1] - [ Guidelines ][3] - [ Tools ][4] - [ Libraries Downloads ][2]
### Cairngorm 2 - [ Home ][5] - [ Framework Downloads ][6] - [ Eclipse Plugin ][7]
### Project - [ Source ][8] - [ Bug Database ][9] - [ Submitting a Patch ][10] - [ Developer Documentation ][11] - [ Forums ][12] - [ License ][13]

How to Use the Cairngorm Observer Library

Summary

The Cairngorm Observer library provides a set of non-visual components for declaration in MXML that observe other objects, react to changes in some way and execute view behaviour. These components can help to reduce the amount of Script-block logic required in MXML components.

Executing View Behaviour

Often view components of a Flex application need to observe and react to changes on a model object. One popular approach to solve this problem in Flex is to leverage data binding. The simplest form of data binding can be achieved via the MXML curly braces syntax such as this example shows:

<mx:TextInput text="{ model.firstName }"/>

This would bind the property "firstName" of the model object to the property "text" of the view control TextInput. Most often, this is all a Flex developers needs, given that most view controls provide properties that can be used as a destination for a data binding expression. However, sometimes, such a property might not exist and a developer needs to call a method defined on a view component.

Listening to Properties - Observe and ObserveValue

In such cases the Observe and ObserveValue tags can be used as the following example shows:

<cg:Observe source="{ model.firstName }"
            handler="runEffectFunction"/>

While the usage of the Observe tag above calls the method on each change of the source property, the ObserveValue tag would only call the method if the value property of ObserveValue equals the source property value.

<cg:ObserveValue source="{ model.firstName }"
                 value="{ Name.SARA }"
                 handler="runEffectFunction"/>

In the above example, only if the firstName property equals Sara, the effect function is being triggered.
Both tags also allow controlling weather arguments would be passed to the view method.

Use Observe/ObserveValue with Caution

Note that Cairngorm recommends separating the layout and visual design from the behaviour of a view component. A simple ActionScript object can be used as part of the Presentation Model to encapsulate view behaviour and view state. It is recommended to first attempt to extract view behaviour into behaviour objects such as the Presentation Model before using Observe/ObserveValue and view behaviour in view components. Use these tags with caution and in rare circumstances with little behaviour that only relates to the layout or visual design of a view component.

Listening to Events - EventListener

Observer and ObserveValue can only listen to bindable properties of models. The EventListener tag adds the ability to listen to events that a model dispatches as the following examples shows:

<observer:EventListener source="{ model }"
                        type="{ Person.UPDATE_EVENT }"
                        handler="runEffectFunction"/>

Reducing View Behaviour

RIAs are usually data-driven, meaning they react differently depending on what data they receive from the external environment such as a remote service. Flex components can i.e. create different children based on data. Flex components that are data provider-based such as the DataGrid allow developers to bind a component to a data collection and let it automatically observe changes such as the below example shows:

<DataGrid dataProvider="{ model.contacts }" />

In the example above every item of the data collection that is added or removed will automatically be added or removed within the Flex component.

However, some components of the Flex framework such as the TabNavigator, Accordion or ViewStack are not data provider-based even though they could well depend on data. When a data collection changes, it is up to the developer to notify the non-data provider based Flex component about the change. One possible implementation could be to manually subscribe to a change event of a collection and execute view behaviour that adds or removes view children to the component.

Even if Flex components do not depend on remote data to define their children at runtime, they could depend on the state of other components such as the selected children of other components. While it is sometimes feasible that view components directly listen to state of other view components, the Presentation Model approach allows to extract the used state and behaviour of view components, which reduces view behaviour and improves readability, maintainability and testability.

When state of i.e. selected children is extracted into collections of within a Presentation Model or other models, a data provider-based view component could easily react to it. When view controls do not support a dataProvider property the ChildProvider or SelectableChildProvider of the Observer library can be used. They connect a collection of data items to non data provider-based control such as the TabNavigator. As with other data provider-based controls, an item renderer also needs to be supplied.

<observer:ChildProvider dataProvider="{ model.contacts.items }"
                        childList="{ tabNavigator }"
                        itemRenderer="insync.presentation.ContactForm"/>

When a Presentation Model also encapsulates the currently selected index, the SelectableChildProvider can be used.

<observer:SelectableChildProvider dataProvider="{ model.contacts.items }"
                                  childList="{ tabNavigator }"
                                  selectedItem="{ model.selectedContact }"
                                  itemRenderer="insync.presentation.ContactForm"/>

Loosely Coupling Parsley Domains - Parsley Extension

The Observer library isn't dependent upon Parsley, except for the Wire tag that is explained below.
As described in the guidelines Options in Loosely Coupling, there are many ways objects can be connected. Not always is the loosest form of coupling beneficial and desirable. The Wire Metadata allows for a different option, that connects two objects without the need for them to know each other via concrete references.

[Wire(id="contacts", propertyName="items")]
public var items:IList

The below, will search a Parsley context for the id "contacts" and bind the "items" property onto the items public variable of the receiver.

The same concept works also for nested properties:

[Wire(id="contacts", propertyName="business.items")]
public var items:IList

More Information

The ObserverTest project provides further documentation in the form of small, working examples and unit test.