From 6c7f330620754c31ef4e4044557835bc7ffea033 Mon Sep 17 00:00:00 2001 From: Kapunahele Wong Date: Fri, 23 Sep 2016 19:53:50 -0400 Subject: [PATCH 01/12] docs(Displaying Data): copy edits (#2435) --- public/docs/ts/latest/guide/_data.json | 2 +- .../docs/ts/latest/guide/displaying-data.jade | 175 +++++++++--------- 2 files changed, 86 insertions(+), 91 deletions(-) diff --git a/public/docs/ts/latest/guide/_data.json b/public/docs/ts/latest/guide/_data.json index be61fbd4ce..25cb193874 100644 --- a/public/docs/ts/latest/guide/_data.json +++ b/public/docs/ts/latest/guide/_data.json @@ -17,7 +17,7 @@ "displaying-data": { "title": "Displaying Data", - "intro": "Interpolation and other forms of property binding help us show app data in the UI.", + "intro": "Property binding helps show app data in the UI.", "nextable": true, "basics": true }, diff --git a/public/docs/ts/latest/guide/displaying-data.jade b/public/docs/ts/latest/guide/displaying-data.jade index 376c2d254c..44af7f3188 100644 --- a/public/docs/ts/latest/guide/displaying-data.jade +++ b/public/docs/ts/latest/guide/displaying-data.jade @@ -2,13 +2,12 @@ block includes include ../_util-fns - var _iterableUrl = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols'; - var _boolean = 'truthy/falsey'; - -:marked - We typically display data in Angular by binding controls in an HTML template - to properties of an Angular component. - In this chapter, we'll create a component with a list of heroes. Each hero has a name. - We'll display the list of hero names and +:marked + You can display data by binding controls in an HTML template to properties of an Angular component. + + In this page, you'll create a component with a list of heroes. + You'll display the list of hero names and conditionally show a message below the list. The final UI looks like this: @@ -17,42 +16,42 @@ figure.image-display img(src="/resources/images/devguide/displaying-data/final.png" alt="Final UI") :marked - # Table Of Contents + # Contents - * [Showing component properties with interpolation](#interpolation) - * [Showing !{_an} !{_array} property with NgFor](#ngFor) - * [Conditional display with NgIf](#ngIf) + * [Showing component properties with interpolation](#interpolation). + * [Showing !{_an} !{_array} property with NgFor](#ngFor). + * [Conditional display with NgIf](#ngIf). .l-sub-section :marked The demonstrates all of the syntax and code - snippets described in this chapter. + snippets described in this page. .l-main-section#interpolation :marked ## Showing component properties with interpolation The easiest way to display a component property is to bind the property name through interpolation. - With interpolation, we put the property name in the view template, enclosed in double curly braces: `{{myHero}}`. + With interpolation, you put the property name in the view template, enclosed in double curly braces: `{{myHero}}`. - Let's build a small illustrative example together. - - Create a new project folder () and follow the steps in the [QuickStart](../quickstart.html). + To build an illustrative example, start by creating a new project folder called + and following the steps in [QuickStart](../quickstart.html). block quickstart-repo include ../_quickstart_repo :marked - Then modify the file by + Then modify the file by changing the template and the body of the component. - When we're done, it should look like this: + + When you're done, it should look like this: +makeExample('app/app.component.1.ts') :marked - We added two properties to the formerly empty component: `title` and `myHero`. + You added two properties to the formerly empty component: `title` and `myHero`. - Our revised template displays the two component properties using double curly brace + The revised template displays the two component properties using double curly brace interpolation: +makeExcerpt('app/app.component.1.ts', 'template', '') @@ -61,10 +60,9 @@ block quickstart-repo .l-sub-section :marked The template is a multi-line string within ECMAScript 2015 backticks (\`). - The backtick (\`) — which is *not* the same character as a single - quote (`'`) — has many nice features. The feature we're exploiting here - is the ability to compose the string over several lines, which makes for - much more readable HTML. + The backtick (\`)—which is *not* the same character as a single + quote (`'`)—allows you to compose a string over several lines, which makes the + HTML more readable. :marked Angular automatically pulls the value of the `title` and `myHero` properties from the component and @@ -74,43 +72,42 @@ block quickstart-repo .l-sub-section :marked More precisely, the redisplay occurs after some kind of asynchronous event related to - the view such as a keystroke, a timer completion, or an async `XHR` response. - We don't have those in this sample. - But then the properties aren't changing on their own either. For the moment we must operate on faith. + the view, such as a keystroke, a timer completion, or a response to an HTTP request. :marked - Notice that we haven't called **new** to create an instance of the `AppComponent` class. - Angular is creating an instance for us. How? + Notice that you don't call **new** to create an instance of the `AppComponent` class. + Angular is creating an instance for you. How? - Notice the CSS `selector` in the `@Component` !{_decorator} that specifies an element named `my-app`. - Remember back in [QuickStart](../quickstart.html) that we added the `` element to the body of our `index.html` file: + The CSS `selector` in the `@Component` !{_decorator} specifies an element named `my-app`. + Remember back in [QuickStart](../quickstart.html) that you added the `` + element to the body of your `index.html` file: +makeExcerpt('index.html', 'body') :marked - When we bootstrap with the `AppComponent` class (in ), Angular looks for a `` + When you bootstrap with the `AppComponent` class (in ), Angular looks for a `` in the `index.html`, finds it, instantiates an instance of `AppComponent`, and renders it inside the `` tag. - Try running the app. It should display the title and hero name: + Now run the app. It should display the title and hero name: figure.image-display img(src="/resources/images/devguide/displaying-data/title-and-hero.png" alt="Title and Hero") +ifDocsFor('ts') :marked - Let's review some of the choices we made and consider alternatives. + The next few sections review some of the coding choices in the app. :marked ## Template inline or template file? - We can store our component's template in one of two places. - We can define it *inline* using the `template` property, as we do here. - Or we can define the template in a separate HTML file and link to it in + You can store your component's template in one of two places. + You can define it *inline* using the `template` property, or you can define + the template in a separate HTML file and link to it in the component metadata using the `@Component` !{_decorator}'s `templateUrl` property. The choice between inline and separate HTML is a matter of taste, circumstances, and organization policy. - Here we're using inline HTML because the template is small, and the demo + Here the app uses inline HTML because the template is small and the demo is simpler without the additional HTML file. In either style, the template data bindings have the same access to the component's properties. @@ -119,49 +116,44 @@ figure.image-display :marked ## Constructor or variable initialization? - We initialized our component properties using variable assignment. - This is a wonderfully concise and compact technique. + Although this example uses variable assignment to initialize the components, you can instead declare and initialize the properties using a constructor: - Some folks prefer to declare the properties and initialize them within a constructor like this: +makeExcerpt('app/app-ctor.component.ts', 'class') :marked - That's fine too. The choice is a matter of taste and organization policy. - We'll adopt the more terse "variable assignment" style in this chapter simply because - there will be less code to read. + This app uses more terse "variable assignment" style simply for brevity. .l-main-section#ngFor :marked ## Showing !{_an} !{_array} property with ***ngFor** - We want to display a list of heroes. We begin by adding !{_an} !{_array} of hero names to the component and redefine `myHero` to be the first name in the !{_array}. + To display a list of heroes, begin by adding !{_an} !{_array} of hero names to the component and redefine `myHero` to be the first name in the !{_array}. +makeExcerpt('app/app.component.2.ts', 'class') :marked - Now we use the Angular `ngFor` directive in the template to display + Now use the Angular `ngFor` directive in the template to display each item in the `heroes` list. +makeExcerpt('app/app.component.2.ts', 'template') :marked - Our presentation is the familiar HTML unordered list with `
    ` and `
  • ` tags. Let's focus on the `
  • ` tag. + This UI uses the HTML unordered list with `
      ` and `
    • ` tags. The `*ngFor` + in the `
    • ` element is the Angular "repeater" directive. + It marks that `
    • ` element (and its children) as the "repeater template": +makeExcerpt('app/app.component.2.ts ()', 'li', '') -:marked - We added a somewhat mysterious `*ngFor` to the `
    • ` element. - That's the Angular "repeater" directive. - Its presence on the `
    • ` tag marks that `
    • ` element (and its children) as the "repeater template". - .alert.is-important :marked Don't forget the leading asterisk (\*) in `*ngFor`. It is an essential part of the syntax. - Learn more about this and `ngFor` in the [Template Syntax](./template-syntax.html#ngFor) chapter. + For more information, see the [Template Syntax](./template-syntax.html#ngFor) page. :marked Notice the `hero` in the `ngFor` double-quoted instruction; - it is an example of a [template input variable](./template-syntax.html#ngForMicrosyntax). + it is an example of a template input variable. Read + more about template input variables in the [microsyntax](./template-syntax.html#ngForMicrosyntax) section of + the [Template Syntax](./template-syntax.html) page. Angular duplicates the `
    • ` for each item in the list, setting the `hero` variable to the item (the hero) in the current iteration. Angular uses that variable as the @@ -169,9 +161,8 @@ figure.image-display .l-sub-section :marked - We happened to give `ngFor` !{_an} !{_array} to display. - In fact, `ngFor` can repeat items for any [iterable](!{_iterableUrl}) - object. + In this case, `ngFor` is displaying !{_an} !{_array}, but `ngFor` can + repeat items for any [iterable](!{_iterableUrl}) object. :marked Now the heroes appear in an unordered list. @@ -182,25 +173,25 @@ figure.image-display :marked ## Creating a class for the data - We are defining our data directly inside our component. - That's fine for a demo but certainly isn't a best practice. It's not even a good practice. - Although we won't do anything about that in this chapter, we'll make a mental note to fix this down the road. + The app's code defines the data directly inside the component, which isn't best practice. + In a simple demo, however, it's fine. - At the moment, we're binding to !{_an} !{_array} of strings. We do that occasionally in real applications, but - most of the time we're binding to more specialized objects. + At the moment, the binding is to !{_an} !{_array} of strings. + In real applications, most bindings are to more specialized objects. - Let's turn our !{_array} of hero names into !{_an} !{_array} of `Hero` objects. For that we'll need a `Hero` class. + To convert this binding to use specialized objects, turn the !{_array} + of hero names into !{_an} !{_array} of `Hero` objects. For that you'll need a `Hero` class. Create a new file in the `!{_appDir}` folder called with the following code: - + +makeExcerpt('app/hero.ts') block hero-class :marked - We've defined a class with a constructor and two properties: `id` and `name`. + You've defined a class with a constructor and two properties: `id` and `name`. - It might not look like we have properties, but we do. We're taking - advantage of a TypeScript shortcut in our declaration of the constructor parameters. + It might not look like the class has properties, but it does. + The declaration of the constructor parameters takes advantage of a TypeScript shortcut. Consider the first parameter: @@ -208,26 +199,28 @@ block hero-class :marked That brief syntax does a lot: - * Declares a constructor parameter and its type - * Declares a public property of the same name - * Initializes that property with the corresponding argument when we "new" an instance of the class + * Declares a constructor parameter and its type. + * Declares a public property of the same name. + * Initializes that property with the corresponding argument when creating an instance of the class. .l-main-section :marked ## Using the Hero class - Let's make the `heroes` property in our component return !{_an} !{_array} of these `Hero` objects. + + The `heroes` property in the component can now use the `Hero` class to return !{_an} !{_array} + of `Hero` objects: +makeExcerpt('app/app.component.3.ts', 'heroes') :marked - We'll have to update the template. + Next, update the template. At the moment it displays the hero's `id` and `name`. - Let's fix that so we display only the hero's `name` property. + Fix that to display only the hero's `name` property. +makeExcerpt('app/app.component.3.ts', 'template') :marked - Our display looks the same, but now we know much better what a hero really is. + The display looks the same, but the code is clearer. .l-main-section#ngIf :marked @@ -235,29 +228,31 @@ block hero-class Sometimes an app needs to display a view or a portion of a view only under specific circumstances. - In our example, we'd like to display a message if we have a large number of heroes, say, more than 3. + Let's change the example to display a message if there are more than three heroes. The Angular `ngIf` directive inserts or removes an element based on a !{_boolean} condition. - We can see it in action by adding the following paragraph at the bottom of the template: + To see it in action, add the following paragraph at the bottom of the template: +makeExcerpt('app/app.component.ts', 'message') .alert.is-important :marked Don't forget the leading asterisk (\*) in `*ngIf`. It is an essential part of the syntax. - Learn more about this and `ngIf` in the [Template Syntax](./template-syntax.html#ngIf) chapter. + Read more about `ngIf` and `*` in the [ngIf section](./template-syntax.html#ngIf) of the [Template Syntax](./template-syntax.html) page. :marked - The [template expression](./template-syntax.html#template-expressions) inside the double quotes - looks much like !{_Lang}, and it _is_ much like !{_Lang}. - When the component's list of heroes has more than 3 items, Angular adds the paragraph to the DOM and the message appears. - If there are 3 or fewer items, Angular omits the paragraph, so no message appears. + The template expression inside the double quotes, + `*ngIf="heros.length > 3"`, looks and behaves much like !{_Lang}. + When the component's list of heroes has more than three items, Angular adds the paragraph + to the DOM and the message appears. If there are three or fewer items, Angular omits the + paragraph, so no message appears. For more information, + see the [template expressions](./template-syntax.html#template-expressions) section of the + [Template Syntax](./template-syntax.html) page. .alert.is-helpful :marked - Angular isn't showing and hiding the message. It is adding and removing the paragraph element from the DOM. - That hardly matters here. But it would matter a great deal, from a performance perspective, if - we were conditionally including or excluding a big chunk of HTML with many data bindings. + Angular isn't showing and hiding the message. It is adding and removing the paragraph element from the DOM. That improves performance, especially in larger projects when conditionally including or excluding + big chunks of HTML with many data bindings. :marked Try it out. Because the !{_array} has four items, the message should appear. @@ -267,13 +262,13 @@ block hero-class .l-main-section :marked ## Summary - Now we know how to use: - - **Interpolation** with double curly braces to display a component property - - **ngFor** to display !{_an} !{_array} of items - - A !{_Lang} class to shape the **model data** for our component and display properties of that model - - **ngIf** to conditionally display a chunk of HTML based on a boolean expression + Now you know how to use: + - **Interpolation** with double curly braces to display a component property. + - **ngFor** to display !{_an} !{_array} of items. + - A !{_Lang} class to shape the **model data** for your component and display properties of that model. + - **ngIf** to conditionally display a chunk of HTML based on a boolean expression. - Here's our final code: + Here's the final code: block final-code +makeTabs(`displaying-data/ts/app/app.component.ts, @@ -281,4 +276,4 @@ block final-code displaying-data/ts/app/app.module.ts, displaying-data/ts/app/main.ts`, 'final,,,', - 'app/app.component.ts, app/hero.ts, app.module.ts, main.ts') + 'app/app.component.ts, app/hero.ts, app.module.ts, main.ts') \ No newline at end of file From 90100bffd9815491b8ef8cdda1f9f4693511244b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Rodr=C3=ADguez?= Date: Sat, 24 Sep 2016 21:03:08 +0200 Subject: [PATCH 02/12] chore: ability to add unit test boilerplate (#2462) --- gulpfile.js | 30 ++++++++++++++++--- .../ts/example-config.json | 3 ++ .../ts/example-config.json | 3 ++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 80b6839cde..8bad101b31 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -38,6 +38,7 @@ var DOCS_PATH = path.join(PUBLIC_PATH, 'docs'); var EXAMPLES_PATH = path.join(DOCS_PATH, '_examples'); var EXAMPLES_PROTRACTOR_PATH = path.join(EXAMPLES_PATH, '_protractor'); +var EXAMPLES_TESTING_PATH = path.join(EXAMPLES_PATH, 'testing/ts'); var NOT_API_DOCS_GLOB = path.join(PUBLIC_PATH, './{docs/*/latest/!(api),!(docs)}/**/*.*'); var RESOURCES_PATH = path.join(PUBLIC_PATH, 'resources'); var LIVE_EXAMPLES_PATH = path.join(RESOURCES_PATH, 'live-examples'); @@ -97,7 +98,7 @@ var _exampleBoilerplateFiles = [ 'tsconfig.json', 'tslint.json', 'typings.json' - ]; +]; var _exampleDartWebBoilerPlateFiles = ['a2docs.css', 'styles.css']; @@ -105,6 +106,11 @@ var _exampleProtractorBoilerplateFiles = [ 'tsconfig.json' ]; +var _exampleUnitTestingBoilerplateFiles = [ + 'karma-test-shim.js', + 'karma.conf.js' +]; + var _exampleConfigFilename = 'example-config.json'; var _styleLessName = 'a2docs.less'; @@ -497,9 +503,17 @@ function copyExampleBoilerplate() { .then(function() { var protractorSourceFiles = _exampleProtractorBoilerplateFiles - .map(function(name) {return path.join(EXAMPLES_PROTRACTOR_PATH, name);});; + .map(function(name) {return path.join(EXAMPLES_PROTRACTOR_PATH, name); }); var e2eSpecPaths = getE2eSpecPaths(EXAMPLES_PATH); return copyFiles(protractorSourceFiles, e2eSpecPaths, destFileMode); + }) + // copy the unit test boilerplate + .then(function() { + var unittestSourceFiles = + _exampleUnitTestingBoilerplateFiles + .map(function(name) { return path.join(EXAMPLES_TESTING_PATH, name); }); + var unittestPaths = getUnitTestingPaths(EXAMPLES_PATH); + return copyFiles(unittestSourceFiles, unittestPaths, destFileMode); }); } @@ -894,7 +908,7 @@ function harpCompile() { } else { gutil.log(`Harp full site compile, including API docs for all languages.`); if (skipLangs) - gutil.log(`Ignoring API docs skip set (${skipLangs}) because full ` + + gutil.log(`Ignoring API docs skip set (${skipLangs}) because full ` + `site has not been built yet or some API HTML files are missing.`); } @@ -1130,6 +1144,14 @@ function getDartExampleWebPaths(basePath) { return paths; } +function getUnitTestingPaths(basePath) { + var examples = getPaths(basePath, _exampleConfigFilename, true); + return examples.filter((example) => { + var exampleConfig = fs.readJsonSync(`${example}/${_exampleConfigFilename}`, {throws: false}); + return exampleConfig && !!exampleConfig.unittesting; + }); +} + function getPaths(basePath, filename, includeBase) { var filenames = getFilenames(basePath, filename, includeBase); var paths = filenames.map(function(fileName) { @@ -1164,7 +1186,7 @@ function watchAndSync(options, cb) { // When using the --focus=name flag, only **/name/**/*.* example files and // **/name.jade files are watched. This is useful for performance reasons. - // Example: gulp serve-and-sync --focus=architecture + // Example: gulp serve-and-sync --focus=architecture var focus = argv.focus; if (options.devGuide) { diff --git a/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/example-config.json b/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/example-config.json index e69de29bb2..6af3884d8d 100644 --- a/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/example-config.json +++ b/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/example-config.json @@ -0,0 +1,3 @@ +{ + "unittesting": true +} diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/example-config.json b/public/docs/_examples/upgrade-phonecat-3-final/ts/example-config.json index e69de29bb2..6af3884d8d 100644 --- a/public/docs/_examples/upgrade-phonecat-3-final/ts/example-config.json +++ b/public/docs/_examples/upgrade-phonecat-3-final/ts/example-config.json @@ -0,0 +1,3 @@ +{ + "unittesting": true +} From f5f1e80bb79fd21f528acd7bb47d9d4384fb2cc7 Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Sat, 24 Sep 2016 12:37:22 -0700 Subject: [PATCH 03/12] docs(lifecycle-hooks): make it easier to get to call sequence (#2465) Per Ben Lesh suggestion. Also converts away from "we" --- .../ts/app/peek-a-boo.component.ts | 2 +- .../docs/ts/latest/guide/lifecycle-hooks.jade | 260 +++++++++--------- 2 files changed, 130 insertions(+), 132 deletions(-) diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/peek-a-boo.component.ts b/public/docs/_examples/lifecycle-hooks/ts/app/peek-a-boo.component.ts index c17bf24082..57b421c7f8 100644 --- a/public/docs/_examples/lifecycle-hooks/ts/app/peek-a-boo.component.ts +++ b/public/docs/_examples/lifecycle-hooks/ts/app/peek-a-boo.component.ts @@ -21,7 +21,7 @@ export class PeekABoo implements OnInit { // implement OnInit's `ngOnInit` method ngOnInit() { this.logIt(`OnInit`); } - protected logIt(msg: string) { + logIt(msg: string) { this.logger.log(`#${nextId++} ${msg}`); } } diff --git a/public/docs/ts/latest/guide/lifecycle-hooks.jade b/public/docs/ts/latest/guide/lifecycle-hooks.jade index a022e681b2..9f164d8b4c 100644 --- a/public/docs/ts/latest/guide/lifecycle-hooks.jade +++ b/public/docs/ts/latest/guide/lifecycle-hooks.jade @@ -9,13 +9,18 @@ block includes checks it when its data-bound properties change, and destroys it before removing it from the DOM. Angular offers **component lifecycle hooks** - that give us visibility into these key moments and the ability to act when they occur. - - We cover these hooks in this chapter and demonstrate how they work in code. + that provide visibility into these key moments and the ability to act when they occur. + ## Table of Contents * [The lifecycle hooks](#hooks-overview) - * [The hook-call sequence](#hook-sequence) - * [Other Angular lifecycle hooks](#other-lifecycles) + * [_What_ they are](#hook-descriptions) + * [_When_ they are called](#hook-sequence) ++ifDocsFor('ts|js') + :marked + * [Interfaces are optional (technically)](#interface-optional) +:marked + * [Other Angular lifecycle hooks](#other-lifecycle-hooks) +

      * [The lifecycle sample](#the-sample) * [All](#peek-a-boo) * [Spying OnInit and OnDestroy](#spy) @@ -32,38 +37,20 @@ a#hooks-overview ## Component lifecycle Hooks Directive and component instances have a lifecycle as Angular creates, updates, and destroys them. - Developers can tap into key moments in that lifecycle by implementing one or more of the *Lifecycle Hook* interfaces in the Angular `core` library. Each interface has a single hook method whose name is the interface name prefixed with `ng`. - For example, the `OnInit` interface has a hook method named `ngOnInit`. - We might implement it in a component class like this: + For example, the `OnInit` interface has a hook method named `ngOnInit` + that Angular calls shortly after creating the component: +makeExample('lifecycle-hooks/ts/app/peek-a-boo.component.ts', 'ngOnInit', 'peek-a-boo.component.ts (excerpt)')(format='.') :marked - No directive or component will implement all of them and some of the hooks only make sense for components. + No directive or component will implement all of the lifecycle hooks and some of the hooks only make sense for components. Angular only calls a directive/component hook method *if it is defined*. -+ifDocsFor('ts|js') - .l-sub-section - :marked - ### Interface optional? - - The interfaces are optional for JavaScript and Typescript developers from a purely technical perspective. - The JavaScript language doesn't have interfaces. - Angular can't see TypeScript interfaces at runtime because they disappear from the transpiled JavaScript. - - Fortunately, they aren't necessary. - We don't have to add the lifecycle hook interfaces to our directives and components to benefit from the hooks themselves. - - Angular instead inspects our directive and component classes and calls the hook methods *if they are defined*. - Angular will find and call methods like `ngOnInit()`, with or without the interfaces. - - Nonetheless, we strongly recommend adding interfaces to TypeScript directive classes - in order to benefit from strong typing and editor tooling. - +a#hook-descriptions :marked - Here are the component lifecycle hook methods: + Here are descriptions of the component lifecycle hook methods followed by a chart describing [when they are called](#hook-sequence): ### Directives and Components @@ -129,7 +116,7 @@ table(width="100%") :marked Angular does not call the hook methods in this order. -a(id="hook-sequence") +a#hook-sequence .l-main-section :marked ## Lifecycle sequence @@ -182,18 +169,37 @@ table(width="100%") :marked just before Angular destroys the directive/component. -a(id="other-lifecycles") ++ifDocsFor('ts|js') + a#interface-optional + .l-main-section + :marked + ## Interface are optional (technically) + + The interfaces are optional for JavaScript and Typescript developers from a purely technical perspective. + The JavaScript language doesn't have interfaces. + Angular can't see TypeScript interfaces at runtime because they disappear from the transpiled JavaScript. + + Fortunately, they aren't necessary. + You don't have to add the lifecycle hook interfaces to directives and components to benefit from the hooks themselves. + + Angular instead inspects directive and component classes and calls the hook methods *if they are defined*. + Angular finds and calls methods like `ngOnInit()`, with or without the interfaces. + + Nonetheless, it's good practice to add interfaces to TypeScript directive classes + in order to benefit from strong typing and editor tooling. + +a#other-lifecycle-hooks .l-main-section :marked ## Other lifecycle hooks - Other Angular sub-systems may have their own lifecycle hooks apart from the component hooks we've listed. + Other Angular sub-systems may have their own lifecycle hooks apart from these component hooks. block other-angular-subsystems //- N/A for TS. :marked - 3rd party libraries might implement their hooks as well in order to give us, the developers, more + 3rd party libraries might implement their hooks as well in order to give developers more control over how these libraries are used. .l-main-section#the-sample @@ -226,10 +232,10 @@ table(width="100%") td :marked Directives have lifecycle hooks too. - We create a `SpyDirective` that logs when the element it spies upon is + A `SpyDirective` can log when the element it spies upon is created or destroyed using the `ngOnInit` and `ngOnDestroy` hooks. - We apply the `SpyDirective` to a `
      ` in an `ngFor` *hero* repeater + This example applies the `SpyDirective` to a `
      ` in an `ngFor` *hero* repeater managed by the parent `SpyComponent`. tr(style=top) td OnChanges @@ -266,22 +272,22 @@ table(width="100%") In this example, a `CounterComponent` logs a change (via `ngOnChanges`) every time the parent component increments its input counter property. - Meanwhile, we apply the `SpyDirective` from the previous example - to the `CounterComponent` log and watch log entries be created and destroyed. + Meanwhile, the `SpyDirective` from the previous example is applied + to the `CounterComponent` log where it watches log entries being created and destroyed. :marked - We discuss the exercises in further detail over this chapter as we learn more about the lifecycle hooks. + The remainder of this chapter discusses selected exercises in further detail. -a(id="peek-a-boo") +a#peek-a-boo .l-main-section :marked ## Peek-a-boo: all hooks The `PeekABooComponent` demonstrates all of the hooks in one component. - In real life, we'd rarely if ever implement all of the interfaces like this. - We do so in peek-a-boo in order to watch Angular call the hooks in the expected order. + You would rarely, if ever, implement all of the interfaces like this. + The peek-a-boo exists to show how Angular calls the hooks in the expected order. - In this snapshot, we clicked the *Create...* button and then the *Destroy...* button. + This snapshot reflects the state of the log after the user clicked the *Create...* button and then the *Destroy...* button. figure.image-display img(src="/resources/images/devguide/lifecycle-hooks/peek-a-boo.png" alt="Peek-a-boo") :marked @@ -292,135 +298,138 @@ figure.image-display .l-sub-section :marked The constructor isn't an Angular hook *per se*. - We log in it to confirm that input properties (the `name` property in this case) have no assigned values at construction. + The log confirms that input properties (the `name` property in this case) have no assigned values at construction. :marked - Had we clicked the *Update Hero* button, we'd have seen another `OnChanges` and two more triplets of + Had the user clicked the *Update Hero* button, the log would show another `OnChanges` and two more triplets of `DoCheck`, `AfterContentChecked` and `AfterViewChecked`. - Clearly these three hooks fire a *lot* and we must keep the logic we put in these hooks - as lean as possible! + Clearly these three hooks fire a *often*. Keep the logic in these hooks as lean as possible! - Our next examples focus on hook details. + The next examples focus on hook details. -.a(id="spy") +a#spy .l-main-section :marked ## Spying *OnInit* and *OnDestroy* - We're going undercover for these two hooks. We want to know when an element is initialized or destroyed, - but we don't want *it* to know we're watching. + Go undercover with these two spy hooks to discover when an element is initialized or destroyed. This is the perfect infiltration job for a directive. - Our heroes will never know it's there. + The heroes will never know they're being watched. .l-sub-section :marked - Kidding aside, we're emphasizing two key points: + Kidding aside, pay attention to two key points: - 1. Angular calls hook methods for *directives* as well as components. + 1. Angular calls hook methods for *directives* as well as components.

      - 2. A spy directive can gives us insight into a DOM object that we cannot change directly. - Obviously we can't change the implementation of a native `div`. - We can't modify a third party component either. - But we can watch both with a directive. + 2. A spy directive can provide insight into a DOM object that you cannot change directly. + Obviously you can't touch the implementation of a native `div`. + You can't modify a third party component either. + But you can watch both with a directive. :marked - Our sneaky spy directive is simple, consisting almost entirely of `ngOnInit` and `ngOnDestroy` hooks + The sneaky spy directive is simple, consisting almost entirely of `ngOnInit` and `ngOnDestroy` hooks that log messages to the parent via an injected `LoggerService`. +makeExample('lifecycle-hooks/ts/app/spy.directive.ts', 'spy-directive')(format=".") :marked - We can apply the spy to any native or component element and it'll be initialized and destroyed + You can apply the spy to any native or component element and it'll be initialized and destroyed at the same time as that element. - Here we attach it to the repeated hero `
      ` + Here it is attached to the repeated hero `
      ` +makeExample('lifecycle-hooks/ts/app/spy.component.html', 'template')(format=".") :marked Each spy's birth and death marks the birth and death of the attached hero `
      ` - with an entry in the *Hook Log* as we see here: + with an entry in the *Hook Log* as seen here: figure.image-display img(src='/resources/images/devguide/lifecycle-hooks/spy-directive.gif' alt="Spy Directive") :marked Adding a hero results in a new hero `
      `. The spy's `ngOnInit` logs that event. - We see a new entry for each hero. The *Reset* button clears the `heroes` list. - Angular removes all hero divs from the DOM and destroys their spy directives at the same time. + Angular removes all hero `
      ` elements from the DOM and destroys their spy directives at the same time. The spy's `ngOnDestroy` method reports its last moments. The `ngOnInit` and `ngOnDestroy` methods have more vital roles to play in real applications. - Let's see why we need them. ### OnInit - We turn to `ngOnInit` for two main reasons: - 1. To perform complex initializations shortly after construction - 1. To set up the component after Angular sets the input properties + Use `ngOnInit` for two main reasons: + 1. to perform complex initializations shortly after construction + 1. to set up the component after Angular sets the input properties - An `ngOnInit` often fetches data for the component as shown in the - [Tutorial](../tutorial/toh-pt4.html#oninit) and [HTTP](server-communication.html#oninit) chapters. - - We don't fetch data in a component constructor. Why? - Because experienced developers agree that components should be cheap and safe to construct. - We shouldn't worry that a new component will try to contact a remote server when - created under test or before we decide to display it. - Constructors should do no more than set the initial local variables to simple values. - - When a component must start working _soon_ after creation, - we can count on Angular to call the `ngOnInit` method to jumpstart it. - That's where the heavy initialization logic belongs. - - Remember also that a directive's data-bound input properties are not set until _after construction_. - That's a problem if we need to initialize the directive based on those properties. - They'll have been set when our `ngOninit` runs. + Experienced developers agree that components should be cheap and safe to construct. .l-sub-section :marked - Our first opportunity to access those properties is the `ngOnChanges` method which - Angular calls before `ngOnInit`. But Angular calls `ngOnChanges` many times after that. + Misko Hevery, Angular team lead, + [explains why](http://misko.hevery.com/code-reviewers-guide/flaw-constructor-does-real-work/) + you should avoid complex constructor logic. + +:marked + Don't fetch data in a component constructor. + You shouldn't worry that a new component will try to contact a remote server when + created under test or before you decide to display it. + Constructors should do no more than set the initial local variables to simple values. + + An `ngOnInit` is a good place for a component to fetch its initial data. The + [Tutorial](../tutorial/toh-pt4.html#oninit) and [HTTP](server-communication.html#oninit) chapter + show how. + + + Remember also that a directive's data-bound input properties are not set until _after construction_. + That's a problem if you need to initialize the directive based on those properties. + They'll have been set when `ngOninit` runs. +.l-sub-section + :marked + The `ngOnChanges` method is your first opportunity to access those properties. + Angular calls `ngOnChanges` before `ngOnInit` ... and many times after that. It only calls `ngOnInit` once. :marked + You can count on Angular to call the `ngOnInit` method _soon_ after creating the component. + That's where the heavy initialization logic belongs. + ### OnDestroy Put cleanup logic in `ngOnDestroy`, the logic that *must* run before Angular destroys the directive. - This is the time to notify another part of the application that this component is going away. + This is the time to notify another part of the application that the component is going away. This is the place to free resources that won't be garbage collected automatically. Unsubscribe from observables and DOM events. Stop interval timers. Unregister all callbacks that this directive registered with global or application services. - We risk memory leaks if we neglect to do so. + You risk memory leaks if you neglect to do so. .l-main-section :marked ## OnChanges - We monitor the `OnChanges` hook in this example. Angular calls its `ngOnChanges` method whenever it detects changes to ***input properties*** of the component (or directive). - - Here is our implementation of the hook. + This example monitors the `OnChanges` hook. +makeExample('lifecycle-hooks/ts/app/on-changes.component.ts', 'ng-on-changes', 'OnChangesComponent (ngOnChanges)')(format=".") :marked The `ngOnChanges` method takes an object that maps each changed property name to a - [SimpleChange](../api/core/index/SimpleChange-class.html) object with the current and previous property values. - We iterate over the changed properties and log them. + [SimpleChange](../api/core/index/SimpleChange-class.html) object holding the current and previous property values. + This hook iterates over the changed properties and logs them. - The input properties for our example `OnChangesComponent` are `hero` and `power`. + The example component, `OnChangesComponent`, has two input properties: `hero` and `power`. +makeExample('lifecycle-hooks/ts/app/on-changes.component.ts', 'inputs')(format=".") :marked - The parent binds to them like this: + The host `OnChangesParentComponent` binds to them like this: +makeExample('lifecycle-hooks/ts/app/on-changes-parent.component.html', 'on-changes') :marked - Here's the sample in action as we make changes. + Here's the sample in action as the user makes changes. figure.image-display img(src='/resources/images/devguide/lifecycle-hooks/on-changes-anim.gif' alt="OnChanges") :marked - We see log entries as the string value of the *power* property changes. But the `ngOnChanges` did not catch changes to `hero.name` + The log entries appear as the string value of the *power* property changes. + But the `ngOnChanges` does not catch changes to `hero.name` That's surprising at first. Angular only calls the hook when the value of the input property changes. @@ -431,39 +440,30 @@ figure.image-display .l-main-section :marked ## DoCheck - We can use the `DoCheck` hook to detect and act upon changes that Angular doesn't catch on its own. + Use the `DoCheck` hook to detect and act upon changes that Angular doesn't catch on its own. .l-sub-section :marked - With this method we can detect a change that Angular overlooked. - What we do with that information to refresh the display is a separate matter. + Use this method to detect a change that Angular overlooked. :marked - The *DoCheck* sample extends the *OnChanges* sample with this implementation of `DoCheck`: + The *DoCheck* sample extends the *OnChanges* sample with the following `ngDoCheck` hook: +makeExample('lifecycle-hooks/ts/app/do-check.component.ts', 'ng-do-check', 'DoCheckComponent (ngDoCheck)')(format=".") :marked - We manually check everything that we care about, capturing and comparing against previous values. - We write a special message to the log when there are no substantive changes - to the hero or the power so we can keep an eye on the method's performance characteristics. - - The results are illuminating: + This code inspects certain _values-of-interest_, capturing and comparing their current state against previous values. + It writes a special message to the log when there are no substantive changes to the `hero` or the `power` + so you can see how often `DoCheck` is called. The results are illuminating: figure.image-display img(src='/resources/images/devguide/lifecycle-hooks/do-check-anim.gif' alt="DoCheck") :marked - We now are able to detect when the hero's `name` has changed. But we must be careful. - - The `ngDoCheck` hook is called with enormous frequency — + While the `ngDoCheck` hook can detect when the hero's `name` has changed, it has a frightful cost. + This hook is called with enormous frequency — after _every_ change detection cycle no matter where the change occurred. It's called over twenty times in this example before the user can do anything. Most of these initial checks are triggered by Angular's first rendering of *unrelated data elsewhere on the page*. Mere mousing into another input box triggers a call. Relatively few calls reveal actual changes to pertinent data. - Clearly our implementation must be very lightweight or the user experience may suffer. - -.l-sub-section - :marked - We also see that the `ngOnChanges` method is called in contradiction of the - [incorrect API documentation](../api/core/index/DoCheck-class.html). + Clearly our implementation must be very lightweight or the user experience will suffer. .l-main-section :marked @@ -478,11 +478,11 @@ figure.image-display +makeExample('lifecycle-hooks/ts/app/after-view.component.ts', 'template', 'AfterViewComponent (template)')(format=".") :marked The following hooks take action based on changing values *within the child view* - which we can only reach by querying for the child view via the property decorated with + which can only be reached by querying for the child view via the property decorated with [@ViewChild](../api/core/index/ViewChild-var.html). +makeExample('lifecycle-hooks/ts/app/after-view.component.ts', 'hooks', 'AfterViewComponent (class excerpts)')(format=".") -.a(id="wait-a-tick") +#wait-a-tick :marked ### Abide by the unidirectional data flow rule The `doSomething` method updates the screen when the hero name exceeds 10 characters. @@ -491,14 +491,14 @@ figure.image-display :marked Why does the `doSomething` method wait a tick before updating `comment`? - Because we must adhere to Angular's unidirectional data flow rule which says that - we may not update the view *after* it has been composed. - Both hooks fire after the component's view has been composed. + Angular's unidirectional data flow rule forbids updates to the view *after* it has been composed. + Both of these hooks fire _after_ the component's view has been composed. - Angular throws an error if we update component's data-bound `comment` property immediately (try it!). + Angular throws an error if the hook updates the component's data-bound `comment` property immediately (try it!). block tick-methods :marked - The `LoggerService.tick` methods, which are implemented by a call to `setTimeout`, postpone the update one turn of the of the browser's JavaScript cycle ... and that's long enough. + The `LoggerService.tick_then()` postpones the log update + for one turn of the browser's JavaScript cycle ... and that's just long enough. :marked Here's *AfterView* in action @@ -523,22 +523,20 @@ figure.image-display Angular 1 developers know this technique as *transclusion*. :marked - We'll illustrate with a variation on the [previous](#afterview) example - whose behavior and output is almost the same. - - This time, instead of including the child view within the template, we'll import it from + Consider this variation on the [previous _AfterView_](#afterview) example. + This time, instead of including the child view within the template, it imports the content from the `AfterContentComponent`'s parent. Here's the parent's template. +makeExample('lifecycle-hooks/ts/app/after-content.component.ts', 'parent-template', 'AfterContentParentComponent (template excerpt)')(format=".") :marked Notice that the `` tag is tucked between the `` tags. - We never put content between a component's element tags *unless we intend to project that content + Never put content between a component's element tags *unless you intend to project that content into the component*. Now look at the component's template: +makeExample('lifecycle-hooks/ts/app/after-content.component.ts', 'template', 'AfterContentComponent (template)')(format=".") :marked The `` tag is a *placeholder* for the external content. - They tell Angular where to insert that content. + It tells Angular where to insert that content. In this case, the projected content is the `` from the parent. figure.image-display img(src='/resources/images/devguide/lifecycle-hooks/projected-child-view.png' width="230" alt="Projected Content") @@ -549,8 +547,8 @@ figure.image-display and (b) the presence of `` tags in the component's template. :marked ### AfterContent hooks - *AfterContent* hooks are similar to the *AfterView* hooks. The key difference is the kind of child component - that we're looking for. + *AfterContent* hooks are similar to the *AfterView* hooks. + The key difference is in the child component * The *AfterView* hooks concern `ViewChildren`, the child components whose element tags appear *within* the component's template. @@ -559,17 +557,17 @@ figure.image-display projected into the component. The following *AfterContent* hooks take action based on changing values in a *content child* - which we can only reach by querying for it via the property decorated with + which can only be reached by querying for it via the property decorated with [@ContentChild](../api/core/index/ContentChild-var.html). +makeExample('lifecycle-hooks/ts/app/after-content.component.ts', 'hooks', 'AfterContentComponent (class excerpts)')(format=".") :marked - ### No unidirectional flow worries + ### No unidirectional flow worries with _AfterContent..._ This component's `doSomething` method update's the component's data-bound `comment` property immediately. There's no [need to wait](#wait-a-tick). Recall that Angular calls both *AfterContent* hooks before calling either of the *AfterView* hooks. Angular completes composition of the projected content *before* finishing the composition of this component's view. - We still have a window of opportunity to modify that view. + There is a small window between the `AfterContent...` and `AfterView...` hooks to modify the host view. From ac0e82cda786092f1211efa88ad7472cc9750858 Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Sat, 24 Sep 2016 14:30:06 -0700 Subject: [PATCH 04/12] docs(js/guide): don't use shredder & _data.json fixes (#2467) replay Patrice's PR #2448 --- public/docs/js/latest/guide/_data.json | 4 ++-- public/docs/js/latest/guide/index.jade | 22 +++++++++++----------- public/docs/ts/latest/guide/index.jade | 12 ++++-------- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/public/docs/js/latest/guide/_data.json b/public/docs/js/latest/guide/_data.json index 72977625c0..b3b33214c3 100644 --- a/public/docs/js/latest/guide/_data.json +++ b/public/docs/js/latest/guide/_data.json @@ -108,7 +108,7 @@ "npm-packages": { "title": "Npm Packages", - "intro": "Details of the recommended npm packages and the different kinds of package dependencies" + "intro": "Recommended npm packages, and how to specify package dependencies" }, "pipes": { @@ -123,7 +123,7 @@ "security": { "title": "Security", - "intro": "Prevent security vulnerabilities" + "intro": "Developing for content security in Angular applications" }, "structural-directives": { diff --git a/public/docs/js/latest/guide/index.jade b/public/docs/js/latest/guide/index.jade index 4af0447111..c29be81578 100644 --- a/public/docs/js/latest/guide/index.jade +++ b/public/docs/js/latest/guide/index.jade @@ -1,12 +1,12 @@ -include ../_util-fns +extends ../../../ts/latest/guide/index.jade -+includeShared('{ts}', 'intro') -+includeShared('{ts}', 'how-to-read-1') -.alert.is-important - :marked - Most of the documentation has been written for TypeScript developers - and has not yet been translated to JavaScript. - Please bear with us. Meanwhile, we've provide links to the TypeScript chapters - where JavaScript versions are unavailable. -+includeShared('{ts}', 'how-to-read-2') -+includeShared('{ts}', 'the-rest') +block includes + include ../_util-fns + +block js-alert + .alert.is-important + :marked + Most of the documentation has been written for TypeScript developers + and has not yet been translated to JavaScript. + Please bear with us. Meanwhile, we've provide links to the TypeScript chapters + where JavaScript versions are unavailable. diff --git a/public/docs/ts/latest/guide/index.jade b/public/docs/ts/latest/guide/index.jade index 3868c3c573..6af522624c 100644 --- a/public/docs/ts/latest/guide/index.jade +++ b/public/docs/ts/latest/guide/index.jade @@ -1,7 +1,6 @@ block includes include ../_util-fns -// #docregion intro - var langName = current.path[1] == 'ts' ? 'TypeScript' : 'JavaScript' figure img(src="/resources/images/devguide/intro/people.png" alt="Us" align="left" style="width:200px; margin-left:-40px;margin-right:10px" ) @@ -10,17 +9,16 @@ figure are building client applications in HTML and #{langName}.
      -// #enddocregion intro -// #docregion how-to-read-1 :marked # Organization The documentation is divided into major thematic sections, each a collection of pages devoted to that theme. -// #enddocregion how-to-read-1 -// #docregion how-to-read-2 + +block js-alert + - var top="vertical-align:top" table(width="100%") col(width="15%") @@ -83,8 +81,7 @@ table(width="100%") 1. [Template Syntax](template-syntax.html) is a comprehensive study of Angular template HTML. After reading the above sections, you can skip to any other pages on this site. -// #enddocregion how-to-read-2 -// #docregion the-rest + :marked # Code samples @@ -119,4 +116,3 @@ block example-links Use the [Angular Github repo](https://github.com/angular/angular) to report issues with **Angular** itself. -// #enddocregion the-rest From f45c9998cc65b8eff78e741e9ea290b5b953f23d Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Sat, 24 Sep 2016 15:50:21 -0700 Subject: [PATCH 05/12] docs(lifecycle-hooks): combine what and when in one chart; add img (#2469) --- .../docs/ts/latest/guide/lifecycle-hooks.jade | 162 ++++++++---------- .../lifecycle-hooks/hooks-in-sequence.png | Bin 0 -> 15084 bytes 2 files changed, 68 insertions(+), 94 deletions(-) create mode 100644 public/resources/images/devguide/lifecycle-hooks/hooks-in-sequence.png diff --git a/public/docs/ts/latest/guide/lifecycle-hooks.jade b/public/docs/ts/latest/guide/lifecycle-hooks.jade index 9f164d8b4c..c2c5cebe4e 100644 --- a/public/docs/ts/latest/guide/lifecycle-hooks.jade +++ b/public/docs/ts/latest/guide/lifecycle-hooks.jade @@ -5,30 +5,37 @@ block includes :marked # Component Lifecycle - A Component has a lifecycle managed by Angular itself. Angular creates it, renders it, creates and renders its children, +figure + img(src="/resources/images/devguide/lifecycle-hooks/hooks-in-sequence.png" alt="Us" align="left" style="width:200px; margin-left:-40px;margin-right:30px" ) +:marked + A component has a lifecycle managed by Angular itself. + + Angular creates it, renders it, creates and renders its children, checks it when its data-bound properties change, and destroys it before removing it from the DOM. - Angular offers **component lifecycle hooks** - that provide visibility into these key moments and the ability to act when they occur. + Angular offers **lifecycle hooks** + that provide visibility into these key life moments and the ability to act when they occur. + A directive has the same set of lifecycle hooks, minus the hooks that are specific to component content and views. +
      ## Table of Contents - * [The lifecycle hooks](#hooks-overview) - * [_What_ they are](#hook-descriptions) - * [_When_ they are called](#hook-sequence) + * [Overview](#hooks-overview) +

      + * [Each hook's purpose and timing](#hooks-purpose-timing) +ifDocsFor('ts|js') :marked * [Interfaces are optional (technically)](#interface-optional) + :marked + * [Other Angular lifecycle hooks](#other-lifecycle-hooks) +

      + * [The lifecycle sample](#the-sample) + * [All](#peek-a-boo) + * [Spying OnInit and OnDestroy](#spy) + * [OnChanges](#onchanges) + * [DoCheck](#docheck) + * [AfterViewInit and AfterViewChecked](#afterview) + * [AfterContentInit and AfterContentChecked](#aftercontent) :marked - * [Other Angular lifecycle hooks](#other-lifecycle-hooks) -

      - * [The lifecycle sample](#the-sample) - * [All](#peek-a-boo) - * [Spying OnInit and OnDestroy](#spy) - * [OnChanges](#onchanges) - * [DoCheck](#docheck) - * [AfterViewInit and AfterViewChecked](#afterview) - * [AfterContentInit and AfterContentChecked](#aftercontent) - Try the . a#hooks-overview @@ -48,75 +55,7 @@ a#hooks-overview No directive or component will implement all of the lifecycle hooks and some of the hooks only make sense for components. Angular only calls a directive/component hook method *if it is defined*. -a#hook-descriptions -:marked - Here are descriptions of the component lifecycle hook methods followed by a chart describing [when they are called](#hook-sequence): - - ### Directives and Components - -table(width="100%") - col(width="20%") - col(width="80%") - tr - th Hook - th Purpose - tr(style=top) - td ngOnInit - td - :marked - Initialize the directive/component after Angular initializes the data-bound input properties. - tr(style=top) - td ngOnChanges - td - :marked - Respond after Angular sets a data-bound input property. - The method receives a `changes` object of current and previous values. - tr(style=top) - td ngDoCheck - td - :marked - Detect and act upon changes that Angular can't or won't - detect on its own. Called every change detection run. - tr(style=top) - td ngOnDestroy - td - :marked - Cleanup just before Angular destroys the directive/component. - Unsubscribe observables and detach event handlers to avoid memory leaks. - -:marked - ### Components only - -table(width="100%") - col(width="20%") - col(width="80%") - tr - th Hook - th Purpose - tr(style=top) - td ngAfterContentInit - td - :marked - After Angular projects external content into its view. - tr(style=top) - td ngAfterContentChecked - td - :marked - After Angular checks the bindings of the external content that it projected into its view. - tr(style=top) - td ngAfterViewInit - td - :marked - After Angular creates the component's view(s). - tr(style=top) - td ngAfterViewChecked - td - :marked - After Angular checks the bindings of the component's view(s). -:marked - Angular does not call the hook methods in this order. - -a#hook-sequence +a#hooks-purpose-timing .l-main-section :marked ## Lifecycle sequence @@ -127,47 +66,82 @@ table(width="100%") col(width="80%") tr th Hook - th Timing + th Purpose and Timing + tr(style=top) td ngOnChanges td :marked - before `ngOnInit` and when a data-bound input property value changes. + Respond when Angular (re)sets data-bound input properties. + The method receives a `SimpleChanges` object of current and previous property values. + + Called before `ngOnInit` and whenever one or more data-bound input properties change. + tr(style=top) td ngOnInit td :marked - after the first `ngOnChanges`. + Initialize the directive/component after Angular first displays the data-bound properties + and sets the directive/component's input properties. + + Called _once_, after the _first_ `ngOnChanges`. + tr(style=top) td ngDoCheck td :marked - during every Angular change detection cycle. + Detect and act upon changes that Angular can't or won't detect on its own. + + Called during every change detection run, immediately after `ngOnChanges` and `ngOnInit`. + tr(style=top) td ngAfterContentInit td :marked - after projecting content into the component. + Respond after Angular projects external content into the component's view. + + Called _once_ after the first `NgDoCheck`. + + _A component-only hook_. + tr(style=top) td ngAfterContentChecked td :marked - after every check of projected component content. + Respond after Angular checks the content projected into the component. + + Called after the `ngAfterContentInit` and every subsequent `NgDoCheck`. + + _A component-only hook_. + tr(style=top) td ngAfterViewInit td :marked - after initializing the component's views and child views. + Respond after Angular initializes the component's views and child views. + + Called _once_ after the first `ngAfterContentChecked`. + + _A component-only hook_. + tr(style=top) td ngAfterViewChecked td :marked - after every check of the component's views and child views. + Respond after Angular checks the component's views and child views. + + Called after the `ngAfterViewInit` and every subsequent `ngAfterContentChecked`. + + _A component-only hook_. + tr(style=top) td ngOnDestroy td :marked - just before Angular destroys the directive/component. + Cleanup just before Angular destroys the directive/component. + Unsubscribe observables and detach event handlers to avoid memory leaks. + + Called _just before_ Angular destroys the directive/component. +ifDocsFor('ts|js') a#interface-optional diff --git a/public/resources/images/devguide/lifecycle-hooks/hooks-in-sequence.png b/public/resources/images/devguide/lifecycle-hooks/hooks-in-sequence.png new file mode 100644 index 0000000000000000000000000000000000000000..128d8673af0b4049a8d7f97821988e03f3fa3228 GIT binary patch literal 15084 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 O0000u literal 0 HcmV?d00001 From 3ee19780b588a04b6d39ba11870adfd08b3c91c3 Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Sun, 25 Sep 2016 15:07:53 -0700 Subject: [PATCH 06/12] docs(testing): incorporate Igor Minar feedback, Part 2 (#2453) docs(testing): incorporate Igor Minar feedback, Part 2 --- public/docs/ts/latest/guide/testing.jade | 62 +++++++++++------------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/public/docs/ts/latest/guide/testing.jade b/public/docs/ts/latest/guide/testing.jade index abea24721d..88360a3afe 100644 --- a/public/docs/ts/latest/guide/testing.jade +++ b/public/docs/ts/latest/guide/testing.jade @@ -706,15 +706,14 @@ a(href="#top").to-top Back to top :marked ### Synchronous tests The first two tests are synchronous. - Neither test can prove that a value from the service will be displayed. - - Thanks to the spy, the second test verifies that `getQuote` is called. - But the quote itself has not arrived, despite the fact that the spy returns a resolved promise. - - This test must wait at least one full turn of the JavaScript engine, a least one "tick", before the - value becomes available. By that time, the test runner has moved on to the next test in the suite. + Thanks to the spy, they verify that `getQuote` is called _after_ + the first change detection cycle during which Angular calls `ngOnInit`. - The test must become an "async test" ... like the third test + Neither test can prove that a value from the service is be displayed. + The quote itself has not arrived, despite the fact that the spy returns a resolved promise. + + This test must wait at least one full turn of the JavaScript engine before the + value becomes available. The test must become _asynchronous_. #async :marked @@ -724,10 +723,9 @@ a(href="#top").to-top Back to top +makeExample('testing/ts/app/shared/twain.component.spec.ts', 'async-test', 'app/shared/twain.component.spec.ts (async test)')(format='.') :marked The `async` function is one of the Angular testing utilities. + It simplifies coding of asynchronous tests by arranging for the tester's code to run in a special _async test zone_. - It simplifyies coding of asynchronous tests by arranging for the tester's code to run in a special _async test zone_. - - The `async` function _takes_ a parameterless function and _returns_ a parameterless function + The `async` function _takes_ a parameterless function and _returns_ a function which becomes the argument to the Jasmine `it` call. The body of the `async` argument looks much like the body of a normal `it` argument. @@ -736,17 +734,14 @@ a(href="#top").to-top Back to top there is no `done` function to call as there is in standard Jasmine asynchronous tests. Some functions called within a test (such as `fixture.whenStable`) continue to reveal their asynchronous behavior. - Consider also the [_fakeAsync_](#fake-async) alternative which affords a more linear coding experience. +.l-sub-section + :marked + The `fakeAsync` alternative, [covered below](#fake-async), removes this artifact and affords a more linear coding experience. #when-stable :marked ## _whenStable_ - The test must wait for the `getQuote` promise to resolve. - - The `getQuote` promise promise resolves in the next turn of the JavaScript engine, thanks to the spy. - But a different test implementation of `getQuote` could take longer. - An integration test might call the _real_ `getQuote`, resulting in an XHR request - that took many seconds to respond. + The test must wait for the `getQuote` promise to resolve in the next turn of the JavaScript engine. This test has no direct access to the promise returned by the call to `testService.getQuote` which is private and inaccessible inside `TwainComponent`. @@ -755,10 +750,10 @@ a(href="#top").to-top Back to top which intercepts all promises issued within the _async_ method call. The `ComponentFixture.whenStable` method returns its own promise which resolves when the `getQuote` promise completes. - In fact, the _whenStable_ promise resolves when _all pending asynchronous activities_ complete ... the definition of "stable". + In fact, the _whenStable_ promise resolves when _all pending asynchronous activities within this test_ complete ... the definition of "stable". - Then the testing continues. - The test kicks off another round of change detection (`fixture.detechChanges`) which tells Angular to update the DOM with the quote. + Then the test resumes and kicks off another round of change detection (`fixture.detectChanges`) + which tells Angular to update the DOM with the quote. The `getQuote` helper method extracts the display element text and the expectation confirms that the text matches the test quote. #fakeAsync @@ -772,23 +767,23 @@ a(href="#top").to-top Back to top Notice that `fakeAsync` replaces `async` as the `it` argument. The `fakeAsync` function is another of the Angular testing utilities. - Like [async](#), it _takes_ a parameterless function and _returns_ a parameterless function - which becomes the argument to the Jasmine `it` call. + Like [async](#async), it _takes_ a parameterless function and _returns_ a function + that becomes the argument to the Jasmine `it` call. The `fakeAsync` function enables a linear coding style by running the test body in a special _fakeAsync test zone_. The principle advantage of `fakeAsync` over `async` is that the test appears to be synchronous. - There are no promises at all. - No `then(...)` chains to disrupt the visible flow of control. + There is no `then(...)` to disrupt the visible flow of control. + The promise-returning `fixture.whenStable` is gone, replaced by `tick()`. - There are limitations. For example, you cannot make an XHR call from within a `fakeAsync`. +.l-sub-section + :marked + There _are_ limitations. For example, you cannot make an XHR call from within a `fakeAsync`. #tick #tick-first-look :marked ## The _tick_ function - Compare the third and fourth tests. Notice that `fixture.whenStable` is gone, replaced by `tick()`. - The `tick` function is one of the Angular testing utilities and a companion to `fakeAsync`. It can only be called within a `fakeAsync` body. @@ -858,25 +853,26 @@ a(href="#top").to-top Back to top :marked ## The _async_ function in _beforeEach_ - Notice the `async` call in the `beforeEach`. + Notice the `async` call in the `beforeEach`, made necessary by the asynchronous `TestBed.compileComponents` method. The `async` function arranges for the tester's code to run in a special _async test zone_ that hides the mechanics of asynchronous execution, just as it does when passed to an [_it_ test)(#async). #compile-components :marked ## _compileComponents_ - In this example, `Testbed.compileComponents` compiles one component, the `DashboardComponent`. + In this example, `TestBed.compileComponents` compiles one component, the `DashboardComponent`. It's the only declared component in this testing module. Tests later in this chapter have more declared components and some of them import application modules that declare yet more components. Some or all of these components could have external templates and css files. - `TestBed.compileComponents` compiles them all asynchonously at one time. + `TestBed.compileComponents` compiles them all asynchronously at one time. The `compileComponents` method returns a promise so you can perform additional tasks _after_ it finishes. + The promise isn't needed here. ### _compileComponents_ closes configuration - After `compileComponents` runs, the current `TestBed` instance is closed to further configuration. + Calling `compileComponents` closes the current `TestBed` instance is further configuration. You cannot call any more `TestBed` configuration methods, not `configureTestModule` nor any of the `override...` methods. The `TestBed` throws an error if you try. @@ -928,7 +924,7 @@ a(href="#top").to-top Back to top The router seems particularly challenging. .l-sub-section :marked - The [discussion below](#routed-component) covers testing components that requre the router. + The [discussion below](#routed-component) covers testing components that require the router. :marked The immediate goal is to test the `DashboardHeroComponent`, not the `DashboardComponent`, and there's no need to work hard unnecessarily. Let's try the second and third options. From 738b714bd36e3e3f600eb941bdb25843d6a2c255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Rodr=C3=ADguez?= Date: Sun, 25 Sep 2016 23:12:04 +0100 Subject: [PATCH 07/12] docs(testing): change createInstance to createComponent (#2475) --- public/docs/ts/latest/guide/testing.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/docs/ts/latest/guide/testing.jade b/public/docs/ts/latest/guide/testing.jade index 88360a3afe..7a99679ff4 100644 --- a/public/docs/ts/latest/guide/testing.jade +++ b/public/docs/ts/latest/guide/testing.jade @@ -880,7 +880,7 @@ a(href="#top").to-top Back to top :marked Do not configure the `TestBed` after calling `compileComponents`. Make `compileComponents` the last step - before calling `TestBed.createInstance` to instantiate the _component-under-test_. + before calling `TestBed.createComponent` to instantiate the _component-under-test_. :marked The `DashboardHeroComponent` spec follows the asynchonous `beforeEach` with a _synchronous_ `beforeEach` that completes the setup steps and runs tests ... as described in the next section. From 6e17d33475c2bd8778245d745f9146645764af42 Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Sun, 25 Sep 2016 15:24:13 -0700 Subject: [PATCH 08/12] chore: update samples to "angular-in-memory-web-api" (#2472) chore: update samples to "angular-in-memory-web-api" --- .../cb-dependency-injection/ts/app/app.module.ts | 2 +- public/docs/_examples/package.json | 2 +- .../_examples/quickstart/ts/systemjs.config.1.js | 6 +++--- .../server-communication/ts/app/app.module.ts | 2 +- .../server-communication/ts/app/hero-data.ts | 2 +- .../ts/app/toh/hero.service.ts | 8 ++++---- public/docs/_examples/style-guide/ts/app/main.ts | 2 +- public/docs/_examples/systemjs.config.js | 6 +++--- .../_examples/systemjs.config.plunker.build.js | 10 +++++----- public/docs/_examples/systemjs.config.plunker.js | 10 +++++----- public/docs/_examples/toh-6/ts/app/app.module.ts | 2 +- .../toh-6/ts/app/in-memory-data.service.ts | 2 +- .../ts/systemjs.config.1.js | 14 +++++++------- .../ts/systemjs.config.1.js | 14 +++++++------- .../docs/ts/_cache/guide/server-communication.jade | 2 +- public/docs/ts/latest/guide/npm-packages.jade | 2 +- .../docs/ts/latest/guide/server-communication.jade | 2 +- 17 files changed, 44 insertions(+), 44 deletions(-) diff --git a/public/docs/_examples/cb-dependency-injection/ts/app/app.module.ts b/public/docs/_examples/cb-dependency-injection/ts/app/app.module.ts index 7b9487e815..5d7ca6ab97 100644 --- a/public/docs/_examples/cb-dependency-injection/ts/app/app.module.ts +++ b/public/docs/_examples/cb-dependency-injection/ts/app/app.module.ts @@ -9,7 +9,7 @@ import { LocationStrategy, import { NgModule } from '@angular/core'; import { HeroData } from './hero-data'; -import { InMemoryWebApiModule } from 'angular2-in-memory-web-api'; +import { InMemoryWebApiModule } from 'angular-in-memory-web-api'; import { AppComponent } from './app.component'; diff --git a/public/docs/_examples/package.json b/public/docs/_examples/package.json index 7baee8a5a9..75df42d440 100644 --- a/public/docs/_examples/package.json +++ b/public/docs/_examples/package.json @@ -37,7 +37,7 @@ "@angular/platform-server": "2.0.0", "@angular/router": "3.0.0", "@angular/upgrade": "2.0.0", - "angular2-in-memory-web-api": "0.0.20", + "angular-in-memory-web-api": "0.1.0", "bootstrap": "^3.3.6", "core-js": "^2.4.1", "reflect-metadata": "^0.1.3", diff --git a/public/docs/_examples/quickstart/ts/systemjs.config.1.js b/public/docs/_examples/quickstart/ts/systemjs.config.1.js index 852c46168d..0ef2c50f4e 100644 --- a/public/docs/_examples/quickstart/ts/systemjs.config.1.js +++ b/public/docs/_examples/quickstart/ts/systemjs.config.1.js @@ -25,8 +25,8 @@ '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js', // other libraries - 'rxjs': 'npm:rxjs', - 'angular2-in-memory-web-api': 'npm:angular2-in-memory-web-api', + 'rxjs': 'npm:rxjs', + 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api', }, // packages tells the System loader how to load when no filename and/or no extension packages: { @@ -37,7 +37,7 @@ rxjs: { defaultExtension: 'js' }, - 'angular2-in-memory-web-api': { + 'angular-in-memory-web-api': { main: './index.js', defaultExtension: 'js' } diff --git a/public/docs/_examples/server-communication/ts/app/app.module.ts b/public/docs/_examples/server-communication/ts/app/app.module.ts index 95490f2b1d..8ac2f8608b 100644 --- a/public/docs/_examples/server-communication/ts/app/app.module.ts +++ b/public/docs/_examples/server-communication/ts/app/app.module.ts @@ -4,7 +4,7 @@ import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { HttpModule, JsonpModule } from '@angular/http'; -import { InMemoryWebApiModule } from 'angular2-in-memory-web-api'; +import { InMemoryWebApiModule } from 'angular-in-memory-web-api'; import { HeroData } from './hero-data'; import { AppComponent } from './app.component'; diff --git a/public/docs/_examples/server-communication/ts/app/hero-data.ts b/public/docs/_examples/server-communication/ts/app/hero-data.ts index e5e0bab986..393d52eef7 100644 --- a/public/docs/_examples/server-communication/ts/app/hero-data.ts +++ b/public/docs/_examples/server-communication/ts/app/hero-data.ts @@ -1,5 +1,5 @@ // #docregion -import { InMemoryDbService } from 'angular2-in-memory-web-api'; +import { InMemoryDbService } from 'angular-in-memory-web-api'; export class HeroData implements InMemoryDbService { createDb() { let heroes = [ diff --git a/public/docs/_examples/server-communication/ts/app/toh/hero.service.ts b/public/docs/_examples/server-communication/ts/app/toh/hero.service.ts index f1f749b507..9e970843ea 100644 --- a/public/docs/_examples/server-communication/ts/app/toh/hero.service.ts +++ b/public/docs/_examples/server-communication/ts/app/toh/hero.service.ts @@ -15,14 +15,14 @@ import { Observable } from 'rxjs/Observable'; @Injectable() export class HeroService { - // #docregion ctor - constructor (private http: Http) {} - // #enddocregion ctor - // #docregion endpoint private heroesUrl = 'app/heroes'; // URL to web API // #enddocregion endpoint + // #docregion ctor + constructor (private http: Http) {} + // #enddocregion ctor + // #docregion methods, error-handling, http-get getHeroes (): Observable { return this.http.get(this.heroesUrl) diff --git a/public/docs/_examples/style-guide/ts/app/main.ts b/public/docs/_examples/style-guide/ts/app/main.ts index 579ffbb101..792f873167 100644 --- a/public/docs/_examples/style-guide/ts/app/main.ts +++ b/public/docs/_examples/style-guide/ts/app/main.ts @@ -3,7 +3,7 @@ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { BrowserModule } from '@angular/platform-browser'; import { HttpModule } from '@angular/http'; -import { InMemoryWebApiModule } from 'angular2-in-memory-web-api'; +import { InMemoryWebApiModule } from 'angular-in-memory-web-api'; import { RouterModule } from '@angular/router'; diff --git a/public/docs/_examples/systemjs.config.js b/public/docs/_examples/systemjs.config.js index cc06fc9422..0ea776d8f3 100644 --- a/public/docs/_examples/systemjs.config.js +++ b/public/docs/_examples/systemjs.config.js @@ -25,8 +25,8 @@ '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js', // other libraries - 'rxjs': 'npm:rxjs', - 'angular2-in-memory-web-api': 'npm:angular2-in-memory-web-api', + 'rxjs': 'npm:rxjs', + 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api', }, // packages tells the System loader how to load when no filename and/or no extension packages: { @@ -37,7 +37,7 @@ rxjs: { defaultExtension: 'js' }, - 'angular2-in-memory-web-api': { + 'angular-in-memory-web-api': { main: './index.js', defaultExtension: 'js' } diff --git a/public/docs/_examples/systemjs.config.plunker.build.js b/public/docs/_examples/systemjs.config.plunker.build.js index 36ad2c7d16..41015e2e43 100644 --- a/public/docs/_examples/systemjs.config.plunker.build.js +++ b/public/docs/_examples/systemjs.config.plunker.build.js @@ -50,10 +50,10 @@ '@angular/forms/testing': 'ng:forms-builds/master/bundles/forms-testing.umd.js', // other libraries - 'rxjs': 'npm:rxjs', - 'angular2-in-memory-web-api': 'npm:angular2-in-memory-web-api', - 'ts': 'npm:plugin-typescript@4.0.10/lib/plugin.js', - 'typescript': 'npm:typescript@2.0.2/lib/typescript.js', + 'rxjs': 'npm:rxjs', + 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api', + 'ts': 'npm:plugin-typescript@4.0.10/lib/plugin.js', + 'typescript': 'npm:typescript@2.0.2/lib/typescript.js', }, // packages tells the System loader how to load when no filename and/or no extension @@ -65,7 +65,7 @@ rxjs: { defaultExtension: 'js' }, - 'angular2-in-memory-web-api': { + 'angular-in-memory-web-api': { main: './index.js', defaultExtension: 'js' } diff --git a/public/docs/_examples/systemjs.config.plunker.js b/public/docs/_examples/systemjs.config.plunker.js index ccfee00019..c5314b3170 100644 --- a/public/docs/_examples/systemjs.config.plunker.js +++ b/public/docs/_examples/systemjs.config.plunker.js @@ -37,10 +37,10 @@ '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js', // other libraries - 'rxjs': 'npm:rxjs', - 'angular2-in-memory-web-api': 'npm:angular2-in-memory-web-api', - 'ts': 'npm:plugin-typescript@4.0.10/lib/plugin.js', - 'typescript': 'npm:typescript@2.0.2/lib/typescript.js', + 'rxjs': 'npm:rxjs', + 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api', + 'ts': 'npm:plugin-typescript@4.0.10/lib/plugin.js', + 'typescript': 'npm:typescript@2.0.2/lib/typescript.js', }, // packages tells the System loader how to load when no filename and/or no extension @@ -52,7 +52,7 @@ rxjs: { defaultExtension: 'js' }, - 'angular2-in-memory-web-api': { + 'angular-in-memory-web-api': { main: './index.js', defaultExtension: 'js' } diff --git a/public/docs/_examples/toh-6/ts/app/app.module.ts b/public/docs/_examples/toh-6/ts/app/app.module.ts index 7c497b8f14..2ab938b8eb 100644 --- a/public/docs/_examples/toh-6/ts/app/app.module.ts +++ b/public/docs/_examples/toh-6/ts/app/app.module.ts @@ -12,7 +12,7 @@ import { HttpModule } from '@angular/http'; // #enddocregion v1 // Imports for loading & configuring the in-memory web api -import { InMemoryWebApiModule } from 'angular2-in-memory-web-api'; +import { InMemoryWebApiModule } from 'angular-in-memory-web-api'; import { InMemoryDataService } from './in-memory-data.service'; // #docregion v1 diff --git a/public/docs/_examples/toh-6/ts/app/in-memory-data.service.ts b/public/docs/_examples/toh-6/ts/app/in-memory-data.service.ts index c63151a122..c915955e22 100644 --- a/public/docs/_examples/toh-6/ts/app/in-memory-data.service.ts +++ b/public/docs/_examples/toh-6/ts/app/in-memory-data.service.ts @@ -1,5 +1,5 @@ // #docregion , init -import { InMemoryDbService } from 'angular2-in-memory-web-api'; +import { InMemoryDbService } from 'angular-in-memory-web-api'; export class InMemoryDataService implements InMemoryDbService { createDb() { let heroes = [ diff --git a/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/systemjs.config.1.js b/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/systemjs.config.1.js index 3661eb52a2..a54f8bb20c 100644 --- a/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/systemjs.config.1.js +++ b/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/systemjs.config.1.js @@ -7,17 +7,17 @@ // map tells the System loader where to look for things // #docregion paths var map = { - 'app': '/app', // 'dist', + 'app': '/app', // 'dist', - '@angular': '/node_modules/@angular', - 'angular2-in-memory-web-api': '/node_modules/angular2-in-memory-web-api', - 'rxjs': '/node_modules/rxjs' + '@angular': '/node_modules/@angular', + 'angular-in-memory-web-api': '/node_modules/angular-in-memory-web-api', + 'rxjs': '/node_modules/rxjs' }; var packages = { - '/app': { main: 'main.js', defaultExtension: 'js' }, - 'rxjs': { defaultExtension: 'js' }, - 'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' }, + '/app': { main: 'main.js', defaultExtension: 'js' }, + 'rxjs': { defaultExtension: 'js' }, + 'angular-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' }, }; // #enddocregion paths diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/systemjs.config.1.js b/public/docs/_examples/upgrade-phonecat-3-final/ts/systemjs.config.1.js index 3661eb52a2..a54f8bb20c 100644 --- a/public/docs/_examples/upgrade-phonecat-3-final/ts/systemjs.config.1.js +++ b/public/docs/_examples/upgrade-phonecat-3-final/ts/systemjs.config.1.js @@ -7,17 +7,17 @@ // map tells the System loader where to look for things // #docregion paths var map = { - 'app': '/app', // 'dist', + 'app': '/app', // 'dist', - '@angular': '/node_modules/@angular', - 'angular2-in-memory-web-api': '/node_modules/angular2-in-memory-web-api', - 'rxjs': '/node_modules/rxjs' + '@angular': '/node_modules/@angular', + 'angular-in-memory-web-api': '/node_modules/angular-in-memory-web-api', + 'rxjs': '/node_modules/rxjs' }; var packages = { - '/app': { main: 'main.js', defaultExtension: 'js' }, - 'rxjs': { defaultExtension: 'js' }, - 'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' }, + '/app': { main: 'main.js', defaultExtension: 'js' }, + 'rxjs': { defaultExtension: 'js' }, + 'angular-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' }, }; // #enddocregion paths diff --git a/public/docs/ts/_cache/guide/server-communication.jade b/public/docs/ts/_cache/guide/server-communication.jade index c254ff9377..b946790935 100644 --- a/public/docs/ts/_cache/guide/server-communication.jade +++ b/public/docs/ts/_cache/guide/server-communication.jade @@ -669,7 +669,7 @@ a#in-mem-web-api .l-sub-section :marked The in-memory web api is not part of the Angular core. - It's an optional service in its own `angular2-in-memory-web-api` library + It's an optional service in its own `angular-in-memory-web-api` library that we installed with npm (see `package.json`) and registered for module loading by SystemJS (see `systemjs.config.js`) diff --git a/public/docs/ts/latest/guide/npm-packages.jade b/public/docs/ts/latest/guide/npm-packages.jade index c3e20b0761..447c34dce9 100644 --- a/public/docs/ts/latest/guide/npm-packages.jade +++ b/public/docs/ts/latest/guide/npm-packages.jade @@ -129,7 +129,7 @@ a(id="other") :marked ### Other helper libraries - ***angular2-in-memory-web-api*** - An Angular-supported library that simulates a remote server's web api + ***angular-in-memory-web-api*** - An Angular-supported library that simulates a remote server's web api without requiring an actual server or real http calls. Good for demos, samples, and early stage development (before we even have a server). Read about it in the [Http Client](server-communication.html#appendix-tour-of-heroes-in-memory-server) page. diff --git a/public/docs/ts/latest/guide/server-communication.jade b/public/docs/ts/latest/guide/server-communication.jade index 181b04ba16..07d20c61bd 100644 --- a/public/docs/ts/latest/guide/server-communication.jade +++ b/public/docs/ts/latest/guide/server-communication.jade @@ -654,7 +654,7 @@ a#in-mem-web-api .l-sub-section :marked The in-memory web api is not part of the Angular core. - It's an optional service in its own `angular2-in-memory-web-api` library + It's an optional service in its own `angular-in-memory-web-api` library that we installed with npm (see `package.json`) and registered for module loading by SystemJS (see `systemjs.config.js`) From 4a6f35f58b04ae3e4ac75f50f0a0605f0c3c1af7 Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Sun, 25 Sep 2016 17:46:06 -0700 Subject: [PATCH 09/12] chore(package.json): update many package versions (#2476) --- public/docs/_examples/package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/public/docs/_examples/package.json b/public/docs/_examples/package.json index 75df42d440..93fbd36f17 100644 --- a/public/docs/_examples/package.json +++ b/public/docs/_examples/package.json @@ -37,7 +37,7 @@ "@angular/platform-server": "2.0.0", "@angular/router": "3.0.0", "@angular/upgrade": "2.0.0", - "angular-in-memory-web-api": "0.1.0", + "angular-in-memory-web-api": "~0.1.0", "bootstrap": "^3.3.6", "core-js": "^2.4.1", "reflect-metadata": "^0.1.3", @@ -45,7 +45,7 @@ "rollup-plugin-node-resolve": "^2.0.0", "rollup-plugin-uglify": "^1.0.1", "rxjs": "5.0.0-beta.12", - "systemjs": "0.19.27", + "systemjs": "0.19.38", "zone.js": "^0.6.23" }, "devDependencies": { @@ -60,8 +60,8 @@ "html-loader": "^0.4.3", "html-webpack-plugin": "^2.16.1", "http-server": "^0.9.0", - "jasmine-core": "^2.4.1", - "karma": "^1.2.0", + "jasmine-core": "^2.5.2", + "karma": "^1.3.0", "karma-chrome-launcher": "^2.0.0", "karma-cli": "^1.0.1", "karma-htmlfile-reporter": "^0.3.4", From 6def9505cc20eb97c63f606ccfbfba2611a2e49b Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Sun, 25 Sep 2016 18:51:54 -0700 Subject: [PATCH 10/12] chore: convert templateUrls to use moduleId where possible. (#2477) --- .../ts/app/hero-detail.component.ts | 3 +- .../ts/app/hero-list.component.ts | 5 +- .../ts/app/app.component.ts | 3 +- .../ts/app/app.component.ts | 7 +- .../ts/app/movie-list.component.ts | 5 +- .../ts/app/app.component.ts | 3 +- .../ts/app/app.component.ts | 5 +- .../e2e-spec.ts.disabled | 27 ---- .../ts/app/app.component.ts | 24 --- .../app/dynamic-form-question.component.html | 17 -- .../ts/app/dynamic-form-question.component.ts | 15 -- .../ts/app/dynamic-form.component.html | 17 -- .../ts/app/dynamic-form.component.ts | 30 ---- .../cb-dynamic-form-deprecated/ts/app/main.ts | 5 - .../ts/app/question-base.ts | 25 --- .../ts/app/question-control.service.ts | 18 --- .../ts/app/question-dropdown.ts | 12 -- .../ts/app/question-textbox.ts | 12 -- .../ts/app/question.service.ts | 47 ------ .../ts/example-config.json | 0 .../cb-dynamic-form-deprecated/ts/index.html | 29 ---- .../cb-dynamic-form-deprecated/ts/plnkr.json | 9 -- .../cb-dynamic-form-deprecated/ts/sample.css | 7 - .../ts/app/dynamic-form-question.component.ts | 5 +- .../ts/app/dynamic-form.component.ts | 3 +- .../forms/ts/app/hero-form.component.ts | 3 +- .../ts/app/hello_world.ts | 5 +- .../lifecycle-hooks/ts/app/app.component.ts | 3 +- .../ts/app/do-check.component.ts | 3 +- .../ts/app/on-changes.component.ts | 3 +- .../lifecycle-hooks/ts/app/spy.component.ts | 3 +- .../ts/app/contact/contact.component.3.ts | 2 +- .../ts/app/contact/contact.component.ts | 2 +- .../_examples/pipes/ts/app/app.component.ts | 3 +- .../pipes/ts/app/flying-heroes.component.ts | 6 +- .../ts/app/bypass-security.component.ts | 3 +- .../ts/app/toh/hero-list.component.promise.ts | 3 +- .../ts/app/toh/hero-list.component.ts | 3 +- .../ts/app/structural-directives.component.ts | 3 +- .../03-06/app/shared/toast/toast.component.ts | 3 +- .../04-10/app/shared/toast/toast.component.ts | 3 +- .../style-guide/ts/app/app.component.ts | 3 +- .../template-syntax/ts/app/app.component.ts | 3 +- .../_examples/testing/ts/app/app.component.ts | 3 +- .../docs/_examples/testing/ts/app/bag/bag.ts | 1 + .../app/dashboard/dashboard-hero.component.ts | 5 +- .../ts/app/dashboard/dashboard.component.ts | 5 +- .../ts/app/hero/hero-detail.component.ts | 5 +- .../ts/app/hero/hero-list.component.ts | 5 +- .../toh-5/ts/app/dashboard.component.2.ts | 3 +- .../toh-5/ts/app/dashboard.component.ts | 5 +- .../toh-5/ts/app/hero-detail.component.ts | 5 +- .../toh-5/ts/app/heroes.component.ts | 5 +- .../toh-6/ts/app/dashboard.component.ts | 5 +- .../toh-6/ts/app/hero-detail.component.ts | 5 +- .../toh-6/ts/app/hero-search.component.ts | 5 +- .../toh-6/ts/app/heroes.component.ts | 5 +- .../phone-detail/phone-detail.component.ts | 3 +- .../ts/app/phone-list/phone-list.component.ts | 3 +- .../phone-detail/phone-detail.component.ts | 3 +- .../ts/app/phone-list/phone-list.component.ts | 3 +- .../user-input/ts/app/app.component.ts | 3 +- public/docs/dart/latest/guide/forms.jade | 2 + public/docs/ts/latest/cookbook/_data.json | 7 - .../cookbook/dynamic-form-deprecated.jade | 149 ------------------ public/docs/ts/latest/guide/architecture.jade | 4 +- public/docs/ts/latest/guide/forms.jade | 2 + public/docs/ts/latest/tutorial/toh-pt5.jade | 13 +- 68 files changed, 118 insertions(+), 526 deletions(-) delete mode 100644 public/docs/_examples/cb-dynamic-form-deprecated/e2e-spec.ts.disabled delete mode 100644 public/docs/_examples/cb-dynamic-form-deprecated/ts/app/app.component.ts delete mode 100644 public/docs/_examples/cb-dynamic-form-deprecated/ts/app/dynamic-form-question.component.html delete mode 100644 public/docs/_examples/cb-dynamic-form-deprecated/ts/app/dynamic-form-question.component.ts delete mode 100644 public/docs/_examples/cb-dynamic-form-deprecated/ts/app/dynamic-form.component.html delete mode 100644 public/docs/_examples/cb-dynamic-form-deprecated/ts/app/dynamic-form.component.ts delete mode 100644 public/docs/_examples/cb-dynamic-form-deprecated/ts/app/main.ts delete mode 100644 public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question-base.ts delete mode 100644 public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question-control.service.ts delete mode 100644 public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question-dropdown.ts delete mode 100644 public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question-textbox.ts delete mode 100644 public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question.service.ts delete mode 100644 public/docs/_examples/cb-dynamic-form-deprecated/ts/example-config.json delete mode 100644 public/docs/_examples/cb-dynamic-form-deprecated/ts/index.html delete mode 100644 public/docs/_examples/cb-dynamic-form-deprecated/ts/plnkr.json delete mode 100644 public/docs/_examples/cb-dynamic-form-deprecated/ts/sample.css delete mode 100644 public/docs/ts/latest/cookbook/dynamic-form-deprecated.jade diff --git a/public/docs/_examples/architecture/ts/app/hero-detail.component.ts b/public/docs/_examples/architecture/ts/app/hero-detail.component.ts index b1a93cf7a2..bdebf09f9e 100644 --- a/public/docs/_examples/architecture/ts/app/hero-detail.component.ts +++ b/public/docs/_examples/architecture/ts/app/hero-detail.component.ts @@ -3,8 +3,9 @@ import { Component, Input } from '@angular/core'; import { Hero } from './hero'; @Component({ + moduleId: module.id, selector: 'hero-detail', - templateUrl: 'app/hero-detail.component.html' + templateUrl: 'hero-detail.component.html' }) export class HeroDetailComponent { @Input() hero: Hero; diff --git a/public/docs/_examples/architecture/ts/app/hero-list.component.ts b/public/docs/_examples/architecture/ts/app/hero-list.component.ts index 868b9251b5..42f18aed2f 100644 --- a/public/docs/_examples/architecture/ts/app/hero-list.component.ts +++ b/public/docs/_examples/architecture/ts/app/hero-list.component.ts @@ -5,9 +5,10 @@ import { HeroService } from './hero.service'; // #docregion metadata, providers @Component({ + moduleId: module.id, selector: 'hero-list', - templateUrl: 'app/hero-list.component.html', - providers: [ HeroService ] + templateUrl: 'hero-list.component.html', + providers: [ HeroService ] }) // #enddocregion providers // #docregion class diff --git a/public/docs/_examples/attribute-directives/ts/app/app.component.ts b/public/docs/_examples/attribute-directives/ts/app/app.component.ts index b8b1fa6f08..cc57c9e6b1 100644 --- a/public/docs/_examples/attribute-directives/ts/app/app.component.ts +++ b/public/docs/_examples/attribute-directives/ts/app/app.component.ts @@ -2,8 +2,9 @@ import { Component } from '@angular/core'; @Component({ + moduleId: module.id, selector: 'my-app', - templateUrl: 'app/app.component.html' + templateUrl: 'app.component.html' }) export class AppComponent { } diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.ts b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.ts index c3eb0c86f4..c6959c2da6 100644 --- a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.ts +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.ts @@ -4,10 +4,11 @@ import { MovieService } from './movie.service'; import { IMovie } from './movie'; @Component({ + moduleId: module.id, selector: 'my-app', - templateUrl: 'app/app.component.html', - styleUrls: ['app/app.component.css'], - providers: [MovieService] + templateUrl: 'app.component.html', + styleUrls: [ 'app.component.css' ], + providers: [ MovieService ] }) export class AppComponent { diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.ts b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.ts index dc6fbd6b63..951cccb6df 100644 --- a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.ts +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.ts @@ -8,11 +8,12 @@ import { MovieService } from './movie.service'; // #docregion component @Component({ + moduleId: module.id, selector: 'movie-list', - templateUrl: 'app/movie-list.component.html', + templateUrl: 'movie-list.component.html', // #enddocregion component // #docregion style-url - styleUrls: ['app/movie-list.component.css'], + styleUrls: [ 'movie-list.component.css' ], // #enddocregion style-url }) // #enddocregion component diff --git a/public/docs/_examples/cb-component-communication/ts/app/app.component.ts b/public/docs/_examples/cb-component-communication/ts/app/app.component.ts index 0a3c992498..be8d89aff7 100644 --- a/public/docs/_examples/cb-component-communication/ts/app/app.component.ts +++ b/public/docs/_examples/cb-component-communication/ts/app/app.component.ts @@ -1,7 +1,8 @@ import { Component } from '@angular/core'; @Component({ + moduleId: module.id, selector: 'my-app', - templateUrl: 'app/app.component.html' + templateUrl: 'app.component.html' }) export class AppComponent { } diff --git a/public/docs/_examples/cb-dependency-injection/ts/app/app.component.ts b/public/docs/_examples/cb-dependency-injection/ts/app/app.component.ts index ab0d9c445b..820d43d6ab 100644 --- a/public/docs/_examples/cb-dependency-injection/ts/app/app.component.ts +++ b/public/docs/_examples/cb-dependency-injection/ts/app/app.component.ts @@ -7,10 +7,11 @@ import { UserContextService } from './user-context.service'; import { UserService } from './user.service'; @Component({ + moduleId: module.id, selector: 'my-app', - templateUrl: 'app/app.component.html', + templateUrl: 'app.component.html', // #docregion providers - providers: [LoggerService, UserContextService, UserService] + providers: [ LoggerService, UserContextService, UserService ] // #enddocregion providers }) export class AppComponent { diff --git a/public/docs/_examples/cb-dynamic-form-deprecated/e2e-spec.ts.disabled b/public/docs/_examples/cb-dynamic-form-deprecated/e2e-spec.ts.disabled deleted file mode 100644 index 725022d0f1..0000000000 --- a/public/docs/_examples/cb-dynamic-form-deprecated/e2e-spec.ts.disabled +++ /dev/null @@ -1,27 +0,0 @@ -/// -'use strict'; -/* tslint:disable:quotemark */ -describe('Dynamic Form Deprecated', function () { - - beforeAll(function () { - browser.get(''); - }); - - it('should submit form', function () { - let firstNameElement = element.all(by.css('input[id=firstName]')).get(0); - expect(firstNameElement.getAttribute('value')).toEqual('Bombasto'); - - let emailElement = element.all(by.css('input[id=emailAddress]')).get(0); - let email = 'test@test.com'; - emailElement.sendKeys(email); - expect(emailElement.getAttribute('value')).toEqual(email); - - element(by.css('select option[value="solid"]')).click(); - - let saveButton = element.all(by.css('button')).get(0); - saveButton.click().then(function(){ - expect(element(by.xpath("//strong[contains(text(),'Saved the following values')]")).isPresent()).toBe(true); - }); - }); - -}); diff --git a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/app.component.ts b/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/app.component.ts deleted file mode 100644 index e51561770e..0000000000 --- a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/app.component.ts +++ /dev/null @@ -1,24 +0,0 @@ -// #docregion -import { Component } from '@angular/core'; - -import { DynamicFormComponent } from './dynamic-form.component'; -import { QuestionService } from './question.service'; - -@Component({ - selector: 'my-app', - template: ` -
      -

      Job Application for Heroes

      - -
      - `, - directives: [DynamicFormComponent], - providers: [QuestionService] -}) -export class AppComponent { - questions: any[]; - - constructor(service: QuestionService) { - this.questions = service.getQuestions(); - } -} diff --git a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/dynamic-form-question.component.html b/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/dynamic-form-question.component.html deleted file mode 100644 index e580ee3027..0000000000 --- a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/dynamic-form-question.component.html +++ /dev/null @@ -1,17 +0,0 @@ - -
      - - -
      - - - - - -
      - -
      {{question.label}} is required
      -
      diff --git a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/dynamic-form-question.component.ts b/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/dynamic-form-question.component.ts deleted file mode 100644 index 0593fd523e..0000000000 --- a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/dynamic-form-question.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -// #docregion -import { Component, Input } from '@angular/core'; -import { ControlGroup } from '@angular/common'; - -import { QuestionBase } from './question-base'; - -@Component({ - selector: 'df-question', - templateUrl: 'app/dynamic-form-question.component.html' -}) -export class DynamicFormQuestionComponent { - @Input() question: QuestionBase; - @Input() form: ControlGroup; - get isValid() { return this.form.controls[this.question.key].valid; } -} diff --git a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/dynamic-form.component.html b/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/dynamic-form.component.html deleted file mode 100644 index e8f14612c9..0000000000 --- a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/dynamic-form.component.html +++ /dev/null @@ -1,17 +0,0 @@ - -
      -
      - -
      - -
      - -
      - -
      -
      - -
      - Saved the following values
      {{payLoad}} -
      -
      diff --git a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/dynamic-form.component.ts b/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/dynamic-form.component.ts deleted file mode 100644 index 5d6eb833ed..0000000000 --- a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/dynamic-form.component.ts +++ /dev/null @@ -1,30 +0,0 @@ -// #docregion -import { Component, Input, OnInit } from '@angular/core'; -import { ControlGroup } from '@angular/common'; - -import { QuestionBase } from './question-base'; -import { QuestionControlService } from './question-control.service'; -import { DynamicFormQuestionComponent } from './dynamic-form-question.component'; - -@Component({ - selector: 'dynamic-form', - templateUrl: 'app/dynamic-form.component.html', - directives: [DynamicFormQuestionComponent], - providers: [QuestionControlService] -}) -export class DynamicFormComponent implements OnInit { - - @Input() questions: QuestionBase[] = []; - form: ControlGroup; - payLoad = ''; - - constructor(private qcs: QuestionControlService) { } - - ngOnInit() { - this.form = this.qcs.toControlGroup(this.questions); - } - - onSubmit() { - this.payLoad = JSON.stringify(this.form.value); - } -} diff --git a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/main.ts b/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/main.ts deleted file mode 100644 index 62ced34a31..0000000000 --- a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/main.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { bootstrap } from '@angular/platform-browser-dynamic'; - -import { AppComponent } from './app.component'; - -bootstrap(AppComponent, []); diff --git a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question-base.ts b/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question-base.ts deleted file mode 100644 index 2b32b00f2a..0000000000 --- a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question-base.ts +++ /dev/null @@ -1,25 +0,0 @@ -// #docregion -export class QuestionBase{ - value: T; - key: string; - label: string; - required: boolean; - order: number; - controlType: string; - - constructor(options: { - value?: T, - key?: string, - label?: string, - required?: boolean, - order?: number, - controlType?: string - } = {}) { - this.value = options.value; - this.key = options.key || ''; - this.label = options.label || ''; - this.required = !!options.required; - this.order = options.order === undefined ? 1 : options.order; - this.controlType = options.controlType || ''; - } -} diff --git a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question-control.service.ts b/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question-control.service.ts deleted file mode 100644 index 3d56b0c2f6..0000000000 --- a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question-control.service.ts +++ /dev/null @@ -1,18 +0,0 @@ -// #docregion -import { Injectable } from '@angular/core'; -import { FormBuilder, Validators } from '@angular/common'; -import { QuestionBase } from './question-base'; - -@Injectable() -export class QuestionControlService { - constructor(private fb: FormBuilder) { } - - toControlGroup(questions: QuestionBase[] ) { - let group = {}; - - questions.forEach(question => { - group[question.key] = question.required ? [question.value || '', Validators.required] : [question.value || '']; - }); - return this.fb.group(group); - } -} diff --git a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question-dropdown.ts b/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question-dropdown.ts deleted file mode 100644 index 35a9074c74..0000000000 --- a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question-dropdown.ts +++ /dev/null @@ -1,12 +0,0 @@ -// #docregion -import { QuestionBase } from './question-base'; - -export class DropdownQuestion extends QuestionBase { - controlType = 'dropdown'; - options: {key: string, value: string}[] = []; - - constructor(options: {} = {}) { - super(options); - this.options = options['options'] || []; - } -} diff --git a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question-textbox.ts b/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question-textbox.ts deleted file mode 100644 index aaa7edf267..0000000000 --- a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question-textbox.ts +++ /dev/null @@ -1,12 +0,0 @@ -// #docregion -import { QuestionBase } from './question-base'; - -export class TextboxQuestion extends QuestionBase { - controlType = 'textbox'; - type: string; - - constructor(options: {} = {}) { - super(options); - this.type = options['type'] || ''; - } -} diff --git a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question.service.ts b/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question.service.ts deleted file mode 100644 index ee169d0827..0000000000 --- a/public/docs/_examples/cb-dynamic-form-deprecated/ts/app/question.service.ts +++ /dev/null @@ -1,47 +0,0 @@ -// #docregion -import { Injectable } from '@angular/core'; - -import { QuestionBase } from './question-base'; -import { TextboxQuestion } from './question-textbox'; -import { DropdownQuestion } from './question-dropdown'; - -@Injectable() -export class QuestionService { - - // Todo: get from a remote source of question metadata - // Todo: make asynchronous - getQuestions() { - - let questions: QuestionBase[] = [ - - new DropdownQuestion({ - key: 'brave', - label: 'Bravery Rating', - options: [ - {key: 'solid', value: 'Solid'}, - {key: 'great', value: 'Great'}, - {key: 'good', value: 'Good'}, - {key: 'unproven', value: 'Unproven'} - ], - order: 3 - }), - - new TextboxQuestion({ - key: 'firstName', - label: 'First name', - value: 'Bombasto', - required: true, - order: 1 - }), - - new TextboxQuestion({ - key: 'emailAddress', - label: 'Email', - type: 'email', - order: 2 - }) - ]; - - return questions.sort((a, b) => a.order - b.order); - } -} diff --git a/public/docs/_examples/cb-dynamic-form-deprecated/ts/example-config.json b/public/docs/_examples/cb-dynamic-form-deprecated/ts/example-config.json deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/public/docs/_examples/cb-dynamic-form-deprecated/ts/index.html b/public/docs/_examples/cb-dynamic-form-deprecated/ts/index.html deleted file mode 100644 index ec3e1cbbb2..0000000000 --- a/public/docs/_examples/cb-dynamic-form-deprecated/ts/index.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - Dynamic Form - - - - - - - - - - - - - - - - - - Loading app... - - - diff --git a/public/docs/_examples/cb-dynamic-form-deprecated/ts/plnkr.json b/public/docs/_examples/cb-dynamic-form-deprecated/ts/plnkr.json deleted file mode 100644 index 5034d652aa..0000000000 --- a/public/docs/_examples/cb-dynamic-form-deprecated/ts/plnkr.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "description": "Dynamic Form Deprecated", - "files":[ - "!**/*.d.ts", - "!**/*.js", - "!**/*.[1].*" - ], - "tags":["cookbook"] -} diff --git a/public/docs/_examples/cb-dynamic-form-deprecated/ts/sample.css b/public/docs/_examples/cb-dynamic-form-deprecated/ts/sample.css deleted file mode 100644 index fe2cc28481..0000000000 --- a/public/docs/_examples/cb-dynamic-form-deprecated/ts/sample.css +++ /dev/null @@ -1,7 +0,0 @@ -.errorMessage{ - color:red; -} - -.form-row{ - margin-top: 10px; -} \ No newline at end of file diff --git a/public/docs/_examples/cb-dynamic-form/ts/app/dynamic-form-question.component.ts b/public/docs/_examples/cb-dynamic-form/ts/app/dynamic-form-question.component.ts index 412f2d8c55..69194fc0e7 100644 --- a/public/docs/_examples/cb-dynamic-form/ts/app/dynamic-form-question.component.ts +++ b/public/docs/_examples/cb-dynamic-form/ts/app/dynamic-form-question.component.ts @@ -1,12 +1,13 @@ // #docregion import { Component, Input } from '@angular/core'; -import { FormGroup } from '@angular/forms'; +import { FormGroup } from '@angular/forms'; import { QuestionBase } from './question-base'; @Component({ + moduleId: module.id, selector: 'df-question', - templateUrl: 'app/dynamic-form-question.component.html' + templateUrl: 'dynamic-form-question.component.html' }) export class DynamicFormQuestionComponent { @Input() question: QuestionBase; diff --git a/public/docs/_examples/cb-dynamic-form/ts/app/dynamic-form.component.ts b/public/docs/_examples/cb-dynamic-form/ts/app/dynamic-form.component.ts index 68bd1f582b..e0331797bf 100644 --- a/public/docs/_examples/cb-dynamic-form/ts/app/dynamic-form.component.ts +++ b/public/docs/_examples/cb-dynamic-form/ts/app/dynamic-form.component.ts @@ -6,8 +6,9 @@ import { QuestionBase } from './question-base'; import { QuestionControlService } from './question-control.service'; @Component({ + moduleId: module.id, selector: 'dynamic-form', - templateUrl: 'app/dynamic-form.component.html', + templateUrl: 'dynamic-form.component.html', providers: [ QuestionControlService ] }) export class DynamicFormComponent implements OnInit { diff --git a/public/docs/_examples/forms/ts/app/hero-form.component.ts b/public/docs/_examples/forms/ts/app/hero-form.component.ts index fb08f7833b..bc011fb4fd 100644 --- a/public/docs/_examples/forms/ts/app/hero-form.component.ts +++ b/public/docs/_examples/forms/ts/app/hero-form.component.ts @@ -6,8 +6,9 @@ import { Component } from '@angular/core'; import { Hero } from './hero'; @Component({ + moduleId: module.id, selector: 'hero-form', - templateUrl: 'app/hero-form.component.html' + templateUrl: 'hero-form.component.html' }) export class HeroFormComponent { diff --git a/public/docs/_examples/homepage-hello-world/ts/app/hello_world.ts b/public/docs/_examples/homepage-hello-world/ts/app/hello_world.ts index 308bc4547b..3db096cd75 100644 --- a/public/docs/_examples/homepage-hello-world/ts/app/hello_world.ts +++ b/public/docs/_examples/homepage-hello-world/ts/app/hello_world.ts @@ -2,11 +2,14 @@ import { Component } from '@angular/core'; @Component({ + // Set the base for module-relative URLs + moduleId: module.id, + // Declare the tag name in index.html to where the component attaches selector: 'hello-world', // Location of the template for this component - templateUrl: 'app/hello_world.html' + templateUrl: 'hello_world.html' }) export class HelloWorldComponent { diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/app.component.ts b/public/docs/_examples/lifecycle-hooks/ts/app/app.component.ts index 9b785144ab..42e09d0fe4 100644 --- a/public/docs/_examples/lifecycle-hooks/ts/app/app.component.ts +++ b/public/docs/_examples/lifecycle-hooks/ts/app/app.component.ts @@ -1,7 +1,8 @@ // #docregion import { Component } from '@angular/core'; @Component({ + moduleId: module.id, selector: 'my-app', - templateUrl: 'app/app.component.html' + templateUrl: 'app.component.html' }) export class AppComponent { } diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/do-check.component.ts b/public/docs/_examples/lifecycle-hooks/ts/app/do-check.component.ts index 6dfcf8dd43..aadd6eb26f 100644 --- a/public/docs/_examples/lifecycle-hooks/ts/app/do-check.component.ts +++ b/public/docs/_examples/lifecycle-hooks/ts/app/do-check.component.ts @@ -75,8 +75,9 @@ export class DoCheckComponent implements DoCheck { /***************************************/ @Component({ + moduleId: module.id, selector: 'do-check-parent', - templateUrl: 'app/do-check-parent.component.html', + templateUrl: 'do-check-parent.component.html', styles: ['.parent {background: Lavender}'] }) export class DoCheckParentComponent { diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/on-changes.component.ts b/public/docs/_examples/lifecycle-hooks/ts/app/on-changes.component.ts index 993eb4040d..4c83d6f864 100644 --- a/public/docs/_examples/lifecycle-hooks/ts/app/on-changes.component.ts +++ b/public/docs/_examples/lifecycle-hooks/ts/app/on-changes.component.ts @@ -49,8 +49,9 @@ export class OnChangesComponent implements OnChanges { /***************************************/ @Component({ + moduleId: module.id, selector: 'on-changes-parent', - templateUrl: 'app/on-changes-parent.component.html', + templateUrl: 'on-changes-parent.component.html', styles: ['.parent {background: Lavender;}'] }) export class OnChangesParentComponent { diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/spy.component.ts b/public/docs/_examples/lifecycle-hooks/ts/app/spy.component.ts index 2d487f4037..99fefac6ec 100644 --- a/public/docs/_examples/lifecycle-hooks/ts/app/spy.component.ts +++ b/public/docs/_examples/lifecycle-hooks/ts/app/spy.component.ts @@ -4,8 +4,9 @@ import { Component } from '@angular/core'; import { LoggerService } from './logger.service'; @Component({ + moduleId: module.id, selector: 'spy-parent', - templateUrl: 'app/spy.component.html', + templateUrl: 'spy.component.html', styles: [ '.parent {background: khaki;}', '.heroes {background: LightYellow; padding: 0 8px}' diff --git a/public/docs/_examples/ngmodule/ts/app/contact/contact.component.3.ts b/public/docs/_examples/ngmodule/ts/app/contact/contact.component.3.ts index 392904086a..30576f8f38 100644 --- a/public/docs/_examples/ngmodule/ts/app/contact/contact.component.3.ts +++ b/public/docs/_examples/ngmodule/ts/app/contact/contact.component.3.ts @@ -8,7 +8,7 @@ import { UserService } from '../user.service'; moduleId: module.id, selector: 'app-contact', templateUrl: 'contact.component.html', - styleUrls: ['contact.component.css'] + styleUrls: [ 'contact.component.css' ] }) export class ContactComponent implements OnInit { contact: Contact; diff --git a/public/docs/_examples/ngmodule/ts/app/contact/contact.component.ts b/public/docs/_examples/ngmodule/ts/app/contact/contact.component.ts index bb6f2e3b42..ee7c387c10 100644 --- a/public/docs/_examples/ngmodule/ts/app/contact/contact.component.ts +++ b/public/docs/_examples/ngmodule/ts/app/contact/contact.component.ts @@ -9,7 +9,7 @@ import { UserService } from '../core/user.service'; moduleId: module.id, selector: 'app-contact', templateUrl: 'contact.component.html', - styleUrls: ['contact.component.css'] + styleUrls: [ 'contact.component.css' ] }) export class ContactComponent implements OnInit { contact: Contact; diff --git a/public/docs/_examples/pipes/ts/app/app.component.ts b/public/docs/_examples/pipes/ts/app/app.component.ts index 1a53c144aa..ca83f1b6af 100644 --- a/public/docs/_examples/pipes/ts/app/app.component.ts +++ b/public/docs/_examples/pipes/ts/app/app.component.ts @@ -2,8 +2,9 @@ import { Component } from '@angular/core'; @Component({ + moduleId: module.id, selector: 'my-app', - templateUrl: 'app/app.component.html' + templateUrl: 'app.component.html' }) export class AppComponent { birthday = new Date(1988, 3, 15); // April 15, 1988 diff --git a/public/docs/_examples/pipes/ts/app/flying-heroes.component.ts b/public/docs/_examples/pipes/ts/app/flying-heroes.component.ts index a6a8dd08b2..26a43997aa 100644 --- a/public/docs/_examples/pipes/ts/app/flying-heroes.component.ts +++ b/public/docs/_examples/pipes/ts/app/flying-heroes.component.ts @@ -5,8 +5,9 @@ import { Component } from '@angular/core'; import { HEROES } from './heroes'; @Component({ + moduleId: module.id, selector: 'flying-heroes', - templateUrl: 'app/flying-heroes.component.html', + templateUrl: 'flying-heroes.component.html', styles: ['#flyers, #all {font-style: italic}'] }) // #docregion v1 @@ -49,8 +50,9 @@ export class FlyingHeroesComponent { ////// Identical except for impure pipe ////// // #docregion impure-component @Component({ + moduleId: module.id, selector: 'flying-heroes-impure', - templateUrl: 'app/flying-heroes-impure.component.html', + templateUrl: 'flying-heroes-impure.component.html', // #enddocregion impure-component styles: ['.flyers, .all {font-style: italic}'], // #docregion impure-component diff --git a/public/docs/_examples/security/ts/app/bypass-security.component.ts b/public/docs/_examples/security/ts/app/bypass-security.component.ts index 7c30903955..2aecfddab9 100644 --- a/public/docs/_examples/security/ts/app/bypass-security.component.ts +++ b/public/docs/_examples/security/ts/app/bypass-security.component.ts @@ -5,7 +5,8 @@ import { DomSanitizer, SafeResourceUrl, SafeUrl } from '@angular/platform-browse @Component({ selector: 'bypass-security', - templateUrl: 'app/bypass-security.component.html', + moduleId: module.id, + templateUrl: 'bypass-security.component.html', }) export class BypassSecurityComponent { dangerousUrl: string; diff --git a/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.promise.ts b/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.promise.ts index f1e6450124..f6306f1e03 100644 --- a/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.promise.ts +++ b/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.promise.ts @@ -6,7 +6,8 @@ import { HeroService } from './hero.service.promise'; @Component({ selector: 'hero-list-promise', - templateUrl: 'app/toh/hero-list.component.html', + moduleId: module.id, + templateUrl: 'hero-list.component.html', providers: [ HeroService ] }) // #docregion component diff --git a/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.ts b/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.ts index a12287dacd..0fa7bbad6e 100644 --- a/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.ts +++ b/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.ts @@ -5,8 +5,9 @@ import { Hero } from './hero'; import { HeroService } from './hero.service'; @Component({ + moduleId: module.id, selector: 'hero-list', - templateUrl: 'app/toh/hero-list.component.html', + templateUrl: 'hero-list.component.html', providers: [ HeroService ] }) // #docregion component diff --git a/public/docs/_examples/structural-directives/ts/app/structural-directives.component.ts b/public/docs/_examples/structural-directives/ts/app/structural-directives.component.ts index 8e36da3462..d831e4960d 100644 --- a/public/docs/_examples/structural-directives/ts/app/structural-directives.component.ts +++ b/public/docs/_examples/structural-directives/ts/app/structural-directives.component.ts @@ -3,8 +3,9 @@ import { Component } from '@angular/core'; @Component({ + moduleId: module.id, selector: 'structural-directives', - templateUrl: 'app/structural-directives.component.html', + templateUrl: 'structural-directives.component.html', styles: ['button { min-width: 100px; }'] }) export class StructuralDirectivesComponent { diff --git a/public/docs/_examples/style-guide/ts/03-06/app/shared/toast/toast.component.ts b/public/docs/_examples/style-guide/ts/03-06/app/shared/toast/toast.component.ts index 24afa50a5b..dd0bba5eba 100644 --- a/public/docs/_examples/style-guide/ts/03-06/app/shared/toast/toast.component.ts +++ b/public/docs/_examples/style-guide/ts/03-06/app/shared/toast/toast.component.ts @@ -3,9 +3,8 @@ import { Component, OnInit } from '@angular/core'; import { ToastService } from './toast.service'; @Component({ - moduleId: module.id, selector: 'toh-toast', - templateUrl: '
      toast
      ' + template: '
      toast
      ' }) export class ToastComponent implements OnInit { constructor(toastService: ToastService) { } diff --git a/public/docs/_examples/style-guide/ts/04-10/app/shared/toast/toast.component.ts b/public/docs/_examples/style-guide/ts/04-10/app/shared/toast/toast.component.ts index 24afa50a5b..dd0bba5eba 100644 --- a/public/docs/_examples/style-guide/ts/04-10/app/shared/toast/toast.component.ts +++ b/public/docs/_examples/style-guide/ts/04-10/app/shared/toast/toast.component.ts @@ -3,9 +3,8 @@ import { Component, OnInit } from '@angular/core'; import { ToastService } from './toast.service'; @Component({ - moduleId: module.id, selector: 'toh-toast', - templateUrl: '
      toast
      ' + template: '
      toast
      ' }) export class ToastComponent implements OnInit { constructor(toastService: ToastService) { } diff --git a/public/docs/_examples/style-guide/ts/app/app.component.ts b/public/docs/_examples/style-guide/ts/app/app.component.ts index 0a3c992498..be8d89aff7 100644 --- a/public/docs/_examples/style-guide/ts/app/app.component.ts +++ b/public/docs/_examples/style-guide/ts/app/app.component.ts @@ -1,7 +1,8 @@ import { Component } from '@angular/core'; @Component({ + moduleId: module.id, selector: 'my-app', - templateUrl: 'app/app.component.html' + templateUrl: 'app.component.html' }) export class AppComponent { } diff --git a/public/docs/_examples/template-syntax/ts/app/app.component.ts b/public/docs/_examples/template-syntax/ts/app/app.component.ts index 9f64d3c98f..fb128c88d8 100644 --- a/public/docs/_examples/template-syntax/ts/app/app.component.ts +++ b/public/docs/_examples/template-syntax/ts/app/app.component.ts @@ -17,8 +17,9 @@ export enum Color {Red, Green, Blue}; * Giant grab bag of stuff to drive the chapter */ @Component({ + moduleId: module.id, selector: 'my-app', - templateUrl: 'app/app.component.html' + templateUrl: 'app.component.html' }) export class AppComponent implements AfterViewInit, OnInit { diff --git a/public/docs/_examples/testing/ts/app/app.component.ts b/public/docs/_examples/testing/ts/app/app.component.ts index 9b785144ab..42e09d0fe4 100644 --- a/public/docs/_examples/testing/ts/app/app.component.ts +++ b/public/docs/_examples/testing/ts/app/app.component.ts @@ -1,7 +1,8 @@ // #docregion import { Component } from '@angular/core'; @Component({ + moduleId: module.id, selector: 'my-app', - templateUrl: 'app/app.component.html' + templateUrl: 'app.component.html' }) export class AppComponent { } diff --git a/public/docs/_examples/testing/ts/app/bag/bag.ts b/public/docs/_examples/testing/ts/app/bag/bag.ts index cbe88f55f5..1c9a005b08 100644 --- a/public/docs/_examples/testing/ts/app/bag/bag.ts +++ b/public/docs/_examples/testing/ts/app/bag/bag.ts @@ -272,6 +272,7 @@ export class ExternalTemplateComponent implements OnInit { export class InnerCompWithExternalTemplateComponent { } @Component({ + moduleId: module.id, selector: 'bad-template-comp', templateUrl: 'non-existant.html' }) diff --git a/public/docs/_examples/testing/ts/app/dashboard/dashboard-hero.component.ts b/public/docs/_examples/testing/ts/app/dashboard/dashboard-hero.component.ts index 3d8ee8a177..26daf8bb54 100644 --- a/public/docs/_examples/testing/ts/app/dashboard/dashboard-hero.component.ts +++ b/public/docs/_examples/testing/ts/app/dashboard/dashboard-hero.component.ts @@ -5,9 +5,10 @@ import { Hero } from '../model'; // #docregion component @Component({ + moduleId: module.id, selector: 'dashboard-hero', - templateUrl: 'app/dashboard/dashboard-hero.component.html', - styleUrls: ['app/dashboard/dashboard-hero.component.css'] + templateUrl: 'dashboard-hero.component.html', + styleUrls: [ 'dashboard-hero.component.css' ] }) export class DashboardHeroComponent { @Input() hero: Hero; diff --git a/public/docs/_examples/testing/ts/app/dashboard/dashboard.component.ts b/public/docs/_examples/testing/ts/app/dashboard/dashboard.component.ts index bc2b707906..a0f08df120 100644 --- a/public/docs/_examples/testing/ts/app/dashboard/dashboard.component.ts +++ b/public/docs/_examples/testing/ts/app/dashboard/dashboard.component.ts @@ -5,9 +5,10 @@ import { Router } from '@angular/router'; import { Hero, HeroService } from '../model'; @Component({ + moduleId: module.id, selector: 'app-dashboard', - templateUrl: 'app/dashboard/dashboard.component.html', - styleUrls: ['app/dashboard/dashboard.component.css'] + templateUrl: 'dashboard.component.html', + styleUrls: [ 'dashboard.component.css' ] }) export class DashboardComponent implements OnInit { diff --git a/public/docs/_examples/testing/ts/app/hero/hero-detail.component.ts b/public/docs/_examples/testing/ts/app/hero/hero-detail.component.ts index 32a59ef2c2..7e8f23bc23 100644 --- a/public/docs/_examples/testing/ts/app/hero/hero-detail.component.ts +++ b/public/docs/_examples/testing/ts/app/hero/hero-detail.component.ts @@ -9,9 +9,10 @@ import { HeroDetailService } from './hero-detail.service'; // #docregion prototype @Component({ + moduleId: module.id, selector: 'app-hero-detail', - templateUrl: 'app/hero/hero-detail.component.html', - styleUrls: ['app/hero/hero-detail.component.css'], + templateUrl: 'hero-detail.component.html', + styleUrls: ['hero-detail.component.css' ], providers: [ HeroDetailService ] }) export class HeroDetailComponent implements OnInit { diff --git a/public/docs/_examples/testing/ts/app/hero/hero-list.component.ts b/public/docs/_examples/testing/ts/app/hero/hero-list.component.ts index 625c402581..623cbaf5fd 100644 --- a/public/docs/_examples/testing/ts/app/hero/hero-list.component.ts +++ b/public/docs/_examples/testing/ts/app/hero/hero-list.component.ts @@ -4,9 +4,10 @@ import { Router } from '@angular/router'; import { Hero, HeroService } from '../model'; @Component({ + moduleId: module.id, selector: 'app-heroes', - templateUrl: 'app/hero/hero-list.component.html', - styleUrls: ['app/hero/hero-list.component.css'] + templateUrl: 'hero-list.component.html', + styleUrls: [ 'hero-list.component.css' ] }) export class HeroListComponent implements OnInit { heroes: Promise; diff --git a/public/docs/_examples/toh-5/ts/app/dashboard.component.2.ts b/public/docs/_examples/toh-5/ts/app/dashboard.component.2.ts index 38decd2b50..4e0e8553bc 100644 --- a/public/docs/_examples/toh-5/ts/app/dashboard.component.2.ts +++ b/public/docs/_examples/toh-5/ts/app/dashboard.component.2.ts @@ -7,8 +7,9 @@ import { HeroService } from './hero.service'; // #enddocregion imports @Component({ + moduleId: module.id, selector: 'my-dashboard', - templateUrl: 'app/dashboard.component.html' + templateUrl: 'dashboard.component.html' }) // #docregion component export class DashboardComponent implements OnInit { diff --git a/public/docs/_examples/toh-5/ts/app/dashboard.component.ts b/public/docs/_examples/toh-5/ts/app/dashboard.component.ts index 3deb5bc2ec..61a56463c5 100644 --- a/public/docs/_examples/toh-5/ts/app/dashboard.component.ts +++ b/public/docs/_examples/toh-5/ts/app/dashboard.component.ts @@ -9,12 +9,13 @@ import { Hero } from './hero'; import { HeroService } from './hero.service'; @Component({ + moduleId: module.id, selector: 'my-dashboard', // #docregion templateUrl - templateUrl: 'app/dashboard.component.html', + templateUrl: 'dashboard.component.html', // #enddocregion templateUrl // #docregion css - styleUrls: ['app/dashboard.component.css'] + styleUrls: [ 'dashboard.component.css' ] // #enddocregion css }) // #docregion component diff --git a/public/docs/_examples/toh-5/ts/app/hero-detail.component.ts b/public/docs/_examples/toh-5/ts/app/hero-detail.component.ts index 5513904452..5b0474f020 100644 --- a/public/docs/_examples/toh-5/ts/app/hero-detail.component.ts +++ b/public/docs/_examples/toh-5/ts/app/hero-detail.component.ts @@ -7,11 +7,12 @@ import { Hero } from './hero'; import { HeroService } from './hero.service'; @Component({ + moduleId: module.id, selector: 'my-hero-detail', // #docregion templateUrl - templateUrl: 'app/hero-detail.component.html', + templateUrl: 'hero-detail.component.html', // #enddocregion templateUrl, v2 - styleUrls: ['app/hero-detail.component.css'] + styleUrls: [ 'hero-detail.component.css' ] // #docregion v2 }) // #docregion implement diff --git a/public/docs/_examples/toh-5/ts/app/heroes.component.ts b/public/docs/_examples/toh-5/ts/app/heroes.component.ts index da66bfa7af..5fa50a3411 100644 --- a/public/docs/_examples/toh-5/ts/app/heroes.component.ts +++ b/public/docs/_examples/toh-5/ts/app/heroes.component.ts @@ -8,10 +8,11 @@ import { HeroService } from './hero.service'; // #docregion renaming, metadata @Component({ + moduleId: module.id, selector: 'my-heroes', // #enddocregion renaming - templateUrl: 'app/heroes.component.html', - styleUrls: ['app/heroes.component.css'] + templateUrl: 'heroes.component.html', + styleUrls: [ 'heroes.component.css' ] // #docregion renaming }) // #enddocregion metadata diff --git a/public/docs/_examples/toh-6/ts/app/dashboard.component.ts b/public/docs/_examples/toh-6/ts/app/dashboard.component.ts index dd2e2ef2ce..92df6569b1 100644 --- a/public/docs/_examples/toh-6/ts/app/dashboard.component.ts +++ b/public/docs/_examples/toh-6/ts/app/dashboard.component.ts @@ -6,9 +6,10 @@ import { Hero } from './hero'; import { HeroService } from './hero.service'; @Component({ + moduleId: module.id, selector: 'my-dashboard', - templateUrl: 'app/dashboard.component.html', - styleUrls: ['app/dashboard.component.css'] + templateUrl: 'dashboard.component.html', + styleUrls: [ 'dashboard.component.css' ] }) // #enddocregion search export class DashboardComponent implements OnInit { diff --git a/public/docs/_examples/toh-6/ts/app/hero-detail.component.ts b/public/docs/_examples/toh-6/ts/app/hero-detail.component.ts index 87333a9fe3..d13f9cd046 100644 --- a/public/docs/_examples/toh-6/ts/app/hero-detail.component.ts +++ b/public/docs/_examples/toh-6/ts/app/hero-detail.component.ts @@ -6,9 +6,10 @@ import { Hero } from './hero'; import { HeroService } from './hero.service'; @Component({ + moduleId: module.id, selector: 'my-hero-detail', - templateUrl: 'app/hero-detail.component.html', - styleUrls: ['app/hero-detail.component.css'] + templateUrl: 'hero-detail.component.html', + styleUrls: [ 'hero-detail.component.css' ] }) export class HeroDetailComponent implements OnInit { hero: Hero; diff --git a/public/docs/_examples/toh-6/ts/app/hero-search.component.ts b/public/docs/_examples/toh-6/ts/app/hero-search.component.ts index 384002098d..bcb04ad549 100644 --- a/public/docs/_examples/toh-6/ts/app/hero-search.component.ts +++ b/public/docs/_examples/toh-6/ts/app/hero-search.component.ts @@ -9,9 +9,10 @@ import { HeroSearchService } from './hero-search.service'; import { Hero } from './hero'; @Component({ + moduleId: module.id, selector: 'hero-search', - templateUrl: 'app/hero-search.component.html', - styleUrls: ['app/hero-search.component.css'], + templateUrl: 'hero-search.component.html', + styleUrls: [ 'hero-search.component.css' ], providers: [HeroSearchService] }) export class HeroSearchComponent implements OnInit { diff --git a/public/docs/_examples/toh-6/ts/app/heroes.component.ts b/public/docs/_examples/toh-6/ts/app/heroes.component.ts index 6c0e8f2306..c8ff6973c0 100644 --- a/public/docs/_examples/toh-6/ts/app/heroes.component.ts +++ b/public/docs/_examples/toh-6/ts/app/heroes.component.ts @@ -6,9 +6,10 @@ import { Hero } from './hero'; import { HeroService } from './hero.service'; @Component({ + moduleId: module.id, selector: 'my-heroes', - templateUrl: 'app/heroes.component.html', - styleUrls: ['app/heroes.component.css'] + templateUrl: 'heroes.component.html', + styleUrls: [ 'heroes.component.css' ] }) export class HeroesComponent implements OnInit { heroes: Hero[]; diff --git a/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/app/phone-detail/phone-detail.component.ts b/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/app/phone-detail/phone-detail.component.ts index bae7fd2ecf..3b3a53176b 100644 --- a/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/app/phone-detail/phone-detail.component.ts +++ b/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/app/phone-detail/phone-detail.component.ts @@ -8,8 +8,9 @@ import { CheckmarkPipe } from '../core/checkmark/checkmark.pipe'; // #docregion initialclass @Component({ + moduleId: module.id, selector: 'phone-detail', - templateUrl: 'phone-detail/phone-detail.template.html', + templateUrl: 'phone-detail.template.html', // #enddocregion initialclass pipes: [ CheckmarkPipe ] // #docregion initialclass diff --git a/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/app/phone-list/phone-list.component.ts b/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/app/phone-list/phone-list.component.ts index 5acd35758b..ca365f327f 100644 --- a/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/app/phone-list/phone-list.component.ts +++ b/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/app/phone-list/phone-list.component.ts @@ -4,8 +4,9 @@ import { Component } from '@angular/core'; import { Phone, PhoneData } from '../core/phone/phone.service'; @Component({ + moduleId: module.id, selector: 'phone-list', - templateUrl: 'phone-list/phone-list.template.html' + templateUrl: 'phone-list.template.html' }) export class PhoneListComponent { phones: PhoneData[]; diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-detail/phone-detail.component.ts b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-detail/phone-detail.component.ts index 36db78632c..7d42e20dee 100644 --- a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-detail/phone-detail.component.ts +++ b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-detail/phone-detail.component.ts @@ -6,8 +6,9 @@ import { Phone, PhoneData } from '../core/phone/phone.service'; import { CheckmarkPipe } from '../core/checkmark/checkmark.pipe'; @Component({ + moduleId: module.id, selector: 'phone-detail', - templateUrl: 'phone-detail/phone-detail.template.html', + templateUrl: 'phone-detail.template.html', pipes: [ CheckmarkPipe ] }) export class PhoneDetailComponent { diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-list/phone-list.component.ts b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-list/phone-list.component.ts index 352c433838..e97e740415 100644 --- a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-list/phone-list.component.ts +++ b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-list/phone-list.component.ts @@ -5,8 +5,9 @@ import { RouterLink } from '@angular/router-deprecated'; import { Phone, PhoneData } from '../core/phone/phone.service'; @Component({ + moduleId: module.id, selector: 'phone-list', - templateUrl: 'phone-list/phone-list.template.html', + templateUrl: 'phone-list.template.html', directives: [ RouterLink ] }) // #enddocregion top diff --git a/public/docs/_examples/user-input/ts/app/app.component.ts b/public/docs/_examples/user-input/ts/app/app.component.ts index 35be5f232d..9368e33455 100644 --- a/public/docs/_examples/user-input/ts/app/app.component.ts +++ b/public/docs/_examples/user-input/ts/app/app.component.ts @@ -2,7 +2,8 @@ import { Component } from '@angular/core'; @Component({ + moduleId: module.id, selector: 'my-app', - templateUrl: 'app/app.component.html' + templateUrl: 'app.component.html' }) export class AppComponent { } diff --git a/public/docs/dart/latest/guide/forms.jade b/public/docs/dart/latest/guide/forms.jade index 3eaa3ae40e..f122411f16 100644 --- a/public/docs/dart/latest/guide/forms.jade +++ b/public/docs/dart/latest/guide/forms.jade @@ -166,6 +166,8 @@ figure.image-display 1. The `@Component` selector value of "hero-form" means we can drop this form in a parent template with a `` tag. + 1. The `moduleId` property sets the base for module-relative URLs such as the `templateUrl`. + 1. The `templateUrl` property points to a separate file for template HTML called `hero_form_component.html`. 1. We defined dummy data for `model` and `powers`, as befits a demo. diff --git a/public/docs/ts/latest/cookbook/_data.json b/public/docs/ts/latest/cookbook/_data.json index 87e4619d56..d5c3a60bc4 100644 --- a/public/docs/ts/latest/cookbook/_data.json +++ b/public/docs/ts/latest/cookbook/_data.json @@ -36,13 +36,6 @@ "intro": "Techniques for Dependency Injection" }, - "dynamic-form-deprecated": { - "title": "Dynamic Forms", - "intro": "Render dynamic forms with NgFormModel", - "basics": true, - "hide": true - }, - "dynamic-form": { "title": "Dynamic Forms", "intro": "Render dynamic forms with FormGroup" diff --git a/public/docs/ts/latest/cookbook/dynamic-form-deprecated.jade b/public/docs/ts/latest/cookbook/dynamic-form-deprecated.jade deleted file mode 100644 index 029c7c7743..0000000000 --- a/public/docs/ts/latest/cookbook/dynamic-form-deprecated.jade +++ /dev/null @@ -1,149 +0,0 @@ -include ../_util-fns - -.alert.is-important - :marked - This cookbook is using the deprecated forms API, which is disabled as of RC5, thus this sample only works up to RC4. - - We have created a new version of this cookbook using the new API here. - -:marked - We can't always justify the cost and time to build handcrafted forms, - especially if we'll need a great number of them, they're similar to each other, and they change frequently - to meet rapidly changing business and regulatory requirements. - - It may be more economical to create the forms dynamically, based on metadata that describe the business object model. - - In this cookbook we show how to use `ngFormModel` to dynamically render a simple form with different control types and validation. - It's a primitive start. - It might evolve to support a much richer variety of questions, more graceful rendering, and superior user experience. - All such greatness has humble beginnings. - - In our example we use a dynamic form to build an online application experience for heroes seeking employment. - The agency is constantly tinkering with the application process. - We can create the forms on the fly *without changing our application code*. - - -:marked - ## Table of contents - - [Question Model](#object-model) - - [Form Component](#form-component) - - [Questionnaire Metadata](#questionnaire-metadata) - - [Dynamic Template](#dynamic-template) - -:marked - **See the **. - -.l-main-section - -:marked - ## Question Model - - The first step is to define an object model that can describe all scenarios needed by the form functionality. - The hero application process involves a form with a lot of questions. - The "question" is the most fundamental object in the model. - - We have created `QuestionBase` as the most fundamental question class. - -+makeExample('cb-dynamic-form-deprecated/ts/app/question-base.ts','','app/question-base.ts') - -:marked - From this base we derived two new classes in `TextboxQuestion` and `DropdownQuestion` that represent Textbox and Dropdown questions. - The idea is that the form will be bound to specific question types and render the appropriate controls dynamically. - - `TextboxQuestion` supports multiple html5 types like text, email, url etc via the `type` property. - -+makeExample('cb-dynamic-form-deprecated/ts/app/question-textbox.ts',null,'app/question-textbox.ts')(format='.') - -:marked - `DropdownQuestion` presents a list of choices in a select box. - -+makeExample('cb-dynamic-form-deprecated/ts/app/question-dropdown.ts',null,'app/question-dropdown.ts')(format='.') - -:marked - Next we have defined `QuestionControlService`, a simple service for transforming our questions to an ngForm control group. - In a nutshell, the control group consumes the metadata from the question model and allows us to specify default values and validation rules. - -+makeExample('cb-dynamic-form-deprecated/ts/app/question-control.service.ts',null,'app/question-control.service.ts')(format='.') - - -:marked - ## Question form components - Now that we have defined the complete model we are ready to create components to represent the dynamic form. - -:marked - `DynamicFormComponent` is the entry point and the main container for the form. -+makeTabs( - `cb-dynamic-form-deprecated/ts/app/dynamic-form.component.html, - cb-dynamic-form-deprecated/ts/app/dynamic-form.component.ts`, - null, - `dynamic-form.component.html, - dynamic-form.component.ts` -) -:marked - It presents a list of questions, each question bound to a `` component element. - The `` tag matches the `DynamicFormQuestionComponent`, - the component responsible for rendering the details of each _individual_ question based on values in the data-bound question object. - -+makeTabs( - `cb-dynamic-form-deprecated/ts/app/dynamic-form-question.component.html, - cb-dynamic-form-deprecated/ts/app/dynamic-form-question.component.ts`, - null, - `dynamic-form-question.component.html, - dynamic-form-question.component.ts` -) -:marked - Notice this component can present any type of question in our model. - We only have two types of questions at this point but we can imagine many more. - The `ngSwitch` determines which type of question to display. - - In both components we're relying on Angular's **ngFormModel** to connect the template HTML to the - underlying control objects, populated from the question model with display and validation rules. - - -:marked - ## Questionnaire data -:marked - `DynamicFormComponent` expects the list of questions in the form of an array bound to `@Input() questions`. - - The set of questions we have defined for the job application is returned from the `QuestionService`. - In a real app we'd retrieve these questions from storage. - - The key point is that we control the hero job application questions entirely through the objects returned from `QuestionService`. - Questionnaire maintenance is a simple matter of adding, updating, and removing objects from the `questions` array. - -+makeExample('cb-dynamic-form-deprecated/ts/app/question.service.ts','','app/question.service.ts') - -:marked - Finally, we display an instance of the form in the `AppComponent` shell. - -+makeExample('cb-dynamic-form-deprecated/ts/app/app.component.ts','','app.component.ts') - - -:marked - ## Dynamic Template - Although in this example we're modelling a job application for heroes, there are no references to any specific hero question - outside the objects returned by `QuestionService`. - - This is very important since it allows us to repurpose the components for any type of survey - as long as it's compatible with our *question* object model. - The key is the dynamic data binding of metadata used to render the form - without making any hardcoded assumptions about specific questions. - In addition to control metadata, we are also adding validation dynamically. - - The *Save* button is disabled until the form is in a valid state. - When the form is valid, we can click *Save* and the app renders the current form values as JSON. - This proves that any user input is bound back to the data model. - Saving and retrieving the data is an exercise for another time. - -:marked - The final form looks like this: -figure.image-display - img(src="/resources/images/cookbooks/dynamic-form/dynamic-form.png" alt="Dynamic-Form") - - -:marked - [Back to top](#top) diff --git a/public/docs/ts/latest/guide/architecture.jade b/public/docs/ts/latest/guide/architecture.jade index b161aced7d..1d15deffd1 100644 --- a/public/docs/ts/latest/guide/architecture.jade +++ b/public/docs/ts/latest/guide/architecture.jade @@ -252,12 +252,14 @@ block ts-decorator Here are a few of the possible `@Component` configuration options: :marked + - `moduleId: module.id`: sets the base for module-relative loading of the `templateUrl`. + - `selector`: CSS selector that tells Angular to create and insert an instance of this component where it finds a `` tag in *parent* HTML. For example, if an app's HTML contains ``, then Angular inserts an instance of the `HeroListComponent` view between those tags. - - `templateUrl`: address of this component's HTML template, shown [above](#templates). + - `templateUrl`: module-relative address of this component's HTML template, shown [above](#templates). - `directives`: !{_array} of the components or directives that *this* template requires. In the last line of `hero-list.component.html`, Angular inserts a `HeroDetailComponent` diff --git a/public/docs/ts/latest/guide/forms.jade b/public/docs/ts/latest/guide/forms.jade index bbe8b6db3a..d1e746f46b 100644 --- a/public/docs/ts/latest/guide/forms.jade +++ b/public/docs/ts/latest/guide/forms.jade @@ -141,6 +141,8 @@ code-example(format=""). 1. The `@Component` selector value of "hero-form" means we can drop this form in a parent template with a `` tag. + 1. The `moduleId: module.id` property sets the base for module-relative loading of the `templateUrl`. + 1. The `templateUrl` property points to a separate file for the template HTML called `hero-form.component.html`. 1. We defined dummy data for `model` and `powers` as befits a demo. diff --git a/public/docs/ts/latest/tutorial/toh-pt5.jade b/public/docs/ts/latest/tutorial/toh-pt5.jade index 706f3fe790..9e5e914a59 100644 --- a/public/docs/ts/latest/tutorial/toh-pt5.jade +++ b/public/docs/ts/latest/tutorial/toh-pt5.jade @@ -370,15 +370,9 @@ block redirect-vs-use-as-default Replace the `template` metadata with a `templateUrl` property that points to a new template file. -+makeExcerpt('app/dashboard.component.ts', 'templateUrl') + Set the `moduleId` property to `module.id` for module-relative loading of the `templateUrl`. -.l-sub-section - block templateUrl-path-resolution - :marked - We specify the path _all the way back to the application root_ — - `app/` in this case — - because Angular doesn't support relative paths _by default_. - We _can_ switch to [component-relative paths](../cookbook/component-relative-paths.html) if we prefer. ++makeExcerpt('app/dashboard.component.ts', 'templateUrl') :marked Create that file with this content: @@ -718,13 +712,12 @@ figure.image-display 1. *Cut-and-paste* the template contents into a new heroes.component.html file. 1. *Cut-and-paste* the styles contents into a new heroes.component.css file. 1. *Set* the component metadata's `templateUrl` and `styleUrls` properties to refer to both files. + 1. *Set* the `moduleId` property to `module.id` so that 'templateUrl` and `styleUrls` are relative to the component. .l-sub-section :marked The `styleUrls` property is !{_an} !{_array} of style file names (with paths). We could list multiple style files from different locations if we needed them. - As with `templateUrl`, we must specify the path _all the way - back to the application root_. block heroes-component-cleanup //- Only relevant for Dart. From 9970094fcbd70e33396998f7434c7816a64e63b6 Mon Sep 17 00:00:00 2001 From: Josh Kramer Date: Sun, 25 Sep 2016 21:55:14 -0400 Subject: [PATCH 11/12] Fix broken link to DatePipe docs (#2452) Fixes issue #2451 --- public/docs/ts/latest/guide/pipes.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/docs/ts/latest/guide/pipes.jade b/public/docs/ts/latest/guide/pipes.jade index 615eed60f6..76f675c119 100644 --- a/public/docs/ts/latest/guide/pipes.jade +++ b/public/docs/ts/latest/guide/pipes.jade @@ -36,7 +36,7 @@ block includes :marked Inside the interpolation expression we flow the component's `birthday` value through the - [pipe operator](./template-syntax.html#pipe) ( | ) to the [Date pipe](../api/common/index/DatePipe-class.html) + [pipe operator](./template-syntax.html#pipe) ( | ) to the [Date pipe](../api/common/index/DatePipe-pipe.html) function on the right. All pipes work this way. .l-sub-section From 556e40695a1cf743891ab51b29bc5f23cf7d80a5 Mon Sep 17 00:00:00 2001 From: Brandon Date: Sun, 25 Sep 2016 20:56:12 -0500 Subject: [PATCH 12/12] docs(toh): Replaced window.history with location service (#2439) --- .../toh-5/ts/app/hero-detail.component.1.ts | 8 +++++--- .../toh-5/ts/app/hero-detail.component.ts | 14 ++++++++------ .../toh-6/ts/app/hero-detail.component.ts | 12 +++++++----- public/docs/ts/latest/tutorial/toh-pt5.jade | 11 ++++++----- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/public/docs/_examples/toh-5/ts/app/hero-detail.component.1.ts b/public/docs/_examples/toh-5/ts/app/hero-detail.component.1.ts index efbe8ee913..6713ce4dc7 100644 --- a/public/docs/_examples/toh-5/ts/app/hero-detail.component.1.ts +++ b/public/docs/_examples/toh-5/ts/app/hero-detail.component.1.ts @@ -5,7 +5,8 @@ // #docregion added-imports // Keep the Input import for now, we'll remove it later: import { Component, Input, OnInit } from '@angular/core'; -import { ActivatedRoute, Params } from '@angular/router'; +import { ActivatedRoute, Params } from '@angular/router'; +import { Location } from '@angular/common'; import { HeroService } from './hero.service'; // #enddocregion added-imports @@ -20,8 +21,9 @@ export class HeroDetailComponent implements OnInit { constructor( private heroService: HeroService, - private route: ActivatedRoute) { - } + private route: ActivatedRoute, + private location: Location + ) {} ngOnInit() {} } diff --git a/public/docs/_examples/toh-5/ts/app/hero-detail.component.ts b/public/docs/_examples/toh-5/ts/app/hero-detail.component.ts index 5b0474f020..38b7384618 100644 --- a/public/docs/_examples/toh-5/ts/app/hero-detail.component.ts +++ b/public/docs/_examples/toh-5/ts/app/hero-detail.component.ts @@ -1,10 +1,11 @@ // #docplaster // #docregion , v2 -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Params } from '@angular/router'; +import { Location } from '@angular/common'; -import { Hero } from './hero'; -import { HeroService } from './hero.service'; +import { Hero } from './hero'; +import { HeroService } from './hero.service'; @Component({ moduleId: module.id, @@ -23,8 +24,9 @@ export class HeroDetailComponent implements OnInit { // #docregion ctor constructor( private heroService: HeroService, - private route: ActivatedRoute) { - } + private route: ActivatedRoute, + private location: Location + ) {} // #enddocregion ctor // #docregion ngOnInit @@ -39,7 +41,7 @@ export class HeroDetailComponent implements OnInit { // #docregion goBack goBack(): void { - window.history.back(); + this.location.back(); } // #enddocregion goBack } diff --git a/public/docs/_examples/toh-6/ts/app/hero-detail.component.ts b/public/docs/_examples/toh-6/ts/app/hero-detail.component.ts index d13f9cd046..001b34baf7 100644 --- a/public/docs/_examples/toh-6/ts/app/hero-detail.component.ts +++ b/public/docs/_examples/toh-6/ts/app/hero-detail.component.ts @@ -1,6 +1,7 @@ // #docregion -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Params } from '@angular/router'; +import { Location } from '@angular/common'; import { Hero } from './hero'; import { HeroService } from './hero.service'; @@ -16,8 +17,9 @@ export class HeroDetailComponent implements OnInit { constructor( private heroService: HeroService, - private route: ActivatedRoute) { - } + private route: ActivatedRoute, + private location: Location + ) {} ngOnInit(): void { this.route.params.forEach((params: Params) => { @@ -30,11 +32,11 @@ export class HeroDetailComponent implements OnInit { // #docregion save save(): void { this.heroService.update(this.hero) - .then(this.goBack); + .then(() => this.goBack()); } // #enddocregion save goBack(): void { - window.history.back(); + this.location.back(); } } diff --git a/public/docs/ts/latest/tutorial/toh-pt5.jade b/public/docs/ts/latest/tutorial/toh-pt5.jade index 9e5e914a59..564537fa60 100644 --- a/public/docs/ts/latest/tutorial/toh-pt5.jade +++ b/public/docs/ts/latest/tutorial/toh-pt5.jade @@ -24,7 +24,7 @@ figure.image-display img(src='/resources/images/devguide/toh/nav-diagram.png' alt="View navigations") :marked - We'll add Angular’s *Component Router* to our app to satisfy these requirements. + We'll add Angular’s *Router* to our app to satisfy these requirements. .l-sub-section :marked @@ -166,7 +166,7 @@ block app-comp-v1 Instead of displaying heroes automatically, we'd like to show them *after* the user clicks a button. In other words, we'd like to navigate to the list of heroes. - We'll need the Angular *Component Router*. + We'll need the Angular *Router*. block angular-router :marked @@ -517,7 +517,7 @@ block route-params - var _ActivatedRoute = _docsFor == 'dart' ? 'RouteParams' : 'ActivatedRoute' :marked - Let's have the `!{_ActivatedRoute}` service and the `HeroService` injected + Let's have the `!{_ActivatedRoute}` service, the `HeroService` and the `Location` service injected into the constructor, saving their values in private fields: +makeExcerpt('app/hero-detail.component.ts (constructor)', 'ctor') @@ -563,7 +563,8 @@ block extract-id How do we navigate somewhere else when we're done? The user could click one of the two links in the `AppComponent`. Or click the browser's back button. - We'll add a third option, a `goBack` method that navigates backward one step in the browser's history stack. + We'll add a third option, a `goBack` method that navigates backward one step in the browser's history stack + using the `Location` service we injected previously. +makeExcerpt('app/hero-detail.component.ts', 'goBack') @@ -894,7 +895,7 @@ block file-tree-end We travelled a great distance in this chapter - - We added the Angular *Component Router* to navigate among different components. + - We added the Angular *Router* to navigate among different components. - We learned how to create router links to represent navigation menu items. - We used router link parameters to navigate to the details of user selected hero. - We shared the `HeroService` among multiple components.