Flex and Deep Linking

What is Deep Linking?

Deep Linking is a term that describes the support for URL based navigation in applications that are not a collection of HTML pages. In a web site, for example, if you have a menu with Home, About Us, and Contact, whenever someone chooses an item from the menu, the browser will point to a new URL, such as http://mysite/home.html or http://mysite/contact.html. This is great because you can bookmark the page that you have an interest in and you can give the link to your friend. Without this, you have to send your friend a link to http://mysite along with an explanation about how to get to the Contact page.

In Flex applications, when you don’t use Deep Linking this is also the case. You are not able to bookmark a particular state of the application or to send someone just a link to get him to the Contact form page. Deep Linking fixes this and also enables the browser back button.

How does it work in Flex?

In Flex 3, Deep Linking is implemented using fragments, the portions of URLs after the “#”. For example, in this link http://mysite/page.html#view=1 the fragment is view=1. Whenever you add to URL fragments (and you can write basically anything you want) the browser does not reload the page. This is exactly what you need in a Flex application. In a Flex app you have all the states inside of a SWF file, and thus you don’t change the content by reloading another page.

Flex uses these fragments to “store” the state and when an URL is loaded, the Flex application can analyze the URL fragments to recreate the state corresponding to that URL. Let’s see how a programmer can write and read URL fragments from within a Flex app.

BrowserManager is a Singleton that acts as a proxy between the browser and the Flex application. It lets you:

  • set fragments in the current URL
  • set the HTML title
  • register event listeners on URL change events

The second class we use is the static class URLUtil which has methods to manipulate URLs. The last thing to know is that we need to turn off the HistoryManager (which enables back/forward navigation in Flex apps) in order to not interfere with fragment processing. We can turn it off by setting the property historyManagementEnabled to false (for example: <mx:Application historyManagementEnabled=”false”>).

Most of the work a programmer does for Deep Linking is centered on creating functions that either “serialize” the current state to URL or “deserialize” the URL and use that information to change the Flex application state.

A Simple Example

Let’s see a simple Flex application that use Deep Linking. It has three states: the default state, “Step 2” state and “Step 3” state. Click here to open the application – you can see the source code by choosing “View Source” from the contextual menu (right click on the application). To illustrate different states in the application, I used an accordion. I could have used mx:states, a tabset or some other UI components. It wouldn’t matter, the principle is the same. As I said the main task a programmer has while working with Deep Linking is to create the functions to serialize the state to URL and deserialize the URL to get the states out of it. Then, you need to hook these functions into your application by registering them as event listeners. Usually, the function for creating the URL gets called a lot from different parts of your application. In my sample these functions are doUpdateURL() for serializing to URL and parseURL() for deserializing the URL. In the application, the URL controls what step of the accordion is selected. For this I read the current selectedIndex from the accordion and I save it as a fragment. For example, for step 2, I will have something like this: http://corlan.org/downloads/examples/deep_linking_project/deep_linking_project.html#view=1 – note the view=1 at the end of the URL, this is the fragment that stores the selectedIndex.

As you can see in the mx:Application I set the historyManagementEnabled property to false. Then I declare three variables: one to keep a reference to BrowserManager, one flag to use it when parsing the URL and one variable to store the titles I want to be displayed for each state.

Then I define the init() function; this is called when the application gets loaded. Here we initialize the browserManager variable and add to browserManager the event listener for URL changes. The last line calls the parseURL() function, see the description of this function below.

//local reference to the singleton class BrowserManager
public var browserManager:IBrowserManager;
//flag to signal that a URL parsing is in progress
private var isParsing:Boolean;
//string arrays which stores the titles to be used for each state
private var arrTitles:Array = ["Welcome to Flex Deep Linking Example", "Step 2", "Step 3"];

/**
 * this function is called when the app is loaded. 
 * It is initializing the browserManager variable and it registers an event listener 
 * for BROWSER_URL_CHANGE event.
 */
private function init():void {
    browserManager = BrowserManager.getInstance();
    browserManager.init("", "Welcome to Flex Deep Linking Example");
    browserManager.addEventListener(BrowserChangeEvent.BROWSER_URL_CHANGE, parseURL);
    callLater(parseURL);
}

