Creating a Popup in a Cairngorm Architecture

Often I see this question coming up:

“How should I best create a popup in my Cairngorm application?”

I think of creating a popup control as something only views should be concerned about. It’s like creating other view components, managing states of view components or effects. Therefore this question isn’t just about creating popups, instead it’s about how to invoke methods that belong to the view. (BTW: I often hear from our User Experience team that they try to prevent popups where possible)


First and foremost, I’d try to let your views directly call a method that dispatches a popup.
However, most of the use cases that came up when questions like the above have been asked are slightly more complex. Users for example want to create a popup in a completely different part of the application. Or they receive an asynchronous remote service response, only want to react to the user with a popup at that point in time and work in a context where no view references are available, such as a typical Cairngorm Command.
Some users have created the code needed for creating a popup directly in the result method of a command or in a model object that’s been called by the result method of a command.
Sticking to my above rule; that only views should be concerned about popups, I think both solutions are not the optimal approach. A command should just be an encapsulated request to your model and a model itself should also not be concerned about any UI behavior. I’d argue we need to tell the model about the state change that has just occurred in your application, but in a model context. For example you might set a loggedIn property on a Login model object to true in order to signal that the login process was successful after a positive remote service response.
So, how can our views react to that state change in our model?
In a typical Cairngorm application, we may bind UI controls to properties of our model objects. But for creating a Popup control, there’s no UI component where we can bind to. How do we best let a view invoke a view related method after a certain state change in our model occurred?
Let’s take a step by step approach using a very simple Cairngorm application, that retrieves a list of employees and displays them in a popup after successful retrieval.
Please do ask your UX team if something like this is really a good idea in a real world application. For the sake of this example we don’t care about the user experience here!
This step by step tutorial will walk you through the relevant parts. You can see and download (via right click > View Source) the complete application here. Let’s go:
Dispatch a Cairngorm Event.
Let the view dispatch a user gesture via a Cairngorm Event in order to trigger the remote service:
On a mx:Button’s click event, the getEmployees method dispatches the Cairngorm event:
Excerpt from GetEmployeesCommand.as:

private function getEmployees() : void
{
var event : GetEmployeesEvent = new GetEmployeesEvent();
event.employees = model.employees;
CairngormEventDispatcher.getInstance().dispatchEvent( event );
}

Call and handle the remote service and modify your model.
The handling GetEmployeesCommand’s execute method calls a server side method. Its result method modifies the model. Here, it retrieves the model object Employeee via the ModelLocator.
Excerpt from GetEmployeesCommand.as:

private var employees : Employees;
public function execute( event : CairngormEvent ) : void
{
employees = GetEmployeesEvent( event ).employees;
employees.hasEmployees = false;
var delegate : EmployeeDelegate = new EmployeeDelegate( this );
delegate.getEmployees();
}
public function result( event : Object ) : void
{
employees.employees = IList( event.result );
employees.hasEmployees = true;
}

Employees.as:

package com.adobe.cairngorm.samples.popup.model
{
import mx.collections.IList;
public class Employees
{
[Bindable]
public var employees : IList;
[Bindable]
public var hasEmployees : Boolean;
}
}

Note that we modify the hasEmployees property of the Empoyees model object.
Let the view react react for you!
And here comes the crux: You can use the mx:Binding tag or the Observe/ObserveValue tag to invoke a view method, once the hasEmployees Boolean value changes.
I’d recommend using the ObserveValue tag to listen to a specific value of a state change of your model. More precisely, you can bind the source property of it to the bindable hasEmployees property of your model object Employees.

<ac:ObserveValue
source="{ model.employees.hasEmployees }"
handler="{ createEmployeeList }"
value="{ true }"/>

You could have also used the Observe tag to listen all updates of the hasEmployees property. For more information, check this out.
The ObserveValue tag above will invoke the createEmployeeList method defined in a Script block of the same MXML file. This method will invoke the popup.

private function createEmployeeList() : void
{
var application : DisplayObject = DisplayObject( Application.application );
var popup : IFlexDisplayObject = PopUpManager.createPopUp( application, EmployeeList, true );
PopUpManager.centerPopUp( popup );
var concretePopup : EmployeeList = EmployeeList( popup );
concretePopup.employees = model.employees;
}

That’s it! Through a state change in your model, you view has reacted. Furthermore, you can now let many other objects observing this particular state of your model and they can all act independently.
Cheers!

