Learn about the single-page navigation model and how you can implement it in your own app by using Page controls and WinJS.Navigation features.
Prerequisites
-
We assume that you can create a basic Windows Store app built for Windows using JavaScript. For help creating your first app, see Create your first Windows Store app using JavaScript.
-
We assume that you are familiar with the Windows Library for JavaScript controls. For help using Windows Library for JavaScript controls, see Quickstart: Adding Windows Library for JavaScript controls and styles.
Creating a basic link
One of the simplest and most commonly used forms of navigation is the hyperlink. The following code creates a hyperlink that navigates to page2.html.
<p><a href="page2.html">Go to page 2</a></p>
Because it's a relative link, the system assumes that page2.html is a local page that's part of your app, relative to current document's base URL. For example, if the link appears in /folder/default.html, clicking the link takes you to /folder1/page2.html.
If you want to explicitly specify the full URI for a local file in your application, you use the ms-appx URL scheme:
ms-appx://package name/file path
If you want, you can omit the package name:
ms-appx:///file path
Here's an example:
<p><a href="ms-appx:///page2.html">Go to page 2</a></p>
You can use the new packaged content URL scheme (ms-appx) to refer to any file that is included in the app’s package.
We recommend using relative URLs because they are automatically resolved based on the document's base URL.
Navigating the recommended way
The previous example showed you how to create a link that performs a top-level navigation, which is fine for a web page, but you shouldn't perform top-level navigations in an app for several reasons, including these:
- The app screen goes blank while it loads the next page.
- The script context is destroyed and must be initialized again. The app might receive system events but not handle them because the script context is being destroyed and reinitialized.
Using the single-page navigation provides better performance and provides a more app-like experience. Windows Store apps using JavaScript don't automatically provide navigation controls, so when you perform a top-level navigation to a new page, there's no way to get back to the first page unless you create a link or other navigation mechanism that takes you back. Also, your start page is the place to define how your app manages its lifecycle: how it behaves when it starts up, shuts down, is suspended, and so on. If you have multiple top-level pages, each one must contain logic for managing the app's lifecycle and state.
Navigation models: multi-page and single-page
Nearly every website provides some form of navigation, usually in the form of hyperlinks that you click to go to a different page. Each page has its own set of JavaScript functions and data, a new set of HTML to display, style information, and so on. This navigation model is known as multi-page navigation.
Another navigation model is single-page navigation, where you use a single page for your app and load additional data into that page as needed. You still split your application into multiple files, but instead of moving from page to page, your app loads other documents into the main page. Because your app's main page is never unloaded, your scripts are never unloaded, which makes it easier to manage state, transitions, or animations. We recommend that Windows Store apps using JavaScript use the single-page navigation model.
Which control should you use to bring content into your main page?
- You can use the DOM to load documents from another source.
- For simple HTML content (content that isn't interactive and doesn't contain script references), use an HtmlControl.
- For external web content, use an iframe.
- For all other content, use a Page control.
Microsoft Visual Studio Express 2012 for Windows 8 provides several new project templates that can make managing navigation easier. The Grid Application, Split Application, and Navigation Application templates provide a navigation control, called PageControlNavigator, that you can use to navigate between different Page controls. The PageControlNavigator class demonstrates one way that you can use Page controls to facilitate single-page navigation.
The next steps show you how to create an app that contains multiple Page controls and how to use the single-page navigation model to navigate between those pages.
Step 1: Create a new Navigation App project
-
Launch Visual Studio Express 2012 for Windows 8.
-
From the Start Page tab, click New Project. The New Project dialog box opens.
-
In the Installed pane, expand Templates, expand JavaScript, and then select the Windows Store app template type. The available project templates for JavaScript are displayed in the center pane of the dialog box.
-
In the center pane, select the Navigation App project template.
-
In the Name text box, enter a name for your project. The examples in this topic use "NavigationAppExample".
-
Click OK to create the project. This will take a moment.
Take of tour of your new project
Your new Navigation app project contains a start page, a home page, and some additional supporting files.

