This page is an archive of my old blog. Please visit DavidTucker.net for my current blog.
This site is no longer being maintained and commenting is disabled.

Getting Started with Cairngorm – Part 2

Recap: In Part 1, I discussed the basic implementation and use of the ModelLocator pattern. This pattern is one of many design patterns contained within the Cairngorm micro-architechture. This design pattern will be used in Part 2 as well, so it is assumed that you are familiar with the concepts in Part 1 of the tutorial. At this point, we still are not working with a "complete" Cairngorm application (that will come in Part 3).

Part 2 - Using a ModelLocator to Manage the View

Note: As with all of the tutorials that will come in this series, this lesson has two parts. First, in the article you will learn the theory behind the topic, and then in the video you will do an actual "code-along". The article will give some instructions in how to set up your project for the "code-along".

In the previous tutorial you learned the advantages of using a ModelLocator to manage data within an application, however, the advantage of the ModelLocator pattern extends beyond the management of data. It can manage the "view" of an application as well. To see how view management works in Cairngorm, you will first need to create a new project named "ViewManager" and name the main application file "Main.mxml". For this project, your will also need to add the Cairngorm.swc to your project build path (as described in Part 1). You will also need to create two new folders inside of the "src" folder: view and model. When you are completed, your project should look similar to Figure 1 below.

Cairngorm Project Window
Figure 1 - ViewManager Project

Next, you will need to take the ModelLocator code from the previous tutorial and place it inside your application. I have posted the code below for your convenience.

Actionscript:
  1. package model {
  2.     import com.adobe.cairngorm.model.IModelLocator;
  3.     [Bindable]
  4.     public class ViewModelLocator implements IModelLocator {
  5.         // Single Instance of Our ModelLocator
  6.         private static var instance:ViewModelLocator;
  7.         public function ViewModelLocator(enforcer:SingletonEnforcer) {
  8.         if (enforcer == null) {
  9.                 throw new Error( "You Can Only Have One ViewModelLocator" );
  10.             }
  11.         }
  12.         // Returns the Single Instance
  13.         public static function getInstance() : ViewModelLocator {
  14.             if (instance == null) {
  15.                 instance = new ViewModelLocator( new SingletonEnforcer );
  16.             }
  17.             return instance;
  18.         }
  19.         //DEFINE YOUR VARIABLES HERE
  20.     }
  21. }
  22. // Utility Class to Deny Access to Constructor
  23. class SingletonEnforcer {}

Example 1 - The ModelLocator from Part 1

If you need information about the ModelLocator, please return to Part 1 of the tutorial.

The only item that must be changed in the ModelLocator is the "package" statement. For this project, you will be placing the ModelLocator in the "model" folder, so the package path simply needs to me "model" (it has already been corrected above). You will also need to add one variable to your ModelLocator initially. This variable will be called "workflowState" and it will be of type "uint". The declaration will look like this:

Actionscript:
  1. public var workflowState:uint = 0;

Example 2 - Defining the workflowState Variable

This variable will be used to "control" the view in your application. The most common way to accomplish this is to use a ViewStack [ Reference ]. If you are not familiar with a ViewStack, feel free to read through this information. A ViewStack has a property named "selectedIndex". This numeric value defines which "child" is visible in the ViewStack. Consider the following code:

mxml:
  1. <mx:ViewStack id="myViewStack">
  2.  
  3.   <mx:HBox id="box1">
  4.     <mx:Label text="I am Box 1" />
  5.   </mx:HBox>
  6.  
  7.   <mx:HBox id="box2">
  8.     <mx:Label text="I am Box 2" />
  9.   </mx:HBox>
  10.  
  11.   <mx:HBox id="box3">
  12.     <mx:Label text="I am Box 3" />
  13.   </mx:HBox>
  14.  
  15. </mx:ViewStack>

Example 3 - A Basic ViewStack Example

Initially the value of selectedIndex is 0. With this setting "box1" would be visible. If you issue the following command:

Actionscript:
  1. myViewStack.selectedIndex = 1;

Example 4 - Manually Setting the selectedIndex

then the box named "box2" would be visible. However, if you apply the ModelLocator to this concept, you could use the workflowState varaible to set the selectedIndex property. By binding the selectedIndex to the workflowState value, you now have complete control over what is displayed in the ViewStack from your ModelLocator.

mxml:
  1. <mx:ViewStack id="myViewStack" selectedIndex="{modelLocator.workflowState}">
  2.   ...
  3. </mx:ViewStack>

Example 5 - Binding the selectedIndex to the workflowState

Defining Constants for Better Code

It would be simple to manipulate the view using this method, however, it could lead to potentially confusing code. For example, assume that you have the following:

  • A ViewStack with two children: a Login Screen and a Welcome Screen
  • The ViewStack's selectedIndex is bound to the workflowState property
  • A login button that performs the action shown in Example 4

