Skip to content
This repository was archived by the owner on Dec 4, 2017. It is now read-only.

Commit c9d4050

Browse files
bennadelwardbell
authored andcommitted
docs(cb-set-document-title): new "Set Title" cookbook chapter
closes #1069
1 parent 634e50a commit c9d4050

File tree

15 files changed

+267
-6
lines changed

15 files changed

+267
-6
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// gulp run-e2e-tests --filter=cb-set-document-title
2+
describe('Set Document Title', function () {
3+
4+
beforeAll(function () {
5+
browser.get('');
6+
});
7+
8+
it('should set the document title', function () {
9+
10+
var titles = [
11+
'Good morning!',
12+
'Good afternoon!',
13+
'Good evening!'
14+
];
15+
16+
element.all( by.css( 'ul li a' ) ).each(
17+
function iterator( element, i ) {
18+
19+
element.click();
20+
expect( browser.getTitle() ).toEqual( titles[ i ] );
21+
22+
}
23+
);
24+
25+
});
26+
27+
});
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
**/*.js
2+
npm-debug.log
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// #docplaster
2+
// #docregion
3+
// Import the native Angular services.
4+
import { Component } from 'angular2/core';
5+
import { Title } from 'angular2/platform/browser';
6+
7+
@Component({
8+
selector: 'my-app',
9+
template:
10+
`<p>
11+
Select a title to set on the current HTML document:
12+
</p>
13+
14+
<ul>
15+
<li><a (click)="setTitle( 'Good morning!' )">Good morning</a>.</li>
16+
<li><a (click)="setTitle( 'Good afternoon!' )">Good afternoon</a>.</li>
17+
<li><a (click)="setTitle( 'Good evening!' )">Good evening</a>.</li>
18+
</ul>
19+
`
20+
})
21+
// #docregion class
22+
export class AppComponent {
23+
public constructor(private _titleService: Title ) { }
24+
25+
public setTitle( newTitle: string) {
26+
this._titleService.setTitle( newTitle );
27+
}
28+
}
29+
// #enddocregion class
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// #docregion
2+
import { bootstrap } from 'angular2/platform/browser';
3+
import { AppComponent } from './app.component';
4+
5+
// While Angular supplies a Title service for setting the HTML document title
6+
// it doesn't include this service as part of the default Browser platform providers.
7+
// As such, if we want to inject it into the components within our application,
8+
// we have to explicitly provide the Angular service in our top component.
9+
// #docregion bootstrap-title
10+
import { Title } from 'angular2/platform/browser';
11+
12+
bootstrap(AppComponent, [ Title ])
13+
// #enddocregion bootstrap-title
14+
.then(
15+
() => window.console.info( 'Angular finished bootstrapping your application!' ),
16+
(error) => {
17+
console.warn( 'Angular was not able to bootstrap your application.' );
18+
console.error( error );
19+
}
20+
);

public/docs/_examples/cb-set-document-title/ts/example-config.json

Whitespace-only changes.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<base href="/">
7+
8+
<title>
9+
Setting The Document Title Using The Title Service
10+
</title>
11+
12+
<!-- #docregion style -->
13+
<link rel="stylesheet" type="text/css" href="styles.css">
14+
<link rel="stylesheet" type="text/css" href="sample.css">
15+
<!-- #enddocregion style -->
16+
17+
<!-- IE required polyfills, in this exact order -->
18+
<script src="node_modules/es6-shim/es6-shim.min.js"></script>
19+
<script src="node_modules/systemjs/dist/system-polyfills.js"></script>
20+
<script src="node_modules/angular2/es6/dev/src/testing/shims_for_IE.js"></script>
21+
22+
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
23+
<script src="node_modules/systemjs/dist/system.src.js"></script>
24+
<script src="node_modules/rxjs/bundles/Rx.js"></script>
25+
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
26+
<script>
27+
// Configure our module loader.
28+
System.config({
29+
packages: {
30+
app: {
31+
format: "register",
32+
defaultExtension: "js"
33+
}
34+
}
35+
});
36+
37+
// Load the root module (which will, in turn, bootstrap the Angular 2 application).
38+
System
39+
.import( "app/main" )
40+
.then(
41+
function handleSuccess() {
42+
console.info( "System.js loaded your application module." );
43+
},
44+
function handleError( error ) {
45+
console.warn( "System.js could not load your application module." );
46+
console.error( error );
47+
48+
}
49+
);
50+
</script>
51+
</head>
52+
<body>
53+
54+
<h1>
55+
Setting The Document Title Using The Title Service
56+
</h1>
57+
58+
<my-app>
59+
Loading app...
60+
</my-app>
61+
62+
</body>
63+
</html>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"description": "Set The Document Title In Angular 2",
3+
"files": [
4+
"!**/*.d.ts",
5+
"!**/*.js",
6+
"!**/*.[1].*"
7+
],
8+
"tags": [ "cookbook" ]
9+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
a {
2+
color: #607D8B ;
3+
text-decoration: underline ;
4+
}

