Recently I have been researching the use of PhoneGap for creating HTML5 Windows Phone 7 applications. I have written an introductory post on the subject and also managed to have a HTML5-based application accepted into the marketplace.
The Windows Phone 7 execution model has a few unique features (when compared to Android and iOS) that need to be considered when developing HTML5 applications. The first one, tombstoning, is something I dealt with in an earlier blogpost. In this post I want to look at how to handle the back-button and the application back-stack.
With Windows Phone 7, as the user navigates from one page to the next, the latest page is added to the top of a stack (the back-stack). The back-button is used to navigate back through the pages within your application by pulling them from the top of this stack. When the back stack holds a single page, i.e. the initial entry point into your application, pressing the back-button should exit the application.
In order to emulate the back-stack functionality in a PhoneGap application you need to subscribe to the PhoneGap backbutton when back-navigation is possible within your application, and unsubscribe when it is not. This means that when the user hits the back-button at the entry-point of your application, the application is terminated as expected.
In this blog I'll add further structure to the code, starting with an
ApplicationViewModel. This view model contains a stack of view-models, with the one that is at the top of the stack, exposed via the
currentViewModel observable property, being the one which is rendered on screen. The ApplicationViewModel also exposes functions for adding to and removing items from this stack:
currentViewModel is implemented as a dependent-observable, a really neat KnockoutJS feature where you create a new observable property based on one or more observable properties of a view model. In this case, KnockoutJS does some magic behind the scenes to deduce that
currentViewModel depends upon the
viewModelBackStack observable array. Each time the array is modified, bindings that depend on
currentViewModel are also updated. That's pretty neat!
The UI code needs to be modified so that the view relating to the
currentViewModel is rendered and bound to its respective view model. This is simply a matter of subscribing to changes in this observable property in our code:
For the above code to work, each view model must expose a
template property which identified the HTML template which is their corresponding view. The above code creates a view instance and appends it to the
The templates for the two view-models within this application are shown below:
When a tweet is clicked on, the
select function is invoked via the Knockout binding. This simply pushes a
TweetViewModel instance onto the application stack:
Handling the Back-Button
The above code navigates to the given view model, this will cause the
currentViewModel dependent observable to notify that a change has occurred and the view that relates to this view model will be rendered. The next step is to wire up the back-button.
ApplicationViewModel has a boolean
When the application is initially created, we handle changes to the observable as follows:
backbutton event is handled and the
backbutton event, this results in the Silverlight container handling the back-button. The Silverlight application back-stack always has a single page, so our application will exit.
This technique for handling the back-stack is simple and elegant, this example has just two simple pages, however this same pattern should scale well for more complex HTML5 applications.
You can download the full sourcecode here: PhoneGapBackStack.zip
Regards, Colin E.