This might seem as if it works properly, but it doesn't account for any changes. If another child is added to the ViewStack, it could throw off the order. There needs to be a better way to manually set the selectedIndex property. To accomplish this you just need to define constants inside of the ModelLocator.

Actionscript:
  1. //DEFINE YOUR VARIABLES HERE
  2. public var workflowState:uint = 0;
  3.  
  4. // DEFINE VIEW CONSTANTS
  5. public static const LOGIN_SCREEN = 0;
  6. public static const WELCOME_SCREEN = 1;

Example 6 - Defining View Constants in the ModelLocator

By using this method, you only have to change the value in one location if the number of children or the order of the children changes in the ViewStack. Now, you would assign the login button the following action to the click event:

Actionscript:
  1. myViewStack.selectedIndex = ViewModelLocator.WELCOME_SCREEN;

Example 7 - Setting the View with Defined Constants

Not only do you protect against future changes, you also have made your code much more logical. Another developer could easily look at the code and understand the process without having to reference all of the children in the ViewStack.

NOTE: The audio was not that great for this video. I will be using a better system for the next tutorial.

Video Example - Controlling the View with a ModelLocator

Application Code
Download (3 kB)




38 Responses to “Getting Started with Cairngorm – Part 2”

  1. Flex New Guy says:

    These tutorials are very helpful coming from a person who has a somewhat limited programming background. I have done a lot of searching online and find your material to be the most easily understood thus far… can’t wait for part 3.

  2. Erno says:

    Hi from Finland!
    Thanks for creating these tutorials! helps me alot! Keep up good work! Whats gonna be in next part?

  3. David Tucker says:

    I am working on Part 3 right now. Part 3 is the Introduction to the full Cairngorm Micro-Architecture. It will cover the Cairngorm Event Flow and the organization of a Cairngorm project.

  4. [...] Teil 2 dreht sich um die Implementierung des Views mittels des ModelLocator Patterns [...]

  5. Tony Chang says:

    Hi David,

    May I download your flv file.the movie is very useful for me.Thanks

  6. Dekki says:

    Hi,I’m from China.
    These tutorials are greet && thanks you!

  7. Azwidohwi says:

    Hi,

    I’m from South Africa and I have been battling with the framework until I stumbled on this tutorials. Thanks to you i now have my view managers setup. Now I’m off to Part 3!! You are great teacher & trainer.

  8. Rob says:

    Great stuff. Thanks for taking the time to publish it.

  9. [...] Getting Started with Cairngorm – Part 2 [...]

  10. [...] Tucker :: Getting Started With Cairngorm :: Part 1 :: Part 2 :: Part 3 :: Part 4 :: Part [...]

  11. [...] Getting Started with Cairngorm – Part2 [...]

  12. goliath says:

    Recently, following your generous tutorials, David, and in an attempt to get the very basic flex-cairngorm skills (by building a helloWorld app, naturally) i bumped into an issue – “unable to bind to property XXX on class ‘Object’ (class is not an IEventDispatcher)”.

    After googling for a while, giving up, googling again, although it seemed that i’m not the only one having the problem, i couldn’t find anything ‘comprehensible’.

    The forms of this warning can be various probably – in my narrow case, it’s a datagrid, that isn’t populated. In others – it’s a view, not responding to changes of a model, but sending a warning to the console.

    I haven’t yet delved into the nature of the problem – being a novice it’s already tough the way it is; so far, this is what i was able to make out.

    The case.
    The application is meant to fetch entries from a db table using 2 different ‘gateways’ (AMFPHP and ZendAMF). Beside this, i thought it wouldn’t be a bad idea to check on the time it takes for each gateway to do it. So, beside a returned recordset it would be nice to have timestamps.
    The model:
    [Bindable]
    public var amfphp:Object = new Object();
    //recordset via AMFPHP (fed to datagrid 1)
    [Bindable]
    public var zendamf:Object = new Object();
    //same recordset via ZendAMF (fed to datagrid 2)

    When handling the result, if you do this:
    model.amfphp = data.result
    //set amfphp to the recordset, Array
    “{model.amfphp}” it works fine

    If you do this, however:
    model.zendamf.dg = data.result

    you get the warning, and the datagrid isn’t populated.

    The reason you want to do “model.zendamf.dg” is because you want to add some extra properties, like:
    model.zendamf['reqTime'] = xxxx;
    model.zendamf['curTime'] = xxxx;

    So, you ask yourself something like – models can’t or shouldn’t be ‘nested’? What/where is the misunderstanding or misuse?

  13. David Tucker says:

    @goliath – The issue here is that an Object can’t dispatch an event (which is required for binding). You aren’t meant to bind variables to an object’s property. A quick alternative might be to use ObjectProxy. Your other option might be to not utilize an object and bind it to a strongly typed variable.

  14. goliath says:

    Thanks for the prompt reply, David

    i’ve been digging for quite some time, but with little luck so far.

    >>The issue here is that an Object can’t dispatch an event (which is required for binding)

    Yes, i think i got that. The Adobe manuals has the details on binding to Objects or their properties. But there is something confusing here (i might actually be missing out on those ‘details’):
    model.zendamf.dg
    - dg IS a property of an Object
    - but the value associated with it – is an ArrayCollection
    “{model.zendamf.dg}” seems like a binding to the ArrayCollection; not to a an object’s property

    the events dispatched by the ArrayCollection are the ones that the binding should listen for, no? Not the events dispatched zendamf by the object zendamf?

    So, the idea was to have ‘amfphp’ and ‘zendamf’ as a way of grouping data, that is a result of calling the 2 gateways and not having something like:
    var amfphp_dg
    var amfphp_curTimestamp
    var amfphp_reqTimestamp
    i.e. moving the datagrid just a bit lower in the hierarchy to keep everything more ‘tangled’.

    There must be a better way than defining all these variables beforehand, so as to have them ‘bindable’?

    i will take a deeper look into the ObjectProxy

    Thanks again for the answer/guide/tips

  15. Nick says:

    Hello,

    Thanks for setting up a bunch of very useful tutorials!

    I just wonder, if there are multiple nested view stacks within an application, what’s the best way to handle those?

    For instance, the main app has a view stack VS1, which uses a custom MXML component containing VS2.

    So the trick here is that the state change events should modify current state of VS2, not VS1.

    So what’s the best way to handle it? Create multiple ViewModelLocators, one for each view stack?

    Thanks.
    Nick.

  16. Wes says:

    Ur blog is awesome …u made my life easy …thank you ..keep up the great work ..ur a gifted trainer …

  17. chen says:

    nice job!

  18. Ced says:

    I read in the cairngorm documentation that the ModelLocator should not be use to stock variables but just their definition. There were no example after this affirmation.
    My interpretation of this sentence is that in the ModelLocator you can do that:

    public const imagePath:String;

    but not that:

    public const imagePath:String=”../products/”;

    I wonder if declaring constant in the ModelLocator is a good practice.

  19. [...] Artigo sobre Cairngorm parte 2 e o Vídeo Cairngorm Part 2 [...]

  20. Bruce Carvey says:

    Hi. I needed to drop you a quick note to impart my thanks. I’ve been watching your blog for a month or so and have picked up a heap of sound information as well as enjoyed the way you’ve structured your site. I am setting about to run my own blog however I think its too general and I would like to focus more on smaller topics.

  21. [...] Getting Started with Cairngorm – Part2 [...]

  22. Daniel Garay says:

    Excelente turorial David…

    Gracias por tomarte la molestia de enseñar a otros…

  23. hi David,
    I can, without even a single instance of doubt, term your tutorial as the most simple and the best tutorial, for beginners in flex applications implementing MVC. now I am heading towards part 3. Please keep on your good work.

  24. You are the man…

    I wonder if you will do a video in the future that will compare between Pure MVC and CairnGrom. Or illustrate the difference between the two.

    Thankx

  25. Scott Matheson says:

    I just completed 1 week of Flex3 trainig and 1 full day of Cairngorm, i got more out you your first 2 session than the full week, good work, please do more, what about you first app on the iphone

  26. Kofi says:

    Hi David, thanks for all the tuts. its much appreciated. i have a question regarding views.
    lets say my main view uses a viewstack to change its view states. now i know i can bind the viewstack indexs to the model locator etc. thats all fine and dandi…
    but what if i have subviews within my views in the viewstack. how do i handle that? do i bind that to the modellocator as well…or can i define the states locally within the subview. hope you get what i mean.
    whats the best way to handle states of views within views.

  27. Amit says:

    Hi David,

    I am from India, I found your tutorial is very very easy to understand.
    I just wanted to ask that do you have any tutorial for “Parsley Framework”?
    If yes then please mail me that link.

  28. harpalsinh says:

    Hello David;

    Very nice example to learn cairngorm.thanks. I would like to learn more about cairngorm with you.

  29. estetik says:

    I’m from South Africa and I have been battling with the framework until I stumbled on this tutorials. Thanks to you i now have my view managers setup. Now I’m off to Part 3!! You are great teacher & trainer.
    tr

  30. srikanth says:

    Thnx a ton…

  31. Henry says:

    Cool stuff you have David, coz’ its easy to flow with. However, i followed strictly the code in part 1 and my application compiled but
    at run time i get this error – TypeError: Error #1034: Type Coercion failed: cannot convert SingletonEnforcer@70fed31 to com.fusion.samples.model.SampleModelLocator.
    at com.fusion.samples.model::SampleModelLocator$/getInstance()
    What can be wrong?

  32. Tunde says:

    Hello David,

    I from Nigeria, I must say that i find your blog educative and simple enough to affirm a 100% delivery.
    I will watch out for more of your articles on flex frameworks.

    Nice piece of work.