164 lines
6.8 KiB
HTML
Executable file
164 lines
6.8 KiB
HTML
Executable file
<a href="http://github.com/angular/angular.js/edit/master/docs/content/cookbook/deeplinking.ngdoc" class="improve-docs btn btn-primary"><i class="icon-edit"> </i> Improve this doc</a><h1><code ng:non-bindable=""></code>
|
|
<div><span class="hint"></span>
|
|
</div>
|
|
</h1>
|
|
<div><div class="cookbook-page cookbook-deep-linking-page"><p>Deep linking allows you to encode the state of the application in the URL so that it can be
|
|
bookmarked and the application can be restored from the URL to the same state.</p>
|
|
<p>While Angular does not force you to deal with bookmarks in any particular way, it has services
|
|
which make the common case described here very easy to implement.</p>
|
|
<h2>Assumptions</h1>
|
|
<p>Your application consists of a single HTML page which bootstraps the application. We will refer
|
|
to this page as the chrome.
|
|
Your application is divided into several screens (or views) which the user can visit. For example,
|
|
the home screen, settings screen, details screen, etc. For each of these screens, we would like to
|
|
assign a URL so that it can be bookmarked and later restored. Each of these screens will be
|
|
associated with a controller which define the screen's behavior. The most common case is that the
|
|
screen will be constructed from an HTML snippet, which we will refer to as the partial. Screens can
|
|
have multiple partials, but a single partial is the most common construct. This example makes the
|
|
partial boundary visible using a blue line.</p>
|
|
<p>You can make a routing table which shows which URL maps to which partial view template and which
|
|
controller.</p>
|
|
<h1>Example</h1>
|
|
<p>In this example we have a simple app which consist of two screens:</p>
|
|
<ul>
|
|
<li>Welcome: url <code>welcome</code> Show the user contact information.</li>
|
|
<li>Settings: url <code>settings</code> Show an edit screen for user contact information.</li>
|
|
</ul>
|
|
<h3>Source</h2>
|
|
<div source-edit="deepLinking" source-edit-deps="angular.js angular-route.js angular-sanitize.js script.js" source-edit-html="index.html-168 settings.html welcome.html" source-edit-css="style.css-167" source-edit-js="script.js-166" source-edit-json="" source-edit-unit="" source-edit-scenario="scenario.js-169"></div>
|
|
<div class="tabbable"><div class="tab-pane" title="index.html">
|
|
<pre class="prettyprint linenums" ng-set-text="index.html-168" ng-html-wrap="deepLinking angular.js angular-route.js angular-sanitize.js script.js"></pre>
|
|
<script type="text/ng-template" id="index.html-168">
|
|
<div ng-controller="AppCntl">
|
|
<h1>Your App Chrome</h1>
|
|
[ <a href="welcome">Welcome</a> | <a href="settings">Settings</a> ]
|
|
<hr/>
|
|
<span class="partial-info">
|
|
Partial: {{$route.current.template}}
|
|
</span>
|
|
<div ng-view></div>
|
|
<small>Your app footer </small>
|
|
</div>
|
|
</script>
|
|
</div>
|
|
<div class="tab-pane" title="settings.html">
|
|
<pre class="prettyprint linenums" ng-set-text="settings.html"></pre>
|
|
<script type="text/ng-template" id="settings.html">
|
|
<label>Name:</label>
|
|
<input type="text" ng:model="form.name" required>
|
|
|
|
<div ng:repeat="contact in form.contacts">
|
|
<select ng:model="contact.type">
|
|
<option>url</option>
|
|
<option>email</option>
|
|
<option>phone</option>
|
|
</select>
|
|
<input type="text" ng:model="contact.url">
|
|
[ <a href="" ng:click="form.contacts.$remove(contact)">X</a> ]
|
|
</div>
|
|
<div>
|
|
[ <a href="" ng:click="form.contacts.$add()">add</a> ]
|
|
</div>
|
|
|
|
<button ng:click="cancel()">Cancel</button>
|
|
<button ng:click="save()">Save</button>
|
|
</script>
|
|
</div>
|
|
<div class="tab-pane" title="welcome.html">
|
|
<pre class="prettyprint linenums" ng-set-text="welcome.html"></pre>
|
|
<script type="text/ng-template" id="welcome.html">
|
|
Hello {{person.name}},
|
|
<div>
|
|
Your contact information:
|
|
<div ng:repeat="contact in person.contacts">{{contact.type}}:
|
|
<span ng-bind-html="contact.url|linky"></span>
|
|
</div>
|
|
</div>
|
|
</script>
|
|
</div>
|
|
<div class="tab-pane" title="style.css">
|
|
<pre class="prettyprint linenums" ng-set-text="style.css-167"></pre>
|
|
<style type="text/css" id="style.css-167">
|
|
[ng-view] {
|
|
border: 1px solid blue;
|
|
margin: 0;
|
|
padding:1em;
|
|
}
|
|
|
|
.partial-info {
|
|
background-color: blue;
|
|
color: white;
|
|
padding: 3px;
|
|
}
|
|
</style>
|
|
</div>
|
|
<div class="tab-pane" title="script.js">
|
|
<pre class="prettyprint linenums" ng-set-text="script.js-166"></pre>
|
|
<script type="text/ng-template" id="script.js-166">
|
|
angular.module('deepLinking', ['ngRoute', 'ngSanitize'])
|
|
.config(function($routeProvider) {
|
|
$routeProvider.
|
|
when("/welcome", {templateUrl:'welcome.html', controller:WelcomeCntl}).
|
|
when("/settings", {templateUrl:'settings.html', controller:SettingsCntl});
|
|
});
|
|
|
|
AppCntl.$inject = ['$scope', '$route']
|
|
function AppCntl($scope, $route) {
|
|
$scope.$route = $route;
|
|
|
|
// initialize the model to something useful
|
|
$scope.person = {
|
|
name:'anonymous',
|
|
contacts:[{type:'email', url:'anonymous@example.com'}]
|
|
};
|
|
}
|
|
|
|
function WelcomeCntl($scope) {
|
|
$scope.greet = function() {
|
|
alert("Hello " + $scope.person.name);
|
|
};
|
|
}
|
|
|
|
function SettingsCntl($scope, $location) {
|
|
$scope.cancel = function() {
|
|
$scope.form = angular.copy($scope.person);
|
|
};
|
|
|
|
$scope.save = function() {
|
|
angular.copy($scope.form, $scope.person);
|
|
$location.path('/welcome');
|
|
};
|
|
|
|
$scope.cancel();
|
|
}
|
|
</script>
|
|
</div>
|
|
<div class="tab-pane" title="End to end test">
|
|
<pre class="prettyprint linenums" ng-set-text="scenario.js-169"></pre>
|
|
<script type="text/ng-template" id="scenario.js-169">
|
|
it('should navigate to URL', function() {
|
|
element('a:contains(Welcome)').click();
|
|
expect(element('[ng-view]').text()).toMatch(/Hello anonymous/);
|
|
element('a:contains(Settings)').click();
|
|
input('form.name').enter('yourname');
|
|
element(':button:contains(Save)').click();
|
|
element('a:contains(Welcome)').click();
|
|
expect(element('[ng-view]').text()).toMatch(/Hello yourname/);
|
|
});
|
|
</script>
|
|
</div>
|
|
</div><h2>Demo</h3>
|
|
<div class="well doc-example-live animate-container" ng-embed-app="deepLinking" ng-set-html="index.html-168" ng-eval-javascript="script.js-166"></div>
|
|
<h1>Things to notice</h2>
|
|
<ul>
|
|
<li>Routes are defined in the <code>AppCntl</code> class. The initialization of the controller causes the
|
|
initialization of the <a href="api/ngRoute.$route">$route</a> service with the proper URL
|
|
routes.</li>
|
|
<li>The <a href="api/ngRoute.$route">$route</a> service then watches the URL and instantiates the
|
|
appropriate controller when the URL changes.</li>
|
|
<li>The <a href="api/ngRoute.directive:ngView">ngView</a> widget loads the
|
|
view when the URL changes. It also sets the view scope to the newly instantiated controller.</li>
|
|
<li>Changing the URL is sufficient to change the controller and view. It makes no difference whether
|
|
the URL is changed programatically or by the user.</li>
|
|
</ul>
|
|
</div></div>
|