Home  >  

Advanced Flex Deep Linking with URLKit

Author photo
| | Comments (21)
AddThis Social Bookmark Button
urlkit

One of the difficulties for rich internet applications (RIA's), is attempting to preserve the traditional browser experience for the user. With Flex applications, there are several barriers to this kind of experience. First, end users are used to using the back and forward buttons to navigate through an a site. Second, users expect each state of an application to be reflected in its URL. Third, users expect that they can bookmark a specific state of an application and return to it at a later time. URLKit addresses these issues in Flex 2/3 applications, and it formed the base of the deep linking support inside of Flex 3. If you are a Flex developer this a tool that you should certainly be familiar with.

Note: URLKit was developed by Joe Berkovitz of NoteFlight and Todd Rein of Adobe Systems.

Introduction to URLKit

Flex 2 provided the history management functionality. There are several reasons why this isn't a complete solution for an application that needs to preserve as much of the traditional browser experience as possible. The developer has little control over the specific URL and how it maps to the specific state of the application (the URL's are automatically created by the Flex application). This also makes it nearly impossible to preserve a URL structure for a future version of the application.

URLKit seeks to extend this type of technology by giving the developer fine-grained bi-directional control over the relationship between the URL and the application's state. It allows you to declare URL mappings for a state of your application within MXML. To understand how this functions inside of Flex, you can view the following sample application that comes bundled with URLKit:

URLKit Sample Application (developed by Joe Berkovitz and Todd Rein)

The Theory Behind URLKit

If you are not familiar with Flex / Flash deep linking technologies, this concept may seem strange. How can the url change without reloading the entire Flex application? In fact any change to the core URL or query string would cause the entire application to reload. However, there is an element of the URL that can be changed - and the page will not reload: anything after the hash symbol. Typically in HTML this is used with 'named anchors', but in this case this string can be used to map the state of a Flex application. Consider the following URL's:

http://www.davidtucker.net/SampleApplication.html
http://www.davidtucker.net/SampleApplication.html#/state1/product1

Both of these URL's would load the same page. Also, if someone entered the first URL, and then he entered the second URL - the page would not reload. This is the core idea behind deep linking with URLKit. In addition, a layer of JavaScript exists between the Flex application and the browser managing the bi-directional communication between the two. With these pieces in place, effective deep linking in Flex can meet all of the criteria for maintaining the traditional browser experience.

Preparing Your Application for URLKit

URLKit can function in both Flex 2 and Flex 3, but the procedure for setting up these environments for URLKit is different. If you are using Flex 2, check out the article listed at the end of this tutorial, "Using Flex 3’s Deep Linking Features in Flex 2".

You will first need to obtain URLKit from here. Once you have downloaded and expanded the file, you will want to look for the urlkitFlex3.swc file inside of the urlkit/bin directory. This will need to be added to your project's build path for URLKit to function properly. Once you have added this to your application, you are ready to start working with URLKit.

A Basic Example

With this knowledge, you can build a simplistic example that will illustrate this functionality. URLKit has four different rules for mapping URL's to an application's state. I will cover these in depth later, but for this example, I will be using UrlValueRule which maps a single value in the URL to a property within the application.

For any URLKit rule to work, you need to have a single instance of the URLBrowserManager component in your application. This is the component that connects URLKit to the BrowserManager inside of Flex 3. Without this, your rules will not work.

In the following example, I created an application with a ViewStack. This ViewStack contains six Box components. I want to be able to map the selectedIndex on the ViewStack to a property in the URL. Since we are using UrlValueRule (later in this article, you will learn about another rule that would work better in this situation), we can map this property to a value inside of the URL.

<url:FlexBrowserManagerAdapter applicationState="{urlRules}" />
<url:UrlValueRule id="urlRules" urlFormat=";view=*"
	sourceValue="mainVS.selectedIndex" defaultValue="0" />

Sample Application (view source enabled)

Know the Rules