Your new Navigation App project includes these HTML files:
- default.html, which is the start page. It is loaded first. It contains an instance of the PageControlNavigator (which loads each page into the main window) and it's where you'd create your AppBar if your app uses one.
- home.html, which is the home page. It displays a "Welcome" title.
The project includes these JavaScript files:
- default.js, which specifies how the app behaves when it's started.
- home.js, which specifies behavior that's associated with the home page.
- navigator.js, which implements the PageControlNavigator object that supports the navigation model for the Windows Store app JavaScript templates.
The project includes these CSS files:
- default.css, which specifies CSS styles for the content host page and for the app as a whole.
- home.css, which specifies CSS styles for the home page.
The project also includes the package.appxmanifest file, which describes the app package for Windows. The project also includes several image files, like splashscreen.png for the splash screen image, and storelogo.png, which is used for Windows Store.
Run the app. It shows the text "Welcome to NavigateAppExample" and "Content goes here".

Notice that this content you're seeing isn't defined in the default.html file. It's defined in the home.html file, a separate Page. It's the PageControlNavigator that retrieves the content of the home page and displays it inside default.html. Here's the complete markup for the default.html page.
<!-- default.html --> <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>NavigationAppExample</title> <!-- WinJS references --> <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" /> <script src="//Microsoft.WinJS.1.0/js/base.js"></script> <script src="//Microsoft.WinJS.1.0/js/ui.js"></script> <!-- NavigationAppExample references --> <link href="/css/default.css" rel="stylesheet" /> <script src="/js/default.js"></script> <script src="/js/navigator.js"></script> </head> <body> <div id="contenthost" data-win-control="Application.PageControlNavigator" data-win-options="{home: '/pages/home/home.html'}"></div> <!-- <div id="appbar" data-win-control="WinJS.UI.AppBar"> <button data-win-control="WinJS.UI.AppBarCommand" data-win-options="{id:'cmd', label:'Command', icon:'placeholder'}"> </button> </div> --> </body> </html>
This illustration shows the different units of content that appear in the app's window:

In the next steps, you'll learn more about how to use the PageControlNavigator and Page controls by creating your own page.
Step 2: Create a new Page control
- In the solution explorer, right click the pages folder and select New Folder. Name the folder "page2".
- Right click the page2 folder and select Add > New Item.
- Select Page Control and use the name "page2.html".
- Click Add to create the Page. Visual Studio creates three files: page2.html, page2.js, and page2.css. Together, these files represent a Page control.
Step 3: Customize your Page
Now, modify your new Page so that it displays a different message and the day of the week.
- Open page2.html. The Page template creates an HTML page that contains a header section (which contains a back button) and a section for the page's main content.
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>page2</title> <!-- WinJS references --> <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" /> <script src="//Microsoft.WinJS.1.0/js/base.js"></script> <script src="//Microsoft.WinJS.1.0/js/ui.js"></script> <link href="page2.css" rel="stylesheet" /> <script src="page2.js"></script> </head> <body> <div class="page2 fragment"> <header aria-label="Header content" role="banner"> <button class="win-backbutton" aria-label="Back" disabled></button> <h1 class="titlearea win-type-ellipsis"> <span class="pagetitle">Welcome to page2</span> </h1> </header> <section aria-label="Main content" role="main"> <p>Content goes here.</p> </section> </div> </body> </html>
- Replace the main content section with this one.
<section aria-label="Main content" role="main"> <p>Page controls make it easy to divide your app into modular portions.</p> <p>Today is <span id="dayPlaceholder"></span>.</p> </section>Your page2.html file should now look like this:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>page2</title> <!-- WinJS references --> <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" /> <script src="//Microsoft.WinJS.1.0/js/base.js"></script> <script src="//Microsoft.WinJS.1.0/js/ui.js"></script> <link href="page2.css" rel="stylesheet" /> <script src="page2.js"></script> </head> <body> <div class="page2 fragment"> <header aria-label="Header content" role="banner"> <button class="win-backbutton" aria-label="Back" disabled></button> <h1 class="titlearea win-type-ellipsis"> <span class="pagetitle">Welcome to page2</span> </h1> </header> <section aria-label="Main content" role="main"> <p>Page controls make it easy to divide your app into modular portions.</p> <p>Today is <span id="dayPlaceholder"></span>.</p> </section> </div> </body> </html>
- Open page2.js. The Page control includes a set of predefined functions that get called automatically, in a predefined order. The Page item templates provide ready, updateLayout, and unload functions for you.
The PageControlNavigator calls the updateLayout function when the app's view state changes. It's called when the app switches between portrait, snapped, full screen, and filled view states. This topic won't show you how to define the updateLayout, but it's something that every app should do. For more info about view states, see Guidelines for layouts.
The ready function is called when the page's DOM has been loaded, controls are activated, and the page has been loaded into the main DOM.
(The Page control supports additional functions for the page lifecycle. For more info, see Adding Page controls.)
Here's the page2.js file that the Page template created.
// page2.js (function () { "use strict"; WinJS.UI.Pages.define("/pages/page2/page2.html", { // This function is called whenever a user navigates to this page. It // populates the page elements with the app's data. ready: function (element, options) { // TODO: Initialize the page here. }, updateLayout: function (element, viewState, lastViewState) { /// <param name="element" domElement="true" /> /// <param name="viewState" value="Windows.UI.ViewManagement.ApplicationViewState" /> /// <param name="lastViewState" value="Windows.UI.ViewManagement.ApplicationViewState" /> // TODO: Respond to changes in viewState. }, unload: function () { // TODO: Respond to navigations away from this page. } }); })();
Modify the ready function so that it retrieves the span you created in step 2 ("dayPlaceholder") and sets its innerText to the current day.
// page2.js (function () { "use strict"; WinJS.UI.Pages.define("/pages/page2/page2.html", { // This function is called whenever a user navigates to this page. It // populates the page elements with the app's data. ready: function (element, options) { // TODO: Initialize the page here. var dayPlaceholder = document.querySelector("#dayPlaceholder"); var calendar = new Windows.Globalization.Calendar(); dayPlaceholder.innerText = calendar.dayOfWeekAsString(); }, updateLayout: function (element, viewState, lastViewState) { /// <param name="element" domElement="true" /> /// <param name="viewState" value="Windows.UI.ViewManagement.ApplicationViewState" /> /// <param name="lastViewState" value="Windows.UI.ViewManagement.ApplicationViewState" /> // TODO: Respond to changes in viewState. }, unload: function () { // TODO: Respond to navigations away from this page. } }); })();
You've created and customized a page. In the next step, you'll enable the user running the app to navigate to your page.
Step 4: Use the navigate function to move between pages
When you run the app right now, it displays home.html; there's no way for the user to navigate to page2.html. A simple way of letting the user make it to page2.html is to link to it from your home.html file:
<!-- home.html --> <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>homePage</title> <!-- WinJS references --> <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" /> <script src="//Microsoft.WinJS.1.0/js/base.js"></script> <script src="//Microsoft.WinJS.1.0/js/ui.js"></script> <link href="/css/default.css" rel="stylesheet" /> <link href="/pages/home/home.css" rel="stylesheet" /> <script src="/pages/home/home.js"></script> </head> <body> <!-- The content that will be loaded and displayed. --> <div class="fragment homepage"> <header aria-label="Header content" role="banner"> <button class="win-backbutton" aria-label="Back" disabled></button> <h1 class="titlearea win-type-ellipsis"> <span class="pagetitle">Welcome to NavigationAppExample!</span> </h1> </header> <section aria-label="Main content" role="main"> <p>Content goes here.</p> <!-- A hyperlink to page2.html. --> <p><a href="/pages/page2/page2.html">Go to page 2.</a></p> </section> </div> </body> </html>
Run the app and click the link. It seems to work: the app displays page2.html. The problem is that the app performs a top-level navigation. Instead of navigating from home.html to page2.html, it navigates from default.html to page2.html.