22 Responses to Creating a Popup in a Cairngorm Architecture

  1. Jaime Bermudez says:

    Hey Alex,
    I’ve been using your Observe tags for the past few months since I discovered your blog and I do like the idea of views controlling pop-ups, but I have a few questions:
    1) Let’s say we’re talking about a pop-up that may be called from various screens (i.e. a Login prompt). Should the developer centralize the Observe code in the Application file?
    2) Is it best to handle Hiding a pop-up in the same manner? I.e. if the user clicks the ‘X’ button or we are hiding the pop-up in response to a service call we add an ObserveValue tag looking for a “false” value?
    3) I noticed you passed the model to the pop-up. Is it not okay for the pop-up to feed off of a model locator? In my project we have separate modules each representing a functional area and each with their own model locator. Any thoughts on this?
    Love your blog.
    Thanks,
    Jaime

  2. AlexU says:

    Hi Jaime,
    1) I’d depend decisions about where to place Observe tags and popup code on what views seem to be most responsible for them. When you’re talking about a popup which displays i.e. a global error message I’d usually think of a view with a similar global responsibilty. This might be your entry level MXML or some other higher level, less nested MXML.
    I’d say the model object that this view listens too should also be of a similar responsibilty. You might even use the same state property on your model to trigger this popup with maybe different status properties that the popup binds to differentiate the particular message. But the later really depends on what your particluar use case may be.
    2) Yes, you can defer the actual closing of a popup the same way, using an ObserveValue tag with listening to false. However, make sure you ask your User Experience experts for the best way to do this. i.e. you might want to display something else view related (i.e. an effect or some loading animation) while you trigger another remote service.
    3) Generally, I’d say it’s a better practice to let objects only know about what they really need to know and pass in only that information instead of letting these objects retrieve what they. The former makes these objects more unit testable and resuable. However, in some situations i.e. involving item renderers you can’t easily do that and the ModelLocator comes to the rescue! 😉
    Best,
    Alex

  3. Pieter says:

    Hi Alex,
    I’ve read through all your cairngorm articles this morning and would like to thank you for your thorough explanations and advice.
    I’m looking forward to more of your articles in the future.
    Best Regards,
    Pieter

  4. Seth Caldwell says:

    Following this practice in a large RIA would seem to turn it into a giant state machine in which unit testing would be a nightmare.
    The nice part about your boolean is that it could be set in many places and the view reacts accordingly. However it feels like the logic to show this popup should be maintained in a helper object of some kind if its being popped up from gestures in many different views – why necessitate some view having the observe tag… what if that view is unloaded for some reason and then another view wants to show the pop up?
    What is the argument against having a (solid easily unit tested) helper object which the command calls directly to do things like show popups or manage views instead of using your observe paradigm?
    I haven’t tried this observer pattern in a large project yet, I’m thinking about it but would like to hear why you prefer it =)
    Thanks a ton,
    Seth

  5. carlos arana says:

    I have a problem ,
    i create a login form ,
    Using carigorm i execute a delegate and the user doesnt exist , then the onsuccess event its called , there i put a flag isErrors = true.
    I observe this variable of the model (isErrors = true) with an ObserveValue tag, when i receive the call i put a Alert indicating the user doesnt exist or the password its wrong.
    ok , all looks good , but when i call a second time and fail again i receive 2 times the call from the Observe tag , WHY , the only way to do this doesnt happen if after call the alert do something like model.isErrors=false , but on the view !!! thats wrong.
    Some ideas, it looks that we need something like ObserveValueChanged , or i dont know.

  6. carlos arana says:

    Oh , the thing goes worst , but is solved the puzzle.
    To test i change to ChangeWatcher, an the same thing !!!
    After doing some research i need to add to my previous post this :
    My form its a popup
    The multiple calls to the handlers only happens when i close the popup and then open again, the worst is that if i open and close 3 times now the handler is called 3 times !!!
    Ok , thats look that is a problem with the pop up manager because it never destroy the previous instances , and also i call the removePopUp method when closing the TitleWindow.
    How i solve the problem ? well using ChngeWatchers and removing them with unwatch before remove the popup. Observer classes doesnt alloow this.
    But the question is , the same is happening with all the bindings of the popup ? its that its true
    flex have serious problems.

  7. Rajesh says:

    Hey Alex thanks for the explanation.
    I want to build a small login application using Cairngorm.I want to use Remote Object to connect to WebORB(PHP Classes). I dont know where to start from.How will i connect Cairngorm with WebORB.
    Can you help me out here.

  8. Mark says:

    I am not sure if this is the best place to ask… but do you have any tips on doing localization?
    I was thinking about creating a LanguageVO for all the labels and the date and time formatters… then storing that in the ModelLocator. Then if a language changed is asked or if a variable is passed from the host page I would pull the new LanguageVO using a Business Delegate.
    Is there any plan to add language localization into Cairngorm?
    Great Blog by the way, I am learning lots.
    Regards
    Mark

  9. Scott says:

    Alex,
    I really appreciate your insights to Cairngorm. One area I’m getting stuck in is handling complex state in business logic. IE: user is modifying multi-part forms and elects to leave either the current item, or the app all together. What is a good way to manage the asynchronous calls to prompt user to save state and the asynchronous responses that are a result of that cleanup process? Sorry for confusing post. Thx.

  10. Evan Gifford says:

    Hello All,
    Something to keep in mind. I’ve run into a case when the observer can prevent garbage collection of DisplayObjects after they have been removed from the display list.
    Imagine a scenario in which the component which is popped up contains another observer. If that popUp is removed with simply “PopUpManager.removePopUp( this )” the observer will prevent the component from being garbage collected and it will still respond to data changes in memory.
    The way I delt with this was to handle the “removed” event of the DisplayObject and null out the observer.
    It seems that since Flex is primairly a language concerned with visual things there is a case for a “DisplayObjectAware” observer which would do this automatically. This could be an observer which extends UIComponent and handles the removed event automatically.
    ideas?

  11. Evan GIfford says:

    Regarding my last post, “removed” is incorrect event, it is actually “remove” – notice not “ed”

  12. Evan Gifford says:

    As of Flash Player 9.0.28 (doesn’t work in 9.0.16) you can listen for the “Event.REMOVED_FROM_STAGE” within child components and clear the observer (or events with strong references) to allow for garbage collection.
    If you are using 9.0.16 there is an alternative solution as well as a description of the problem here: http://www.kirupa.com/forum/showthread.php?p=1950401

  13. Peter says:

    I was thinking about creating a LanguageVO for all the labels and the date and time formatters… then storing that in the ModelLocator. Then if a language changed is asked or if a variable is passed from the host page I would pull the new LanguageVO using a Business Delegate.

  14. popups, heh i hate popups however thanks for this explanation, it can be useful for some ads.

  15. Hörmann says:

    I was thinking about creating a LanguageVO for all the labels and the date and time formatters… then storing that in the ModelLocator. Then if a language changed is asked or if a variable is passed from the host page I would pull the new LanguageVO using a Business Delegate.

  16. sharp aquos says:

    2) Yes, you can defer the actual closing of a popup the same way, using an ObserveValue tag with listening to false. However, make sure you ask your User Experience experts for the best way to do this. i.e. you might want to display something else view related (i.e. an effect or some loading animation) while you trigger another remote service.

  17. I would pull the new LanguageVO using a Business Delegate.

  18. Something to keep in mind. I’ve run into a case when the observer can prevent garbage collection of DisplayObjects after they have been removed from the display list.

  19. Werbeagentur says:

    Many thanks for the great informations. I hope i will learn more about it 🙂
    Thanks again from Germany, Werbeagentur

  20. Young says:

    Not sure if using the ObserveValue to show a pop up is a good idea when developing a large project. I felt in love with the ObserveValue and I have about 200 flags that update view. It became very difficult to Debug/maintain my codes. It makes sense to use ObserveValue for a small/medium projects but, NOT for a large enterprize projects.

  21. AlexU says:

    Hi Young, maybe it’s worth looking into the reason why you need to call the view directly on so many occasions. I found that when extracting behaviour out of views into Presentation Models and domain models, there’s only a small amount of view behaviour that we could consider calling directly via Observe tags. These kind of behaviour would i.e. be effects that are defined in ActionScript instead of view states and transitions. Only for view behaviour that cannot be extracted into a different context and absolutely belongs to the view are candidates for Observe.

  22. EC says:

    This is really illuminating. Thank you. I was getting tired of all the same Cairngorm examples just demonstrating how to control views in a simple ViewStack. These articles give me insight in how to adapt my situation to Cairngorm.