As I mentioned previously, UrlValueRule is not the only value that you can use with URLKit. By default, URLKit has four different rules:

  • UrlValueRule - As show previously, this rule enables the developer to map a portion of the URL to a property of the application. When using the UrlValueRule in this manner, the two values (the URL and the application property) are both bound to each other which means that a change in one will mean a change in the other. If you do not wish to use the binding, UrlValueRule also dispatches a change event which can also be used to trigger a change in state.
  • UrlNavigatorRule - I mentioned previously that our application could have benefitted from a different rule other than UrlValueRule. UrlNavigatorRule is designed specifically to work with Accordian's, NavBar's, TabNavigator's, and ViewStack's. So, instead of having to map the URL value to the selectedIndex property, you simply need to tell the rule what navigator it needs to point to. It handles the rest. Sample UrlNavigatorRule Example (View Source Enabled)
  • UrlDelegateRule - This rule allows the developer to pass off a portion of the URL mapping to another rule (or rule set). This is commonly used so that the main application can pass off a portion of the mapping to a child component. In that way the URL can reflect the state of nested components. For this to work properly, you will need to use the next rule, UrlRuleSet.
  • UrlRuleSet - This rule allows you to group multiple rules together so that a single URL can be parsed for multiple values. It also allows you to state in which way you want to the child rules to match the URL.

By using these rules, you can accomplish sophisticated deep linking through multiple nested components inside of Flex.

Using Multiple Rules

UrlRuleSet enables you to chain multiple rules together: with each rule taking a piece of the URL and working with it. To illustrate this point, I created a simple example that extends our previous one. Now, both the ViewStack's selected child and the color of those children are bound to the URL. This is defined within a UrlRuleSet like this:

<url:UrlRuleSet id="urlRules">
	<url:UrlNavigatorRule id="viewRule" urlFormat=";view=*"
		title="Application View" viewStack="{mainVS}" />
	<url:UrlValueRule id="colorRule" urlFormat=";color=*"
		numberValue="{bgColor}"
		change="bgColor = colorRule.numberValue" defaultValue="0"/>
</url:UrlRuleSet>

The application now also contains a color picker at the bottom that lets the user pick the color. When either the color or view is changed, both are reflected in the URL.

In this example - there is one important distinction to make. The two links below both contain the same color value. If everything works, both of these examples should come up with a dark red background. If you go to the following URL, everything should work as planned:

http://www.davidtucker.net/staging/urlkit/three/#;view=View0;color=10027008

However, the following link does not work correctly:

http://www.davidtucker.net/staging/urlkit/three/#;color=10027008

The reason lies with the type property for the UrlRuleSet. UrlRuleSet allows you to match URL's in one of three ways:

  • all (default) - When the type property is set to 'all', every rule inside of the UrlRuleSet must match the URL. If even one rule does not match the URL, none of the rules are mapped.
  • any - If the type property is set to 'any', some of the child rules may be mapped - and others won't be.
  • one - For the times when the type property is set to 'one', only the first rule in the UrlRuleSet that matches the URL will be mapped.

This explains the reason that the second example above did not work correctly. If you pass in a color alone, the viewRule is not matched. However, because the color has a default value, you can pass in the view alone, and the rules will be mapped. Consider the following example:

URL: /index.html#/view1;minValue=2;maxValue=10

<url:UrlRuleSet id="urlRules" type="all">
	<url:UrlNavigatorRule id="viewRule" urlFormat="/*"
		title="Application View" viewStack="{mainVS}" />
	<url:UrlValueRule id="minValueRule" urlFormat=";minValue=*"
		sourceValue="this.minValue" />
	<url:UrlValueRule id="maxValueRule" urlFormat=";maxValue=*"
		sourceValue="this.maxValue" />
	<url:UrlValueRule id="sortOrderRule" urlFormat=";sortOrder=*"
		sourceValue="this.sortOrder" />
</url:UrlRuleSet>

There are four child rules for the above UrlRuleSet. In this example, the type property of the UrlRuleSet is 'all'. This means that all of the rules must match for any of them to be mapped. In this case (with the URL listed above), none of the rules would be mapped. If the type property was set to 'any' the first three rules would be executed since they have matched in the URL. Finally, if the type property was set to 'one', only the first rule would executed (since it is the first child rule of the UrlRuleSet that matches the URL).