What you want instead is to replace the content of home.html with page2.html.

Fortunately, the PageControlNavigator control makes performing this type of navigation fairly easy. The PageControlNavigator code (in your app's navigator.js file) handles the WinJS.Navigation.navigated event for you. When the event occurs, the PageControlNavigator loads the page specified by the event.
The WinJS.Navigation.navigated event occurs when you use the WinJS.Navigation.navigate, WinJS.Navigation.back, or WinJS.Navigation.forward functions to navigate.
You need to call WinJS.Navigation.navigate yourself rather than using the hyperlink's default behavior. You could replace the link with a button and use the button's click event handler to call WinJS.Navigation.navigate. Or you could change the default behavior of the hyperlink so that when the user clicks on a link, the app uses WinJS.Navigation.navigate to navigate to the link target. To do this, handle the hyperlink's click event and use the event to stop the hyperlink's default navigation behavior, and then call the WinJS.Navigation.navigate function and pass it the link target.
- In your home.js file, define a click event handler for your hyperlinks.
function linkClickEventHandler(eventInfo) { } - Call the preventDefault method to prevent the default link behavior (navigating directly to the specified page).
function linkClickEventHandler(eventInfo) { eventInfo.preventDefault(); } - Retrieve the hyperlink that triggered the event.
function linkClickEventHandler(eventInfo) { eventInfo.preventDefault(); var link = eventInfo.target; }
- Call the WinJS.Navigation.navigate function and pass it the link target. (Optionally, you could also pass a state object that describes the state for that page. For more information, see the WinJS.Navigation.navigate page.)
function linkClickEventHandler(eventInfo) { eventInfo.preventDefault(); var link = eventInfo.target; WinJS.Navigation.navigate(link.href); }
- In the home.js file's ready function, attach the event handler to your hyperlinks.
WinJS.UI.Pages.define("/pages/home/home.html", { // This function is called whenever a user navigates to this page. It // populates the page elements with the app's data. ready: function (element, options) { // TODO: Initialize the page here. WinJS.Utilities.query("a").listen("click", linkClickEventHandler, false); } });That's the last step. Here's the complete code for your home.js file.
// home.js (function () { "use strict"; WinJS.UI.Pages.define("/pages/home/home.html", { // This function is called whenever a user navigates to this page. It // populates the page elements with the app's data. ready: function (element, options) { // TODO: Initialize the page here. WinJS.Utilities.query("a").listen("click", linkClickEventHandler, false); } }); function linkClickEventHandler(eventInfo) { eventInfo.preventDefault(); var link = eventInfo.target; WinJS.Navigation.navigate(link.href); } })();
Run the app and click the link for page2.html.

This time the page displays using the proper navigation pattern.

Notice that the page now has a back button. The Page control template includes a back button that becomes enabled when you use the WinJS.Navigation functions to navigate. When you use the WinJS.Navigation functions, the app stores navigation history for you. You can use the navigation history to navigate backwards by calling WinJS.Navigation.back or to navigate forward by calling WinJS.Navigation.forward. For more info, see the WinJS.Navigation namespace.
Saving navigation history when your app is suspended
Navigation history is not automatically stored when your app is suspended or shut down, but it's easy to store this info yourself. Use the WinJS.Navigation.history property to retrieve and navigation history and use the WinJS.Application.sessionState object to store it. To ensure a smooth suspend/resume experience, it's best to store this info each time the user navigates.
When your app resumes, retrieve the history info from the WinJS.Application.sessionState object and use it to set the WinJS.Navigation.history property.
For an example showing how to use the WinJS.Application.sessionState object to store and restore session data, see "Hello, world" part 2: Manage app lifecycle and state. For more info about suspending and resuming, see Launching, resuming, and multitasking.
Summary
You learned how to use WinJS.UI.Pages to support the single-page navigation model.
You leaned how to build apps using the single-page navigation model. You used the PageControlNavigator class, provided by the templates, to implement this model in your own app using PageControl objects and WinJS.Navigation features.
Related topics
Build date: 11/27/2012