NavigationYour app can navigate from the page hosting the Cordova WebView to additional all-native pages (and back). These pages can be constructed programmatically in JavaScript, or they can be defined in markup. You have three markup options:
When using XAML, you gain the option of using elements from the cross-platform UI framework in addition to (or instead of) raw platform-specific elements. Navigating with <a>If your target page is defined in markup, you can use a hyperlink: <a href="native://page.xaml"> Go to an all-native page </a> <a href="android://page.xml"> Go to an Android XML page </a> <a href="ios://page.xib"> Go to an Interface Builder page </a> Clicking the hyperlink triggers a native navigation, complete with a purely-native animated transition. (On Android, the new content opens in a child activity. On iOS, the new content opens in a new view controller hosted inside a navigation controller.) The original page with the Cordova WebView remains intact, and the WebView’s internal history remains unaffected. You can navigate back to it with the ace.goBack() API. If you use XAML markup, this can even be attached inline: <Button ace:On.Click="ace.goBack()">Back</Button> Navigating with document.locationIf your target page is defined in markup, you can also change the document’s location in JavaScript:
// Three options:
document.location.href = "native://page.xaml";
document.location.href = "android://page.xml";
document.location.href = "ios://page.xib";
This behaves just like following a hyperlink. Navigating with the navigate APIYou can also use a navigate API, which enables you to navigate to markup or any UI object constructed programmatically: Navigate to a markup file:
// Three options:
ace.navigate("native://page.xaml");
ace.navigate("android://page.xml");
ace.navigate("ios://page.xib");
Navigate to an arbitrary UI object:
// Navigate to a Page constructed dynamically:
var page = new ace.Page();
...
ace.navigate(page);
// You aren't required to use a Page object:
var button = new ace.Button();
...
ace.navigate(button);
Notice that you’re not required to use a Page object. (But Page is useful if you want to show app bars or control the navigation bar.) You don’t need to use the cross-platform UI framework, either. Here’s an example that navigates to a raw iOS control, which occupies the whole screen upon navigation: if (ace.platform == "iOS") { // Create a UISegmentedControl var uiSegmentedControl = new ace.NativeObject("UISegmentedControl"); // Add two segments uiSegmentedControl.invoke("insertSegmentWithTitle:atIndex:animated:", "One", 0, false); uiSegmentedControl.invoke("insertSegmentWithTitle:atIndex:animated:", "Two", 1, false); // Select the last segment uiSegmentedControl.invoke("setSelectedSegmentIndex", 1); // Navigate to the single control ace.navigate(uiSegmentedControl, // Just so we have a way to get back: function () { ace.Frame.showNavigationBar(); }, function () { ace.Frame.hideNavigationBar(); }); } Here’s a similar example, but with raw Android controls constructed entirely in JavaScript (no Android XML): Click here to expand example And here’s a complete example of navigating to cross-platform UI constructed entirely in JavaScript (no XAML): Click here to expand example Interacting with the New Native ContentA key feature of the navigate API, compared to the other navigation approaches, is that it returns the root UI object that you just navigated to. This enables you to manipulate the UI, attach event handlers, and so on.
ace.navigate("native://page.xaml", function (root) {
// Navigation done
root.setBackground("Salmon");
});
ace.navigate("native://page.xaml", function (root) {
// Attach event handler
root.doneButton.addEventListener("click", function() { ... });
});
Retrieving SubelementsIf you’re using XAML markup, you can mark elements with a Name attribute. You can then access elements by name directly from the root element, e.g.:
ace.navigate("native://page.xaml", function (root) {
// There is an element with Name="doneButton"
root.doneButton.addEventListener("click", function() { ... });
});
Or, from any element in the same scope (not just the root), you can use a findName API:
ace.navigate("native://page.xaml", function (root) {
// There is an element with Name="doneButton"
root.findName("doneButton").addEventListener("click", function() { ... });
});
If you’re using Android XML, you can set ids as you normally would, and programmatically leverage those ids in JavaScript the same way you would in Java. Navigating BackwardTo go back from a native navigation, call ace.goBack(). Navigation EventsIf you use the navigate API, you can pass an extra callback that acts like a “navigating away from” event: ace.navigate("native://page.xaml", function (root) { // Navigated to root.doneButton.addEventListener("click", function() { ... }); }, function (root) { // Navigating away root.doneButton.removeEventListener("click", function() { ... }); }); Global Navigation Events You can handle global Navigating and Navigated events, which is especially useful when navigation is done via hyperlinks rather than the navigate API:
ace.addEventListener("navigating", function (oldContent, newContent) {
console.log("NAVIGATING: " + oldContent + " -> " + newContent);
});
ace.addEventListener("navigated", function (root, url) {
// There's no url in the case of navigating to a live object
console.log("NAVIGATED: " + url);
});
Controlling the Navigation BarFrame has exposes showNavigationBar and hideNavigationBar APIs. A previous example demonstrated these in conjunction with the navigate API callbacks: ace.navigate(uiSegmentedControl, // Just so we have a way to get back: function () { ace.Frame.showNavigationBar(); }, function () { ace.Frame.hideNavigationBar(); }); } |