public/docs/dart/latest/cookbook/_data.json

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
"navTitle": "Overview",
55
"intro": "A collection of recipes for common Angular application scenarios"
66
},
7-
7+
88
"a1-a2-quick-reference": {
99
"title": "Angular 1 to 2 Quick Reference",
1010
"navTitle": "Angular 1 to 2 Quick Ref",
1111
"intro": "Learn how Angular 1 concepts and techniques map to Angular 2",
1212
"hide": true
1313
},
14-
14+
1515
"component-communication": {
1616
"title": "Component Interaction",
1717
"intro": "Share information between different directives and components"
@@ -22,16 +22,21 @@
2222
"intro": "Techniques for Dependency Injection",
2323
"hide": true
2424
},
25-
25+
2626
"dynamic-forms": {
2727
"title": "Dynamic Form",
2828
"intro": "Render dynamic forms with NgFormModel",
2929
"hide": true
3030
},
3131

32+
"set-document-title": {
33+
"title": "Set the Document Title",
34+
"intro": "Setting the document or window title using the Title service."
35+
},
36+
3237
"ts-to-js": {
3338
"title": "TypeScript to JavaScript",
3439
"intro": "Convert Angular 2 TypeScript examples into ES5 JavaScript",
3540
"hide": true
3641
}
37-
}
42+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
!= partial("../../../_includes/_ts-temp")

public/docs/js/latest/cookbook/_data.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@
2626
"intro": "Render dynamic forms with NgFormModel"
2727
},
2828

29+
"set-document-title": {
30+
"title": "Set the Document Title",
31+
"intro": "Setting the document or window title using the Title service."
32+
},
33+
2934
"ts-to-js": {
3035
"title": "TypeScript to JavaScript",
3136
"intro": "Convert Angular 2 TypeScript examples into ES5 JavaScript"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
!= partial("../../../_includes/_ts-temp")

public/docs/ts/latest/cookbook/_data.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
"navTitle": "Overview",
55
"description": "A collection of recipes for common Angular application scenarios"
66
},
7-
7+
88
"a1-a2-quick-reference": {
99
"title": "Angular 1 to 2 Quick Reference",
1010
"navTitle": "Angular 1 to 2 Quick Ref",
1111
"intro": "Learn how Angular 1 concepts and techniques map to Angular 2"
1212
},
13-
13+
1414
"component-communication": {
1515
"title": "Component Interaction",
1616
"intro": "Share information between different directives and components"
@@ -26,6 +26,11 @@
2626
"intro": "Render dynamic forms with NgFormModel"
2727
},
2828