Next I define the parseURL() function which is the event listener registered to browserManager. This function reads the URL, and if fragments are found, it sets the title and changes the selection in the accordion.

/**
 * This is the event listener called whenever the browser URL changes. 
 * @param event
 */
private function parseURL(event:Event = null):void {
    isParsing = true;
    //retrieve the current fragmens from the browser URL and parse them into an Object;
    //eg if we had view=1 we will have an object with the propery "view" and value "1"
    var o:Object = URLUtil.stringToObject(browserManager.fragment);
    //if it is the default state URL;
    if (o.view == undefined)
        o.view = 0;
    //set the accordion selection to the one retrieve it from URL    
    ac.selectedIndex = o.view;
    //set the title displayed by the browser to the title coresponding to accordion selection
    var title:String = arrTitles[o.view];
    browserManager.setTitle(title);
    isParsing = false;
}

Then I define the updateURL() function which is called when someone makes a selection in the accordion. This function verifies that no other instance of parseURL() is running in the same time; if not, it calls doUpdateURL().

/**
 * Event listener registered for accordion changes;
 */
private function updateURL():void {
    //if we are not doing a parsing of URL
    if (!isParsing)
        //callLater postpones the execution of the given function until the next frame; 
        //thus the UI has a chance to be created;
        callLater(doUpdateURL);
}

The last function is doUpdateURL(). This function rewrites the browser URL and page title:

/**
 * This function modifies the browser URL.
 */
private function doUpdateURL():void {
    var title:String = "";
    var fragments:String = "";
    var o:Object = {};
    //if the user selected other step of the accordion than the first one
    if (ac.selectedIndex > 0)
        o.view = ac.selectedIndex;
    //retrieve the title for the selected state    
    title = arrTitles[ac.selectedIndex];
    //serialize the object to fragmenst string
    fragments = URLUtil.objectToString(o);
    //sets the title of the browser
    browserManager.setTitle(title);
    //sets the fragments to the browser URL
    browserManager.setFragment(fragments);
}

And last we need the UI. I used an accordion to simulate different states. On the mx:accordion I registered the function updateURL() for the change event.

<mx:HBox>
        <mx:Accordion id="ac" change="updateURL()" width="200">
            <mx:Canvas label="Step 1" width="100%" height="100%">
                <mx:TextArea editable="false" text="Step 1 Accordion Content" height="300" width="100%"/>
            </mx:Canvas>
            <mx:Canvas label="Step 2" width="100%" height="100%">
                <mx:TextArea editable="false" text="Step 2 Accordion Content" height="300" width="100%"/>
            </mx:Canvas>
            <mx:Canvas label="Step 3" width="100%" height="100%">
                <mx:TextArea editable="false" text="Step 3 Accordion Content" height="300" width="100%"/>
            </mx:Canvas>
        </mx:Accordion>

        <mx:Canvas width="439" height="82">
            <mx:TextArea x="19" y="10" width="410" height="62" editable="false" text="Sample Application for Deep Linking in Flex. As you change the Accordion selection the URL is updated and you can paste this URL in a new browser. The state of the application is recreated from the URL."/>
        </mx:Canvas>
    </mx:HBox>

One last thing: BrowserManager talks to the browser using JavaScript. because not all browsers work the same, Deep Linking works with: Internet Explorer 6 & 7 (Win), Firefox (Mac & Win), Safari (Mac).

That’s it! If you want to find more you can visit the Adobe page or you can search the Flex 3 documentation on BrowserManager.

4 thoughts on “Flex and Deep Linking

  1. I have a application with login screen. After login, user will see another screen. The another screen is added with addChild, when the login screen is removed with removeChild. The login screen and after login screen are custom components.

    Now when i refresh the browser, the application returns in the login screen. I want to remain in the same place. I tried with HistoryManager, but i cant make it.

    Please help me out. Thanks in advance.

Leave a Reply

Your email address will not be published. Required fields are marked *