With the previous examples as evidence, the defaultValue property can be very important. It can directly affect the way in which URL's are parsed. If it cannot match a portion of the URL it will just default to the defaultValue. Every rule that you consider 'optional' or every value that you do not want reflected in the URL all the time - should have a defaultValue set. Also, if there is a default state that the application resides in, you probably need to set a defaultValue for its URL mapping rule.

Delegating Responsibility

As stated earlier, URLKit can map the state not only in the root file, but also in child components. To accomplish this, you will use the UrlDelegateRule. The UrlDelegateRule will in most cases will need only one parameter, 'rule', which will be the rule that the mapping will be delegated to.

When working with UrlNavigatorRule's there is a property that eases the use of UrlDelegateRule's. According to the URLKit documentation, "navigatorChildRule is a special, bindable, property on UrlNavigatorRule, that returns a child’s URL rules. It updates whenever the selected child of the navigator changes." The developer could also choose to use an expression in place of navigatorChildRule (which would be required if you were using another rule besides UrlNavigatorRule). However, for this to work properly, each UrlRuleSet in the child components must have an id of 'urls'.

In the following example, there are three levels of nesting within the application:

  • Main.mxml - The root of the application contains a TabNavigator with three child components of type SampleView. It has a UrlRuleSet that takes the first portion of the URL and delegates the rest of the URL to the currently selected child component of TabNavigator.
  • SampleView.mxml - This component contains another TabNavigator with three child components of type ChildView. It contains a UrlRuleSet (with an id of 'urls'). The rule set contains a UrlNavigatorRule that maps the first portion of the URL. The remaining portion of the URL is delegated to the currently selected child of the TabNavigator.
  • ChildView.mxml - This component contains an Accordian with three child components of type HBox. It has a single UrlNavigatorRule that maps the final portion of the URL to the Accordian.
appDiagram-large.jpg
Figure 1. UrlDelegateRule Sample Application

Sample Application (view source enabled)

Conclusion

Hopefully, you see the value of having a deep linking tool as powerful as URLKit in your arsenal. If URLKit is more than what you need, you may want to check out the basic Flex 3 Deep Linking functionality. I have included links to LiveDocs below where you can get additional information on its functionality.

Resources

URLKit at Google Code
URLKit Documentation
Using Flex 3’s Deep Linking Features in Flex 2
Flex 3 - Using the BrowserManager
Flex 3 Language Reference - BrowserManager

Read more from David Tucker. David Tucker's Atom feed

Comments

21 Comments

Steve W said:

Thanks for the information. Any idea if this will be baked into Flex 4?

David Tucker said:

My assumption is that the current deep linking that was introduced in Flex 3 will remain, but URLKit will remain a separate project.

Adnan Doric said:

There is no preloader in "URLKit Sample Application".
Is this because of deep linking ?

If yes, it is not very usefull for the moment.

( Firefox 3.0.3 / FP 9.0.124 )

matthew said:

thank u r information

it very useful

u r blog Is very nice


Until I read the comment by Adnan, I thought the sample application was improperly compiled. If the preloader malfunctions when an app implements the URLKit, I personally think most developers will be inclined to avoid it.

I still think the project is a great tool for flex devs. Keep up the good work!

multik said:

This is not working in opera browser.

David Liu said:

There is no preloader for any Flex application when using "#" in URL. This is a known bug for now.

Refer to: http://www.mail-archive.com/flexcoders@yahoogroups.com/msg99894.html

and: http://bugs.adobe.com/jira/browse/SDK-14162

Just to give credit to URLKit, not their fault.

sky said:

thanks David, that is a great article.

Adnan Doric said:

@David Liu

Indeed, sorry if it wasn't clear. Deep linking is broken and not useful atm. URLKit can be useful for lot of people even if I'll stick to SWFAddress.

When I try using navBar with a ToggleButtonBar I get an error, anyone can help me with this? I modified the code fourth example so it looks something like this:



david said:

In the fist sample (http://www.davidtucker.net/staging/urlkit/one/#), how to prevent an out of index exception of the stackview. Because users can enter URL with negative index (like view = -1)

Thank you

Dil said:


David,
Thank you for providing a detailed information about urlkit.
I was trying to implement this in my app and faced the following issues

1) In your first sample application (viewstack) we cannot move backward up to "0" position, as it was the first screen - how can we set it to that initial step? (the defaultValue is set to "0")


2) downloaded urlkit from googlecode is having a tag prefix as instead of

Hope you can help me

Thanks
Dil

Dil said:


David,
Thank you for providing a detailed information about urlkit.
I was trying to implement this in my app and faced the following issues

1) In your first sample application (viewstack) we cannot move backward up to "0" position, as it was the first screen - how can we set it to that initial step? (the defaultValue is set to "0")


2) downloaded urlkit from googlecode is having a tag prefix as instead of

Hope you can help me

Thanks
Dil

Rob said:

This is great, I look forward to implementing it soon!

Lance said:

Man, this is great! I got to using URLKit in like 5 minutes from this, awesome!

I am still wondering how this compares to SWFAddress, because their google analytics and sitemap features sound interesting. Would this be possible with URLKit?

Thanks!
Lance

Rich Tretola said:

David,

What is the event that you can listen for when the URL address is rewritten?

leo said:

David Liu said:

There is no preloader for any Flex application when using "#" in URL. This is a known bug for now.

Refer to: http://copilka.info/

and: http://tsitologiya.ru/

johnsmth.smith15 said:

Let's get one thing out of the way - Flex 2 is not a replacement for Flash. Flash 9 will hopefully arrive some time near christmas and a preview was released on Labs today. Flex was the first to to leverage the possibilties of the new Flash Player 9 but if you download the AS3 extension from dedicated hosting Labs you can code AS3 in Flash 8 today. Flex is a tool for building applications. It has no Timeline, no Library, no drawing tools. It is primarily a tool to create applications based on a set of easy extendable components that connects to data services on the web. It may be used by designers to lay out the forms in an application, but it is created with Programmers in mind for web site design

Does this still work with Flex 4?

Because I get:

TypeError: Error #1009: Cannot access a property or method of a null object reference.
at urlkit.rules::FlexBrowserManagerAdapter/initializeState()[/Users/joeb/Work/urlkit/urlkit/src/urlkit/rules/FlexBrowserManagerAdapter.as:284]
at urlkit.rules::FlexBrowserManagerAdapter/syncState()[/Users/joeb/Work/urlkit/urlkit/src/urlkit/rules/FlexBrowserManagerAdapter.as:239]
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/callLaterDispatcher2()[E:\dev\beta1\frameworks\projects\framework\src\mx\core\UIComponent.as:10408]
at mx.core::UIComponent/callLaterDispatcher()[E:\dev\beta1\frameworks\projects\framework\src\mx\core\UIComponent.as:10348]

When changing it to Flex 4 code like this:


xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo"
xmlns:url="http://www.allurent.com/2006/urlkit"
viewSourceURL="srcview/index.html">






title="Application View {mainVS.selectedIndex}"
sourceValue="mainVS.selectedIndex"
defaultValue="0" />











click="mainVS.selectedIndex = ( ( mainVS.selectedIndex == 5 ) ? 0 : mainVS.selectedIndex + 1 )" />

FYI: Fixed the previous issue.
It was just 2 lines of code that needed to be adjusted for Flex 4 compatibility.

Greets

Mark Foster said:

Helpful post.

Am I correct in the conclusion that URLKit is based around tags in the view for its implementation vs. managing state in ActionScript.

I am working with using a State Design pattern and a presentation model so the view is not really where I want my URL rules and logic.

If this is the case, I suspect swfAddress is better for my approach as I need to implement my url management in actionscript and it seems better adapted to that.

Comments? Thanks.

Leave a comment


Tag Cloud

Poll: Mobile Features

What feature do you use most on your mobile phone?

Vote | View Poll Results | Read Related Blog Entry

Latest Features

Recommended for You

@InsideRIA on Twitter

Archives

  • Or, visit our complete archive.  

About This Site

Welcome to the premiere community site for all things RIA sponsored by O'Reilly Media and Adobe Systems Incorporated.