29+
"set-document-title": {
30+
"title": "Set the Document Title",
31+
"intro": "Setting the document or window title using the Title service."
32+
},
33+
2934
"ts-to-js": {
3035
"title": "TypeScript to JavaScript",
3136
"intro": "Convert Angular 2 TypeScript examples into ES5 JavaScript"
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
include ../_util-fns
2+
3+
a(id='top')
4+
:marked
5+
Our app should be able to make the browser title bar say whatever we want it to say.
6+
This cookbook explains how to do it.
7+
:marked
8+
**See the [live example](/resources/live-examples/cb-set-document-title/ts/plnkr.html)**.
9+
.l-sub-section
10+
img(src='/resources/images/devguide/plunker-separate-window-button.png' alt="pop out the window" align="right" style="margin-right:-20px")
11+
:marked
12+
To see the browser Title bar changes,
13+
pop out the preview window by clicking the blue 'X' button in the upper right corner.
14+
:marked
15+
## The problem with *&lt;title&gt;*
16+
17+
The obvious approach is to bind a property of the component to the HTML `<title>` like this:
18+
code-example(format='')
19+
&lt;title&gt;{{This_Does_Not_Work}}&lt;/title&gt;
20+
:marked
21+
Sorry but that won't work.
22+
The root component of our application is an element contained within the `<body>` tag.
23+
The HTML `<title>` is in the document `<head>`, outside the body, making it inaccessible to Angular data binding.
24+
25+
We could grab the browser `document` object and set the title manually.
26+
That's dirty and undermines our chances of running the app outside of a browser someday.
27+
.l-sub-section
28+
:marked
29+
That's a major Angular architectural goal. It may not seem important to us right now.
30+
But why squander that future just to set the title bar?
31+
32+
:marked
33+
## Use the *Title* service
34+
Fortunately, Angular 2 bridges the gap by providing a `Title` service as part of the *Browser platform*.
35+
The [Title](../api//platform/browser/Title-class.html) service is a simple class that provides an API
36+
for getting and setting the current HTML document title:
37+
38+
* `getTitle() : string` &mdash; Gets the title of the current HTML document.
39+
* `setTitle( newTitle : string )` &mdash; Sets the title of the current HTML document.
40+
41+
While this class is part of the Browser platform package, it is *not part of the default Browser
42+
platform providers* that Angular loads automatically.
43+
This means as we bootstrap our application using the Browser platform `boostrap()`
44+
function, we'll also have to include `Title` service explicitly as one of the bootstrap providers:
45+
46+
+makeExample( "cb-set-document-title/ts/app/main.ts", "bootstrap-title", "app/main.ts (provide Title service)" )(format='.')
47+
:marked
48+
Once we've explicitly provided the `Title` service we can then inject the `Title` service into any of our
49+
custom application components and services.
50+
51+
Let's inject the `Title` service into the root `AppComponent` and expose a bindable `setTitle` method that calls it:
52+
53+
+makeExample( "cb-set-document-title/ts/app/app.component.ts", "class", "app/app.component.ts (class)" )(format='.')
54+
:marked
55+
We bind that method to three anchor tags and, voilà!
56+
figure.image-display
57+
img(src="/resources/images/cookbooks/set-document-title/set-title-anim.gif" alt="Set title")
58+
59+
:marked
60+
Here's the complete solution
61+
62+
+makeTabs(
63+
`cb-set-document-title/ts/app/main.ts,
64+
cb-set-document-title/ts/app/app.component.ts`,
65+
'',
66+
'app/main.ts, app/app.component.ts' )
67+
68+
//
69+
Todo: tie this back to the router so we can see how to use this Title service to (re)set the title
70+
that appears in the window navigation history and shows up in the back/forward buttons
71+
during routing.
72+
73+
See https://github.com/angular/angular/issues/7630#issuecomment-198328802
74+
75+
.l-main-section
76+
:marked
77+
## Why we provide the *Title* service in *bootstrap*
78+
79+
We generally recommended providing application-wide services in the root application component, `AppComponent`.
80+
81+
Here we recommend registering the title service during bootstrapping,
82+
a location we reserve for configuring the runtime Angular enviroment.
83+
84+
That's exactly what we're doing.
85+
The `Title` service is part of the Angular *browser platform*.
86+
If we bootstrap our application into a different platform,
87+
we'll have to provide a different `Title` service that understands the concept of a "document title" for that specific platform.
88+
Ideally the application itself neither knows nor cares about the runtime environment.
89+
:marked
90+
[Back to top](#top)
Loading

0 commit comments

Comments
 (0)