Compare commits

...

296 Commits

Author SHA1 Message Date
6ccb93728e docs: add changelog for 4.0.3 2017-04-20 23:41:41 -05:00
b54a957ef4 release: cut the 4.0.3 release 2017-04-20 23:39:36 -05:00
21c14a79fa fix(compiler): suppress another closure warning (#16137)
closure compiler warns in generated .ngfactory.ts files:
```
WARNING - property createInternal already defined on superclass module$contents$..$core$src$linker$ng_module_factory_NgModuleInjector; use @override to override it
```

PR Close #16137
2017-04-20 23:39:36 -05:00
eed2d456d7 refactor(tsc-wrapped): cleanup (#16178)
PR Close #16178
2017-04-20 23:39:36 -05:00
719c232321 fix(core): distribute externs for testability API (#16179)
Workaround for #11119

PR Close #16179
2017-04-20 23:39:36 -05:00
bd033b69c1 feat: add support for TS 2.3 2017-04-20 23:39:36 -05:00
5b92f7ee6d fix(core): benchmarks - enable ng1 benchmark again
Also make it match the ng2 benchmark.
2017-04-20 23:39:36 -05:00
20ffb4196d fix(benchpress): chrome - prevent trace buffer overflow 2017-04-20 23:39:36 -05:00
11e6f45387 build: bump protractor to 4.0.14 2017-04-20 23:39:36 -05:00
a30a73c2aa fix(compiler): ignore calls to unresolved symbols in metadata
This only shows up in the language service. Calls to symbols
that are not resolve resulted in null instead of being resolved
causing the language service to see exceptions when the null
was not expected such as in the animations array.

Fixes #15969
2017-04-20 23:39:36 -05:00
fb94c9937c feat(upgrade): fixes for allow setting the angularjs lib at runtime
- always have a value for `angular`, even if no angular is on the page
- use `const` instead of `function` to allow to export a variable `module`
  without breaking tsickle / closure.
2017-04-20 23:39:36 -05:00
b3259e26fe feat(upgrade): allow setting the angularjs lib at runtime (#15168)
Readds 8ad464d90e.
2017-04-20 23:39:36 -05:00
be406f8464 fix(compiler): Inform user where Quoted error was thrown 2017-04-20 23:39:36 -05:00
5cab3b146e fix(router): prevent RouterLinkActive from causing an infinite CD loop
fixes #15825
2017-04-20 23:39:36 -05:00
eff6216319 fix(language-service): only use canonical symbols
Language service was treating some alias TypeScript symbols as if
they where the canonical symbol. If the symbol in scope is an alias
of another symbol the symbol should be converted to the canonical
symbol.
2017-04-20 23:39:35 -05:00
88b2ab09ea Revert "fix(compiler): ignore calls to unresolved symbols in metadata (#15970)"
This reverts commit ce47d33cd9.
2017-04-20 23:39:35 -05:00
5ad6d55a45 Revert "feat(upgrade): allow setting the angularjs lib at runtime (#15168)"
This reverts commit 8ad464d90e.

Breaks G3.
2017-04-20 23:39:35 -05:00
c81c7c0920 fix(compiler): fix build error in xliff2 2017-04-20 23:39:35 -05:00
6f8e23b061 refactor(router): drop the InternalRoute interface 2017-04-20 23:39:35 -05:00
dc9711107d refactor(router): misc refactoring 2017-04-20 23:39:35 -05:00
4c0c1e5fa0 feat(compiler): Implement i18n XLIFF 2.0 serializer (#14185)
- Ensure that the result passes OASIS XLIFF 2.0 schema validation
- Use <ph/> for self-closing placeholder tags
- Use <pc></pc> for other placeholder tags
- Check for the correct XLIFF file version
- Add ICU support

fixes #11735
2017-04-20 23:39:35 -05:00
06ef0908c7 feat(upgrade): allow setting the angularjs lib at runtime (#15168)
This PR adds an ability to reset the angularjs library, which is often needed when Angular
is loaded lazily using RequireJS.
2017-04-20 23:39:35 -05:00
a893d5e0a9 fix(packaging): increased buffer size (#15840) 2017-04-20 23:39:35 -05:00
44afa5a03a fix(core): key-value differ changes iteration (#15968)
fixes #14997
2017-04-20 23:39:35 -05:00
0733f8d3e1 fix(compiler): ignore calls to unresolved symbols in metadata (#15970)
This only shows up in the language service. Calls to symbols
that are not resolve resulted in null instead of being resolved
causing the language service to see exceptions when the null
was not expected such as in the animations array.

Fixes #15969
2017-04-20 23:39:35 -05:00
6604a4dc40 refactor(compiler): cleanup (#15960) 2017-04-20 23:39:35 -05:00
96c63a92e2 fix(platform-server): handle innerText (#15818) 2017-04-20 23:39:35 -05:00
c444b1575f fix(tsc-wrapped): collect new expressions with no arguments (#15908)
Fixes #15906
2017-04-20 23:39:35 -05:00
2b676192f6 docs: add changelog for 4.1.0-beta.1 2017-04-20 23:39:34 -05:00
14a2d1a6f7 docs: add changelog for 4.0.2 2017-04-11 14:56:13 -07:00
61e089931f release: cut the 4.0.2 release 2017-04-11 14:50:12 -07:00
cbf30cb101 ci: add jasonaden to the router 2017-04-11 14:38:46 -07:00
2f41b52e78 fix(router): fix query param parsing 2017-04-11 14:38:46 -07:00
dcf60da16d refactor(router): cleanup & simplifications 2017-04-11 14:38:45 -07:00
9c9f409364 test(router): enable running the campaign in non-ES6 browsers
Closes #15806.
2017-04-11 14:38:45 -07:00
b44b983c1f test(router): test preloading when a module is already loaded 2017-04-11 14:38:45 -07:00
978f80985c fix(router): the preloader use the module from the loaded config 2017-04-11 14:38:45 -07:00
c10e50cf38 fix(tsc-wrapped): ensure valid path separators in metadata
* Fixes that `tsc-wrapped` stores invalid path separators in the bundled metadata files. Previous errors could have been: `Cannot find module '.corecoordinationnique-selection-dispatcher'.` (See https://github.com/angular/material2/issues/3834)
* Fixes failing tests on Windows. Now all tooling tests are green on Windows.

Related to #15403
2017-04-11 14:38:45 -07:00
168a2eb5bf fix(language-service): detect when there isn't a tsconfig.json
Fixes #15874
2017-04-11 14:38:44 -07:00
c9c7acd484 fix(language-service): parse extended i18n forms 2017-04-11 14:34:15 -07:00
5b99533315 fix(language-service): initialize static reflector correctly
Fixes #15768
2017-04-11 14:34:14 -07:00
037805b741 style(router): fix typo in router preloader method 2017-04-11 14:34:14 -07:00
0861fda69c fix(language-service): avoid throwing exceptions when reporting metadata errors 2017-04-11 14:34:13 -07:00
feae7b6059 fix(language-service): resolve any parameter types to any result 2017-04-11 14:34:12 -07:00
e4277a0869 fix(language-service): improve resilience to incomplete information 2017-04-11 14:34:12 -07:00
1864ccb3dd fix(compiler): fix inheritance for AOT with summaries (#15583)
Allows to inherit ctor args, lifecycle hooks and statics from a class
in another compilation unit. 
Will error if trying to inherit from a class in another compilation unit 
that has an `@Component` / `@Directive` / `@Pipe` / `@NgModule`.
2017-04-11 14:34:11 -07:00
6b79ab5abe docs: add changelog for 4.0.1 2017-03-29 16:27:40 -07:00
53c12a84dc release: cut the 4.0.1 release 2017-03-29 16:26:06 -07:00
ca665303f4 fix(core): fix inheritance in JIT mode for TS 2.1 (#15599)
Fixes #15502
2017-03-29 16:19:15 -07:00
0fe4985756 fix(language-service): correctly determine base members of types (#15600)
Fixes #15460
2017-03-29 16:19:09 -07:00
74087cb39d docs(http): remove deprecated stuff and outdated plunkrs (#15598) 2017-03-29 15:18:03 -07:00
902bb2f026 fix(compiler): throw when a component defines both template and templateUrl (#15572)
Closes #15566
2017-03-29 10:29:00 -07:00
23bf34853c refactor(router): cleanup & simplification (#15436) 2017-03-29 10:15:00 -07:00
8c4b963927 fix(core): Update types for TypeScript nullability support (#15472) 2017-03-29 10:14:55 -07:00
bfa4f70204 fix(language-service): don't require reflect-metadata module to be provided (#15569)
Fixes #15568
2017-03-29 10:14:48 -07:00
d481f6d150 docs(core): fix API docs for Injector.get 2017-03-29 10:14:38 -07:00
fd6114561b perf(router): don't create new serializer every time UrlTree.toString is called (#15565) 2017-03-29 10:11:21 -07:00
c82851172e fix(animations): make sure style calculations are not computed too early (#15540)
Closes #15507
2017-03-29 10:11:06 -07:00
75478b2078 fix(router): should run CanActivate after CanDeactivate guards
Closes #14059
Closes #15467
2017-03-29 10:11:00 -07:00
cdbb3dbd2a refactor(router): fix tests structure 2017-03-29 10:10:53 -07:00
e72124c888 fix(core): fix the key/value differ (#15539)
fixes #15457
2017-03-29 10:10:43 -07:00
b8c0a97e35 fix(core): check for undefined on normalizeDebugBindingValue (#15503)
DebugServices is parsing false atributes values incorrectly.
Parse5 expects a string value for attributes, but currently boolean is being sent.

Closes #15494
2017-03-29 10:10:37 -07:00
5597fd3180 fix(language-service): improve performance of updateModuleAnalysis() (#15543) 2017-03-29 10:10:26 -07:00
a88413f871 fix(compiler): ignore errors when evaluating base classes (#15560)
Fixes #15536
2017-03-29 10:10:22 -07:00
aa116524e6 refactor(router): improve flatten fn
closes #15505
2017-03-29 10:10:10 -07:00
4a5ad7ba30 refactor(router): use object spread operator instead of merge fn 2017-03-29 10:10:06 -07:00
d74e4d0633 fix(core): improve error msg for invalid KeyValueDiffer.diff arg (#15489)
Closes #15402
2017-03-29 10:09:55 -07:00
a2c2b87aa3 fix(language-service): be resilient to invalidate ordering (#15470)
Fixes #15466
2017-03-29 10:09:19 -07:00
8f4ea3e4b8 docs(core): fix typo and example in InjectionToken doc (#15449)
The doc included an example that didn't use InjectionToken.
2017-03-29 10:08:22 -07:00
bf25e94f19 fix(language-service): guard access to Symbol.members (#15529)
Fixes #15528 

What is the current behavior?
The language service access TypeScript's Symbol.members without checking for null or undefined.
What is the new behavior?
The access is guarded.
2017-03-29 10:08:06 -07:00
7983414e6a ci: add tbosch and vicb as approvers of the language service (#15530) 2017-03-29 10:07:58 -07:00
8248eba3e2 docs: in doc comments, replace [aA]ngular2 with Angular (#15463) 2017-03-29 10:07:44 -07:00
a65487528f fix(compiler): allow single quotes into named interpolations (#15461)
Fixes #15318
2017-03-29 10:07:32 -07:00
426b3a19b7 refactor: use object spread operator rather than merge (#15426) 2017-03-29 10:07:14 -07:00
2360676a7b fix(router): shouldn't execute CanLoad when a route has been loaded
Closes #14475
Closes #15438
2017-03-29 10:07:01 -07:00
ce3e03ff1a refactor(router): polishing 2017-03-29 10:06:52 -07:00
858c11cf7b docs: clarify querying all descendants (#15400)
Fixes #14417
Updated example to illustrate @ContentChildren default behavior (only query direct children), and how to query for nested elements/all descendants.
2017-03-29 10:06:09 -07:00
95afaf495b test(compiler): refactor i18n integration test 2017-03-24 14:35:10 -07:00
d92930e975 docs: fixed broken links (#15455)
Closes #15446
2017-03-24 08:14:23 -07:00
c2892dada3 docs: revert the move of CONTRIBUTING.md to docs/CONTRIBUTING.md
Because the root path has a special meeting for GitHub, Jeremy, unicorns and red arrows.
2017-03-23 20:57:49 -07:00
b2b1195534 docs: update the contributing link one more time :-) 2017-03-23 19:26:25 -07:00
e1b09e3bcc docs: update CONTRIBUTING link in README.md 2017-03-23 19:25:46 -07:00
c65b75443e docs: add the 4.0.0 code name to the changelog 2017-03-23 17:46:02 -07:00
db0dca3fc1 docs: add a note about exclusion of symbols prefixed with ɵ from our public api surface (#15440) 2017-03-23 17:21:52 -07:00
7a715b2403 docs: add changelog for 4.0.0 2017-03-23 16:48:54 -07:00
1ba296644d release: cut the 4.0.0 release 2017-03-23 16:45:16 -07:00
b800a0c824 fix: prevent strictNullChecks support until #15432 is fixed (#15434) 2017-03-23 14:54:19 -07:00
0dda01e37c fix(compiler): correctly handle when toString is exported (#15430)
Fixes #15420
2017-03-23 13:38:01 -07:00
c8ab5cb0c5 fix(compiler): assume queries with no matches as static (#15429)
This has the side effect of allowing `@Input` and `@ContentChild`
on the same property if the query is static (see the bug description
for details).

Fixes #15417
2017-03-23 13:37:45 -07:00
92084f2b6a fix(platform-browser): setAttribute should work with xmlns namespace (#14874)
Closes #14865
2017-03-23 12:52:06 -07:00
08f2f08d74 fix(router): should pass new data to Observable when query params change (#15387)
Fixes #15290
2017-03-23 10:43:14 -07:00
376088da70 build(aio): delete content folder before doc-gen (#15414)
This should prevent false-positive e2e test runs where stale files
are left lying around.
2017-03-23 10:23:09 -07:00
73808dd38b build(aio): upgrade to @angular@4.0.0-rc.6 (#15412) 2017-03-22 23:52:43 -07:00
ee03418b10 release: cut the 4.0.0-rc.6 release 2017-03-22 23:09:47 -07:00
da700d1842 docs: move markdown docs from root dir to docs/ and remove obsolete files (#15410) 2017-03-22 22:50:12 -07:00
de87c47dd9 docs: spelling errors 2017-03-22 21:28:24 -07:00
1060805a1f docs: fix spelling 2017-03-22 21:28:24 -07:00
08d86751b9 fix(compiler): only log template deprecation warning once (#15364) 2017-03-22 21:26:53 -07:00
9319b5f329 docs(common): update ngFor docs to new as syntax (#15166) 2017-03-22 17:18:22 -07:00
26f6bd4d3b ci(travis): update excluded branch to g3 (#15391) 2017-03-22 17:15:38 -07:00
edb2571a59 docs: spelling error (#15406) 2017-03-22 17:14:56 -07:00
98cb974796 docs(router): fix typo in ParamMap api doc (#15397) 2017-03-22 17:14:11 -07:00
8b414222aa fix(aio): do not fallback to index.html for file requests (#15401)
Previously, all URLs were rewritten to `index.html` in order to support
deep-linking. This works when navigating to URLs that correspond to existing
resources. E.g. navigating to `/tutorial` returns `index.html` and then the
`DocViewer` takes over and requests `tutorial.json`.
Navigating to a non-existent URL (e.g. `/foo`), will return `index.html`, which
in turn requests (the non-existent) `foo.json` and throws an error when trying
to parse the returned `index.html` as JSON.

This commit fixes it by only rewriting URLs that do not request a file (i.e. do
not include a `.` in the last path segment).

Fixes #15398
2017-03-22 15:31:47 -07:00
ea49a95bd9 fix(upgrade): component injectors should not link the module injector tree (#15385) 2017-03-22 15:22:38 -07:00
a50d79df47 fix(compiler-cli): adding missing format xliff for the extractor (#15386)
To generate XLF files with ng-xi18n we could use the format parameter "xlf" or "xlif". The real name is "xliff" not "xlif", so this probably was a typo. This PR adds "xliff" as can be expected
2017-03-22 15:12:02 -07:00
64285a2171 docs: update 4.0.0-rc.5 release schedule (#15288) 2017-03-22 13:26:12 -07:00
941f194a83 docs: spelling errors (#15375) 2017-03-22 13:25:35 -07:00
8b4edcc7ad build(aio): output {@example} tags as <code-example> elements (#15382) 2017-03-22 13:24:40 -07:00
c58499786c fix(tsc-wrapped): use windows friendly path normalization in bundler (#15374)
Fixes #15289

PR Close #15374
2017-03-21 22:30:57 -05:00
1bcbcfd56f revert: build(aio): implement prerendering (#15346)
This reverts commit d0bc83ca27.

Protractor-based prerendering is flakey on Travis and takes several minutes to
complete, slowing down the build. Prerendering has a lower impact now that we
use a ServiceWorker. We will revisit in the future (probably using a
`PlatformServer`-based approach).

PR Close #15346
2017-03-21 19:05:36 -05:00
90d2518d9a fix(compiler): look for flat module resources using declaration module path (#15367)
`ngc` would look for flat module resources relative to the flat module index.
`ngc` now looks for flat module resources relative to the `.d.ts` file that declarates
the component.

Fixes #15221

PR Close #15367
2017-03-21 19:05:03 -05:00
7354949763 feat(tsc-wrapped): record original location of flattened symbols (#15367)
Added an "origins" section to the flat module `.metadata.json` files
that records where the original symbols was declared. This allows
correctly calculating relative path references recorded in metadata.
2017-03-21 19:05:00 -05:00
5efc86069f fix(forms): make composition event buffering configurable (#15256)
This commit fixes a regression where `ngModel` no longer syncs
letter by letter on Android devices, and instead syncs at the
end of every word. This broke when we introduced buffering of
IME events so IMEs like Pinyin keyboards or Katakana keyboards
wouldn't display composition strings. Unfortunately, iOS devices
and Android devices have opposite event behavior. Whereas iOS
devices fire composition events for IME keyboards only, Android
fires composition events for Latin-language keyboards. For
this reason, languages like English don't work as expected on
Android if we always buffer. So to support both platforms,
composition string buffering will only be turned on by default
for non-Android devices.

However, we have also added a `COMPOSITION_BUFFER_MODE` token
to make this configurable by the application. In some cases, apps
might might still want to receive intermediate values. For example,
some inputs begin searching based on Latin letters before a
character selection is made.

As a provider, this is fairly flexible. If you want to turn
composition buffering off, simply provide the token at the top
level:

```ts
providers: [
   {provide: COMPOSITION_BUFFER_MODE, useValue: false}
]
```

Or, if you want to change the mode  based on locale or platform,
you can use a factory:

```ts
import {shouldUseBuffering} from 'my/lib';

....
providers: [
   {provide: COMPOSITION_BUFFER_MODE, useFactory: shouldUseBuffering}
]
```

Closes #15079.

PR Close #15256
2017-03-21 16:47:18 -05:00
97149f9424 fix(core): update peer dep on zone.js to ^0.8.5 (#15365)
Closes #15185

PR Close #15365
2017-03-21 16:47:01 -05:00
bac265fdc2 refactor(core): misc cleanup (#15366)
PR Close #15366
2017-03-21 16:46:51 -05:00
e59e5e24b9 build(aio): upgrade to rxjs@5.2.0 2017-03-21 15:20:29 -05:00
9e5d4781cb refactor(aio): cleanup polyfill imports and realign them with the latest cli blueprint
This shouldn't change anything. But it's interesting that we used to have this  import
that seemed bogus, but there were no compilation or rutime errors.
2017-03-21 15:20:28 -05:00
fc1f6efe0d build(aio): fix paths to "index" pages
Content pages like `tutorial/index.md` were being mapped to `tutorial.index.json`,
which meant that they could only be rendered if you browsed to `/tutorial/index`.

This didn't sit well so now these pages are mapped to `tutorial.json`, which
means that you browser to them via `/tutorial/` or just `/tutorial`.

Fixed #15335
2017-03-21 15:20:28 -05:00
c9710d4fb5 build(aio): upgrade @angular/cli to 1.0.0-rc.4 2017-03-21 15:20:28 -05:00
cf16f3b0dd build(aio): update @angular to 4.0.0-rc.5 and zone.js to 0.8.4 2017-03-21 15:20:28 -05:00
a9e91115bf build(aio): add version into navigation.json
The navigation.json is now passed through the dgeni pipeline.
The source file has been moved to `aio/content/navigation.json`
but the generated file will now appear where the original source file
was found, `aio/src/content/navigation.json`.

Everything inside `aio/src/content` is now generated and ignored by git.

The `processNavigationMap` processor in this commit adds the current version
information to the navigation.json file and verifies the relative urls in
the file map to real documents.

The navigationService exposes the versionInfo as an observable, which the
AppComponent renders at the top of the sidenav.
2017-03-21 15:20:28 -05:00
90f699fdcf build(aio): ensure that internal document links work with base href 2017-03-21 15:20:28 -05:00
fd7b855cfc test(aio): fix test descriptions for ordering of processors 2017-03-21 15:20:28 -05:00
20aab64c65 test(aio): use MockLogger in AppComponent tests
This component sends a lot of messages to the console, which makes the
test run less easy to follow.
2017-03-21 15:20:28 -05:00
2eb027a793 build(aio): don't process unnecessary example files in doc-gen
This lowers the `yarn docs` processing time by about 40% (from 50 secs
to 30 secs).
2017-03-21 15:20:28 -05:00
b0a7bc77ee build(aio): remove cheatsheet processing and content
This will be replaced by a single file migrated from angular.io
2017-03-21 15:20:28 -05:00
4e10faf1eb build(aio): add version into navigation.json
The navigation.json is now passed through the dgeni pipeline.
The source file has been moved to `aio/content/navigation.json`
but the generated file will now appear where the original source file
was found, `aio/src/content/navigation.json`.

Everything inside `aio/src/content` is now generated and ignored by git.

The `processNavigationMap` processor in this commit adds the current version
information to the navigation.json file and verifies the relative urls in
the file map to real documents.

The navigationService exposes the versionInfo as an observable, which the
AppComponent renders at the top of the sidenav.
2017-03-21 15:20:28 -05:00
a0c6d44e18 build(aio): ensure that internal document links work with base href 2017-03-21 15:20:28 -05:00
9bc998c7a1 build(aio): use forked version of Rho rendering engine
The original Rho is too strict when it comes to markdown headings.
It requires that there be a blank line separating the heading and the
next paragraph.  The forked version here fixes that; but the Rho project
will not merge it as it goes against there basic rules.
2017-03-21 15:20:28 -05:00
1a0c6d89b1 build(aio): do not render ignored docs 2017-03-21 15:20:28 -05:00
8c12374c4c build(aio): do not render private classes and members 2017-03-21 15:20:28 -05:00
45e2126273 refactor(aio): removed dead code 2017-03-21 15:20:28 -05:00
41497b052d feat(aio): font change and toolbar shadow 2017-03-21 15:20:28 -05:00
068cad1c1b build: update to angular 4.0.0-rc.4 and service-worker@1.0.0-beta.7 2017-03-21 15:20:28 -05:00
31ef92fc36 build(aio): fix generated github links
The change from `modules` to `packages` needed to be applied to these links.
2017-03-21 15:20:28 -05:00
b4081e3713 build(aio): update to dgeni-packages 0.17.0
This new version fixes the problem with mistaking
content inside inline HTML blocks as tags

Related to #15199
2017-03-21 15:20:28 -05:00
c8b4a33a7f ci(aio): lower prerender browser instances
Hopefully this will reduce aio test flakes
2017-03-21 15:20:28 -05:00
a13ddf2e8a feat(aio): expand nav menu branch of select item on page load 2017-03-21 15:20:28 -05:00
64beae9527 fix(core): mark components for check when host events trigger. (#15359)
Fixes #15352

PR Close #15359
2017-03-21 14:27:01 -05:00
15a082c74e fix(platform-server): throw a better error message for relative URLs (#15357)
Unlike in the browser, on the server there is no concept of a document origin.
Thus, it is illegal to make requests for relative URLs against Http on platform-server.

Currently this fails with a vague error:

Error: Uncaught (in promise): Error at resolvePromise

This change adds explicit validation and a friendlier error message:

Error: URLs requested via Http on the server must be absolute. URL: /testing

Another option considered was to track the concept of an origin for the platform
and automatically prepend it to relative URLs. This would cause automatic "local
RPCs" to be made, though, which would be an unexpected and undesirable default
behavior.

Fixes #15349

PR Close #15357
2017-03-21 14:26:51 -05:00
fbccd5cd38 fix(animations): ensure empty animate() steps work at the end of a sequence (#15328)
Closes #15310
Closes #15328

PR Close #15328
2017-03-21 14:26:43 -05:00
1e8b132ade refactor(compiler): only produce log expressions for elements / text (#15350)
This change reduces the amount of generated code by only adding `log`
calls for elements and text nodes.

We need the `log` calls to allow users to jump to the right place
in the template via source maps. However, we only need it for element
and text nodes, but not for directives, queries, … as for them we 
first locate the corresponding element or text node.

Related to #15239

PR Close #15350
2017-03-21 14:26:30 -05:00
431eb309f3 fix(core): provide NgModuleRef in ViewContainerRef.createComponent. (#15350)
This is needed to support the corner cases:
- usage of a `ComponentFactory` that was created on the fly via `Compiler`
- overwriting of the `NgModuleRef` that is associated to a
  `ComponentFactory` by the `ComponentFactoryResolver` from
  which it was read.

Fixes #15241
2017-03-21 14:26:26 -05:00
8e6995c91e fix(core): stringify shouldn't throw when toString returns null/undefined (#14975)
Fixes #14948

PR Close #14975
2017-03-21 12:20:44 -05:00
0759911431 docs(compiler-cli): mention that .ngsummary.json files should be gitignore'd (#15047)
PR Close #15047
2017-03-21 12:20:38 -05:00
1d7693c1e1 fix(compiler): use attribute id to merge translations (#15302)
We extracted ids from i18n attributes but forgot to use them when merging the translations, resulting in an error about missing translations even when they were correctly defined.

Fixes #15234

PR Close #15302
2017-03-21 12:20:31 -05:00
16e0423085 revert: feat(compiler-cli): support metadata file aliases (#15331)
This reverts commit 0ab49d4cec.

PR Close #15331
2017-03-21 12:20:14 -05:00
c2ffb6bfcd build: remove use of alias metadata (#15331) 2017-03-21 12:20:06 -05:00
2489e4ba1b fix(animations): correct the main entry path in package.json (#15300)
PR Close #15300
2017-03-20 22:36:37 -05:00
94da80148e fix(animations): stringify boolean values as 1 and 0 (#15311)
Closes #15247
Closes #15311

PR Close #15311
2017-03-20 22:36:29 -05:00
764e90f9bb fix(compiler): don’t call check if we don’t need to (#15322)
If a directive has not bindings nor has a `ngDoCheck` / `ngOnInit`
lifecycle hook, don’t generate a `check` call.

This does not have an impact on the behavior, but produces
less code.

PR Close #15322
2017-03-20 22:36:20 -05:00
9bf2fb4a74 fix(animations): ensure enter/leave cancellations work (#15323)
Closes #15315
Closes #15323

PR Close #15323
2017-03-20 22:36:11 -05:00
de3d2eeeba fix(platform-server): interpret Native view encapsulation as Emulated on the server (#15155)
PR Close #15155
2017-03-20 17:14:09 -05:00
a805d00256 ci(forms): add tina as secondary for forms (#15262)
PR Close #15262
2017-03-20 17:13:52 -05:00
61135bc842 fix: remove left over debugger statement (#15309)
PR Close #15309
2017-03-20 17:13:44 -05:00
fa36ffda14 Revert "fix(compiler): shouldn't throw when Symbol is used as DI token (#13701)" (#15319)
This reverts commit 8b5c6b2732.

This feature is not compatible with the `Injector.get` which now only 
takes `Type` or `InjectableToken`. `Symbol` is not a valid type.

Closes #15183

PR Close #15319
2017-03-20 17:13:37 -05:00
d3eda7a5b5 feat(router): add ParamMap.keys to get a list of parameters 2017-03-20 09:19:32 -07:00
a755b715ed feat(router): introduce ParamMap to access parameters
The Router use the type `Params` for all of:
- position parameters,
- matrix parameters,
- query parameters.

`Params` is defined as follow `type Params = {[key: string]: any}`

Because parameters can either have single or multiple values, the type should
actually be `type Params = {[key: string]: string | string[]}`.

The client code often assumes that parameters have single values, as in the
following exemple:

```
class MyComponent {
sessionId: Observable<string>;

constructor(private route: ActivatedRoute) {}

ngOnInit() {
    this.sessionId = this.route
      .queryParams
      .map(params => params['session_id'] || 'None');
}
}

```

The problem here is that `params['session_id']` could be `string` or `string[]`
but the error is not caught at build time because of the `any` type.

Fixing the type as describe above would break the build because `sessionId`
would becomes an `Observable<string | string[]>`.

However the client code knows if it expects a single or multiple values. By
using the new `ParamMap` interface the user code can decide when it needs a
single value (calling `ParamMap.get(): string`) or multiple values (calling
`ParamMap.getAll(): string[]`).

The above exemple should be rewritten as:

```
class MyComponent {
sessionId: Observable<string>;

constructor(private route: ActivatedRoute) {}

ngOnInit() {
    this.sessionId = this.route
      .queryParamMap
      .map(paramMap => paramMap.get('session_id') || 'None');
}
}

```

Added APIs:
- `interface ParamMap`,
- `ActivatedRoute.paramMap: ParamMap`,
- `ActivatedRoute.queryParamMap: ParamMap`,
- `ActivatedRouteSnapshot.paramMap: ParamMap`,
- `ActivatedRouteSnapshot.queryParamMap: ParamMap`,
- `UrlSegment.parameterMap: ParamMap`
2017-03-20 09:19:32 -07:00
a9d5de0e56 refactor(router): misc minor updates 2017-03-20 09:19:32 -07:00
f634c62cb3 test: add systemjs+umd integration test (#14196)
This test ensures the `__esModule` is set on UMD bundles, thus making them compatible with SystemJS@^0.22.3.

Followup from https://github.com/frankwallis/plugin-typescript/issues/185.

PR Close #14196
2017-03-19 12:23:07 -05:00
f8c075ae27 fix(core): don’t create a comment for components with empty template. (#15260)
Fixes #15143

PR Close #15260
2017-03-19 12:22:26 -05:00
aeb99645bb test(animations): test various combinations of animations with host bindings (#15251)
PR Close #15251
2017-03-19 12:21:54 -05:00
0d3e314df0 fix(core): trigger host animations for elements that are removed. (#15251)
Fixes #14813
Fixes #15193
2017-03-19 12:21:42 -05:00
28ce68a13d refactor(core): view engine - change BindingType to BindingFlags (#15251) 2017-03-19 12:21:37 -05:00
80075afe8a fix(animations): only process element nodes through the animation engine (#15268)
Closes #15267
Closes #15268

PR Close #15268
2017-03-19 10:50:07 -05:00
bcc29ffdd1 build: update rollup (#15258)
PR Close #15258
2017-03-17 17:39:19 -05:00
0c43535ccc fix(core): only apply WrappedValue to the binding of the pipe (#15257)
Previously, a pipe that returned a `WrappedValue` would force the change
of the next bound property, independent of the binding in which the pipe
was used.

Now only the binding in which the `WrappedValue` is used will be assumed
as changed.

Fixes #15116

PR Close #15257
2017-03-17 17:38:36 -05:00
49829b4a4d build: add package names to secondary endpoint package.json files (#15253)
Fixes #14736

PR Close #15253
2017-03-17 16:52:55 -05:00
5c5c2ae405 fix(platform-server): setup NoopAnimationsModule in ServerModule by default (#15131)
This is so that server side rendering does not throw an exception when it encounters animations on the server side and does not need the user to explicitly setup NoopAnimationsModule in their app server module.

Fixes #15098, #14784.

PR Close #15131
2017-03-17 16:21:51 -05:00
6e9264a79c fix(tsc-wrapped): emit flat module format correctly on Windows (#15215)
File name needed to be normalized before comparison when using
synthetic file names.

Fixes #15192

PR Close #15215
2017-03-17 15:35:28 -05:00
a6fb78ee3c fix(animations): make sure non-transitioned leave operations cancel existing animations (#15254)
Closes #15213

PR Close #15254
2017-03-17 15:35:11 -05:00
d0bc83ca27 build(aio): implement prerendering
The current implementation is based on @igorminar's [angular-io-v42][1]. It is
using Protractor to request all docs URLs, let them fallback to `/index.html`
and save the rendered page.

[1]: https://github.com/IgorMinar/angular-io-v42/tree/05508ab3/tools/prerenderer

Fixes #15104
2017-03-17 15:31:22 -05:00
b5b2fed54d refactor(aio): re-arrange npm scripts 2017-03-17 15:31:22 -05:00
4cef5dddc6 build(aio): use own .gitignore file 2017-03-17 15:31:22 -05:00
f92591054b fix(animations): make sure easing values work with web-animations (#15195)
Closes #15115
Closes #15195

PR Close #15195
2017-03-17 13:53:19 -05:00
2a0e55ffb5 fix(core): allow tree shaking of component factories and styles (#15214)
Closure compiler is very sensitive to top level function calls.
This commit makes the function calls `createComponentFactory`
and `createRendererTypeV2` logic-less.

Fixes #15181

PR Close #15214
2017-03-17 13:52:57 -05:00
9429032da1 feat(upgrade): use ComponentFactory.inputs/outputs/ngContentSelectors (#15214)
DEPRECATION:
- the arguments `inputs` / `outputs` / `ngContentSelectors` of `downgradeComponent`
  are no longer used as Angular calculates these automatically now.
- Compiler.getNgContentSelectors is deprecated. Use
  ComponentFactory.ngContentSelectors instead.
2017-03-17 13:52:50 -05:00
791534f2f4 feat(core): expose inputs, outputs and ngContentSelectors on ComponentFactory. (#15214)
E.g. for a component like this:
```
@Component({
  template: ‘<ng-content select=“child”></ng-content>’
})
class MyComp {
  @Input(‘aInputName’)
  aInputProp: string;

  @Output(‘aEventName’)
  aOuputProp: EventEmitter<any>;
}
```

the `ComponentFactory` will now contain the following:
- `inputs = {aInputProp: ‘aInputName’}`
- `outputs = {aOutputProp: ‘aOutputName’}`
- `ngContentSelectors = [‘child’]`
2017-03-17 13:52:41 -05:00
604546c287 refactor(upgrade): don’t rely on compiler internals (#15214)
Uses `Element.matches` to match selectors, instead
of copying the code from our compiler.
2017-03-17 13:52:34 -05:00
c66437fc13 fix(animations): only treat view removals as void state transitions (#15245)
Closes #15223

PR Close #15245
2017-03-17 13:48:25 -05:00
8415910375 fix(compiler): add an empty content for source file of non mapped code. (#15246)
Before this when using ngc, tools tried to load `ng://…<component>.ts`
if `…<component>.ts` was the source file of a template.

PR Close #15246
2017-03-17 13:48:09 -05:00
5486e5417b feat(forms): allow to compile forms in strictNullChecks mode (#14679)
Closes #14667

PR Close #14679
2017-03-17 13:47:12 -05:00
2d78c8cc05 docs: add changelog for 4.0.0-rc.5 2017-03-17 10:18:16 -07:00
52bed7f9b3 release: cut the 4.0.0-rc.5 release 2017-03-17 10:16:53 -07:00
7fb45283df fix(compiler-cli): update the tsc-wrapped dependency version (#15226) 2017-03-17 09:41:28 -07:00
b7212f5afe docs: add changelog for 4.0.0-rc.4 2017-03-16 20:10:54 -07:00
4e25601c4d release: cut the 4.0.0-rc.4 release 2017-03-16 20:10:53 -07:00
add7829cb7 docs: add changelog for 2.4.10 2017-03-16 20:10:53 -07:00
a52184bdda fix(core): update peer dep on zone.js to ^0.8.4 (#15209) 2017-03-16 20:10:53 -07:00
410aa33005 build: fix paths to typings files so tsickle resolves imports correctly
Fixes #15080
2017-03-16 17:34:29 -07:00
0ab49d4cec feat(compiler-cli): support metadata file aliases 2017-03-16 17:34:29 -07:00
994089d36b fix(compiler): always use ng:// prefix for sourcemap urls (#15218)
Fixes:
- In G3, filePaths don’t start with a `/` and therefore became relative.
- Always using the `ng://` prefix groups angular resources in the same
  way for AOT and JIT.
2017-03-16 17:33:17 -07:00
d2fbbb44ae fix(core): update peer dep on zone.js to ^0.8.4 (#15209)
Closes #15180
Closes #15185
2017-03-16 13:23:09 -07:00
77fd91d615 fix(core): ErrorHandler should not rethrow an error by default (#15077) (#15208)
ErrorHandler can not throw errors because it will unsubscribe itself from
the error stream.

Zones captures errors and feed it into NgZone, which than has a Rx Observable
to feed it into ErrorHandler. If the ErroHandler throws, then Rx will teardown
the observable which in essence causes the ErrorHandler to be removed from the
error handling. This implies that the ErrorHandler can never throw errors.

Closes #14949
Closes #15182
Closes #14316
2017-03-16 12:58:41 -07:00
492153a986 fix(compiler): make sourcemaps work in AOT mode
Inlcuded fixes:
- include preamble in generated source map
- always add a mapping for line/col 0 so that the
  generated sourcemap is not sparse
- use a uniue sourceUrl for inline templates even
  in the AOT case
2017-03-16 12:56:56 -07:00
c0e05e6f03 fix(tsc-wrapped): emit js files in all cases 2017-03-16 12:56:56 -07:00
73a46205a0 build(tsc-wrapped): update tsickle to version 0.21.6
Update tsickle to version 0.21.6 which fixes a bug where input source maps which specified filenames differently than the names supplied to tsc didn't get composed with tsc's source maps.  Also adds a test that the bug was fixed.
2017-03-16 12:56:56 -07:00
992aa17361 build: add source maps into NPM distribution (#15159)
Previous to 2.x there were some source maps distrubted, but they didn't go
all the way back to the TypeScript sources and they weren't available for
all JavaScript distrubted to NPM.

With this change source maps will be available for FESM distributions as
well as UMD and will go all the way back to TypeScript sources.

Fixes #15184
2017-03-16 12:55:15 -07:00
a4076c70cc fix(platform-browser): prevent clobbered elements from freezing the browser
see
4f69d38f09
2017-03-16 10:16:39 -07:00
52bbc9baf4 refactor(platform-browser): cleanup HtmlSanitizer specs 2017-03-16 10:16:39 -07:00
26d4ce29e8 fix(forms): ensure observable validators are properly canceled (#15132)
Observable subscriptions from previous validation runs should be canceled
before a new subscription is created for the next validation run.
Currently the subscription that sets the errors is canceled properly,
but the source observable created by the validator is not. While this
does not affect validation status or error setting, the source
observables will incorrectly continue through the pipeline until they
complete. This change ensures that the whole stream is canceled.

AsyncValidatorFn previously had an "any" return type, but now it more
explicitly requires a Promise or Observable return type. We don't
anticipate this causing problems given that any other return type
would have caused a runtime error already.
2017-03-16 10:15:17 -07:00
41f61b0b5b test: integration test that Angular apps compile with TS 2.2 (#15153) 2017-03-16 09:13:48 -07:00
f92d644c95 ci: disable Android 4.1, 4.2 and 4.3 in SauceLabs (#14461)
These browsers are not supported anymore: https://wiki.saucelabs.com/pages/viewpage.action?pageId=67012495

Tried to switch them to BrowserStack, but the emulators are too slow to run the full campaign (time out in tests, and disconnect eventually).
2017-03-16 09:13:07 -07:00
923d0c56e7 fix: correct UMD resolutions for platform-browser_animations (#15190)
Fixes #15114
2017-03-15 17:14:20 -07:00
dd36d413ba build: update symlink scripts for Windows (#14987) 2017-03-15 17:13:54 -07:00
013d806b79 fix(platform-server): handle styles with extra ':'s correctly (#15189)
Previously, style values were parsed with a regex that split on /:+/.

This causes errors for CSS such as

div {
  background-url: url(http://server.com/img.png);
}

since the regex would split the background-url line into 3 values instead of 2.

Now, the : character is detected with indexOf, avoiding this error.

A test was added to verify the behavior is correct.
2017-03-15 17:13:31 -07:00
6e98757665 fix(core): use presence of .subscribe to detect observables rather then Symbol.observable (#15171)
Fixes #14298
Fixes #14473
Fixes #14926
2017-03-15 17:13:03 -07:00
313158132d Revert "fix(core): ErrorHandler should not rethrow an error by default (#15077)"
This reverts commit 6559425b07.
2017-03-15 16:29:24 -07:00
6772c913c7 fix(aio): scroll to hash fragment element on URL change 2017-03-15 16:11:30 -07:00
b11d0119ac feat(aio): top bar typography, sidenav size 2017-03-15 16:11:30 -07:00
637a489996 refactor(aio): indent and org cleanup 2017-03-15 16:11:30 -07:00
c2bd357825 feat(aio): initial design commit
Implemented style guide elements to top header bar, side hamburger nav menu, content and search. Consolidated SCSS files to styles folder. Fixed PWA test.
2017-03-15 16:11:30 -07:00
4870f910d6 feat(aio): hide search results when click outside search elements
Clicking anywhere except on the search results and the search box will
now hide the search results

Closes #15095
2017-03-15 16:11:30 -07:00
c95a3048ce fix(aio): SearchBoxComponent should send query on click
The input may still have focus when the user hits ESC,
causing the search to be hidden.

If the user then clicks on the input again, they would expect
it to reopen the results.
2017-03-15 16:11:30 -07:00
0e6eb6d719 test(aio): fill in missing API page unit tests 2017-03-15 16:11:30 -07:00
09574fc285 build(aio): yarn test --sourcemap=false for faster dev/test cycles 2017-03-15 16:11:29 -07:00
4347cb2119 ci(aio): whitelist 'aio-contributors' for deploying PR previews 2017-03-15 16:11:29 -07:00
f600d4e9e4 refactor(aio): move window:resize handler into component 2017-03-15 16:11:29 -07:00
eaa04354d5 fix(aio): intercept all clicks on anchors
Previously we had the `LinkDirective` which intercepted clicks on anchors
outside the doc viewer. Now we intercept "all" link clicks within the app.
2017-03-15 16:11:29 -07:00
3f7cfde476 fix(aio): ignore private exports
Closes #14992
2017-03-15 16:11:29 -07:00
62d5543b01 fix(animations): make sure easing values are applied to an empty animate() step (#15174)
Closes #15115
Closes #15174
2017-03-15 15:31:06 -07:00
f1b33ab7b1 fix(http): Make ResponseOptionsArgs an interface (#14607) (#14623)
closes #13708
2017-03-15 15:28:52 -07:00
029d0f25e5 fix(router): fix query parameters with multiple values (#15129)
fixes #14796
2017-03-15 15:27:19 -07:00
3f38c6fdcd fix(animations): always fire callbacks even for noop animations (#15170)
Closes #15170
2017-03-15 13:41:00 -07:00
80112a9ea1 fix: fix path locally to empty.js (#15073) 2017-03-15 13:40:24 -07:00
795638e18b ci: remove unused import from integration test (#15175) 2017-03-15 13:39:00 -07:00
322bf7a0d5 Revert "refactor(upgrade): don’t rely on compiler internals"
This reverts commit 8e2c8b3e4d.
2017-03-15 13:23:31 -07:00
cd981499f9 Revert "feat(core): expose inputs, outputs and ngContentSelectors on ComponentFactory."
This reverts commit 1171f91a80.
2017-03-15 13:23:10 -07:00
c439742a54 Revert "feat(upgrade): use ComponentFactory.inputs/outputs/ngContentSelectors"
This reverts commit a3e32fb7e1.
2017-03-15 13:22:54 -07:00
a3e32fb7e1 feat(upgrade): use ComponentFactory.inputs/outputs/ngContentSelectors
DEPRECATION:
- the arguments `inputs` / `outputs` / `ngContentSelectors` of `downgradeComponent`
  are no longer used as Angular calculates these automatically now.
- Compiler.getNgContentSelectors is deprecated. Use
  ComponentFactory.ngContentSelectors instead.
2017-03-15 11:42:12 -07:00
1171f91a80 feat(core): expose inputs, outputs and ngContentSelectors on ComponentFactory.
E.g. for a component like this:
```
@Component({
  template: ‘<ng-content select=“child”></ng-content>’
})
class MyComp {
  @Input(‘aInputName’)
  aInputProp: string;

  @Output(‘aEventName’)
  aOuputProp: EventEmitter<any>;
}
```

the `ComponentFactory` will now contain the following:
- `inputs = {aInputProp: ‘aInputName’}`
- `outputs = {aOutputProp: ‘aOutputName’}`
- `ngContentSelectors = [‘child’]`
2017-03-15 11:42:12 -07:00
8e2c8b3e4d refactor(upgrade): don’t rely on compiler internals
Uses `Element.matches` to match selectors, instead
of copying the code from our compiler.
2017-03-15 11:42:12 -07:00
b00fe20afd fix(compiler): support interface types in injectable constuctors (#14894)
Fixes #12631
2017-03-15 09:24:56 -07:00
36ce0afff6 fix(animations): support multiple state names per state() call (#15147)
Closes #14732
Closes #15147
2017-03-15 09:24:09 -07:00
5c0ea20bd0 build(tsc-wrapped): use tsickleCompilerHost for initial file load
In order for tsickle's new support for input source maps to work, the tsickleCompilerHost must be used for the initial load of source files, since that's when the inline source maps are read and stripped.
2017-03-15 09:23:36 -07:00
49764a5bff build(tsc-wrapped): update tsickle to version 0.21.5 2017-03-15 09:23:36 -07:00
4f7d62adac fix(platform-server): fix an exception when HostListener('window:scroll') is used on the server (#15019) 2017-03-14 20:48:01 -07:00
c10c060d20 feat(common): support as syntax in template/* bindings (#15025)
* feat(common): support `as` syntax in template/* bindings

Closes #15020

Showing the new and the equivalent old syntax.
- `*ngIf="exp as var1”`
   => `*ngIf="exp; let var1 = ngIf”`
- `*ngFor="var item of itemsStream |async as items”`
   => `*ngFor="var item of itemsStream |async; let items = ngForOf”`

* feat(common): convert ngIf to use `*ngIf="exp as local“` syntax

* feat(common): convert ngForOf to use `*ngFor=“let i of exp as local“` syntax

* feat(common): expose NgForOfContext and NgIfContext
2017-03-14 20:46:29 -07:00
5fe2d8fd80 fix(core): update peer dep on zone.js to ^0.8.2 (#15078) 2017-03-14 20:42:39 -07:00
5c34066058 fix(compiler): only warn for @Injectable classes with invalid args.
In v2.x, users had to annotate classes that they intended to use as tokens with `@Injectable`. This is no longer required in v4.x for tokens,
and we now require the constructor parameters of classes annotated
with `@Injectable` to be statically analyzable by ngc.

This commit reduces the error into a warning
if the constructor parameters do not meet this condition.

DEPRECATION:
- Classes annotated with `@Injectable` but whose constructor’s parameter types
  are not statically analyzable by ngc will produce a warning.

Closes #15003
2017-03-14 19:52:53 -07:00
50ab06e29d fix(compiler): generated code should pass noUnusedLocals check
Closes #14797
2017-03-14 19:52:53 -07:00
06fc42bc44 fix(core): don’t throw if queries change during change detection.
Throwing on query changes would be a breaking change compared to v2.
Also discovers a bug with querying manually projected content, see #15117.

Related to #14748
Closes #14925
2017-03-14 19:52:53 -07:00
959a03a61f fix(compiler): fix utf8encode, move to sharted utils, add tests (#15076) 2017-03-14 17:13:39 -07:00
3b1956bbf2 fix(compiler): warning prints "WARNING" instead of "ERROR" (#15125) 2017-03-14 17:12:44 -07:00
3c15916e17 fix(compiler): Improve error message for missing annotations (#14724)
Currently, it says:
Unexpected value 'FuzzyTimePipe in
javascript/angular2/example/search/fuzzy_time.ts' declared by the module
'SearchModule in javascript/angular2/example/search/search_module.ts'

The new error message also suggests: 'Please add a @Pipe/@Directive/@Component annotation.'
2017-03-14 17:12:18 -07:00
ff60c041f6 test(platform-server): add initial e2e tests for platform-server (#15061) 2017-03-14 17:11:39 -07:00
13686bb518 fix: element injector vs module injector (#15044)
fixes #12869
fixes #12889
fixes #13885
fixes #13870

Before this change there was a single injector tree.
Now we have 2 injector trees, one for the modules and one for the components.
This fixes lazy loading modules.

See the design docs for details:
https://docs.google.com/document/d/1OEUIwc-s69l1o97K0wBd_-Lth5BBxir1KuCRWklTlI4

BREAKING CHANGES

`ComponentFactory.create()` takes an extra optional `NgModuleRef` parameter.
No change should be required in user code as the correct module will be used
when none is provided

DEPRECATIONS

The following methods were used internally and are no more required:
- `RouterOutlet.locationFactoryResolver`
- `RouterOutlet.locationInjector`
2017-03-14 16:26:17 -07:00
f093501501 fix(platform-server): support svg elements with namespaced attributes (#15101) 2017-03-14 15:40:55 -07:00
80649ea03c fix(platform-server): correctly implement get href in parse5 adapter (#15022) 2017-03-14 15:38:24 -07:00
778f7d6f33 fix(forms): remove equalsTo validator (#15050)
This API was introduced only in a beta release, and is being removed because we found it to be incorrect prior to launch. For more information about why this is being removed, see https://github.com/angular/angular/pull/15050.
2017-03-14 15:37:51 -07:00
2c5a671341 fix: don't instantiate providers with ngOnDestroy eagerly. (#15070)
BREAKING CHANGE:

Perviously, any provider that had an ngOnDestroy lifecycle hook would be created eagerly.

Now, only classes that are annotated with @Component, @Directive, @Pipe, @NgModule are eager. Providers only become eager if they are either directly or transitively injected into one of the above.

This also makes all `useValue` providers eager, which
should have no observable impact other than code size.

EXPECTED IMPACT:
Making providers eager was an incorrect behavior and never documented.
Also, providers that are used by a directive / pipe / ngModule stay eager.
So the impact should be rather small.

Fixes #14552
2017-03-14 14:32:26 -07:00
0aad270267 refactor(platform-browser): move platform-browser/animations to animations/browser (#15130)
Closes: #15130
2017-03-14 11:55:49 -07:00
221899a930 ci: fix incorrect github credetials (#15146) 2017-03-14 11:49:33 -07:00
060a2d11e5 ci(aio): deploy previews from aio-master (#15137) 2017-03-14 10:28:52 -07:00
abbbb4d52c ci: do not use shell to expand secure tokens to prevent leaks 2017-03-14 10:27:56 -07:00
ccd38dd54d ci: changing deployment token 2017-03-14 10:27:56 -07:00
cdc882bd36 feat: introduce source maps for templates (#15011)
The main use case for the generated source maps is to give
errors a meaningful context in terms of the original source
that the user wrote.

Related changes that are included in this commit:

* renamed virtual folders used for jit:
  * ng://<module type>/module.ngfactory.js
  * ng://<module type>/<comp type>.ngfactory.js
  * ng://<module type>/<comp type>.html (for inline templates)
* error logging:
  * all errors that happen in templates are logged
    from the place of the nearest element.
  * instead of logging error messages and stacks separately,
    we log the actual error. This is needed so that browsers apply
    source maps to the stack correctly.
  * error type and error is logged as one log entry.

Note that long-stack-trace zone has a bug that 
disables source maps for stack traces,
see https://github.com/angular/zone.js/issues/661.

BREAKING CHANGE:

- DebugNode.source no more returns the source location of a node.  

Closes 14013
2017-03-14 09:16:15 -07:00
1c1085b140 feat(aio): add google analytics (#15081) 2017-03-13 18:08:23 -07:00
914797a8ff feat(upgrade): support multi-slot projection in upgrade/static (#14282)
Closes #14261
2017-03-13 17:34:53 -07:00
ab40fcb068 docs(aio): fix relative links
The migrator was updated to automatically fix these links.
See fca5fb0280
and 3927b7a038

The result of this is that, going forward, we should ask
authors to include the path from the base href to the thing
being linked. E.g. guide/architecture#intro
2017-03-13 16:56:23 -07:00
1847550ad1 docs(aio): move cookbooks into guide
Also update all docs with migrated versions from latest angular.io

Fixes #14941
2017-03-13 16:56:23 -07:00
6497633529 feat(aio): improve search results functionality
* Ensure that all indexed documents are displayed in the search results.
(Previously the guide documents were not appearing because we only showed
results that had a `name` property, rather than a `name` or `title`.)
* Group the results by their containing folder (e.g. api, guide, tutorial, etc).
* Hide the results when the user hits the ESC key.
* Hide the results when the user clicks on a search result

Closes #14852
2017-03-13 16:55:52 -07:00
8850098ea4 build(aio): ensure API docs are generated in the correct place (#15103)
The move of the source code from modules/@angular to packages, caused a
problem with the path to the API docs.
2017-03-13 16:53:47 -07:00
eedca09d73 build(aio): generate the api-list.json file from the API docs 2017-03-13 16:52:58 -07:00
7b6dbf0952 fix(aio): LocationService search should handle corner cases
Adds tests and fixes corners cases for both `search()` and `setSearc()`
for things like empty queries and param keys that need encoding.

This commit refactors the `LocationService` to rely upon the `PlatformLocation`
rather than using `window.history` directly. This makes testing easier but also
makes the code simpler since `PlatformLocation` deals with platforms that
do not support history for us.
2017-03-13 16:52:58 -07:00
e6c81d2a42 Revert "refactor(platform-browser): move platform-browser/animations to animations/browser (#15043)"
This reverts commit 195b863ea4.
2017-03-13 15:46:44 -07:00
498a95148b Revert "build(animations): adjust animations/browser source to new standard for automatic build (#15043)"
This reverts commit 21a18d6ceb.
2017-03-13 15:46:07 -07:00
21a18d6ceb build(animations): adjust animations/browser source to new standard for automatic build (#15043) 2017-03-13 14:39:42 -07:00
195b863ea4 refactor(platform-browser): move platform-browser/animations to animations/browser (#15043) 2017-03-13 14:39:19 -07:00
75147ff008 fix(aio): remove invalid brace from CSS (#15122) 2017-03-13 13:36:22 -07:00
018e5c979b fix(platform-server): fix get/set title in parse5 adapter (#14965) 2017-03-13 13:22:03 -07:00
e7dab7e6c1 feat(aio): hard code a "Home" image link into the toolbar
Closes #15017
2017-03-13 12:55:11 -07:00
26efa3a25c style(aio): tidy up SCSS files 2017-03-13 12:55:11 -07:00
893652a813 fix(aio): upgrade to zone.js 0.7.8 (#15099)
This new version supports empty jasmine it clauses.
2017-03-13 12:53:45 -07:00
6559425b07 fix(core): ErrorHandler should not rethrow an error by default (#15077) 2017-03-13 11:27:01 -07:00
df914ef4bf fix(core): don’t recreate TemplateRef when used as a reference. (#15066)
This was a regression introduced in v4 rc.0.

Fixes #14873
2017-03-13 10:44:12 -07:00
4e1cf5b41a build(aio): replace all occurrences of env vars on a line in aio-builds-setup 2017-03-13 10:30:49 -07:00
0c5f893f6e test(aio): improve test description and expectations 2017-03-13 10:30:49 -07:00
17f5f3b32c ci(aio): fix clean-up script on ngbuilds.io 2017-03-13 10:30:49 -07:00
3bb59902f7 docs(aio): add more docs about aio-builds-setup 2017-03-13 10:30:49 -07:00
b804a488c5 feat(aio): make it easy to keep relevant logs outside the docker container 2017-03-13 10:30:49 -07:00
cbde75e77b feat(aio): redirect HTTP to HTTPS 2017-03-13 10:30:49 -07:00
413e11fac2 build(aio): remove redundant arg 2017-03-13 10:30:49 -07:00
0e2dd76c3b build: remove obsolete ci-lite/ directory and files (#14994)
The directory was removed in 91fe3aadb but then accidentally re-introduced while
rebasing and merging ab0db66bf.
2017-03-13 10:29:45 -07:00
ff71eff157 refactor(core): use flags in Renderer2.setStyle instead of booleans (#15045)
BREAKING CHANGE: (since v4 rc.1)
- `Renderer2.setStyle` no longer takes booleans but rather a
  bit mask of flags.
2017-03-13 09:45:04 -07:00
fa1920a02b feat(aio): enable deep-linking on deployed apps (until prerendering is done) (#15049) 2017-03-13 09:35:16 -07:00
71cd2957f7 ci: add wardbell and gkalpak to aio approvers (#15030) 2017-03-13 09:34:40 -07:00
6c8638cf01 feat(core): allow to provide multiple default testing modules (#15054)
This can be used to e.g. add the NoopAnimationsModule by default:

```
TestBed.initTestEnvironment([
  BrowserDynamicTestingModule,
  NoopAnimationsModule
], platformBrowserDynamicTesting());
```
2017-03-10 16:55:32 -08:00
8b5c6b2732 fix(compiler): shouldn't throw when Symbol is used as DI token (#13701)
Closes #13314
2017-03-10 15:26:37 -08:00
601494734c Revert "fix(core): ErrorHandler should not rethrow an error by default (#13534)"
This reverts commit 1aebea52e1.
2017-03-10 15:05:48 -08:00
1aebea52e1 fix(core): ErrorHandler should not rethrow an error by default (#13534)
Closes #14949
Closes #13159
Closes #8993
2017-03-10 14:44:14 -08:00
920b3d259d feat(aio): support @angular/service-worker using the CLI generated service worker manifest (#15042) 2017-03-10 14:05:29 -08:00
fce55d87d2 feat(aio): add Kapunahele animations v2 (#15023) 2017-03-10 14:05:00 -08:00
53d62fa7d0 ci: use angular-builds credentials for publishing artifacts (#15072) 2017-03-10 14:03:40 -08:00
a69afeb614 ci: skip root pullapproval for packages directory (#15071) 2017-03-10 13:54:28 -08:00
5f9fb911f7 fix(compiler): improve error msg for unexpected closing tags (#14747)
Closes #6652
2017-03-10 13:05:17 -08:00
725 changed files with 19251 additions and 13163 deletions

4
.gitignore vendored
View File

@ -26,7 +26,3 @@ yarn-error.log
# rollup-test output
/modules/rollup-test/dist/
# angular.io
/aio/src/content/docs
/aio/dist

View File

@ -20,6 +20,8 @@
# tbosch - Tobias Bosch
# vicb - Victor Berchet
# vikerman - Vikram Subramanian
# wardbell - Ward Bell
# tinayuangao - Tina Gao
version: 2
@ -40,6 +42,7 @@ groups:
- "aio/*"
- "integration/*"
- "modules/*"
- "packages/*"
- "tools/*"
users:
- IgorMinar
@ -153,7 +156,7 @@ groups:
- "packages/forms/*"
users:
- kara #primary
# needs secondary
- tinayuangao #secondary
- IgorMinar #fallback
- mhevery #fallback
@ -173,7 +176,8 @@ groups:
- "packages/language-service/*"
users:
- chuckjaz #primary
# needs secondary
- tbosch #secondary
- vicb
- IgorMinar #fallback
- mhevery #fallback
@ -182,8 +186,8 @@ groups:
files:
- "packages/router/*"
users:
- vicb #primary
# needs secondary
- jasonaden
- vicb
- IgorMinar #fallback
- mhevery #fallback
@ -246,7 +250,8 @@ groups:
files:
- "aio/*"
users:
- IgorMinar
- robwormald
- petebacondarwin
- IgorMinar #primary
- petebacondarwin #secondary
- gkalpak
- wardbell
- mhevery #fallback

View File

@ -19,7 +19,7 @@ addons:
- secure: "L7nrZwkAtFtYrP2DykPXgZvEKjkv0J/TwQ/r2QGxFTaBq4VZn+2Dw0YS7uCxoMqYzDwH0aAOqxoutibVpk8Z/16nE3tNmU5RzltMd6Xmt3qU2f/JDQLMo6PSlBodnjOUsDHJgmtrcbjhqrx/znA237BkNUu6UZRT7mxhXIZpn0U="
branches:
except:
- g3_v2_0
- g3
cache:
yarn: true
@ -30,9 +30,9 @@ cache:
env:
global:
# GITHUB_TOKEN_ANGULAR
# GITHUB_TOKEN_ANGULAR=<github token, a personal access token of the angular-builds account, account access in valentine>
# This is needed for the e2e Travis matrix task to publish packages to github for continuous packages delivery.
- secure: "fq/U7VDMWO8O8SnAQkdbkoSe2X92PVqg4d044HmRYVmcf6YbO48+xeGJ8yOk0pCBwl3ISO4Q2ot0x546kxfiYBuHkZetlngZxZCtQiFT9kyId8ZKcYdXaIW9OVdw3Gh3tQyUwDucfkVhqcs52D6NZjyE2aWZ4/d1V4kWRO/LMgo="
- secure: "rNqXoy2gqjbF5tBXlRBy+oiYntO3BtzcxZuEtlLMzNaTNzC4dyMOFub0GkzIPWwOzkARoEU9Kv+bC97fDVbCBUKeyzzEqxqddUKhzRxeaYjsefJ6XeTvBvDxwo7wDwyxZSuWdBeGAe4eARVHm7ypsd+AlvqxtzjyS27TK2BzdL4="
# FIREBASE_TOKEN
# This is needed for publishing builds to the "aio-staging" firebase site.
# TODO(i): the token was generated using the iminar@google account, we should switch to a shared/role-base account.
@ -40,6 +40,7 @@ env:
matrix:
# Order: a slower build first, so that we don't occupy an idle travis worker waiting for others to complete.
- CI_MODE=e2e
- CI_MODE=e2e_2
- CI_MODE=js
- CI_MODE=saucelabs_required
- CI_MODE=browserstack_required

View File

@ -1,3 +1,269 @@
<a name="4.0.3"></a>
## [4.0.3](https://github.com/angular/angular/compare/4.0.2...4.0.3) (2017-04-21)
### Bug Fixes
* **benchpress:** chrome - prevent trace buffer overflow ([d216f94](https://github.com/angular/angular/commit/d216f94))
* **compiler:** fix build error in xliff2 ([1870347](https://github.com/angular/angular/commit/1870347))
* **compiler:** ignore calls to unresolved symbols in metadata ([d4038ab](https://github.com/angular/angular/commit/d4038ab)), closes [#15969](https://github.com/angular/angular/issues/15969)
* **compiler:** ignore calls to unresolved symbols in metadata ([#15970](https://github.com/angular/angular/issues/15970)) ([db25f08](https://github.com/angular/angular/commit/db25f08)), closes [#15969](https://github.com/angular/angular/issues/15969)
* **compiler:** Inform user where Quoted error was thrown ([3184cc5](https://github.com/angular/angular/commit/3184cc5))
* **compiler:** suppress another closure warning ([#16137](https://github.com/angular/angular/issues/16137)) ([72e240a](https://github.com/angular/angular/commit/72e240a))
* **core:** benchmarks - enable ng1 benchmark again ([ccac4c6](https://github.com/angular/angular/commit/ccac4c6))
* **core:** distribute externs for testability API ([#16179](https://github.com/angular/angular/issues/16179)) ([e377d9d](https://github.com/angular/angular/commit/e377d9d))
* **core:** key-value differ changes iteration ([#15968](https://github.com/angular/angular/issues/15968)) ([a8600dc](https://github.com/angular/angular/commit/a8600dc)), closes [#14997](https://github.com/angular/angular/issues/14997)
* **language-service:** only use canonical symbols ([786093a](https://github.com/angular/angular/commit/786093a))
* **packaging:** increased buffer size ([#15840](https://github.com/angular/angular/issues/15840)) ([88ad490](https://github.com/angular/angular/commit/88ad490))
* **platform-server:** handle innerText ([#15818](https://github.com/angular/angular/issues/15818)) ([7de340d](https://github.com/angular/angular/commit/7de340d))
* **router:** prevent `RouterLinkActive` from causing an infinite CD loop ([4479c42](https://github.com/angular/angular/commit/4479c42)), closes [#15825](https://github.com/angular/angular/issues/15825)
* **tsc-wrapped:** collect new expressions with no arguments ([#15908](https://github.com/angular/angular/issues/15908)) ([41cac9e](https://github.com/angular/angular/commit/41cac9e)), closes [#15906](https://github.com/angular/angular/issues/15906)
### Features
* **compiler:** Implement i18n XLIFF 2.0 serializer ([#14185](https://github.com/angular/angular/issues/14185)) ([a7d8edd](https://github.com/angular/angular/commit/a7d8edd)), closes [#11735](https://github.com/angular/angular/issues/11735)
* **upgrade:** allow setting the angularjs lib at runtime ([#15168](https://github.com/angular/angular/issues/15168)) ([a75d056](https://github.com/angular/angular/commit/a75d056))
* **upgrade:** allow setting the angularjs lib at runtime ([#15168](https://github.com/angular/angular/issues/15168)) ([4f172b0](https://github.com/angular/angular/commit/4f172b0))
* **upgrade:** fixes for allow setting the angularjs lib at runtime ([bb6932d](https://github.com/angular/angular/commit/bb6932d))
* add support for TS 2.3 ([5cf101f](https://github.com/angular/angular/commit/5cf101f))
<a name="4.1.0-beta.1"></a>
# [4.1.0-beta.1](https://github.com/angular/angular/compare/4.1.0-beta.0...4.1.0-beta.1) (2017-04-12)
### Bug Fixes
* **compiler:** fix inheritance for AOT with summaries ([#15583](https://github.com/angular/angular/issues/15583)) ([8ef621a](https://github.com/angular/angular/commit/8ef621a))
* **language-service:** avoid throwing exceptions when reporting metadata errors ([7764c5c](https://github.com/angular/angular/commit/7764c5c))
* **language-service:** detect when there isn't a tsconfig.json ([258d539](https://github.com/angular/angular/commit/258d539)), closes [#15874](https://github.com/angular/angular/issues/15874)
* **language-service:** improve resilience to incomplete information ([71a8627](https://github.com/angular/angular/commit/71a8627))
* **language-service:** initialize static reflector correctly ([fe0d02f](https://github.com/angular/angular/commit/fe0d02f)), closes [#15768](https://github.com/angular/angular/issues/15768)
* **language-service:** parse extended i18n forms ([bde9771](https://github.com/angular/angular/commit/bde9771))
* **language-service:** resolve any parameter types to any result ([5fbb0d0](https://github.com/angular/angular/commit/5fbb0d0))
* **router:** fix query param parsing ([a487563](https://github.com/angular/angular/commit/a487563))
* **router:** the preloader use the module from the loaded config ([6d12aa9](https://github.com/angular/angular/commit/6d12aa9))
* **tsc-wrapped:** ensure valid path separators in metadata ([96aa236](https://github.com/angular/angular/commit/96aa236))
### Features
* **animations:** Update types for TypeScript nullability support ([38d75d4](https://github.com/angular/angular/commit/38d75d4)), closes [#15870](https://github.com/angular/angular/issues/15870)
* **benchpress:** Update types for TypeScript nullability support ([14669f2](https://github.com/angular/angular/commit/14669f2))
* **common:** Update types for TypeScript nullability support ([d8b73e4](https://github.com/angular/angular/commit/d8b73e4))
* **compiler:** Update types for TypeScript nullability support ([09d9f5f](https://github.com/angular/angular/commit/09d9f5f))
* **language-service:** Update types for TypeScript nullability support ([540581d](https://github.com/angular/angular/commit/540581d))
<a name="4.0.2"></a>
## [4.0.2](https://github.com/angular/angular/compare/4.0.1...4.0.2) (2017-04-11)
### Bug Fixes
* **compiler:** fix inheritance for AOT with summaries ([#15583](https://github.com/angular/angular/issues/15583)) ([1864ccb](https://github.com/angular/angular/commit/1864ccb))
* **language-service:** avoid throwing exceptions when reporting metadata errors ([0861fda](https://github.com/angular/angular/commit/0861fda))
* **language-service:** detect when there isn't a tsconfig.json ([168a2eb](https://github.com/angular/angular/commit/168a2eb)), closes [#15874](https://github.com/angular/angular/issues/15874)
* **language-service:** improve resilience to incomplete information ([e4277a0](https://github.com/angular/angular/commit/e4277a0))
* **language-service:** initialize static reflector correctly ([5b99533](https://github.com/angular/angular/commit/5b99533)), closes [#15768](https://github.com/angular/angular/issues/15768)
* **language-service:** parse extended i18n forms ([c9c7acd](https://github.com/angular/angular/commit/c9c7acd))
* **language-service:** resolve any parameter types to any result ([feae7b6](https://github.com/angular/angular/commit/feae7b6))
* **router:** fix query param parsing ([2f41b52](https://github.com/angular/angular/commit/2f41b52))
* **router:** the preloader use the module from the loaded config ([978f809](https://github.com/angular/angular/commit/978f809))
* **tsc-wrapped:** ensure valid path separators in metadata ([c10e50c](https://github.com/angular/angular/commit/c10e50c))
<a name="4.0.1"></a>
## [4.0.1](https://github.com/angular/angular/compare/4.0.0...4.0.1) (2017-03-29)
### Bug Fixes
* **animations:** make sure style calculations are not computed too early ([#15540](https://github.com/angular/angular/issues/15540)) ([c828511](https://github.com/angular/angular/commit/c828511)), closes [#15507](https://github.com/angular/angular/issues/15507)
* **compiler:** allow single quotes into named interpolations ([#15461](https://github.com/angular/angular/issues/15461)) ([a654875](https://github.com/angular/angular/commit/a654875)), closes [#15318](https://github.com/angular/angular/issues/15318)
* **compiler:** ignore errors when evaluating base classes ([#15560](https://github.com/angular/angular/issues/15560)) ([a88413f](https://github.com/angular/angular/commit/a88413f)), closes [#15536](https://github.com/angular/angular/issues/15536)
* **compiler:** throw when a component defines both template and templateUrl ([#15572](https://github.com/angular/angular/issues/15572)) ([902bb2f](https://github.com/angular/angular/commit/902bb2f)), closes [#15566](https://github.com/angular/angular/issues/15566)
* **core:** check for undefined on normalizeDebugBindingValue ([#15503](https://github.com/angular/angular/issues/15503)) ([b8c0a97](https://github.com/angular/angular/commit/b8c0a97)), closes [#15494](https://github.com/angular/angular/issues/15494)
* **core:** fix inheritance in JIT mode for TS 2.1 ([#15599](https://github.com/angular/angular/issues/15599)) ([ca66530](https://github.com/angular/angular/commit/ca66530)), closes [#15502](https://github.com/angular/angular/issues/15502)
* **core:** fix the key/value differ ([#15539](https://github.com/angular/angular/issues/15539)) ([e72124c](https://github.com/angular/angular/commit/e72124c)), closes [#15457](https://github.com/angular/angular/issues/15457)
* **core:** improve error msg for invalid KeyValueDiffer.diff arg ([#15489](https://github.com/angular/angular/issues/15489)) ([d74e4d0](https://github.com/angular/angular/commit/d74e4d0)), closes [#15402](https://github.com/angular/angular/issues/15402)
* **core:** Update types for TypeScript nullability support ([#15472](https://github.com/angular/angular/issues/15472)) ([8c4b963](https://github.com/angular/angular/commit/8c4b963))
* **language-service:** be resilient to invalidate ordering ([#15470](https://github.com/angular/angular/issues/15470)) ([a2c2b87](https://github.com/angular/angular/commit/a2c2b87)), closes [#15466](https://github.com/angular/angular/issues/15466)
* **language-service:** correctly determine base members of types ([#15600](https://github.com/angular/angular/issues/15600)) ([0fe4985](https://github.com/angular/angular/commit/0fe4985)), closes [#15460](https://github.com/angular/angular/issues/15460)
* **language-service:** don't require `reflect-metadata` module to be provided ([#15569](https://github.com/angular/angular/issues/15569)) ([bfa4f70](https://github.com/angular/angular/commit/bfa4f70)), closes [#15568](https://github.com/angular/angular/issues/15568)
* **language-service:** guard access to `Symbol.members` ([#15529](https://github.com/angular/angular/issues/15529)) ([bf25e94](https://github.com/angular/angular/commit/bf25e94)), closes [#15528](https://github.com/angular/angular/issues/15528)
* **language-service:** improve performance of `updateModuleAnalysis()` ([#15543](https://github.com/angular/angular/issues/15543)) ([5597fd3](https://github.com/angular/angular/commit/5597fd3))
* **router:** should run CanActivate after CanDeactivate guards ([75478b2](https://github.com/angular/angular/commit/75478b2)), closes [#14059](https://github.com/angular/angular/issues/14059) [#15467](https://github.com/angular/angular/issues/15467)
* **router:** shouldn't execute CanLoad when a route has been loaded ([2360676](https://github.com/angular/angular/commit/2360676)), closes [#14475](https://github.com/angular/angular/issues/14475) [#15438](https://github.com/angular/angular/issues/15438)
### Performance Improvements
* **router:** don't create new serializer every time UrlTree.toString is called ([#15565](https://github.com/angular/angular/issues/15565)) ([fd61145](https://github.com/angular/angular/commit/fd61145))
<a name="4.0.0"></a>
# [4.0.0](https://github.com/angular/angular/compare/4.0.0-rc.6...4.0.0) invisible-makeover (2017-03-23)
### Bug Fixes
* **compiler:** assume queries with no matches as static ([#15429](https://github.com/angular/angular/issues/15429)) ([c8ab5cb](https://github.com/angular/angular/commit/c8ab5cb)), closes [#15417](https://github.com/angular/angular/issues/15417)
* **compiler:** correctly handle when `toString` is exported ([#15430](https://github.com/angular/angular/issues/15430)) ([0dda01e](https://github.com/angular/angular/commit/0dda01e)), closes [#15420](https://github.com/angular/angular/issues/15420)
* **platform-browser:** setAttribute should work with xmlns namespace ([#14874](https://github.com/angular/angular/issues/14874)) ([92084f2](https://github.com/angular/angular/commit/92084f2)), closes [#14865](https://github.com/angular/angular/issues/14865)
* **router:** should pass new data to Observable when query params change ([#15387](https://github.com/angular/angular/issues/15387)) ([08f2f08](https://github.com/angular/angular/commit/08f2f08)), closes [#15290](https://github.com/angular/angular/issues/15290)
* prevent strictNullChecks support until [#15432](https://github.com/angular/angular/issues/15432) is fixed ([#15434](https://github.com/angular/angular/issues/15434)) ([b800a0c](https://github.com/angular/angular/commit/b800a0c))
<a name="4.0.0-rc.6"></a>
# [4.0.0-rc.6](https://github.com/angular/angular/compare/4.0.0-rc.5...4.0.0-rc.6) (2017-03-23)
### Bug Fixes
* **animations:** correct the main entry path in package.json ([#15300](https://github.com/angular/angular/issues/15300)) ([2489e4b](https://github.com/angular/angular/commit/2489e4b))
* **animations:** ensure empty animate() steps work at the end of a sequence ([#15328](https://github.com/angular/angular/issues/15328)) ([fbccd5c](https://github.com/angular/angular/commit/fbccd5c)), closes [#15310](https://github.com/angular/angular/issues/15310)
* **animations:** ensure enter/leave cancellations work ([#15323](https://github.com/angular/angular/issues/15323)) ([9bf2fb4](https://github.com/angular/angular/commit/9bf2fb4)), closes [#15315](https://github.com/angular/angular/issues/15315)
* **animations:** make sure easing values work with web-animations ([#15195](https://github.com/angular/angular/issues/15195)) ([f925910](https://github.com/angular/angular/commit/f925910)), closes [#15115](https://github.com/angular/angular/issues/15115)
* **animations:** make sure non-transitioned leave operations cancel existing animations ([#15254](https://github.com/angular/angular/issues/15254)) ([a6fb78e](https://github.com/angular/angular/commit/a6fb78e)), closes [#15213](https://github.com/angular/angular/issues/15213)
* **animations:** only process element nodes through the animation engine ([#15268](https://github.com/angular/angular/issues/15268)) ([80075af](https://github.com/angular/angular/commit/80075af)), closes [#15267](https://github.com/angular/angular/issues/15267)
* **animations:** only treat view removals as `void` state transitions ([#15245](https://github.com/angular/angular/issues/15245)) ([c66437f](https://github.com/angular/angular/commit/c66437f)), closes [#15223](https://github.com/angular/angular/issues/15223)
* **animations:** stringify boolean values as `1` and `0` ([#15311](https://github.com/angular/angular/issues/15311)) ([94da801](https://github.com/angular/angular/commit/94da801)), closes [#15247](https://github.com/angular/angular/issues/15247)
* **compiler:** add an empty content for source file of non mapped code. ([#15246](https://github.com/angular/angular/issues/15246)) ([8415910](https://github.com/angular/angular/commit/8415910))
* **compiler:** dont call `check` if we dont need to ([#15322](https://github.com/angular/angular/issues/15322)) ([764e90f](https://github.com/angular/angular/commit/764e90f))
* **compiler:** look for flat module resources using declaration module path ([#15367](https://github.com/angular/angular/issues/15367)) ([90d2518](https://github.com/angular/angular/commit/90d2518)), closes [#15221](https://github.com/angular/angular/issues/15221)
* **compiler:** only log template deprecation warning once ([#15364](https://github.com/angular/angular/issues/15364)) ([08d8675](https://github.com/angular/angular/commit/08d8675))
* **compiler:** use attribute id to merge translations ([#15302](https://github.com/angular/angular/issues/15302)) ([1d7693c](https://github.com/angular/angular/commit/1d7693c)), closes [#15234](https://github.com/angular/angular/issues/15234)
* **compiler-cli:** adding missing format xliff for the extractor ([#15386](https://github.com/angular/angular/issues/15386)) ([a50d79d](https://github.com/angular/angular/commit/a50d79d))
* **core:** allow tree shaking of component factories and styles ([#15214](https://github.com/angular/angular/issues/15214)) ([2a0e55f](https://github.com/angular/angular/commit/2a0e55f)), closes [#15181](https://github.com/angular/angular/issues/15181)
* **core:** dont create a comment for components with empty template. ([#15260](https://github.com/angular/angular/issues/15260)) ([f8c075a](https://github.com/angular/angular/commit/f8c075a)), closes [#15143](https://github.com/angular/angular/issues/15143)
* **core:** mark components for check when host events trigger. ([#15359](https://github.com/angular/angular/issues/15359)) ([64beae9](https://github.com/angular/angular/commit/64beae9)), closes [#15352](https://github.com/angular/angular/issues/15352)
* **core:** only apply `WrappedValue` to the binding of the pipe ([#15257](https://github.com/angular/angular/issues/15257)) ([0c43535](https://github.com/angular/angular/commit/0c43535)), closes [#15116](https://github.com/angular/angular/issues/15116)
* **core:** provide `NgModuleRef` in `ViewContainerRef.createComponent`. ([#15350](https://github.com/angular/angular/issues/15350)) ([431eb30](https://github.com/angular/angular/commit/431eb30)), closes [#15241](https://github.com/angular/angular/issues/15241)
* **core:** stringify shouldn't throw when toString returns null/undefined ([#14975](https://github.com/angular/angular/issues/14975)) ([8e6995c](https://github.com/angular/angular/commit/8e6995c)), closes [#14948](https://github.com/angular/angular/issues/14948)
* **core:** trigger host animations for elements that are removed. ([#15251](https://github.com/angular/angular/issues/15251)) ([0d3e314](https://github.com/angular/angular/commit/0d3e314)), closes [#14813](https://github.com/angular/angular/issues/14813) [#15193](https://github.com/angular/angular/issues/15193)
* **core:** update peer dep on zone.js to ^0.8.5 ([#15365](https://github.com/angular/angular/issues/15365)) ([97149f9](https://github.com/angular/angular/commit/97149f9)), closes [#15185](https://github.com/angular/angular/issues/15185)
* **forms:** make composition event buffering configurable ([#15256](https://github.com/angular/angular/issues/15256)) ([5efc860](https://github.com/angular/angular/commit/5efc860)), closes [#15079](https://github.com/angular/angular/issues/15079)
* **platform-server:** interpret Native view encapsulation as Emulated on the server ([#15155](https://github.com/angular/angular/issues/15155)) ([de3d2ee](https://github.com/angular/angular/commit/de3d2ee))
* **platform-server:** setup NoopAnimationsModule in ServerModule by default ([#15131](https://github.com/angular/angular/issues/15131)) ([5c5c2ae](https://github.com/angular/angular/commit/5c5c2ae)), closes [#15098](https://github.com/angular/angular/issues/15098) [#14784](https://github.com/angular/angular/issues/14784)
* **platform-server:** throw a better error message for relative URLs ([#15357](https://github.com/angular/angular/issues/15357)) ([15a082c](https://github.com/angular/angular/commit/15a082c)), closes [#15349](https://github.com/angular/angular/issues/15349)
* **tsc-wrapped:** emit flat module format correctly on Windows ([#15215](https://github.com/angular/angular/issues/15215)) ([6e9264a](https://github.com/angular/angular/commit/6e9264a)), closes [#15192](https://github.com/angular/angular/issues/15192)
* **tsc-wrapped:** use windows friendly path normalization in bundler ([#15374](https://github.com/angular/angular/issues/15374)) ([c584997](https://github.com/angular/angular/commit/c584997)), closes [#15289](https://github.com/angular/angular/issues/15289)
* **upgrade:** component injectors should not link the module injector tree ([#15385](https://github.com/angular/angular/issues/15385)) ([ea49a95](https://github.com/angular/angular/commit/ea49a95))
### Features
* **core:** expose `inputs`, `outputs` and `ngContentSelectors` on `ComponentFactory`. ([#15214](https://github.com/angular/angular/issues/15214)) ([791534f](https://github.com/angular/angular/commit/791534f))
* **router:** add `ParamMap.keys` to get a list of parameters ([d3eda7a](https://github.com/angular/angular/commit/d3eda7a))
* **router:** introduce `ParamMap` to access parameters ([a755b71](https://github.com/angular/angular/commit/a755b71))
* **tsc-wrapped:** record original location of flattened symbols ([#15367](https://github.com/angular/angular/issues/15367)) ([7354949](https://github.com/angular/angular/commit/7354949))
* **upgrade:** use `ComponentFactory.inputs/outputs/ngContentSelectors` ([#15214](https://github.com/angular/angular/issues/15214)) ([9429032](https://github.com/angular/angular/commit/9429032))
<a name="4.0.0-rc.5"></a>
# [4.0.0-rc.5](https://github.com/angular/angular/compare/4.0.0-rc.4...4.0.0-rc.5) (2017-03-17)
### Bug Fixes
* **compiler-cli:** update the tsc-wrapped dependency version ([#15226](https://github.com/angular/angular/issues/15226)) ([7fb4528](https://github.com/angular/angular/commit/7fb4528))
<a name="4.0.0-rc.4"></a>
# [4.0.0-rc.4](https://github.com/angular/angular/compare/4.0.0-rc.3...4.0.0-rc.4) (2017-03-17)
### Bug Fixes
* **animations:** always fire callbacks even for noop animations ([#15170](https://github.com/angular/angular/issues/15170)) ([3f38c6f](https://github.com/angular/angular/commit/3f38c6f))
* **animations:** make sure easing values are applied to an empty animate() step ([#15174](https://github.com/angular/angular/issues/15174)) ([62d5543](https://github.com/angular/angular/commit/62d5543)), closes [#15115](https://github.com/angular/angular/issues/15115)
* **animations:** support multiple state names per state() call ([#15147](https://github.com/angular/angular/issues/15147)) ([36ce0af](https://github.com/angular/angular/commit/36ce0af)), closes [#14732](https://github.com/angular/angular/issues/14732)
* **compiler:** always use `ng://` prefix for sourcemap urls ([#15218](https://github.com/angular/angular/issues/15218)) ([994089d](https://github.com/angular/angular/commit/994089d))
* **compiler:** fix utf8encode, move to sharted utils, add tests ([#15076](https://github.com/angular/angular/issues/15076)) ([959a03a](https://github.com/angular/angular/commit/959a03a))
* **compiler:** generated code should pass `noUnusedLocals` check ([50ab06e](https://github.com/angular/angular/commit/50ab06e)), closes [#14797](https://github.com/angular/angular/issues/14797)
* **compiler:** Improve error message for missing annotations ([#14724](https://github.com/angular/angular/issues/14724)) ([3c15916](https://github.com/angular/angular/commit/3c15916))
* **compiler:** improve error msg for unexpected closing tags ([#14747](https://github.com/angular/angular/issues/14747)) ([5f9fb91](https://github.com/angular/angular/commit/5f9fb91)), closes [#6652](https://github.com/angular/angular/issues/6652)
* **compiler:** make sourcemaps work in AOT mode ([492153a](https://github.com/angular/angular/commit/492153a))
* **compiler:** only warn for `[@Injectable](https://github.com/Injectable)` classes with invalid args. ([5c34066](https://github.com/angular/angular/commit/5c34066)), closes [#15003](https://github.com/angular/angular/issues/15003)
* **compiler:** shouldn't throw when Symbol is used as DI token ([#13701](https://github.com/angular/angular/issues/13701)) ([8b5c6b2](https://github.com/angular/angular/commit/8b5c6b2)), closes [#13314](https://github.com/angular/angular/issues/13314)
* **compiler:** support interface types in injectable constuctors ([#14894](https://github.com/angular/angular/issues/14894)) ([b00fe20](https://github.com/angular/angular/commit/b00fe20)), closes [#12631](https://github.com/angular/angular/issues/12631)
* **compiler:** warning prints "WARNING" instead of "ERROR" ([#15125](https://github.com/angular/angular/issues/15125)) ([3b1956b](https://github.com/angular/angular/commit/3b1956b))
* **core:** dont recreate `TemplateRef` when used as a reference. ([#15066](https://github.com/angular/angular/issues/15066)) ([df914ef](https://github.com/angular/angular/commit/df914ef)), closes [#14873](https://github.com/angular/angular/issues/14873)
* **core:** dont throw if queries change during change detection. ([06fc42b](https://github.com/angular/angular/commit/06fc42b)), closes [#14925](https://github.com/angular/angular/issues/14925)
* **core:** ErrorHandler should not rethrow an error by default ([#15077](https://github.com/angular/angular/issues/15077)) ([#15208](https://github.com/angular/angular/issues/15208)) ([77fd91d](https://github.com/angular/angular/commit/77fd91d)), closes [#14949](https://github.com/angular/angular/issues/14949) [#15182](https://github.com/angular/angular/issues/15182) [#14316](https://github.com/angular/angular/issues/14316)
* **core:** update peer dep on zone.js to ^0.8.4 ([#15209](https://github.com/angular/angular/issues/15209)) ([d2fbbb4](https://github.com/angular/angular/commit/d2fbbb4)), closes [#15180](https://github.com/angular/angular/issues/15180) [#15185](https://github.com/angular/angular/issues/15185)
* **core:** use presence of .subscribe to detect observables rather then Symbol.observable ([#15171](https://github.com/angular/angular/issues/15171)) ([6e98757](https://github.com/angular/angular/commit/6e98757)), closes [#14298](https://github.com/angular/angular/issues/14298) [#14473](https://github.com/angular/angular/issues/14473) [#14926](https://github.com/angular/angular/issues/14926)
* **forms:** ensure observable validators are properly canceled ([#15132](https://github.com/angular/angular/issues/15132)) ([26d4ce2](https://github.com/angular/angular/commit/26d4ce2))
* **forms:** remove equalsTo validator ([#15050](https://github.com/angular/angular/issues/15050)) ([778f7d6](https://github.com/angular/angular/commit/778f7d6))
* element injector vs module injector ([#15044](https://github.com/angular/angular/issues/15044)) ([13686bb](https://github.com/angular/angular/commit/13686bb)), closes [#12869](https://github.com/angular/angular/issues/12869) [#12889](https://github.com/angular/angular/issues/12889) [#13885](https://github.com/angular/angular/issues/13885) [#13870](https://github.com/angular/angular/issues/13870)
* **http:** Make ResponseOptionsArgs an interface ([#14607](https://github.com/angular/angular/issues/14607)) ([#14623](https://github.com/angular/angular/issues/14623)) ([f1b33ab](https://github.com/angular/angular/commit/f1b33ab)), closes [#13708](https://github.com/angular/angular/issues/13708)
* **platform-browser:** prevent clobbered elements from freezing the browser ([a4076c7](https://github.com/angular/angular/commit/a4076c7))
* **platform-server:** correctly implement get href in parse5 adapter ([#15022](https://github.com/angular/angular/issues/15022)) ([80649ea](https://github.com/angular/angular/commit/80649ea))
* **platform-server:** fix an exception when HostListener('window:scroll') is used on the server ([#15019](https://github.com/angular/angular/issues/15019)) ([4f7d62a](https://github.com/angular/angular/commit/4f7d62a))
* correct UMD resolutions for platform-browser_animations ([#15190](https://github.com/angular/angular/issues/15190)) ([923d0c5](https://github.com/angular/angular/commit/923d0c5)), closes [#15114](https://github.com/angular/angular/issues/15114)
* don't instantiate providers with ngOnDestroy eagerly. ([#15070](https://github.com/angular/angular/issues/15070)) ([2c5a671](https://github.com/angular/angular/commit/2c5a671)), closes [#14552](https://github.com/angular/angular/issues/14552)
* fix path locally to empty.js ([#15073](https://github.com/angular/angular/issues/15073)) ([80112a9](https://github.com/angular/angular/commit/80112a9))
* **platform-server:** fix get/set title in parse5 adapter ([#14965](https://github.com/angular/angular/issues/14965)) ([018e5c9](https://github.com/angular/angular/commit/018e5c9))
* **platform-server:** handle styles with extra ':'s correctly ([#15189](https://github.com/angular/angular/issues/15189)) ([013d806](https://github.com/angular/angular/commit/013d806))
* **platform-server:** support svg elements with namespaced attributes ([#15101](https://github.com/angular/angular/issues/15101)) ([f093501](https://github.com/angular/angular/commit/f093501))
* **router:** fix query parameters with multiple values ([#15129](https://github.com/angular/angular/issues/15129)) ([029d0f2](https://github.com/angular/angular/commit/029d0f2)), closes [#14796](https://github.com/angular/angular/issues/14796)
* **tsc-wrapped:** emit js files in all cases ([c0e05e6](https://github.com/angular/angular/commit/c0e05e6))
### Code Refactoring
* **core:** use flags in `Renderer2.setStyle` instead of booleans ([#15045](https://github.com/angular/angular/issues/15045)) ([ff71eff](https://github.com/angular/angular/commit/ff71eff))
### Features
* **common:** support `as` syntax in template/* bindings ([#15025](https://github.com/angular/angular/issues/15025)) ([c10c060](https://github.com/angular/angular/commit/c10c060)), closes [#15020](https://github.com/angular/angular/issues/15020)
* **compiler-cli:** support metadata file aliases ([0ab49d4](https://github.com/angular/angular/commit/0ab49d4))
* **core:** allow to provide multiple default testing modules ([#15054](https://github.com/angular/angular/issues/15054)) ([6c8638c](https://github.com/angular/angular/commit/6c8638c))
* **core:** expose `inputs`, `outputs` and `ngContentSelectors` on `ComponentFactory`. ([1171f91](https://github.com/angular/angular/commit/1171f91))
* **upgrade:** support multi-slot projection in upgrade/static ([#14282](https://github.com/angular/angular/issues/14282)) ([914797a](https://github.com/angular/angular/commit/914797a)), closes [#14261](https://github.com/angular/angular/issues/14261)
* **upgrade:** use `ComponentFactory.inputs/outputs/ngContentSelectors` ([a3e32fb](https://github.com/angular/angular/commit/a3e32fb))
* introduce source maps for templates ([#15011](https://github.com/angular/angular/issues/15011)) ([cdc882b](https://github.com/angular/angular/commit/cdc882b))
### BREAKING CHANGES
* Perviously, any provider that had an ngOnDestroy lifecycle hook would be created eagerly.
Now, only classes that are annotated with @Component, @Directive, @Pipe, @NgModule are eager. Providers only become eager if they are either directly or transitively injected into one of the above.
This also makes all `useValue` providers eager, which
should have no observable impact other than code size.
**EXPECTED IMPACT**:
Making providers eager was an incorrect behavior and never documented.
Also, providers that are used by a directive / pipe / ngModule stay eager.
So the impact should be rather small.
* DebugNode.source no longer returns the source location of a node.
Closes 14013
* core: (since v4 rc.1)
- `Renderer2.setStyle` no longer takes booleans but rather a
bit mask of flags.
<a name="2.4.10"></a>
## [2.4.10](https://github.com/angular/angular/compare/2.4.9...2.4.10) (2017-03-17)
### Bug Fixes
* **compiler:** fix decoding surrogate pairs ([#15154](https://github.com/angular/angular/issues/15154)) ([e5c9bbc](https://github.com/angular/angular/commit/e5c9bbc))
* **router:** do not finish bootstrap until all the routes are resolved ([#15121](https://github.com/angular/angular/issues/15121)) ([34403cd](https://github.com/angular/angular/commit/34403cd))
<a name="4.0.0-rc.3"></a>
# [4.0.0-rc.3](https://github.com/angular/angular/compare/4.0.0-rc.2...4.0.0-rc.3) (2017-03-10)
@ -19,7 +285,6 @@
- rename `RendererTypeV2` to `RendererType2`
- rename `RendererFactoryV2` to `RendererFactory2`
<a name="2.4.9"></a>
## [2.4.9](https://github.com/angular/angular/compare/2.4.8...2.4.9) (2017-03-02)

View File

@ -147,7 +147,7 @@ To ensure consistency throughout the source code, keep these rules in mind as yo
* All public API methods **must be documented**. (Details TBC).
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at
**100 characters**. An automated formatter is available, see
[DEVELOPER.md](DEVELOPER.md#clang-format).
[DEVELOPER.md](docs/DEVELOPER.md#clang-format).
## <a name="commit"></a> Commit Message Guidelines
@ -263,7 +263,7 @@ changes to be accepted, the CLA must be signed. It's a quick process, we promise
[coc]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
[dev-doc]: https://github.com/angular/angular/blob/master/DEVELOPER.md
[dev-doc]: https://github.com/angular/angular/blob/master/docs/DEVELOPER.md
[github]: https://github.com/angular/angular
[gitter]: https://gitter.im/angular/angular
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html

View File

@ -19,6 +19,7 @@
"test": "test.ts",
"tsconfig": "tsconfig.json",
"prefix": "aio",
"serviceWorker": true,
"styles": [
"styles.scss"
],

11
aio/.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
# Ignore node_modules
node_modules
# Ignore npm/yarn debug log
npm-debug.log
yarn-error.log
# Ignore generated content
/dist
/src/content
/.sass-cache

View File

@ -19,8 +19,8 @@ ARG AIO_DOMAIN_NAME=ngbuilds.io
ARG TEST_AIO_DOMAIN_NAME=$AIO_DOMAIN_NAME.localhost
ARG AIO_GITHUB_ORGANIZATION=angular
ARG TEST_AIO_GITHUB_ORGANIZATION=angular
ARG AIO_GITHUB_TEAM_SLUGS=angular-core
ARG TEST_AIO_GITHUB_TEAM_SLUGS=angular-core
ARG AIO_GITHUB_TEAM_SLUGS=angular-core,aio-contributors
ARG TEST_AIO_GITHUB_TEAM_SLUGS=angular-core,aio-contributors
ARG AIO_NGINX_HOSTNAME=$AIO_DOMAIN_NAME
ARG TEST_AIO_NGINX_HOSTNAME=$TEST_AIO_DOMAIN_NAME
ARG AIO_NGINX_PORT_HTTP=80
@ -42,6 +42,7 @@ ENV AIO_BUILDS_DIR=$AIO_BUILDS_DIR TEST_AIO_BUILDS_DIR=$TEST
AIO_GITHUB_TEAM_SLUGS=$AIO_GITHUB_TEAM_SLUGS TEST_AIO_GITHUB_TEAM_SLUGS=$TEST_AIO_GITHUB_TEAM_SLUGS \
AIO_LOCALCERTS_DIR=/etc/ssl/localcerts TEST_AIO_LOCALCERTS_DIR=/etc/ssl/localcerts-test \
AIO_NGINX_HOSTNAME=$AIO_NGINX_HOSTNAME TEST_AIO_NGINX_HOSTNAME=$TEST_AIO_NGINX_HOSTNAME \
AIO_NGINX_LOGS_DIR=/var/log/aio/nginx TEST_AIO_NGINX_LOGS_DIR=/var/log/aio/nginx-test \
AIO_NGINX_PORT_HTTP=$AIO_NGINX_PORT_HTTP TEST_AIO_NGINX_PORT_HTTP=$TEST_AIO_NGINX_PORT_HTTP \
AIO_NGINX_PORT_HTTPS=$AIO_NGINX_PORT_HTTPS TEST_AIO_NGINX_PORT_HTTPS=$TEST_AIO_NGINX_PORT_HTTPS \
AIO_REPO_SLUG=$AIO_REPO_SLUG TEST_AIO_REPO_SLUG=$TEST_AIO_REPO_SLUG \
@ -82,14 +83,15 @@ RUN yarn global add pm2@2
COPY cronjobs/aio-builds-cleanup /etc/cron.d/
RUN chmod 0744 /etc/cron.d/aio-builds-cleanup
RUN crontab /etc/cron.d/aio-builds-cleanup
RUN printenv | grep AIO_ >> /etc/environment
# Set up dnsmasq
COPY dnsmasq/dnsmasq.conf /etc/
RUN sed -i "s|{{\$AIO_NGINX_HOSTNAME}}|$AIO_NGINX_HOSTNAME|" /etc/dnsmasq.conf
RUN sed -i "s|{{\$AIO_UPLOAD_HOSTNAME}}|$AIO_UPLOAD_HOSTNAME|" /etc/dnsmasq.conf
RUN sed -i "s|{{\$TEST_AIO_NGINX_HOSTNAME}}|$TEST_AIO_NGINX_HOSTNAME|" /etc/dnsmasq.conf
RUN sed -i "s|{{\$TEST_AIO_UPLOAD_HOSTNAME}}|$TEST_AIO_UPLOAD_HOSTNAME|" /etc/dnsmasq.conf
RUN sed -i "s|{{\$AIO_NGINX_HOSTNAME}}|$AIO_NGINX_HOSTNAME|g" /etc/dnsmasq.conf
RUN sed -i "s|{{\$AIO_UPLOAD_HOSTNAME}}|$AIO_UPLOAD_HOSTNAME|g" /etc/dnsmasq.conf
RUN sed -i "s|{{\$TEST_AIO_NGINX_HOSTNAME}}|$TEST_AIO_NGINX_HOSTNAME|g" /etc/dnsmasq.conf
RUN sed -i "s|{{\$TEST_AIO_UPLOAD_HOSTNAME}}|$TEST_AIO_UPLOAD_HOSTNAME|g" /etc/dnsmasq.conf
# Set up SSL/TLS certificates
@ -105,25 +107,27 @@ RUN update-ca-certificates
RUN rm /etc/nginx/sites-enabled/*
COPY nginx/aio-builds.conf /etc/nginx/sites-available/aio-builds-prod.conf
RUN sed -i "s|{{\$AIO_BUILDS_DIR}}|$AIO_BUILDS_DIR|" /etc/nginx/sites-available/aio-builds-prod.conf
RUN sed -i "s|{{\$AIO_DOMAIN_NAME}}|$AIO_DOMAIN_NAME|" /etc/nginx/sites-available/aio-builds-prod.conf
RUN sed -i "s|{{\$AIO_LOCALCERTS_DIR}}|$AIO_LOCALCERTS_DIR|" /etc/nginx/sites-available/aio-builds-prod.conf
RUN sed -i "s|{{\$AIO_NGINX_PORT_HTTP}}|$AIO_NGINX_PORT_HTTP|" /etc/nginx/sites-available/aio-builds-prod.conf
RUN sed -i "s|{{\$AIO_NGINX_PORT_HTTPS}}|$AIO_NGINX_PORT_HTTPS|" /etc/nginx/sites-available/aio-builds-prod.conf
RUN sed -i "s|{{\$AIO_UPLOAD_HOSTNAME}}|$AIO_UPLOAD_HOSTNAME|" /etc/nginx/sites-available/aio-builds-prod.conf
RUN sed -i "s|{{\$AIO_UPLOAD_MAX_SIZE}}|$AIO_UPLOAD_MAX_SIZE|" /etc/nginx/sites-available/aio-builds-prod.conf
RUN sed -i "s|{{\$AIO_UPLOAD_PORT}}|$AIO_UPLOAD_PORT|" /etc/nginx/sites-available/aio-builds-prod.conf
RUN sed -i "s|{{\$AIO_BUILDS_DIR}}|$AIO_BUILDS_DIR|g" /etc/nginx/sites-available/aio-builds-prod.conf
RUN sed -i "s|{{\$AIO_DOMAIN_NAME}}|$AIO_DOMAIN_NAME|g" /etc/nginx/sites-available/aio-builds-prod.conf
RUN sed -i "s|{{\$AIO_LOCALCERTS_DIR}}|$AIO_LOCALCERTS_DIR|g" /etc/nginx/sites-available/aio-builds-prod.conf
RUN sed -i "s|{{\$AIO_NGINX_LOGS_DIR}}|$AIO_NGINX_LOGS_DIR|g" /etc/nginx/sites-available/aio-builds-prod.conf
RUN sed -i "s|{{\$AIO_NGINX_PORT_HTTP}}|$AIO_NGINX_PORT_HTTP|g" /etc/nginx/sites-available/aio-builds-prod.conf
RUN sed -i "s|{{\$AIO_NGINX_PORT_HTTPS}}|$AIO_NGINX_PORT_HTTPS|g" /etc/nginx/sites-available/aio-builds-prod.conf
RUN sed -i "s|{{\$AIO_UPLOAD_HOSTNAME}}|$AIO_UPLOAD_HOSTNAME|g" /etc/nginx/sites-available/aio-builds-prod.conf
RUN sed -i "s|{{\$AIO_UPLOAD_MAX_SIZE}}|$AIO_UPLOAD_MAX_SIZE|g" /etc/nginx/sites-available/aio-builds-prod.conf
RUN sed -i "s|{{\$AIO_UPLOAD_PORT}}|$AIO_UPLOAD_PORT|g" /etc/nginx/sites-available/aio-builds-prod.conf
RUN ln -s /etc/nginx/sites-available/aio-builds-prod.conf /etc/nginx/sites-enabled/aio-builds-prod.conf
COPY nginx/aio-builds.conf /etc/nginx/sites-available/aio-builds-test.conf
RUN sed -i "s|{{\$AIO_BUILDS_DIR}}|$TEST_AIO_BUILDS_DIR|" /etc/nginx/sites-available/aio-builds-test.conf
RUN sed -i "s|{{\$AIO_DOMAIN_NAME}}|$TEST_AIO_DOMAIN_NAME|" /etc/nginx/sites-available/aio-builds-test.conf
RUN sed -i "s|{{\$AIO_LOCALCERTS_DIR}}|$TEST_AIO_LOCALCERTS_DIR|" /etc/nginx/sites-available/aio-builds-test.conf
RUN sed -i "s|{{\$AIO_NGINX_PORT_HTTP}}|$TEST_AIO_NGINX_PORT_HTTP|" /etc/nginx/sites-available/aio-builds-test.conf
RUN sed -i "s|{{\$AIO_NGINX_PORT_HTTPS}}|$TEST_AIO_NGINX_PORT_HTTPS|" /etc/nginx/sites-available/aio-builds-test.conf
RUN sed -i "s|{{\$AIO_UPLOAD_HOSTNAME}}|$TEST_AIO_UPLOAD_HOSTNAME|" /etc/nginx/sites-available/aio-builds-test.conf
RUN sed -i "s|{{\$AIO_UPLOAD_MAX_SIZE}}|$TEST_AIO_UPLOAD_MAX_SIZE|" /etc/nginx/sites-available/aio-builds-test.conf
RUN sed -i "s|{{\$AIO_UPLOAD_PORT}}|$TEST_AIO_UPLOAD_PORT|" /etc/nginx/sites-available/aio-builds-test.conf
RUN sed -i "s|{{\$AIO_BUILDS_DIR}}|$TEST_AIO_BUILDS_DIR|g" /etc/nginx/sites-available/aio-builds-test.conf
RUN sed -i "s|{{\$AIO_DOMAIN_NAME}}|$TEST_AIO_DOMAIN_NAME|g" /etc/nginx/sites-available/aio-builds-test.conf
RUN sed -i "s|{{\$AIO_LOCALCERTS_DIR}}|$TEST_AIO_LOCALCERTS_DIR|g" /etc/nginx/sites-available/aio-builds-test.conf
RUN sed -i "s|{{\$AIO_NGINX_LOGS_DIR}}|$TEST_AIO_NGINX_LOGS_DIR|g" /etc/nginx/sites-available/aio-builds-test.conf
RUN sed -i "s|{{\$AIO_NGINX_PORT_HTTP}}|$TEST_AIO_NGINX_PORT_HTTP|g" /etc/nginx/sites-available/aio-builds-test.conf
RUN sed -i "s|{{\$AIO_NGINX_PORT_HTTPS}}|$TEST_AIO_NGINX_PORT_HTTPS|g" /etc/nginx/sites-available/aio-builds-test.conf
RUN sed -i "s|{{\$AIO_UPLOAD_HOSTNAME}}|$TEST_AIO_UPLOAD_HOSTNAME|g" /etc/nginx/sites-available/aio-builds-test.conf
RUN sed -i "s|{{\$AIO_UPLOAD_MAX_SIZE}}|$TEST_AIO_UPLOAD_MAX_SIZE|g" /etc/nginx/sites-available/aio-builds-test.conf
RUN sed -i "s|{{\$AIO_UPLOAD_PORT}}|$TEST_AIO_UPLOAD_PORT|g" /etc/nginx/sites-available/aio-builds-test.conf
RUN ln -s /etc/nginx/sites-available/aio-builds-test.conf /etc/nginx/sites-enabled/aio-builds-test.conf

View File

@ -1,2 +1,2 @@
# Periodically clean up builds that do not correspond to currently open PRs
0 4 * * * root /usr/local/bin/aio-clean-up >> /var/log/cron.log 2>&1
0 12 * * * root /usr/local/bin/aio-clean-up >> /var/log/cron.log 2>&1

View File

@ -1,9 +1,22 @@
# Redirect all HTTP traffic to HTTPS
server {
server_name _;
listen {{$AIO_NGINX_PORT_HTTP}} default_server;
listen [::]:{{$AIO_NGINX_PORT_HTTP}};
access_log {{$AIO_NGINX_LOGS_DIR}}/access.log;
error_log {{$AIO_NGINX_LOGS_DIR}}/error.log;
# Ideally we want 308 (permanent + keep original method),
# but it is relatively new and not supported by some clients (e.g. cURL).
return 307 https://$host:{{$AIO_NGINX_PORT_HTTPS}}$request_uri;
}
# Serve PR-preview requests
server {
server_name "~^pr(?<pr>[1-9][0-9]*)-(?<sha>[0-9a-f]{40})\.";
listen {{$AIO_NGINX_PORT_HTTP}};
listen [::]:{{$AIO_NGINX_PORT_HTTP}};
listen {{$AIO_NGINX_PORT_HTTPS}} ssl;
listen [::]:{{$AIO_NGINX_PORT_HTTPS}} ssl;
@ -14,31 +27,39 @@ server {
disable_symlinks on from=$document_root;
index index.html;
location / {
access_log {{$AIO_NGINX_LOGS_DIR}}/access.log;
error_log {{$AIO_NGINX_LOGS_DIR}}/error.log;
location "~/[^/]+\.[^/]+$" {
try_files $uri $uri/ =404;
}
location / {
try_files $uri $uri/ /index.html =404;
}
}
# Handle all other requests
server {
server_name _;
listen {{$AIO_NGINX_PORT_HTTP}} default_server;
listen [::]:{{$AIO_NGINX_PORT_HTTP}};
listen {{$AIO_NGINX_PORT_HTTPS}} ssl default_server;
listen [::]:{{$AIO_NGINX_PORT_HTTPS}} ssl;
ssl_certificate {{$AIO_LOCALCERTS_DIR}}/{{$AIO_DOMAIN_NAME}}.crt;
ssl_certificate_key {{$AIO_LOCALCERTS_DIR}}/{{$AIO_DOMAIN_NAME}}.key;
access_log {{$AIO_NGINX_LOGS_DIR}}/access.log;
error_log {{$AIO_NGINX_LOGS_DIR}}/error.log;
# Health check
location "~^\/health-check\/?$" {
location "~^/health-check/?$" {
add_header Content-Type text/plain;
return 200 '';
}
# Upload builds
location "~^\/create-build\/(?<pr>[1-9][0-9]*)\/(?<sha>[0-9a-f]{40})\/?$" {
location "~^/create-build/(?<pr>[1-9][0-9]*)/(?<sha>[0-9a-f]{40})/?$" {
if ($request_method != "POST") {
add_header Allow "POST";
return 405;

View File

@ -12,6 +12,8 @@ _main();
// Functions
function _main() {
console.log(`[${new Date()}] - Cleaning up builds...`);
const buildCleaner = new BuildCleaner(AIO_BUILDS_DIR, AIO_REPO_SLUG, AIO_GITHUB_TOKEN);
buildCleaner.cleanUp().catch(err => {

View File

@ -3,16 +3,41 @@ import * as path from 'path';
import {helper as h} from './helper';
// Tests
h.runForAllSupportedSchemes((scheme, port) => describe(`nginx (on ${scheme.toUpperCase()})`, () => {
describe(`nginx`, () => {
beforeEach(() => jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000);
afterEach(() => h.cleanUp());
it('should redirect HTTP to HTTPS', done => {
const httpHost = `${h.nginxHostname}:${h.nginxPortHttp}`;
const httpsHost = `${h.nginxHostname}:${h.nginxPortHttps}`;
const urlMap = {
[`http://${httpHost}/`]: `https://${httpsHost}/`,
[`http://${httpHost}/foo`]: `https://${httpsHost}/foo`,
[`http://foo.${httpHost}/`]: `https://foo.${httpsHost}/`,
};
const verifyRedirection = (httpUrl: string) => h.runCmd(`curl -i ${httpUrl}`).then(result => {
h.verifyResponse(307)(result);
const headers = result.stdout.split(/(?:\r?\n){2,}/)[0];
expect(headers).toContain(`Location: ${urlMap[httpUrl]}`);
});
Promise.
all(Object.keys(urlMap).map(verifyRedirection)).
then(done);
});
h.runForAllSupportedSchemes((scheme, port) => describe(`nginx (on ${scheme.toUpperCase()})`, () => {
const hostname = h.nginxHostname;
const host = `${hostname}:${port}`;
const pr = '9';
const sha9 = '9'.repeat(40);
const sha0 = '0'.repeat(40);
beforeEach(() => jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000);
afterEach(() => h.cleanUp());
describe(`pr<pr>-<sha>.${host}/*`, () => {
@ -24,21 +49,21 @@ h.runForAllSupportedSchemes((scheme, port) => describe(`nginx (on ${scheme.toUpp
it('should return /index.html', done => {
const origin = `${scheme}://pr${pr}-${sha9}.${host}`;
const bodyegex = new RegExp(`^PR: ${pr} | SHA: ${sha9} | File: /index\\.html$`);
const bodyRegex = new RegExp(`^PR: ${pr} | SHA: ${sha9} | File: /index\\.html$`);
Promise.all([
h.runCmd(`curl -iL ${origin}/index.html`).then(h.verifyResponse(200, bodyegex)),
h.runCmd(`curl -iL ${origin}/`).then(h.verifyResponse(200, bodyegex)),
h.runCmd(`curl -iL ${origin}`).then(h.verifyResponse(200, bodyegex)),
h.runCmd(`curl -iL ${origin}/index.html`).then(h.verifyResponse(200, bodyRegex)),
h.runCmd(`curl -iL ${origin}/`).then(h.verifyResponse(200, bodyRegex)),
h.runCmd(`curl -iL ${origin}`).then(h.verifyResponse(200, bodyRegex)),
]).then(done);
});
it('should return /foo/bar.js', done => {
const bodyegex = new RegExp(`^PR: ${pr} | SHA: ${sha9} | File: /foo/bar\\.js$`);
const bodyRegex = new RegExp(`^PR: ${pr} | SHA: ${sha9} | File: /foo/bar\\.js$`);
h.runCmd(`curl -iL ${scheme}://pr${pr}-${sha9}.${host}/foo/bar.js`).
then(h.verifyResponse(200, bodyegex)).
then(h.verifyResponse(200, bodyRegex)).
then(done);
});
@ -51,13 +76,23 @@ h.runForAllSupportedSchemes((scheme, port) => describe(`nginx (on ${scheme.toUpp
});
it('should respond with 404 for unknown paths', done => {
it('should respond with 404 for unknown paths to files', done => {
h.runCmd(`curl -iL ${scheme}://pr${pr}-${sha9}.${host}/foo/baz.css`).
then(h.verifyResponse(404)).
then(done);
});
it('should rewrite to \'index.html\' for unknown paths that don\'t look like files', done => {
const bodyRegex = new RegExp(`^PR: ${pr} | SHA: ${sha9} | File: /index\\.html$`);
Promise.all([
h.runCmd(`curl -iL ${scheme}://pr${pr}-${sha9}.${host}/foo/baz`).then(h.verifyResponse(200, bodyRegex)),
h.runCmd(`curl -iL ${scheme}://pr${pr}-${sha9}.${host}/foo/baz/`).then(h.verifyResponse(200, bodyRegex)),
]).then(done);
});
it('should respond with 404 for unknown PRs/SHAs', done => {
const otherPr = 54321;
const otherSha = '8'.repeat(40);
@ -92,12 +127,14 @@ h.runForAllSupportedSchemes((scheme, port) => describe(`nginx (on ${scheme.toUpp
});
it('should accept SHAs with leading zeros (but not ignore them)', done => {
const bodyegex = new RegExp(`^PR: ${pr} | SHA: ${sha0} | File: /index\\.html$`);
it('should accept SHAs with leading zeros (but not trim the zeros)', done => {
const bodyRegex9 = new RegExp(`^PR: ${pr} | SHA: ${sha9} | File: /index\\.html$`);
const bodyRegex0 = new RegExp(`^PR: ${pr} | SHA: ${sha0} | File: /index\\.html$`);
Promise.all([
h.runCmd(`curl -iL ${scheme}://pr${pr}-0${sha9}.${host}`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://pr${pr}-${sha0}.${host}`).then(h.verifyResponse(200, bodyegex)),
h.runCmd(`curl -iL ${scheme}://pr${pr}-${sha9}.${host}`).then(h.verifyResponse(200, bodyRegex9)),
h.runCmd(`curl -iL ${scheme}://pr${pr}-${sha0}.${host}`).then(h.verifyResponse(200, bodyRegex0)),
]).then(done);
});
@ -194,7 +231,7 @@ h.runForAllSupportedSchemes((scheme, port) => describe(`nginx (on ${scheme.toUpp
});
it('should accept SHAs with leading zeros (but not ignore them)', done => {
it('should accept SHAs with leading zeros (but not trim the zeros)', done => {
const cmdPrefix = `curl -iLX POST ${scheme}://${host}/create-build/${pr}`;
const bodyRegex = /Missing or empty 'AUTHORIZATION' header/;
@ -229,4 +266,6 @@ h.runForAllSupportedSchemes((scheme, port) => describe(`nginx (on ${scheme.toUpp
});
}));
}));
});

View File

@ -84,9 +84,10 @@ describe('upload-server (on HTTP)', () => {
});
it('should accept SHAs with leading zeros (but not ignore them)', done => {
it('should accept SHAs with leading zeros (but not trim the zeros)', done => {
Promise.all([
h.runCmd(`${curl} http://${host}/create-build/${pr}/0${sha9}`).then(h.verifyResponse(404)),
h.runCmd(`${curl} http://${host}/create-build/${pr}/${sha9}`).then(h.verifyResponse(500)),
h.runCmd(`${curl} http://${host}/create-build/${pr}/${sha0}`).then(h.verifyResponse(500)),
]).then(done);
});

View File

@ -65,8 +65,12 @@ describe('BuildVerifier', () => {
});
it('should return a promise', () => {
expect(bv.verify(pr, createAuthHeader())).toEqual(jasmine.any(Promise));
it('should return a promise', done => {
const promise = bv.verify(pr, createAuthHeader());
promise.then(done); // Do not complete the test (and release the spies) synchronously
// to avoid running the actual `bvGetPrAuthorTeamMembership()`.
expect(promise).toEqual(jasmine.any(Promise));
});
@ -194,8 +198,12 @@ describe('BuildVerifier', () => {
});
it('should return a promise', () => {
expect(bv.getPrAuthorTeamMembership(pr)).toEqual(jasmine.any(Promise));
it('should return a promise', done => {
const promise = bv.getPrAuthorTeamMembership(pr);
promise.then(done); // Do not complete the test (and release the spies) synchronously
// to avoid running the actual `GithubTeams#isMemberBySlug()`.
expect(promise).toEqual(jasmine.any(Promise));
});

View File

@ -323,18 +323,16 @@ describe('uploadServerFactory', () => {
});
it('should accept SHAs with leading zeros (but not ignore them)', done => {
const sha41 = '0'.repeat(41);
it('should accept SHAs with leading zeros (but not trim the zeros)', done => {
const sha40 = '0'.repeat(40);
const sha41 = `0${sha40}`;
const request41 = agent.get(`/create-build/${pr}/${sha41}`);
const request40 = agent.get(`/create-build/${pr}/${sha40}`).
set('AUTHORIZATION', 'foo').
set('X-FILE', 'bar');
const request40 = agent.get(`/create-build/${pr}/${sha40}`).set('AUTHORIZATION', 'foo').set('X-FILE', 'bar');
const request41 = agent.get(`/create-build/${pr}/${sha41}`).set('AUTHORIZATION', 'baz').set('X-FILE', 'qux');
Promise.all([
promisifyRequest(request41.expect(404)),
promisifyRequest(request40.expect(201)),
promisifyRequest(request41.expect(404)),
]).then(done, done.fail);
});

View File

@ -1,4 +1,8 @@
#!/bin/bash
set -e -o pipefail
# Set up env variables
export AIO_GITHUB_TOKEN=$(head -c -1 /aio-secrets/GITHUB_TOKEN 2>/dev/null)
# Run the clean-up
node $AIO_SCRIPTS_JS_DIR/dist/lib/clean-up >> /var/log/aio/clean-up.log 2>&1

View File

@ -6,6 +6,9 @@ exec 2>&1
# Start the services
echo [`date`] - Starting services...
mkdir -p $AIO_NGINX_LOGS_DIR
mkdir -p $TEST_AIO_NGINX_LOGS_DIR
service rsyslog start
service cron start
service dnsmasq start

View File

@ -1,31 +0,0 @@
# VM Setup Instructions
- Set up secrets (access tokens, passwords, etc)
- Set up docker
- Attach persistent disk
- Build docker image (+ checkout repo)
- Run image (+ setup for run on boot)
## Build image
- `<aio-builds-setup-dir>/build.sh [<name>[:<tag>] [--build-arg <NAME>=<value> ...]]`
## Run image
- `sudo docker run \
-d \
--dns 127.0.0.1 \
--name <instance-name> \
-p 80:80 \
-p 443:443 \
--restart unless-stopped \
[-v <host-cert-dir>:/etc/ssl/localcerts:ro] \
-v <host-secrets-dir>:/aio-secrets:ro \
-v <host-builds-dir>:/var/www/aio-builds \
<name>[:<tag>]
`
## Questions
- Do we care to keep logs (e.g. cron, nginx, aio-upload-server, aio-clean-up, pm2) outside of the container?
- Instead of creating new comments for each commit, update the original comment?

View File

@ -0,0 +1,28 @@
# VM Setup Instructions
## Overview
- [General overview](overview--general.md)
- [Security model](overview--security-model.md)
- [Available Commands](overview--scripts-and-commands.md)
## Setting up the VM
- [Set up secrets](vm-setup--set-up-secrets.md)
- [Set up docker](vm-setup--set-up-docker.md)
- [Attach persistent disk](vm-setup--attach-persistent-disk.md)
- [Create host directories and files](vm-setup--create-host-dirs-and-files.md)
- [Create docker image](vm-setup--create-docker-image.md)
## Configuring the docker image
- [Available environment variables](image-config--environment-variables.md)
## Starting the docker container
- [Create docker image](vm-setup--start-docker-container.md)
## Miscellaneous
- [Debug docker container](misc--debug-docker-container.md)
- [Integrate with CI](misc--integrate-with-ci.md)

View File

@ -0,0 +1,52 @@
# Image config - Environment variables
Below is a list of environment variables that can be configured when creating the docker image (as
described [here](vm-setup--create-docker-image.md)). An up-to-date list of the configurable
environment variables and their default values can be found in the
[Dockerfile](../dockerbuild/Dockerfile).
**Note:**
Each variable has a `TEST_` prefixed counterpart, which is used for testing purposes. In most cases
you don't need to specify values for those.
- `AIO_BUILDS_DIR`:
The directory (inside the container) where the uploaded build artifacts are kept.
- `AIO_DOMAIN_NAME`:
The domain name of the server.
- `AIO_GITHUB_ORGANIZATION`:
The GitHub organization whose teams arew whitelisted for accepting uploads.
See also `AIO_GITHUB_TEAM_SLUGS`.
- `AIO_GITHUB_TEAM_SLUGS`:
A comma-separated list of teams, whose authors are allowed to upload PRs.
See also `AIO_GITHUB_ORGANIZATION`.
- `AIO_NGINX_HOSTNAME`:
The internal hostname for accessing the nginx server. This is mostly used for performing a
periodic health-check.
- `AIO_NGINX_PORT_HTTP`:
The port number on which nginx listens for HTTP connections. This should be mapped to the
corresponding port on the host VM (as described [here](vm-setup--start-docker-container.md)).
- `AIO_NGINX_PORT_HTTPS`:
The port number on which nginx listens for HTTPS connections. This should be mapped to the
corresponding port on the host VM (as described [here](vm-setup--start-docker-container.md)).
- `AIO_REPO_SLUG`:
The repository slug (in the form `<user>/<repo>`) for which PRs will be uploaded.
- `AIO_UPLOAD_HOSTNAME`:
The internal hostname for accessing the Node.js upload-server. This is used by nginx for
delegating upload requests and also for performing a periodic health-check.
- `AIO_UPLOAD_MAX_SIZE`:
The maximum allowed size for the uploaded gzip archive containing the build artifacts. Files
larger than this will be rejected.
- `AIO_UPLOAD_PORT`:
The port number on which the Node.js upload-server listens for HTTP connections. This is used by
nginx for delegating upload requests and also for performing a periodic health-check.

View File

@ -0,0 +1,12 @@
# Miscellaneous - Debug docker container
TODO (gkalpak): Add docs. Mention:
- `aio-health-check`
- `aio-verify-setup`
- Test nginx accessible at:
- `http://$TEST_AIO_NGINX_HOTNAME:$TEST_AIO_NGINX_PORT_HTTP`
- `https://$TEST_AIO_NGINX_HOTNAME:$TEST_AIO_NGINX_PORT_HTTPS`
- Test upload-server accessible at:
- `http://$TEST_AIO_UPLOAD_HOTNAME:$TEST_AIO_UPLOAD_PORT`
- Local DNS (via dnsmasq) maps the above hostnames to 127.0.0.1

View File

@ -0,0 +1,12 @@
# Miscellaneous - Integrate with CI
TODO (gkalpak): Add docs. Mention:
- Travis' JWT addon (+ limitations).
Relevant files: `.travis.yml`
- Testing on CI.
Relevant files: `ci/test-aio.sh`, `aio/aio-builds-setup/scripts/test.sh`
- Preverifying on CI.
Relevant files: `ci/deploy.sh`, `aio/aio-builds-setup/scripts/travis-preverify-pr.sh`
- Deploying from CI.
Relevant files: `ci/deploy.sh`, `aio/scripts/deploy-preview.sh`

View File

@ -0,0 +1,84 @@
# Overview - General
## Objective
Whenever a PR job is run on Travis, we want to build `angular.io` and upload the build artifacts to
a publicly accessible server so that collaborators (developers, designers, authors, etc) can preview
the changes without having to checkout and build the app locally.
## Source code
In order to make it easier to administer the server and version-control the setup, we are using
[docker](https://www.docker.com) to run a container on a VM. The Dockerfile and all other files
necessary for creating the docker container are stored (and versioned) along with the angular.io
project's source code (currently part of the angular/angular repo) in the `aio-builds-setup/`
directory.
## Setup
The VM is hosted on [Google Compute Engine](https://cloud.google.com/compute/). The host OS is
debian:jessie. For more info how to set up the host VM take a look at the "Setting up the VM"
section in [TOC](_TOC.md).
## Security model
Since we are managing a public server, it is important to take appropriate measures in order to
prevent abuse. For more details on the challenges and the chosen approach take a look at the
[security model](overview--security-model.md).
## The 10000 feet view
This section gives a brief summary of the several operations performed on CI and by the docker
container:
### On CI (Travis)
- Build job completes successfully (i.e. build succeeds and tests pass).
- The CI script checks whether the build job was initiated by a PR against the angular/angular
master branch.
- The CI script checks whether the PR has touched any files inside the angular.io project directory
(currently `aio/`).
- The CI script checks whether the author of the PR is a member of one of the whitelisted GitHub
teams (and therefore allowed to upload).
**Note:**
For security reasons, the same checks will be performed on the server as well. This is an optional
step with the purpose of:
1. Avoiding the wasted overhead associated with uploads that are going to be rejected (e.g.
building the artifacts, sending them to the server, running checks on the server, etc).
2. Avoiding failing the build (due to an error response from the server) or requiring additional
logic for detecting the reasons of the failure.
- The CI script gzip and upload the build artifacts to the server.
More info on how to set things up on CI can be found [here](misc--integrate-with-ci.md).
### Uploading build artifacts
- nginx receives upload request.
- nginx checks that the uploaded gzip archive does not exceed the specified max file size, stores it
in a temporary location and passes the filepath to the Node.js upload-server.
- The upload-server verifies that the uploaded file is not trying to overwrite an existing build,
and runs several checks to determine whether the request should be accepted (more details can be
found [here](overview--security-model.md)).
- The upload-server deploys the artifacts to a sub-directory named after the PR number and SHA:
`<PR>/<SHA>/`
- The upload-server posts a comment on the corresponding PR on GitHub mentioning the SHA and the
the link where the preview can be found.
### Serving build artifacts
- nginx receives a request for an uploaded resource on a subdomain corresponding to the PR and SHA.
E.g.: `pr<PR>-<SHA>.ngbuilds.io/path/to/resurce`
- nginx maps the subdomain to the correct sub-direcory and serves the resource.
E.g.: `/<PR>/<SHA>/path/to/resource`
### Removing obsolete artifacts
In order to avoid flooding the disk with unnecessary build artifacts, there is a cronjob that runs a
clean-up tasks once a day. The task retrieves all open PRs from GitHub and removes all directories
that do not correspond with an open PR.
### Health-check
The docker service runs a periodic health-check that verifies the running conditions of the
container. This includes verifying the status of specific system services, the responsiveness of
nginx and the upload-server and internet connectivity.

View File

@ -0,0 +1,55 @@
# Overview - Scripts and Commands
This is an overview of the available scripts and commands.
## Scripts
The scripts are located inside `<aio-builds-setup-dir>/scripts/`. The following scripts are
available:
- `build.sh`:
Can be used for creating a preconfigured docker image.
See [here](vm-setup--create-docker-image.md) for more info.
- `test.sh`
Can be used for running the tests for `<aio-builds-setup-dir>/dockerbuild/scripts-js/`. This is
useful for CI integration. See [here](misc--integrate-with-ci.md) for more info.
- `travis-preverify-pr.sh`
Can be used for "preverifying" a PR before uploading the artifacts to the server. It checks that
the author of the PR a member of one of the specified GitHub teams and therefore allowed to upload
build artifacts. This is useful for CI integration. See [here](misc--integrate-with-ci.md) for
more info.
## Commands
The following commands are available globally from inside the docker container. They are either used
by the container to perform its various operations or can be used ad-hoc, mainly for testing
purposes. Each command is backed by a corresponding script inside
`<aio-builds-setup-dir>/dockerbuild/scripts-sh/`.
- `aio-clean-up`:
Cleans up the builds directory by removing the artifacts that do not correspond to an open PR.
_It is run as a daily cronjob._
- `aio-health-check`:
Runs a basic health-check, verifying that the necessary services are running, the servers are
responding and there is a working internet connection.
_It is used periodically by docker for determining the container's health status._
- `aio-init`:
Initializes the container (mainly by starting the necessary services).
_It is run (by default) when starting the container._
- `aio-upload-server-prod`:
Spins up a Node.js upload-server instance.
_It is used in `aio-init` (see above) during initialization._
- `aio-upload-server-test`:
Spins up a Node.js upload-server instance for tests.
_It is used in `aio-verify-setup` (see below) for running tests._
- `aio-verify-setup`:
Runs a suite of e2e-like tests, mainly verifying the correct (inter)operation of nginx and the
Node.js upload-server.

View File

@ -0,0 +1,116 @@
# Overview - Security model
Whenever a PR job is run on Travis, we want to build `angular.io` and upload the build artifacts to
a publicly accessible server so that collaborators (developers, designers, authors, etc) can preview
the changes without having to checkout and build the app locally.
This document discusses the security considerations associated with uploading build artifacts as
part of the CI setup and serving them publicly.
## Security objectives
- **Prevent uploading arbitrary content to our servers.**
Since there is no restriction on who can submit a PR, we cannot allow any PR's build artifacts to
be uploaded.
- **Prevent overwriting other peoples uploaded content.**
There needs to be a mechanism in place to ensure that the uploaded content does indeed correspond
to the PR indicated by its URL.
- **Prevent arbitrary access on the server.**
Since the PR author has full access over the build artifacts that would be uploaded, we must
ensure that the uploaded files will not enable arbitrary access to the server or expose sensitive
info.
## Issues / Caveats
- Because the PR author can change the scripts run on CI, any security mechanisms must be immune to
such changes.
- For security reasons, encrypted Travis variables are not available to PRs, so we can't rely on
them to implement security.
## Implemented approach
### In a nutshell
The implemented approach can be broken up to the following sub-tasks:
1. Verify which PR the uploaded artifacts correspond to.
2. Determine the author of the PR.
3. Check whether the PR author is a member of some whitelisted GitHub team.
4. Deploy the artifacts to the corresponding PR's directory.
5. Prevent overwriting previously deployed artifacts (which ensures that the guarantees established
during deployment will remain valid until the artifacts are removed).
6. Prevent uploaded files from accessing anything outside their directory.
### Implementation details
This section describes how each of the aforementioned sub-tasks is accomplished:
1. **Verify which PR the uploaded artifacts correspond to.**
We are taking advantage of Travis' [JWT addon](https://docs.travis-ci.com/user/jwt). By sharing
a secret between Travis (which keeps it private but uses it to sign a JWT) and the server (which
uses it to verify the authenticity of the JWT), we can accomplish the following:
a. Verify that the upload request comes from Travis.
b. Determine the PR that these artifacts correspond to (since Travis puts that information into
the JWT, without the PR author being able to modify it).
_Note:_
_There are currently certain limitation in the implementation of the JWT addon._
_See the next section for more details._
2. **Determine the author of the PR.**
Once we have securely associated the uploaded artifaacts to a PR, we retrieve the PR's metadata -
including the author's username - using the [GitHub API](https://developer.github.com/v3/).
To avoid rate-limit restrictions, we use a Personal Access Token (issued by
[@mary-poppins](https://github.com/mary-poppins)).
3. **Check whether the PR author is a member of some whitelisted GitHub team.**
Again using the GitHub API, we can verify the author's membership in one of the
whitelisted/trusted GitHub teams. For this operation, we need a PErsonal Access Token with the
`read:org` scope issued by a user that can "see" the specified GitHub organization.
Here too, we use token by @mary-poppins.
4. **Deploy the artifacts to the corresponding PR's directory.**
With the preceeding steps, we have verified that the uploaded artifacts have been uploaded by
Travis and correspond to a PR whose author is a member of a trusted team. Essentially, as long as
sub-tasks 1, 2 and 3 can be securely accomplished, it is possible to "project" the trust we have
in a team's members through the PR and Travis to the build artifacts.
5. **Prevent overwriting previously deployed artifacts**.
In order to enforce this restriction (and ensure that the deployed artifacts validity is
preserved throughout their "lifetime"), the server that handles the upload (currently a Node.js
Express server) rejects uploads that target an existing directory.
_Note: A PR can contain multiple uploads; one for each SHA that was built on Travis._
6. **Prevent uploaded files from accessing anything outside their directory.**
Nginx (which is used to serve the uploaded artifacts) has been configured to not follow symlinks
outside of the directory where the build artifacts are stored.
## Assumptions / Things to keep in mind
- Each trusted PR author has full control over the content that is uploaded for their PRs. Part of
the security model relies on the trustworthiness of these authors.
- If anyone gets access to the `PREVIEW_DEPLOYMENT_TOKEN` (a.k.a. `NGBUILDS_IO_KEY` on
angular/angular) variable generated for each Travis job, they will be able to impersonate the
corresponding PR's author on the preview server for as long as the token is valid (currently 90
mins). Because of this, the value of the `PREVIEW_DEPLOYMENT_TOKEN` should not be made publicly
accessible (e.g. by printing it on the Travis job log).
- Travis does only allow specific whitelisted property names to be used with the JWT addon. The only
known such property at the time is `SAUCE_ACCESS_KEY` (used for integration with SauceLabs). In
order to be able to actually use the JWT addon we had to name the encrypted variable
`SAUCE_ACCESS_KEY` (which we later re-assign to `NGBUILDS_IO_KEY`).

View File

@ -13,5 +13,8 @@
## Mount disk on boot
- ``echo UUID=`sudo blkid -s UUID -o value /dev/disk/by-id/google-aio-builds` \
/mnt/disks/aio-builds ext4 discard,defaults,nofail 0 2 | sudo tee -a /etc/fstab``
- Run:
```
echo UUID=`sudo blkid -s UUID -o value /dev/disk/by-id/google-aio-builds` \
/mnt/disks/aio-builds ext4 discard,defaults,nofail 0 2 | sudo tee -a /etc/fstab
```

View File

@ -0,0 +1,32 @@
# VM setup - Create docker image
## Checkout repository
- `git clone <repo-url>`
## Build docker image
- `<aio-builds-setup-dir>/scripts/build.sh [<name>[:<tag>] [--build-arg <NAME>=<value> ...]]`
- You can overwrite the default environment variables inside the image, by passing new values using
`--build-arg`.
**Note:** The build script has to execute docker commands with `sudo`.
## Example
The following commands would create a docker image from GitHub repo `foo/bar` to be deployed on the
`foobar-builds.io` domain and accepting PR deployments from authors that are members of the
`bar-core` and `bar-docs-authors` teams of organization `foo`:
- `git clone https://github.com/foo/bar.git foobar`
- Run:
```
./foobar/aio-builds-setup/scripts/build.sh foobar-builds \
--build-arg AIO_REPO_SLUG=foo/bar \
--build-arg AIO_DOMAIN_NAME=foobar-builds.io \
--build-arg AIO_GITHUB_ORGANIZATION=foo \
--build-arg AIO_GITHUB_TEMA_SLUGS=bar-core,bar-docs-authors
```
A full list of the available environment variables can be found
[here](image-config--environment-variables.md).

View File

@ -0,0 +1,74 @@
# VM setup - Create host directories and files
## Create directory with secrets
For security reasons, sensitive info (such as tokens and passwords) are not hardcoded into the
docker image, nor passed as environment variables at runtime. They are passed to the docker
container from the host VM as files inside a directory. Each file's name is the name of the variable
and the file content is the value. These are read from inside the running container when necessary.
More info on how to create `secrets` directory and files can be found
[here](vm-setup--set-up-secrets.md).
## Create directory for build artifacts
The uploaded build artifacts should be kept on a directory outside the docker container, so it is
easier to replace the container without losing the uploaded builds. For portability across VMs a
persistent disk can be used (as described [here](vm-setup--attach-persistent-disk.md)).
**Note:** The directories created inside that directory will be owned by user `www-data`.
## Create SSL certificates (Optional for dev)
The host VM can attach a directory containing the SSL certificate and key to be used by the nginx
server for serving the uploaded build artifacts. More info on how to attach the directory when
starting the container can be found [here](vm-setup--start-docker-container.md).
In order for the container to be able to find the certificate and key, they should be named
`<DOMAIN_NAME>.crt` and `<DOMAIN_NAME>.key` respectively. For example, for a domain name
`ngbuild.io`, nginx will look for files `ngbuilds.io.crt` and `ngbuilds.io.key`. More info on how to
specify the domain name see [here](vm-setup--create-docker-image.md).
If no directory is attached, nginx will use an internal self-signed certificate. This is convenient
during development, but is not suitable for production.
**Note:**
Since nginx needs to be able to serve requests for both the main domain as well as any subdomain
(e.g. `ngbuilds.io/` and `foo-bar.ngbuilds.io/`), the provided certificate needs to be a wildcard
certificate covering both the domain and subdomains.
## Create directory for logs (Optional)
Optionally, a logs directory can pe passed to the docker container for storing non-system-related
logs. If not provided, the logs are kept locally on the container and will be lost whenever the
container is replaced (e.g. when updating to use a newer version of the docker image).
The following files log files are kept in this directory:
- `clean-up.log`:
Output of the `aio-clean-up` command, run as a cronjob for cleaning up the build artifacts of
closed PRs.
- `init.log`:
Output of the `aio-init` command, run (by default) when starting the container.
- `nginx/{access,error}.log`:
The access and error logs produced by the nginx server while serving "production" files.
- `nginx-test/{access,error}.log`:
The access and error logs produced by the nginx server while serving "test" files. This is only
used when running tests locally from inside the container, e.g. with the `aio-verify-setup`
command. (See [here](overview--scripts-and-commands.md) for more info.)
- `upload-server-{prod,test,verify-setup}-*.log`:
The logs produced by the Node.js upload-server while serving either:
- `-prod`: "Production" files (g.g during normal operation).
- `-test`: "Test" files (e.g. when a test instance is started with the `aio-upload-server-test`
command).
- `-verify-setup`: "Test" files, but while running `aio-verify-setup`.
(See [here](overview--scripts-and-commands.md) for more info the commands mentioned above.)
- `verify-setup.log`:
The output of the `aio-verify-setup` command (e.g. Jasmine output), except for upload-server
output which is logged to `upload-server-verify-setup-*.log` (see above).

View File

@ -0,0 +1,92 @@
# VM setup - Start docker container
## The `docker run` command
Once everything has been setup and configured, a docker container can be started with the following
command:
```
sudo docker run \
-d \
--dns 127.0.0.1 \
--name <instance-name> \
-p 80:80 \
-p 443:443 \
--restart unless-stopped \
[-v <host-cert-dir>:/etc/ssl/localcerts:ro] \
-v <host-secrets-dir>:/aio-secrets:ro \
-v <host-builds-dir>:/var/www/aio-builds \
[-v <host-logs-dir>:/var/log/aio] \
<name>[:<tag>]
```
Below is the same command with inline comments explaining each option. The aPI docs for `docker run`
can be found [here](https://docs.docker.com/engine/reference/run/).
```
sudo docker run \
# Start as a daemon.
-d \
# Use the local DNS server.
# (This is necessary for mapping internal URLs, e.g. for the Node.js upload-server.)
--dns 127.0.0.1 \
# USe `<instance-name>` as an alias for the container.
# Useful for running `docker` commands, e.g.: `docker stop <instance-name>`
--name <instance-name> \
# Map ports of the hosr VM (left) to ports of the docker container (right)
-p 80:80 \
-p 443:443 \
# Automatically restart the container (unless it was explicitly stopped by the user).
# (This ensures that the container will be automatically started on boot.)
--restart unless-stopped \
# The directory the contains the SSL certificates.
# (See [here](vm-setup--create-host-dirs-and-files.md) for more info.)
# If not provided, the container will use self-signed certificates.
[-v <host-cert-dir>:/etc/ssl/localcerts:ro] \
# The directory the contains the secrets (e.g. GitHub token, JWT secret, etc).
# (See [here](vm-setup--set-up-secrets.md) for more info.)
-v <host-secrets-dir>:/aio-secrets:ro \
# The uploaded build artifacts will stored to and served from this directory.
# (If you are using a persistent disk - as described [here](vm-setup--attach-persistent-disk.md) -
# this will be a directory inside the disk.)
-v <host-builds-dir>:/var/www/aio-builds \
# The directory where the logs are being kept.
# (See [here](vm-setup--create-host-dirs-and-files.md) for more info.)
# If not provided, the logs will be kept inside the container, which means they will be lost
# whenever a new container is created.
[-v <host-logs-dir>:/var/log/aio] \
# The name of the docker image to use (and an optional tag; defaults to `latest`).
# (See [here](vm-setup--create-docker-image.md) for instructions on how to create the iamge.)
<name>[:<tag>]
```
## Example
The following command would start a docker container based on the previously created `foobar-builds`
docker image, alias it as 'foobar-builds-1' and map predefined directories on the host VM to be used
by the container for accesing secrets and SSL certificates and keeping the build artifacts and logs.
```
sudo docker run \
-d \
--dns 127.0.0.1 \
--name foobar-builds-1 \
-p 80:80 \
-p 443:443 \
--restart unless-stopped \
-v /etc/ssl/localcerts:/etc/ssl/localcerts:ro \
-v /foobar-secrets:/aio-secrets:ro \
-v /mnt/disks/foobar-builds:/var/www/aio-builds \
-v /foobar-logs:/var/log/aio \
foobar-builds
```

View File

@ -6,7 +6,7 @@ source "`dirname $0`/env.sh"
# Preverify PR
AIO_GITHUB_ORGANIZATION="angular" \
AIO_GITHUB_TEAM_SLUGS="angular-core" \
AIO_GITHUB_TEAM_SLUGS="angular-core,aio-contributors" \
AIO_GITHUB_TOKEN=$(echo ${GITHUB_TEAM_MEMBERSHIP_CHECK_KEY} | rev) \
AIO_REPO_SLUG=$TRAVIS_REPO_SLUG \
AIO_PREVERIFY_PR=$TRAVIS_PULL_REQUEST \

View File

@ -1,18 +0,0 @@
@cheatsheetSection
Bootstrapping
@cheatsheetIndex 0
@description
{@target ts}`import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';`{@endtarget}
{@target js}Available from the `ng.platformBrowserDynamic` namespace{@endtarget}
@cheatsheetItem
syntax(ts):
`platformBrowserDynamic().bootstrapModule(AppModule);`|`platformBrowserDynamic().bootstrapModule`
syntax(js):
`document.addEventListener('DOMContentLoaded', function() {
ng.platformBrowserDynamic
.platformBrowserDynamic()
.bootstrapModule(app.AppModule);
});`|`platformBrowserDynamic().bootstrapModule`
description:
Bootstraps the app, using the root component from the specified `NgModule`. {@target js}Must be wrapped in the event listener to fire when the page loads.{@endtarget}

View File

@ -1,34 +0,0 @@
@cheatsheetSection
Built-in directives
@cheatsheetIndex 3
@description
{@target ts}`import { CommonModule } from '@angular/common';`{@endtarget}
{@target js}Available using the `ng.common.CommonModule` module{@endtarget}
@cheatsheetItem
syntax:
`<section *ngIf="showSection">`|`*ngIf`
description:
Removes or recreates a portion of the DOM tree based on the `showSection` expression.
@cheatsheetItem
syntax:
`<li *ngFor="let item of list">`|`*ngFor`
description:
Turns the li element and its contents into a template, and uses that to instantiate a view for each item in list.
@cheatsheetItem
syntax:
`<div [ngSwitch]="conditionExpression">
<ng-template [ngSwitchCase]="case1Exp">...</ng-template>
<ng-template ngSwitchCase="case2LiteralString">...</ng-template>
<ng-template ngSwitchDefault>...</ng-template>
</div>`|`[ngSwitch]`|`[ngSwitchCase]`|`ngSwitchCase`|`ngSwitchDefault`
description:
Conditionally swaps the contents of the div by selecting one of the embedded templates based on the current value of `conditionExpression`.
@cheatsheetItem
syntax:
`<div [ngClass]="{active: isActive, disabled: isDisabled}">`|`[ngClass]`
description:
Binds the presence of CSS classes on the element to the truthiness of the associated map values. The right-hand expression should return {class-name: true/false} map.

View File

@ -1,49 +0,0 @@
@cheatsheetSection
Class decorators
@cheatsheetIndex 5
@description
{@target ts}`import { Directive, ... } from '@angular/core';`{@endtarget}
{@target js}Available from the `ng.core` namespace{@endtarget}
@cheatsheetItem
syntax(ts):
`@Component({...})
class MyComponent() {}`|`@Component({...})`
syntax(js):
`var MyComponent = ng.core.Component({...}).Class({...})`|`ng.core.Component({...})`
description:
Declares that a class is a component and provides metadata about the component.
@cheatsheetItem
syntax(ts):
`@Directive({...})
class MyDirective() {}`|`@Directive({...})`
syntax(js):
`var MyDirective = ng.core.Directive({...}).Class({...})`|`ng.core.Directive({...})`
description:
Declares that a class is a directive and provides metadata about the directive.
@cheatsheetItem
syntax(ts):
`@Pipe({...})
class MyPipe() {}`|`@Pipe({...})`
syntax(js):
`var MyPipe = ng.core.Pipe({...}).Class({...})`|`ng.core.Pipe({...})`
description:
Declares that a class is a pipe and provides metadata about the pipe.
@cheatsheetItem
syntax(ts):
`@Injectable()
class MyService() {}`|`@Injectable()`
syntax(js):
`var OtherService = ng.core.Class(
{constructor: function() { }});
var MyService = ng.core.Class(
{constructor: [OtherService, function(otherService) { }]});`|`var MyService = ng.core.Class({constructor: [OtherService, function(otherService) { }]});`
description:
{@target ts}Declares that a class has dependencies that should be injected into the constructor when the dependency injector is creating an instance of this class.
{@endtarget}
{@target js}
Declares a service to inject into a class by providing an array with the services, with the final item being the function to receive the injected services.
{@endtarget}

View File

@ -1,38 +0,0 @@
@cheatsheetSection
Component configuration
@cheatsheetIndex 7
@description
{@target js}`ng.core.Component` extends `ng.core.Directive`,
so the `ng.core.Directive` configuration applies to components as well{@endtarget}
{@target ts}`@Component` extends `@Directive`,
so the `@Directive` configuration applies to components as well{@endtarget}
@cheatsheetItem
syntax:
`moduleId: module.id`|`moduleId:`
description:
If set, the `templateUrl` and `styleUrl` are resolved relative to the component.
@cheatsheetItem
syntax(ts):
`viewProviders: [MyService, { provide: ... }]`|`viewProviders:`
syntax(js):
`viewProviders: [MyService, { provide: ... }]`|`viewProviders:`
description:
List of dependency injection providers scoped to this component's view.
@cheatsheetItem
syntax:
`template: 'Hello {{name}}'
templateUrl: 'my-component.html'`|`template:`|`templateUrl:`
description:
Inline template or external template URL of the component's view.
@cheatsheetItem
syntax:
`styles: ['.primary {color: red}']
styleUrls: ['my-component.css']`|`styles:`|`styleUrls:`
description:
List of inline CSS styles or external stylesheet URLs for styling the components view.

View File

@ -1,30 +0,0 @@
@cheatsheetSection
Dependency injection configuration
@cheatsheetIndex 10
@description
@cheatsheetItem
syntax(ts):
`{ provide: MyService, useClass: MyMockService }`|`provide`|`useClass`
syntax(js):
`{ provide: MyService, useClass: MyMockService }`|`provide`|`useClass`
description:
Sets or overrides the provider for `MyService` to the `MyMockService` class.
@cheatsheetItem
syntax(ts):
`{ provide: MyService, useFactory: myFactory }`|`provide`|`useFactory`
syntax(js):
`{ provide: MyService, useFactory: myFactory }`|`provide`|`useFactory`
description:
Sets or overrides the provider for `MyService` to the `myFactory` factory function.
@cheatsheetItem
syntax(ts):
`{ provide: MyValue, useValue: 41 }`|`provide`|`useValue`
syntax(js):
`{ provide: MyValue, useValue: 41 }`|`provide`|`useValue`
description:
Sets or overrides the provider for `MyValue` to the value `41`.

View File

@ -1,86 +0,0 @@
@cheatsheetSection
Class field decorators for directives and components
@cheatsheetIndex 8
@description
{@target ts}`import { Input, ... } from '@angular/core';`{@endtarget}
{@target js}Available from the `ng.core` namespace{@endtarget}
@cheatsheetItem
syntax(ts):
`@Input() myProperty;`|`@Input()`
syntax(js):
`ng.core.Input(myProperty, myComponent);`|`ng.core.Input(`|`);`
description:
Declares an input property that you can update via property binding (example:
`<my-cmp [myProperty]="someExpression">`).
@cheatsheetItem
syntax(ts):
`@Output() myEvent = new EventEmitter();`|`@Output()`
syntax(js):
`myEvent = new ng.core.EventEmitter();
ng.core.Output(myEvent, myComponent);`|`ng.core.Output(`|`);`
description:
Declares an output property that fires events that you can subscribe to with an event binding (example: `<my-cmp (myEvent)="doSomething()">`).
@cheatsheetItem
syntax(ts):
`@HostBinding('class.valid') isValid;`|`@HostBinding('class.valid')`
syntax(js):
`ng.core.HostBinding('class.valid',
'isValid', myComponent);`|`ng.core.HostBinding('class.valid', 'isValid'`|`);`
description:
Binds a host element property (here, the CSS class `valid`) to a directive/component property (`isValid`).
@cheatsheetItem
syntax(ts):
`@HostListener('click', ['$event']) onClick(e) {...}`|`@HostListener('click', ['$event'])`
syntax(js):
`ng.core.HostListener('click',
['$event'], onClick(e) {...}, myComponent);`|`ng.core.HostListener('click', ['$event'], onClick(e)`|`);`
description:
Subscribes to a host element event (`click`) with a directive/component method (`onClick`), optionally passing an argument (`$event`).
@cheatsheetItem
syntax(ts):
`@ContentChild(myPredicate) myChildComponent;`|`@ContentChild(myPredicate)`
syntax(js):
`ng.core.ContentChild(myPredicate,
'myChildComponent', myComponent);`|`ng.core.ContentChild(myPredicate,`|`);`
description:
Binds the first result of the component content query (`myPredicate`) to a property (`myChildComponent`) of the class.
@cheatsheetItem
syntax(ts):
`@ContentChildren(myPredicate) myChildComponents;`|`@ContentChildren(myPredicate)`
syntax(js):
`ng.core.ContentChildren(myPredicate,
'myChildComponents', myComponent);`|`ng.core.ContentChildren(myPredicate,`|`);`
description:
Binds the results of the component content query (`myPredicate`) to a property (`myChildComponents`) of the class.
@cheatsheetItem
syntax(ts):
`@ViewChild(myPredicate) myChildComponent;`|`@ViewChild(myPredicate)`
syntax(js):
`ng.core.ViewChild(myPredicate,
'myChildComponent', myComponent);`|`ng.core.ViewChild(myPredicate,`|`);`
description:
Binds the first result of the component view query (`myPredicate`) to a property (`myChildComponent`) of the class. Not available for directives.
@cheatsheetItem
syntax(ts):
`@ViewChildren(myPredicate) myChildComponents;`|`@ViewChildren(myPredicate)`
syntax(js):
`ng.core.ViewChildren(myPredicate,
'myChildComponents', myComponent);`|`ng.core.ViewChildren(myPredicate,`|`);`
description:
Binds the results of the component view query (`myPredicate`) to a property (`myChildComponents`) of the class. Not available for directives.

View File

@ -1,23 +0,0 @@
@cheatsheetSection
Directive configuration
@cheatsheetIndex 6
@description
{@target ts}`@Directive({ property1: value1, ... })`{@endtarget}
{@target js}`ng.core.Directive({ property1: value1, ... }).Class({...})`{@endtarget}
@cheatsheetItem
syntax:
`selector: '.cool-button:not(a)'`|`selector:`
description:
Specifies a CSS selector that identifies this directive within a template. Supported selectors include `element`,
`[attribute]`, `.class`, and `:not()`.
Does not support parent-child relationship selectors.
@cheatsheetItem
syntax(ts):
`providers: [MyService, { provide: ... }]`|`providers:`
syntax(js):
`providers: [MyService, { provide: ... }]`|`providers:`
description:
List of dependency injection providers for this directive and its children.

View File

@ -1,12 +0,0 @@
@cheatsheetSection
Forms
@cheatsheetIndex 4
@description
{@target ts}`import { FormsModule } from '@angular/forms';`{@endtarget}
{@target js}Available using the `ng.forms.FormsModule` module{@endtarget}
@cheatsheetItem
syntax:
`<input [(ngModel)]="userName">`|`[(ngModel)]`
description:
Provides two-way data-binding, parsing, and validation for form controls.

View File

@ -1,86 +0,0 @@
@cheatsheetSection
Directive and component change detection and lifecycle hooks
@cheatsheetIndex 9
@description
{@target ts}(implemented as class methods){@endtarget}
{@target js}(implemented as component properties){@endtarget}
@cheatsheetItem
syntax(ts):
`constructor(myService: MyService, ...) { ... }`|`constructor(myService: MyService, ...)`
syntax(js):
`constructor: function(MyService, ...) { ... }`|`constructor: function(MyService, ...)`
description:
Called before any other lifecycle hook. Use it to inject dependencies, but avoid any serious work here.
@cheatsheetItem
syntax(ts):
`ngOnChanges(changeRecord) { ... }`|`ngOnChanges(changeRecord)`
syntax(js):
`ngOnChanges: function(changeRecord) { ... }`|`ngOnChanges: function(changeRecord)`
description:
Called after every change to input properties and before processing content or child views.
@cheatsheetItem
syntax(ts):
`ngOnInit() { ... }`|`ngOnInit()`
syntax(js):
`ngOnInit: function() { ... }`|`ngOnInit: function()`
description:
Called after the constructor, initializing input properties, and the first call to `ngOnChanges`.
@cheatsheetItem
syntax(ts):
`ngDoCheck() { ... }`|`ngDoCheck()`
syntax(js):
`ngDoCheck: function() { ... }`|`ngDoCheck: function()`
description:
Called every time that the input properties of a component or a directive are checked. Use it to extend change detection by performing a custom check.
@cheatsheetItem
syntax(ts):
`ngAfterContentInit() { ... }`|`ngAfterContentInit()`
syntax(js):
`ngAfterContentInit: function() { ... }`|`ngAfterContentInit: function()`
description:
Called after `ngOnInit` when the component's or directive's content has been initialized.
@cheatsheetItem
syntax(ts):
`ngAfterContentChecked() { ... }`|`ngAfterContentChecked()`
syntax(js):
`ngAfterContentChecked: function() { ... }`|`ngAfterContentChecked: function()`
description:
Called after every check of the component's or directive's content.
@cheatsheetItem
syntax(ts):
`ngAfterViewInit() { ... }`|`ngAfterViewInit()`
syntax(js):
`ngAfterViewInit: function() { ... }`|`ngAfterViewInit: function()`
description:
Called after `ngAfterContentInit` when the component's view has been initialized. Applies to components only.
@cheatsheetItem
syntax(ts):
`ngAfterViewChecked() { ... }`|`ngAfterViewChecked()`
syntax(js):
`ngAfterViewChecked: function() { ... }`|`ngAfterViewChecked: function()`
description:
Called after every check of the component's view. Applies to components only.
@cheatsheetItem
syntax(ts):
`ngOnDestroy() { ... }`|`ngOnDestroy()`
syntax(js):
`ngOnDestroy: function() { ... }`|`ngOnDestroy: function()`
description:
Called once, before the instance is destroyed.

View File

@ -1,58 +0,0 @@
@cheatsheetSection
NgModules
@cheatsheetIndex 1
@description
{@target ts}`import { NgModule } from '@angular/core';`{@endtarget}
{@target js}Available from the `ng.core` namespace{@endtarget}
@cheatsheetItem
syntax(ts):
`@NgModule({ declarations: ..., imports: ...,
exports: ..., providers: ..., bootstrap: ...})
class MyModule {}`|`NgModule`
description:
Defines a module that contains components, directives, pipes, and providers.
syntax(js):
`ng.core.NgModule({declarations: ..., imports: ...,
exports: ..., providers: ..., bootstrap: ...}).
Class({ constructor: function() {}})`
description:
Defines a module that contains components, directives, pipes, and providers.
@cheatsheetItem
syntax:
`declarations: [MyRedComponent, MyBlueComponent, MyDatePipe]`|`declarations:`
description:
List of components, directives, and pipes that belong to this module.
@cheatsheetItem
syntax(ts):
`imports: [BrowserModule, SomeOtherModule]`|`imports:`
description:
List of modules to import into this module. Everything from the imported modules
is available to `declarations` of this module.
syntax(js):
`imports: [ng.platformBrowser.BrowserModule, SomeOtherModule]`|`imports:`
description:
List of modules to import into this module. Everything from the imported modules
is available to `declarations` of this module.
@cheatsheetItem
syntax:
`exports: [MyRedComponent, MyDatePipe]`|`exports:`
description:
List of components, directives, and pipes visible to modules that import this module.
@cheatsheetItem
syntax:
`providers: [MyService, { provide: ... }]`|`providers:`
description:
List of dependency injection providers visible both to the contents of this module and to importers of this module.
@cheatsheetItem
syntax:
`bootstrap: [MyAppComponent]`|`bootstrap:`
description:
List of components to bootstrap when this module is bootstrapped.

View File

@ -1,170 +0,0 @@
@cheatsheetSection
Routing and navigation
@cheatsheetIndex 11
@description
{@target ts}`import { Routes, RouterModule, ... } from '@angular/router';`{@endtarget}
{@target js}Available from the `ng.router` namespace{@endtarget}
@cheatsheetItem
syntax(ts):
`const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'path/:routeParam', component: MyComponent },
{ path: 'staticPath', component: ... },
{ path: '**', component: ... },
{ path: 'oldPath', redirectTo: '/staticPath' },
{ path: ..., component: ..., data: { message: 'Custom' } }
]);
const routing = RouterModule.forRoot(routes);`|`Routes`
syntax(js):
`var routes = [
{ path: '', component: HomeComponent },
{ path: ':routeParam', component: MyComponent },
{ path: 'staticPath', component: ... },
{ path: '**', component: ... },
{ path: 'oldPath', redirectTo: '/staticPath' },
{ path: ..., component: ..., data: { message: 'Custom' } }
]);
var routing = ng.router.RouterModule.forRoot(routes);`|`ng.router.Routes`
description:
Configures routes for the application. Supports static, parameterized, redirect, and wildcard routes. Also supports custom route data and resolve.
@cheatsheetItem
syntax:
`
<router-outlet></router-outlet>
<router-outlet name="aux"></router-outlet>
`|`router-outlet`
description:
Marks the location to load the component of the active route.
@cheatsheetItem
syntax:
`
<a routerLink="/path">
<a [routerLink]="[ '/path', routeParam ]">
<a [routerLink]="[ '/path', { matrixParam: 'value' } ]">
<a [routerLink]="[ '/path' ]" [queryParams]="{ page: 1 }">
<a [routerLink]="[ '/path' ]" fragment="anchor">
`|`[routerLink]`
description:
Creates a link to a different view based on a route instruction consisting of a route path, required and optional parameters, query parameters, and a fragment. To navigate to a root route, use the `/` prefix; for a child route, use the `./`prefix; for a sibling or parent, use the `../` prefix.
@cheatsheetItem
syntax:
`<a [routerLink]="[ '/path' ]" routerLinkActive="active">`
description:
The provided classes are added to the element when the `routerLink` becomes the current active route.
@cheatsheetItem
syntax(ts):
`class CanActivateGuard implements CanActivate {
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean>|Promise<boolean>|boolean { ... }
}
{ path: ..., canActivate: [CanActivateGuard] }`|`CanActivate`
syntax(js):
`var CanActivateGuard = ng.core.Class({
canActivate: function(route, state) {
// return Observable/Promise boolean or boolean
}
});
{ path: ..., canActivate: [CanActivateGuard] }`|`CanActivate`
description:
An interface for defining a class that the router should call first to determine if it should activate this component. Should return a boolean or an Observable/Promise that resolves to a boolean.
@cheatsheetItem
syntax(ts):
`class CanDeactivateGuard implements CanDeactivate<T> {
canDeactivate(
component: T,
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean>|Promise<boolean>|boolean { ... }
}
{ path: ..., canDeactivate: [CanDeactivateGuard] }`|`CanDeactivate`
syntax(js):
`var CanDeactivateGuard = ng.core.Class({
canDeactivate: function(component, route, state) {
// return Observable/Promise boolean or boolean
}
});
{ path: ..., canDeactivate: [CanDeactivateGuard] }`|`CanDeactivate`
description:
An interface for defining a class that the router should call first to determine if it should deactivate this component after a navigation. Should return a boolean or an Observable/Promise that resolves to a boolean.
@cheatsheetItem
syntax(ts):
`class CanActivateChildGuard implements CanActivateChild {
canActivateChild(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean>|Promise<boolean>|boolean { ... }
}
{ path: ..., canActivateChild: [CanActivateGuard],
children: ... }`|`CanActivateChild`
syntax(js):
`var CanActivateChildGuard = ng.core.Class({
canActivateChild: function(route, state) {
// return Observable/Promise boolean or boolean
}
});
{ path: ..., canActivateChild: [CanActivateChildGuard],
children: ... }`|`CanActivateChild`
description:
An interface for defining a class that the router should call first to determine if it should activate the child route. Should return a boolean or an Observable/Promise that resolves to a boolean.
@cheatsheetItem
syntax(ts):
`class ResolveGuard implements Resolve<T> {
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<any>|Promise<any>|any { ... }
}
{ path: ..., resolve: [ResolveGuard] }`|`Resolve`
syntax(js):
`var ResolveGuard = ng.core.Class({
resolve: function(route, state) {
// return Observable/Promise value or value
}
});
{ path: ..., resolve: [ResolveGuard] }`|`Resolve`
description:
An interface for defining a class that the router should call first to resolve route data before rendering the route. Should return a value or an Observable/Promise that resolves to a value.
@cheatsheetItem
syntax(ts):
`class CanLoadGuard implements CanLoad {
canLoad(
route: Route
): Observable<boolean>|Promise<boolean>|boolean { ... }
}
{ path: ..., canLoad: [CanLoadGuard], loadChildren: ... }`|`CanLoad`
syntax(js):
`var CanLoadGuard = ng.core.Class({
canLoad: function(route) {
// return Observable/Promise boolean or boolean
}
});
{ path: ..., canLoad: [CanLoadGuard], loadChildren: ... }`|`CanLoad`
description:
An interface for defining a class that the router should call first to check if the lazy loaded module should be loaded. Should return a boolean or an Observable/Promise that resolves to a boolean.

View File

@ -1,94 +0,0 @@
@cheatsheetSection
Template syntax
@cheatsheetIndex 2
@description
@cheatsheetItem
syntax:
`<input [value]="firstName">`|`[value]`
description:
Binds property `value` to the result of expression `firstName`.
@cheatsheetItem
syntax:
`<div [attr.role]="myAriaRole">`|`[attr.role]`
description:
Binds attribute `role` to the result of expression `myAriaRole`.
@cheatsheetItem
syntax:
`<div [class.extra-sparkle]="isDelightful">`|`[class.extra-sparkle]`
description:
Binds the presence of the CSS class `extra-sparkle` on the element to the truthiness of the expression `isDelightful`.
@cheatsheetItem
syntax:
`<div [style.width.px]="mySize">`|`[style.width.px]`
description:
Binds style property `width` to the result of expression `mySize` in pixels. Units are optional.
@cheatsheetItem
syntax:
`<button (click)="readRainbow($event)">`|`(click)`
description:
Calls method `readRainbow` when a click event is triggered on this button element (or its children) and passes in the event object.
@cheatsheetItem
syntax:
`<div title="Hello {{ponyName}}">`|`{{ponyName}}`
description:
Binds a property to an interpolated string, for example, "Hello Seabiscuit". Equivalent to:
`<div [title]="'Hello ' + ponyName">`
@cheatsheetItem
syntax:
`<p>Hello {{ponyName}}</p>`|`{{ponyName}}`
description:
Binds text content to an interpolated string, for example, "Hello Seabiscuit".
@cheatsheetItem
syntax:
`<my-cmp [(title)]="name">`|`[(title)]`
description:
Sets up two-way data binding. Equivalent to: `<my-cmp [title]="name" (titleChange)="name=$event">`
@cheatsheetItem
syntax:
`<video #movieplayer ...>
<button (click)="movieplayer.play()">
</video>`|`#movieplayer`|`(click)`
description:
Creates a local variable `movieplayer` that provides access to the `video` element instance in data-binding and event-binding expressions in the current template.
@cheatsheetItem
syntax:
`<p *myUnless="myExpression">...</p>`|`*myUnless`
description:
The `*` symbol turns the current element into an embedded template. Equivalent to:
`<ng-template [myUnless]="myExpression"><p>...</p></ng-template>`
@cheatsheetItem
syntax:
`<p>Card No.: {{cardNumber | myCardNumberFormatter}}</p>`|`{{cardNumber | myCardNumberFormatter}}`
description:
Transforms the current value of expression `cardNumber` via the pipe called `myCardNumberFormatter`.
@cheatsheetItem
syntax:
`<p>Employer: {{employer?.companyName}}</p>`|`{{employer?.companyName}}`
description:
The safe navigation operator (`?`) means that the `employer` field is optional and if `undefined`, the rest of the expression should be ignored.
@cheatsheetItem
syntax:
`<svg:rect x="0" y="0" width="100" height="100"/>`|`svg:`
description:
An SVG snippet template needs an `svg:` prefix on its root element to disambiguate the SVG element from an HTML component.
@cheatsheetItem
syntax:
`<svg>
<rect x="0" y="0" width="100" height="100"/>
</svg>`|`svg`
description:
An `<svg>` root element is detected as an SVG element automatically, without the prefix.

View File

@ -17,15 +17,15 @@ by mapping AngularJS syntax to the equivalent Angular syntax.
## Contents
* [Template basics](#template-basics)&mdash;binding and local variables.
* [Template basics](guide/ajs-quick-reference#template-basics)&mdash;binding and local variables.
* [Template directives](#template-directives)&mdash;built-in directives `ngIf` and `ngClass`.
* [Template directives](guide/ajs-quick-reference#template-directives)&mdash;built-in directives `ngIf` and `ngClass`.
* [Filters/pipes](#filters-pipes)&mdash;built-in *filters*, known as *pipes* in Angular.
* [Filters/pipes](guide/ajs-quick-reference#filters-pipes)&mdash;built-in *filters*, known as *pipes* in Angular.
* [Modules/controllers/components](#controllers-components)&mdash;*modules* in Angular are slightly different from *modules* in AngularJS, and *controllers* are *components* in Angular.
* [Modules/controllers/components](guide/ajs-quick-reference#controllers-components)&mdash;*modules* in Angular are slightly different from *modules* in AngularJS, and *controllers* are *components* in Angular.
* [Style sheets](#style-sheets)&mdash;more options for CSS than in AngularJS.
* [Style sheets](guide/ajs-quick-reference#style-sheets)&mdash;more options for CSS than in AngularJS.
## Template basics
Templates are the user-facing part of an Angular application and are written in HTML.
@ -86,8 +86,8 @@ The following table lists some of the key AngularJS template features with their
The context of the binding is implied and is always the
associated component, so it needs no reference variable.
For more information, see the [Interpolation](../guide/template-syntax.html#interpolation)
section of the [Template Syntax](../guide/template-syntax.html) page.
For more information, see the [Interpolation](guide/template-syntax)
section of the [Template Syntax](guide/template-syntax) page.
</td>
@ -117,7 +117,7 @@ The following table lists some of the key AngularJS template features with their
Many (but not all) of the built-in filters from AngularJS are
built-in pipes in Angular.
For more information, see [Filters/pipes](#filters-pipes) below.
For more information, see [Filters/pipes](guide/ajs-quick-reference#filters-pipes) below.
</td>
@ -145,8 +145,8 @@ The following table lists some of the key AngularJS template features with their
Angular has true template input variables that are explicitly defined using the `let` keyword.
For more information, see the [ngFor micro-syntax](../guide/template-syntax.html#microsyntax)
section of the [Template Syntax](../guide/template-syntax.html) page.
For more information, see the [ngFor micro-syntax](guide/template-syntax)
section of the [Template Syntax](guide/template-syntax) page.
</td>
@ -155,7 +155,7 @@ The following table lists some of the key AngularJS template features with their
</table>
[Back to top](#top)
[Back to top](guide/ajs-quick-reference#top)
## Template directives
AngularJS provides more than seventy built-in directives for templates.
@ -219,7 +219,7 @@ The following are some of the key AngularJS built-in directives and their equiva
in `main.ts`
and the application's root component (`AppComponent`) in `app.module.ts`.
For more information see the [Setup](../guide/setup.html) page.
For more information see the [Setup](guide/setup) page.
</td>
@ -262,8 +262,8 @@ The following are some of the key AngularJS built-in directives and their equiva
Angular also has **class binding**, which is a good way to add or remove a single class,
as shown in the third example.
For more information see the [Attribute, class, and style bindings](../guide/template-syntax.html#other-bindings)
section of the [Template Syntax](../guide/template-syntax.html) page.
For more information see the [Attribute, class, and style bindings](guide/template-syntax)
section of the [Template Syntax](guide/template-syntax) page.
</td>
@ -309,8 +309,8 @@ The following are some of the key AngularJS built-in directives and their equiva
For a list of DOM events, see: https://developer.mozilla.org/en-US/docs/Web/Events.
For more information, see the [Event binding](../guide/template-syntax.html#event-binding)
section of the [Template Syntax](../guide/template-syntax.html) page.
For more information, see the [Event binding](guide/template-syntax)
section of the [Template Syntax](guide/template-syntax) page.
</td>
@ -340,7 +340,7 @@ The following are some of the key AngularJS built-in directives and their equiva
In Angular, the template no longer specifies its associated controller.
Rather, the component specifies its associated template as part of the component class decorator.
For more information, see [Architecture Overview](../guide/architecture.html#component).
For more information, see [Architecture Overview](guide/architecture).
</td>
@ -353,14 +353,14 @@ The following are some of the key AngularJS built-in directives and their equiva
<td>
### ng-hide
In AngularJS, the `ng-hide` directive shows or hides the associated HTML element based on
an expression. For more information, see [ng-show](#ng-show).
an expression. For more information, see [ng-show](guide/ajs-quick-reference#ng-show).
</td>
<td>
### Bind to the `hidden` property
In Angular, you use property binding; there is no built-in *hide* directive.
For more information, see [ng-show](#ng-show).
For more information, see [ng-show](guide/ajs-quick-reference#ng-show).
</td>
@ -396,15 +396,15 @@ The following are some of the key AngularJS built-in directives and their equiva
Angular uses property binding; there is no built-in *href* directive.
Place the element's `href` property in square brackets and set it to a quoted template expression.
For more information see the [Property binding](../guide/template-syntax.html#property-binding)
section of the [Template Syntax](../guide/template-syntax.html) page.
For more information see the [Property binding](guide/template-syntax)
section of the [Template Syntax](guide/template-syntax) page.
In Angular, `href` is no longer used for routing. Routing uses `routerLink`, as shown in the following example.
{@example 'cb-ajs-quick-reference/ts/src/app/app.component.html' region='router-link'}
For more information on routing, see the [RouterLink binding](../guide/router.html#router-link)
section of the [Routing & Navigation](../guide/router.html) page.
For more information on routing, see the [RouterLink binding](guide/router)
section of the [Routing & Navigation](guide/router) page.
</td>
@ -438,7 +438,7 @@ The following are some of the key AngularJS built-in directives and their equiva
In this example, the `<table>` element is removed from the DOM unless the `movies` array has a length.
The (*) before `ngIf` is required in this example.
For more information, see [Structural Directives](../guide/structural-directives.html).
For more information, see [Structural Directives](guide/structural-directives).
</td>
@ -468,7 +468,7 @@ The following are some of the key AngularJS built-in directives and their equiva
For more information on two-way binding with `ngModel`, see the [NgModel&mdash;Two-way binding to
form elements with `[(ngModel)]`](../guide/template-syntax.html#ngModel)
section of the [Template Syntax](../guide/template-syntax.html) page.
section of the [Template Syntax](guide/template-syntax) page.
</td>
@ -505,7 +505,7 @@ The following are some of the key AngularJS built-in directives and their equiva
the `let` keyword identifies `movie` as an input variable;
the list preposition is `of`, not `in`.
For more information, see [Structural Directives](../guide/structural-directives.html).
For more information, see [Structural Directives](guide/structural-directives).
</td>
@ -542,8 +542,8 @@ The following are some of the key AngularJS built-in directives and their equiva
In this example, the `<div>` element is hidden if the `favoriteHero` variable is not truthy.
For more information on property binding, see the [Property binding](../guide/template-syntax.html#property-binding)
section of the [Template Syntax](../guide/template-syntax.html) page.
For more information on property binding, see the [Property binding](guide/template-syntax)
section of the [Template Syntax](guide/template-syntax) page.
</td>
@ -572,8 +572,8 @@ The following are some of the key AngularJS built-in directives and their equiva
Angular uses property binding; there is no built-in *src* directive.
Place the `src` property in square brackets and set it to a quoted template expression.
For more information on property binding, see the [Property binding](../guide/template-syntax.html#property-binding)
section of the [Template Syntax](../guide/template-syntax.html) page.
For more information on property binding, see the [Property binding](guide/template-syntax)
section of the [Template Syntax](guide/template-syntax) page.
</td>
@ -608,11 +608,11 @@ The following are some of the key AngularJS built-in directives and their equiva
Angular also has **style binding**, which is good way to set a single style. This is shown in the second example.
For more information on style binding, see the [Style binding](../guide/template-syntax.html#style-binding) section of the
[Template Syntax](../guide/template-syntax.html) page.
For more information on style binding, see the [Style binding](guide/template-syntax) section of the
[Template Syntax](guide/template-syntax) page.
For more information on the `ngStyle` directive, see [NgStyle](../guide/template-syntax.html#ngStyle)
section of the [Template Syntax](../guide/template-syntax.html) page.
For more information on the `ngStyle` directive, see [NgStyle](guide/template-syntax)
section of the [Template Syntax](guide/template-syntax) page.
</td>
@ -664,8 +664,8 @@ The following are some of the key AngularJS built-in directives and their equiva
The (*) before `ngSwitchCase` and `ngSwitchDefault` is required in this example.
For more information, see [The NgSwitch directives](../guide/template-syntax.html#ngSwitch)
section of the [Template Syntax](../guide/template-syntax.html) page.
For more information, see [The NgSwitch directives](guide/template-syntax)
section of the [Template Syntax](guide/template-syntax) page.
</td>
@ -674,7 +674,7 @@ The following are some of the key AngularJS built-in directives and their equiva
</table>
[Back to top](#top)
[Back to top](guide/ajs-quick-reference#top)
{@a filters-pipes}
@ -682,7 +682,7 @@ The following are some of the key AngularJS built-in directives and their equiva
## Filters/pipes
Angular **pipes** provide formatting and transformation for data in the template, similar to AngularJS **filters**.
Many of the built-in filters in AngularJS have corresponding pipes in Angular.
For more information on pipes, see [Pipes](../guide/pipes.html).
For more information on pipes, see [Pipes](guide/pipes).
<table width="100%">
@ -896,7 +896,7 @@ For more information on pipes, see [Pipes](../guide/pipes.html).
</code-example>
Displays the collection in the order specified by the expression.
In this example, the movie title orders the movieList.
In this example, the movie title orders the `movieList`.
</td>
@ -913,7 +913,7 @@ For more information on pipes, see [Pipes](../guide/pipes.html).
</table>
[Back to top](#top)
[Back to top](guide/ajs-quick-reference#top)
{@a controllers-components}
@ -975,8 +975,8 @@ The Angular code is shown using TypeScript.
This is a nonissue in Angular because ES 2015 modules
handle the namespacing for you.
For more information on modules, see the [Modules](../guide/architecture.html#modules) section of the
[Architecture Overview](../guide/architecture.html).
For more information on modules, see the [Modules](guide/architecture) section of the
[Architecture Overview](guide/architecture).
</td>
@ -1005,7 +1005,7 @@ The Angular code is shown using TypeScript.
- `imports`: specifies the list of other modules that this module depends upon
- `declaration`: keeps track of your components, pipes, and directives.
For more information on modules, see [Angular Modules (NgModule)](../guide/ngmodule.html).
For more information on modules, see [Angular Modules (NgModule)](guide/ngmodule).
</td>
@ -1043,8 +1043,8 @@ The Angular code is shown using TypeScript.
This is how you associate a template with logic, which is defined in the component class.
For more information, see the [Components](../guide/architecture.html#components)
section of the [Architecture Overview](../guide/architecture.html) page.
For more information, see the [Components](guide/architecture)
section of the [Architecture Overview](guide/architecture) page.
</td>
@ -1073,8 +1073,8 @@ The Angular code is shown using TypeScript.
NOTE: If you are using TypeScript with AngularJS, you must use the `export` keyword to export the component class.
For more information, see the [Components](../guide/architecture.html#components)
section of the [Architecture Overview](../guide/architecture.html) page.
For more information, see the [Components](guide/architecture)
section of the [Architecture Overview](guide/architecture) page.
</td>
@ -1108,8 +1108,8 @@ The Angular code is shown using TypeScript.
This example injects a `MovieService`.
The first parameter's TypeScript type tells Angular what to inject, even after minification.
For more information, see the [Dependency injection](../guide/architecture.html#dependency-injection)
section of the [Architecture Overview](../guide/architecture.html).
For more information, see the [Dependency injection](guide/architecture)
section of the [Architecture Overview](guide/architecture).
</td>
@ -1118,7 +1118,7 @@ The Angular code is shown using TypeScript.
</table>
[Back to top](#top)
[Back to top](guide/ajs-quick-reference#top)
{@a style-sheets}
@ -1192,4 +1192,4 @@ also encapsulate a style sheet within a specific component.
</table>
[Back to top](#top)
[Back to top](guide/ajs-quick-reference#top)

View File

@ -30,16 +30,16 @@ add it to your page.
# Contents
* [Example: Transitioning between two states](#example-transitioning-between-states).
* [States and transitions](#states-and-transitions).
* [Example: Entering and leaving](#example-entering-and-leaving).
* [Example: Entering and leaving from different states](#example-entering-and-leaving-from-different-states).
* [Animatable properties and units](#animatable-properties-and-units).
* [Automatic property calculation](#automatic-property-calculation).
* [Animation timing](#animation-timing).
* [Multi-step animations with keyframes](#multi-step-animations-with-keyframes).
* [Parallel animation groups](#parallel-animation-groups).
* [Animation callbacks](#animation-callbacks).
* [Example: Transitioning between two states](guide/animations#example-transitioning-between-states).
* [States and transitions](guide/animations#states-and-transitions).
* [Example: Entering and leaving](guide/animations#example-entering-and-leaving).
* [Example: Entering and leaving from different states](guide/animations#example-entering-and-leaving-from-different-states).
* [Animatable properties and units](guide/animations#animatable-properties-and-units).
* [Automatic property calculation](guide/animations#automatic-property-calculation).
* [Animation timing](guide/animations#animation-timing).
* [Multi-step animations with keyframes](guide/animations#multi-step-animations-with-keyframes).
* [Parallel animation groups](guide/animations#parallel-animation-groups).
* [Animation callbacks](guide/animations#animation-callbacks).
The examples in this page are available as a <live-example></live-example>.

View File

@ -2,7 +2,7 @@
Ahead-of-Time Compilation
@intro
Learn how to use Ahead-of-time compilation
Learn how to use Ahead-of-time compilation.
@description
This cookbook describes how to radically improve performance by compiling _Ahead of Time_ (AOT)
@ -11,16 +11,16 @@ during a build process.
{@a toc}
## Table of Contents
* [Overview](#overview)
* [_Ahead-of-Time_ vs _Just-in-Time_](#aot-jit)
* [Compile with AOT](#compile)
* [Bootstrap](#bootstrap)
* [Tree Shaking](#tree-shaking)
* [Load the bundle](#load)
* [Serve the app](#serve)
* [Workflow and convenience script](#workflow)
* [Source Code](#source-code)
* [Tour of Heroes](#toh)
* [Overview](guide/aot-compiler#overview)
* [_Ahead-of-Time_ vs _Just-in-Time_](guide/aot-compiler#aot-jit)
* [Compile with AOT](guide/aot-compiler#compile)
* [Bootstrap](guide/aot-compiler#bootstrap)
* [Tree Shaking](guide/aot-compiler#tree-shaking)
* [Load the bundle](guide/aot-compiler#load)
* [Serve the app](guide/aot-compiler#serve)
* [Workflow and convenience script](guide/aot-compiler#workflow)
* [Source Code](guide/aot-compiler#source-code)
* [Tour of Heroes](guide/aot-compiler#toh)
{@a overview}
@ -128,7 +128,7 @@ then modify it to look as follows.
The `compilerOptions` section is unchanged except for one property.
**Set the `module` to `es2015`**.
This is important as explained later in the [Tree Shaking](#tree-shaking) section.
This is important as explained later in the [Tree Shaking](guide/aot-compiler#tree-shaking) section.
What's really new is the `ngc` section at the bottom called `angularCompilerOptions`.
Its `"genDir"` property tells the compiler
@ -198,7 +198,7 @@ The AOT path changes application bootstrapping.
Instead of bootstrapping `AppModule`, you bootstrap the application with the generated module factory, `AppModuleNgFactory`.
Make a copy of `main.ts` and name it `main-jit.ts`.
This is the JIT version; set it aside as you may need it [later](#run-jit "Running with JIT").
This is the JIT version; set it aside as you may need it [later](guide/aot-compiler#run-jit "Running with JIT").
Open `main.ts` and convert it to AOT compilation.
Switch from the `platformBrowserDynamic.bootstrap` used in JIT compilation to
@ -408,7 +408,7 @@ The same source code can be built both ways. Here's one way to do that.
{@example 'cb-aot-compiler/ts/src/index-jit.html' region='jit'}
Notice the slight change to the `system.import` which now specifies `src/app/main-jit`.
That's the JIT version of the bootstrap file that we preserved [above](#bootstrap)
That's the JIT version of the bootstrap file that we preserved [above](guide/aot-compiler#bootstrap)
Open a _different_ terminal window and enter.
<code-example language="none" class="code-shell">
npm start
@ -434,7 +434,7 @@ Now you can develop JIT and AOT, side-by-side.
The sample above is a trivial variation of the QuickStart app.
In this section you apply what you've learned about AOT compilation and Tree Shaking
to an app with more substance, the tutorial [_Tour of Heroes_](../tutorial/toh-pt6.html).
to an app with more substance, the tutorial [_Tour of Heroes_](tutorial/toh-pt6).
### JIT in development, AOT in production
@ -472,7 +472,7 @@ It does not need `SystemJS`, so that script is absent from its `index.html`
***main.ts***
JIT and AOT applications boot in much the same way but require different Angular libraries to do so.
The key differences, covered in the [Bootstrap](#bootstrap) section above,
The key differences, covered in the [Bootstrap](guide/aot-compiler#bootstrap) section above,
are evident in these `main` files which can and should reside in the same folder:
<md-tab-group>

View File

@ -7,17 +7,17 @@ Tell Angular how to construct and bootstrap the app in the root "AppModule".
@description
An Angular module class describes how the application parts fit together.
Every application has at least one Angular module, the _root_ module
that you [bootstrap](#main) to launch the application.
that you [bootstrap](guide/appmodule#main) to launch the application.
You can call it anything you want. The conventional name is `AppModule`.
The [setup](setup.html) instructions produce a new project with the following minimal `AppModule`.
The [setup](guide/setup) instructions produce a new project with the following minimal `AppModule`.
You'll evolve this module as your application grows.
{@example 'setup/ts/src/app/app.module.ts'}
After the `import` statements, you come to a class adorned with the
**`@NgModule`** [_decorator_](glossary.html#decorator '"Decorator" explained').
**`@NgModule`** [_decorator_](guide/glossary).
The `@NgModule` decorator identifies `AppModule` as an Angular module class (also called an `NgModule` class).
`@NgModule` takes a _metadata_ object that tells Angular how to compile and launch the application.
@ -26,7 +26,7 @@ The `@NgModule` decorator identifies `AppModule` as an Angular module class (als
* **_declarations_** &mdash; the application's lone component, which is also ...
* **_bootstrap_** &mdash; the _root_ component that Angular creates and inserts into the `index.html` host web page.
The [Angular Modules (NgModule)](ngmodule.html) guide dives deeply into the details of Angular modules.
The [Angular Modules (NgModule)](guide/ngmodule) guide dives deeply into the details of Angular modules.
All you need to know at the moment is a few basics about these three properties.
@ -76,7 +76,7 @@ You must declare _every_ component in an `NgModule` class.
If you use a component without declaring it, you'll see a clear error message in the browser console.
You'll learn to create two other kinds of classes &mdash;
[directives](attribute-directives.html) and [pipes](pipes.html) &mdash;
[directives](guide/attribute-directives) and [pipes](guide/pipes) &mdash;
that you must also add to the `declarations` array.
@ -93,7 +93,7 @@ Do not put any other kind of class in `declarations`; _not_ `NgModule` classes,
{@a bootstrap-array}
### The _bootstrap_ array
You launch the application by [_bootstrapping_](#main) the root `AppModule`.
You launch the application by [_bootstrapping_](guide/appmodule#main) the root `AppModule`.
Among other things, the _bootstrapping_ process creates the component(s) listed in the `bootstrap` array
and inserts each one into the browser DOM.
@ -154,4 +154,4 @@ As your app grows, you'll consider subdividing it into multiple "feature" module
some of which can be loaded later ("lazy loaded") if and when the user chooses
to visit those features.
When you're ready to explore these possibilities, visit the [Angular Modules (NgModule)](ngmodule.html) guide.
When you're ready to explore these possibilities, visit the [Angular Modules (NgModule)](guide/ngmodule) guide.

View File

@ -2,7 +2,7 @@
Architecture Overview
@intro
The basic building blocks of Angular applications
The basic building blocks of Angular applications.
@description
You write Angular applications by composing HTML *templates* with Angularized markup,
@ -22,14 +22,14 @@ You'll learn the details in the pages that follow. For now, focus on the big pic
The architecture diagram identifies the eight main building blocks of an Angular application:
* [Modules](#modules)
* [Components](#components)
* [Templates](#templates)
* [Metadata](#metadata)
* [Data binding](#data-binding)
* [Directives](#directives)
* [Services](#services)
* [Dependency injection](#dependency-injection)
* [Modules](guide/architecture#modules)
* [Components](guide/architecture#components)
* [Templates](guide/architecture#templates)
* [Metadata](guide/architecture#metadata)
* [Data binding](guide/architecture#data-binding)
* [Directives](guide/architecture#directives)
* [Services](guide/architecture#services)
* [Dependency injection](guide/architecture#dependency-injection)
Learn these building blocks, and you're on your way.
@ -78,7 +78,7 @@ For example, this `HeroListComponent` has a `heroes` property that returns !{_an
that it acquires from a service.
`HeroListComponent` also has a `selectHero()` method that sets a `selectedHero` property when the user clicks to choose a hero from that list.
Angular creates, updates, and destroys components as the user moves through the application.
Your app can take action at each moment in this lifecycle through optional [lifecycle hooks](lifecycle-hooks.html), like `ngOnInit()` declared above.
Your app can take action at each moment in this lifecycle through optional [lifecycle hooks](guide/lifecycle-hooks), like `ngOnInit()` declared above.
<div class='l-hr'>
@ -99,7 +99,7 @@ template for our `HeroListComponent`:
{@example 'architecture/ts/src/app/hero-list.component.html'}
Although this template uses typical HTML elements like `<h2>` and `<p>`, it also has some differences. Code like `*ngFor`, `{{hero.name}}`, `(click)`, `[hero]`, and `<hero-detail>` uses Angular's [template syntax](template-syntax.html).
Although this template uses typical HTML elements like `<h2>` and `<p>`, it also has some differences. Code like `*ngFor`, `{{hero.name}}`, `(click)`, `[hero]`, and `<hero-detail>` uses Angular's [template syntax](guide/template-syntax).
In the last line of the template, the `<hero-detail>` tag is a custom element that represents a new component, `HeroDetailComponent`.
@ -126,7 +126,7 @@ Notice how `<hero-detail>` rests comfortably among native HTML elements. Custom
</figure>
<p style="padding-top:10px">Metadata tells Angular how to process a class.</p>
<br class="l-clear-both">[Looking back at the code](#component-code) for `HeroListComponent`, you can see that it's just a class.
<br class="l-clear-both">[Looking back at the code](guide/architecture#component-code) for `HeroListComponent`, you can see that it's just a class.
There is no evidence of a framework, no "Angular" in it at all.
In fact, `HeroListComponent` really is *just a class*. It's not a component until you *tell Angular about it*.
@ -144,7 +144,7 @@ where it finds a `<hero-list>` tag in *parent* HTML.
For example, if an app's HTML contains `<hero-list></hero-list>`, then
Angular inserts an instance of the `HeroListComponent` view between those tags.
- `templateUrl`: module-relative address of this component's HTML template, shown [above](#templates).
- `templateUrl`: module-relative address of this component's HTML template, shown [above](guide/architecture#templates).
- `providers`: !{_array} of **dependency injection providers** for services that the component requires.
This is one way to tell Angular that the component's constructor requires a `HeroService`
so it can get the list of heroes to display.
@ -178,14 +178,14 @@ Angular supports **data binding**,
a mechanism for coordinating parts of a template with parts of a component.
Add binding markup to the template HTML to tell Angular how to connect both sides.
As the diagram shows, there are four forms of data binding syntax. Each form has a direction &mdash; to the DOM, from the DOM, or in both directions.<br class="l-clear-both">The `HeroListComponent` [example](#templates) template has three forms:
* The `{{hero.name}}` [*interpolation*](displaying-data.html#interpolation)
As the diagram shows, there are four forms of data binding syntax. Each form has a direction &mdash; to the DOM, from the DOM, or in both directions.<br class="l-clear-both">The `HeroListComponent` [example](guide/architecture#templates) template has three forms:
* The `{{hero.name}}` [*interpolation*](guide/displaying-data)
displays the component's `hero.name` property value within the `<li>` element.
* The `[hero]` [*property binding*](template-syntax.html#property-binding) passes the value of `selectedHero` from
* The `[hero]` [*property binding*](guide/template-syntax) passes the value of `selectedHero` from
the parent `HeroListComponent` to the `hero` property of the child `HeroDetailComponent`.
* The `(click)` [*event binding*](user-input.html#click) calls the component's `selectHero` method when the user clicks a hero's name.
* The `(click)` [*event binding*](guide/user-input) calls the component's `selectHero` method when the user clicks a hero's name.
**Two-way data binding** is an important fourth form
that combines property and event binding in a single notation, using the `ngModel` directive.
@ -234,9 +234,9 @@ sometimes by name but more often as the target of an assignment or a binding.
**Structural** directives alter layout by adding, removing, and replacing elements in DOM.
The [example template](#templates) uses two built-in structural directives:
* [`*ngFor`](displaying-data.html#ngFor) tells Angular to stamp out one `<li>` per hero in the `heroes` list.
* [`*ngIf`](displaying-data.html#ngIf) includes the `HeroDetail` component only if a selected hero exists.
The [example template](guide/architecture#templates) uses two built-in structural directives:
* [`*ngFor`](guide/displaying-data) tells Angular to stamp out one `<li>` per hero in the `heroes` list.
* [`*ngIf`](guide/displaying-data) includes the `HeroDetail` component only if a selected hero exists.
**Attribute** directives alter the appearance or behavior of an existing element.
In templates they look like regular HTML attributes, hence the name.
@ -245,9 +245,9 @@ an example of an attribute directive. `ngModel` modifies the behavior of
an existing element (typically an `<input>`)
by setting its display value property and responding to change events.
Angular has a few more directives that either alter the layout structure
(for example, [ngSwitch](template-syntax.html#ngSwitch))
(for example, [ngSwitch](guide/template-syntax))
or modify aspects of DOM elements and components
(for example, [ngStyle](template-syntax.html#ngStyle) and [ngClass](template-syntax.html#ngClass)).
(for example, [ngStyle](guide/template-syntax) and [ngClass](guide/template-syntax)).
Of course, you can also write your own directives. Components such as
`HeroListComponent` are one kind of custom directive.
@ -336,7 +336,7 @@ Registering at a component level means you get a new instance of the
service with each new instance of that component.
<!-- We've vastly oversimplified dependency injection for this overview.
The full story is in the [dependency injection](dependency-injection.html) page. -->
The full story is in the [dependency injection](guide/dependency-injection) page. -->
Points to remember about dependency injection:
@ -359,14 +359,14 @@ Points to remember about dependency injection:
You've learned the basics about the eight main building blocks of an Angular application:
* [Modules](#modules)
* [Components](#components)
* [Templates](#templates)
* [Metadata](#metadata)
* [Data binding](#data-binding)
* [Directives](#directives)
* [Services](#services)
* [Dependency injection](#dependency-injection)
* [Modules](guide/architecture#modules)
* [Components](guide/architecture#components)
* [Templates](guide/architecture#templates)
* [Metadata](guide/architecture#metadata)
* [Data binding](guide/architecture#data-binding)
* [Directives](guide/architecture#directives)
* [Services](guide/architecture#services)
* [Dependency injection](guide/architecture#dependency-injection)
That's a foundation for everything else in an Angular application,
and it's more than enough to get going.
@ -375,7 +375,7 @@ But it doesn't include everything you need to know.
Here is a brief, alphabetical list of other important Angular features and services.
Most of them are covered in this documentation (or soon will be).
> [**Animations**](animations.html): Animate component behavior
> [**Animations**](guide/animations): Animate component behavior
without deep knowledge of animation techniques or CSS with Angular's animation library.
> **Change detection**: The change detection documentation will cover how Angular decides that a component property value has changed,
@ -384,18 +384,18 @@ when to update the screen, and how it uses **zones** to intercept asynchronous a
> **Events**: The events documentation will cover how to use components and services to raise events with mechanisms for
publishing and subscribing to events.
> [**Forms**](forms.html): Support complex data entry scenarios with HTML-based validation and dirty checking.
> [**Forms**](guide/forms): Support complex data entry scenarios with HTML-based validation and dirty checking.
> [**HTTP**](server-communication.html): Communicate with a server to get data, save data, and invoke server-side actions with an HTTP client.
> [**HTTP**](guide/server-communication): Communicate with a server to get data, save data, and invoke server-side actions with an HTTP client.
> [**Lifecycle hooks**](lifecycle-hooks.html): Tap into key moments in the lifetime of a component, from its creation to its destruction,
> [**Lifecycle hooks**](guide/lifecycle-hooks): Tap into key moments in the lifetime of a component, from its creation to its destruction,
by implementing the lifecycle hook interfaces.
> [**Pipes**](pipes.html): Use pipes in your templates to improve the user experience by transforming values for display. Consider this `currency` pipe expression:
> [**Pipes**](guide/pipes): Use pipes in your templates to improve the user experience by transforming values for display. Consider this `currency` pipe expression:
>
> > `price | currency:'USD':true`
>
> It displays a price of 42.33 as `$42.33`.
> [**Router**](router.html): Navigate from page to page within the client
> [**Router**](guide/router): Navigate from page to page within the client
application and never leave the browser.

View File

@ -9,19 +9,15 @@ An **Attribute** directive changes the appearance or behavior of a DOM element.
# Contents
* [Directives overview](#directive-overview)
* [Build a simple attribute directive](#write-directive)
* [Apply the attribute directive to an element in a template](#apply-directive)
* [Respond to user-initiated events](#respond-to-user)
* [Pass values into the directive with an _@Input_ data binding](#bindings)
* [Bind to a second property](#second-property)
* [Directives overview](guide/attribute-directives#directive-overview)
* [Build a simple attribute directive](guide/attribute-directives#write-directive)
* [Apply the attribute directive to an element in a template](guide/attribute-directives#apply-directive)
* [Respond to user-initiated events](guide/attribute-directives#respond-to-user)
* [Pass values into the directive with an _@Input_ data binding](guide/attribute-directives#bindings)
* [Bind to a second property](guide/attribute-directives#second-property)
Try the <live-example title="Attribute Directive example"></live-example>.
{@a directive-overview}
## Directives overview
There are three kinds of directives in Angular:
@ -31,20 +27,19 @@ There are three kinds of directives in Angular:
1. Attribute directives&mdash;change the appearance or behavior of an element, component, or another directive.
*Components* are the most common of the three directives.
You saw a component for the first time in the [QuickStart](../quickstart.html) guide.
You saw a component for the first time in the [QuickStart](quickstart) guide.
*Structural Directives* change the structure of the view.
Two examples are [NgFor](template-syntax.html#ngFor) and [NgIf](template-syntax.html#ngIf).
Learn about them in the [Structural Directives](structural-directives.html) guide.
Two examples are [NgFor](guide/template-syntax) and [NgIf](guide/template-syntax).
Learn about them in the [Structural Directives](guide/structural-directives) guide.
*Attribute directives* are used as attributes of elements.
The built-in [NgStyle](template-syntax.html#ngStyle) directive in the [Template Syntax](template-syntax.html) guide, for example,
The built-in [NgStyle](guide/template-syntax) directive in the
[Template Syntax](guide/template-syntax) guide, for example,
can change several element styles at the same time.
{@a write-directive}
## Build a simple attribute directive
An attribute directive minimally requires building a controller class annotated with
`@Directive`, which specifies the selector that identifies
the attribute.
@ -53,35 +48,45 @@ The controller class implements the desired directive behavior.
This page demonstrates building a simple _myHighlight_ attribute
directive to set an element's background color
when the user hovers over that element. You can apply it like this:
{@example 'attribute-directives/ts/src/app/app.component.1.html' region='applied'}
### Write the directive code
Follow the [setup](setup.html) instructions for creating a new local project
Follow the [setup](guide/setup) instructions for creating a new local project
named <span ngio-ex>attribute-directives</span>.
Create the following source file in `src/app` with the following code:
Create the following source file in the indicated folder:
{@example 'attribute-directives/ts/src/app/highlight.directive.1.ts'}
The `import` statement specifies symbols from the Angular `core`:
1. `Directive` provides the functionality of the `@Directive` decorator.
1. `ElementRef` [injects](guide/dependency-injection) into the directive's constructor
so the code can access the DOM element.
1. `Input` allows data to flow from the binding expression into the directive.
Next, the `@Directive` decorator function contains the directive metadata in a configuration object
as an argument.
`@Directive` requires a CSS selector to identify
the HTML in the template that is associated with the directive.
The [CSS selector for an attribute](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors)
is the attribute name in square brackets.
Here, the directive's selector is `[myHighlight]`.
Angular locates all elements in the template that have an attribute named `myHighlight`.
### Why not call it "highlight"?
Though *highlight* is a more concise name than *myHighlight* and would work,
a best practice is to prefix selector names to ensure
they don't conflict with standard HTML attributes.
This also reduces the risk of colliding with third-party directive names.
Make sure you do **not** prefix the `highlight` directive name with **`ng`** because
that prefix is reserved for Angular and using it could cause bugs that are difficult to diagnose. For a simple demo, the short prefix, `my`, helps distinguish your custom directive.
<p>
After the <code> @Directive </code> metadata comes the directive's controller class, called <code> HighlightDirective </code> , which contains the logic for the directive.
</p>
that prefix is reserved for Angular and using it could cause bugs that are difficult to diagnose.
For a simple demo, the short prefix, `my`, helps distinguish your custom directive.
After the `@Directive` metadata comes the directive's controller class,
called `HighlightDirective`, which contains the logic for the directive.
<span if-docs="ts">Exporting `HighlightDirective` makes it accessible to other components.</span>
Angular creates a new instance of the directive's controller class for
each matching element, injecting an Angular `ElementRef`
@ -89,29 +94,28 @@ into the constructor.
`ElementRef` is a service that grants direct access to the DOM element
through its `nativeElement` property.
{@a apply-directive}
## Apply the attribute directive
To use the new `HighlightDirective`, create a template that
applies the directive as an attribute to a paragraph (`<p>`) element.
In Angular terms, the `<p>` element is the attribute **host**.
<p>
Put the template in its own <code> </code> file that looks like this:
</p>
Put the template in its own <span ngio-ex>app.component.html</span>
file that looks like this:
{@example 'attribute-directives/ts/src/app/app.component.1.html'}
Now reference this template in the `AppComponent`:
{@example 'attribute-directives/ts/src/app/app.component.ts'}
Next, add an `import` statement to fetch the `Highlight` directive and
add that class to the `declarations` NgModule metadata. This way Angular
recognizes the directive when it encounters `myHighlight` in the template.
{@example 'attribute-directives/ts/src/app/app.module.ts'}
Now when the app runs, the `myHighlight` directive highlights the paragraph text.
@ -123,8 +127,10 @@ Now when the app runs, the `myHighlight` directive highlights the paragraph text
### Your directive isn't working?
Did you remember to add the directive to the `declarations` attribute of `@NgModule`? It is easy to forget!
Did you remember to add the directive to the `declarations` attribute of `@NgModule`?
It is easy to forget!
Open the console in the browser tools and look for an error like this:
<code-example format="nocode">
EXCEPTION: Template parse errors:
Can't bind to 'myHighlight' since it isn't a known property of 'p'.
@ -140,9 +146,6 @@ It created an instance of the `HighlightDirective` class and
injected a reference to the `<p>` element into the directive's constructor
which sets the `<p>` element's background style to yellow.
{@a respond-to-user}
## Respond to user-initiated events
Currently, `myHighlight` simply sets an element color.
@ -152,14 +155,10 @@ and respond by setting or clearing the highlight color.
Begin by adding `HostListener` to the list of imported symbols;
add the `Input` symbol as well because you'll need it soon.
{@example 'attribute-directives/ts/src/app/highlight.directive.ts' region='imports'}
Then add two eventhandlers that respond when the mouse enters or leaves, each adorned by the `HostListener` !{_decorator}.
{@example 'attribute-directives/ts/src/app/highlight.directive.2.ts' region='mouse-methods'}
The `@HostListener` !{_decorator} lets you subscribe to events of the DOM element that hosts an attribute directive, the `<p>` in this case.
Then add two eventhandlers that respond when the mouse enters or leaves,
each adorned by the `HostListener` !{_decorator}.
The `@HostListener` !{_decorator} lets you subscribe to events of the DOM
element that hosts an attribute directive, the `<p>` in this case.
Of course you could reach into the DOM with standard JavaScript and and attach event listeners manually.
There are at least three problems with _that_ approach:
@ -169,24 +168,19 @@ There are at least three problems with _that_ approach:
1. Talking to DOM API directly isn't a best practice.
The handlers delegate to a helper method that sets the color on the DOM element, `#{_priv}el`,
which you declare and initialize in the constructor.
{@example 'attribute-directives/ts/src/app/highlight.directive.2.ts' region='ctor'}
Here's the updated directive in full:
{@example 'attribute-directives/ts/src/app/highlight.directive.2.ts'}
Run the app and confirm that the background color appears when the mouse hovers over the `p` and
disappears as it moves out.
Run the app and confirm that the background color appears when
the mouse hovers over the `p` and disappears as it moves out.
<figure class='image-display'>
<img src="assets/images/devguide/attribute-directives/highlight-directive-anim.gif" alt="Second Highlight"> </img>
</figure>
{@a bindings}
## Pass values into the directive with an _@Input_ data binding
Currently the highlight color is hard-coded _within_ the directive. That's inflexible.
@ -194,9 +188,6 @@ In this section, you give the developer the power to set the highlight color whi
Start by adding a `highlightColor` property to the directive class like this:
{@example 'attribute-directives/ts/src/app/highlight.directive.2.ts' region='color'}
{@a input}
### Binding to an _@Input_ property
@ -204,33 +195,18 @@ Start by adding a `highlightColor` property to the directive class like this:
Notice the `@Input` !{_decorator}. It adds metadata to the class that makes the directive's `highlightColor` property available for binding.
It's called an *input* property because data flows from the binding expression _into_ the directive.
Without that input metadata, Angular rejects the binding; see [below](#why-input "Why add @Input?") for more about that.
Without that input metadata, Angular rejects the binding; see [below](guide/attribute-directives#why-input "Why add @Input?") for more about that.
Try it by adding the following directive binding variations to the `AppComponent` template:
{@example 'attribute-directives/ts/src/app/app.component.1.html' region='color-1'}
Add a `color` property to the `AppComponent`.
{@example 'attribute-directives/ts/src/app/app.component.1.ts' region='class'}
Let it control the highlight color with a property binding.
{@example 'attribute-directives/ts/src/app/app.component.1.html' region='color-2'}
That's good, but it would be nice to _simultaneously_ apply the directive and set the color _in the same attribute_ like this.
{@example 'attribute-directives/ts/src/app/app.component.html' region='color'}
The `[myHighlight]` attribute binding both applies the highlighting directive to the `<p>` element
and sets the directive's highlight color with a property binding.
You're re-using the directive's attribute selector (`[myHighlight]`) to do both jobs.
That's a crisp, compact syntax.
You'll have to rename the directive's `highlightColor` property to `myHighlight` because that's now the color property binding name.
{@example 'attribute-directives/ts/src/app/highlight.directive.2.ts' region='color-2'}
This is disagreeable. The word, `myHighlight`, is a terrible property name and it doesn't convey the property's intent.
@ -244,64 +220,58 @@ _Inside_ the directive the property is known as `highlightColor`.
_Outside_ the directive, where you bind to it, it's known as `myHighlight`.
You get the best of both worlds: the property name you want and the binding syntax you want:
{@example 'attribute-directives/ts/src/app/app.component.html' region='color'}
Now that you're binding to `highlightColor`, modify the `onMouseEnter()` method to use it.
If someone neglects to bind to `highlightColor`, highlight in "red" by default.
If someone neglects to bind to `highlightColor`, highlight in red:
Here's the latest version of the directive class.
## Write a harness to try it
{@example 'attribute-directives/ts/src/app/highlight.directive.3.ts' region='mouse-enter'}
Here's the latest version of the directive class.## Write a harness to try itIt may be difficult to imagine how this directive actually works.
It may be difficult to imagine how this directive actually works.
In this section, you'll turn `AppComponent` into a harness that
lets you pick the highlight color with a radio button and bind your color choice to the directive.
Update `app.component.html` as follows:
Revise the `AppComponent.color` so that it has no initial value.Here is the harness and directive in action.
Update <span ngio-ex>app.component.html</span> as follows:
Revise the `AppComponent.color` so that it has no initial value.
Here are the harness and directive in action.
<figure class='image-display'>
<img src="assets/images/devguide/attribute-directives/highlight-directive-v2-anim.gif" alt="Highlight v.2"> </img>
</figure>
{@a second-property}
## Bind to a second property
This highlight directive has a single customizable property. In a real app, it may need more.
At the moment, the default color&mdash;the color that prevails until
the user picks a highlight color&mdash;is hard-coded as "red".
Let the template developer set the default color.
Add a second **input** property to `HighlightDirective` called `defaultColor`:Revise the directive's `onMouseEnter` so that it first tries to highlight with the `highlightColor`,
Add a second **input** property to `HighlightDirective` called `defaultColor`:
Revise the directive's `onMouseEnter` so that it first tries to highlight with the `highlightColor`,
then with the `defaultColor`, and falls back to "red" if both properties are undefined.
{@example 'attribute-directives/ts/src/app/highlight.directive.ts' region='mouse-enter'}
How do you bind to a second property when you're already binding to the `myHighlight` attribute name?
As with components, you can add as many directive property bindings as you need by stringing them along in the template.
The developer should be able to write the following template HTML to both bind to the `AppComponent.color`
and fall back to "violet" as the default color.
{@example 'attribute-directives/ts/src/app/app.component.html' region='defaultColor'}
Angular knows that the `defaultColor` binding belongs to the `HighlightDirective`
because you made it _public_ with the `@Input` !{_decorator}.
Here's how the harness should work when you're done coding.
<figure class='image-display'>
<img src="assets/images/devguide/attribute-directives/highlight-directive-final-anim.gif" alt="Final Highlight"> </img>
</figure>
## Summary
This page covered how to:
- [Build an **attribute directive**](#write-directive) that modifies the behavior of an element.
- [Apply the directive](#apply-directive) to an element in a template.
- [Respond to **events**](#respond-to-user) that change the directive's behavior.
- [**Bind** values to the directive](#bindings).
- [Build an **attribute directive**](guide/attribute-directives#write-directive) that modifies the behavior of an element.
- [Apply the directive](guide/attribute-directives#apply-directive) to an element in a template.
- [Respond to **events**](guide/attribute-directives#respond-to-user) that change the directive's behavior.
- [**Bind** values to the directive](guide/attribute-directives#bindings).
The final source code follows:
@ -341,20 +311,11 @@ The final source code follows:
You can also experience and download the <live-example title="Attribute Directive example"></live-example>.
{@a why-input}
### Appendix: Why add _@Input_?
In this demo, the `hightlightColor` property is an ***input*** property of
the `HighlightDirective`. You've seen it applied without an alias:
{@example 'attribute-directives/ts/src/app/highlight.directive.2.ts' region='color'}
You've seen it with an alias:
{@example 'attribute-directives/ts/src/app/highlight.directive.ts' region='color'}
Either way, the `@Input` !{_decorator} tells Angular that this property is
_public_ and available for binding by a parent component.
Without `@Input`, Angular refuses to bind to the property.
@ -377,20 +338,17 @@ Only then can it be bound by some other component or directive.
You can tell if `@Input` is needed by the position of the property name in a binding.
* When it appears in the template expression to the ***right*** of the equals (=),
it belongs to the template's component and does not require the `@Input` !{_decorator}.
it belongs to the template's component and does not require the `@Input` !{_decorator}.
* When it appears in **square brackets** ([ ]) to the **left** of the equals (=),
the property belongs to some _other_ component or directive;
that property must be adorned with the `@Input` !{_decorator}.
the property belongs to some _other_ component or directive;
that property must be adorned with the `@Input` !{_decorator}.
Now apply that reasoning to the following example:
{@example 'attribute-directives/ts/src/app/app.component.html' region='color'}
* The `color` property in the expression on the right belongs to the template's component.
The template and its component trust each other.
The `color` property doesn't require the `@Input` !{_decorator}.
The template and its component trust each other.
The `color` property doesn't require the `@Input` !{_decorator}.
* The `myHighlight` property on the left refers to an _aliased_ property of the `MyHighlightDirective`,
not a property of the template's component. There are trust issues.
Therefore, the directive property must carry the `@Input` !{_decorator}.
* The `myHighlight` property on the left refers to an _aliased_ property of the `HighlightDirective`,
not a property of the template's component. There are trust issues.
Therefore, the directive property must carry the `@Input` !{_decorator}.

View File

@ -244,7 +244,7 @@ using <a href="https://saucelabs.com/" target="_blank">SauceLabs</a> and
Angular is built on the latest standards of the web platform.
Targeting such a wide range of browsers is challenging because they do not support all features of modern browsers.
You compensate by loading polyfill scripts ("polyfills") on the host web page (`index.html`)
You can compensate by loading polyfill scripts ("polyfills") on the host web page (`index.html`)
that implement missing features in JavaScript.
{@example 'quickstart/ts/src/index.html' region='polyfills'}
@ -252,12 +252,12 @@ that implement missing features in JavaScript.
A particular browser may require at least one polyfill to run _any_ Angular application.
You may need additional polyfills for specific features.
The tables below will help you determine which polyfills to load, depending on the browsers you target and the features you use.
The tables below can help you determine which polyfills to load, depending on the browsers you target and the features you use.
~~~ {.alert.is-important}
The suggested polyfills are the ones we know will run full Angular applications.
The suggested polyfills are the ones that run full Angular applications.
You may need additional polyfills to support features not covered by this list.
Note that polyfills cannot magically transform an old, slow browser into a modern, fast one.
@ -307,7 +307,7 @@ These are the polyfills required to run an Angular application on each supported
<td>
[ES6](#core-es6)
[ES6](guide/browser-support#core-es6)
</td>
@ -322,7 +322,7 @@ These are the polyfills required to run an Angular application on each supported
<td>
[ES6<br>classList](#classlist)
[ES6<br>classList](guide/browser-support#classlist)
</td>
@ -370,7 +370,7 @@ Here are the features which may require additional polyfills:
<td>
[Web Animations](#web-animations)
[Web Animations](guide/browser-support#web-animations)
</td>
@ -390,7 +390,7 @@ Here are the features which may require additional polyfills:
<td>
[Intl API](#intl)
[Intl API](guide/browser-support#intl)
</td>
@ -410,7 +410,7 @@ Here are the features which may require additional polyfills:
<td>
[classList](#classlist)
[classList](guide/browser-support#classlist)
</td>
@ -430,7 +430,7 @@ Here are the features which may require additional polyfills:
<td>
[Typed&nbsp;Array](#typedarray) <br>[Blob](#blob)<br>[FormData](#formdata)
[Typed&nbsp;Array](guide/browser-support#typedarray) <br>[Blob](guide/browser-support#blob)<br>[FormData](guide/browser-support#formdata)
</td>
@ -457,7 +457,7 @@ Below are the polyfills which are used to test the framework itself. They are a
<th>
Licence
License
</th>
@ -517,7 +517,7 @@ Below are the polyfills which are used to test the framework itself. They are a
<td>
MIT / Unicode licence
MIT / Unicode license
</td>
@ -611,4 +611,5 @@ Below are the polyfills which are used to test the framework itself. They are a
</table>
\* Figures are for minified and gzipped code, computed with the <a href="http://closure-compiler.appspot.com/home" target="_blank">closure compiler</a>
\* Figures are for minified and gzipped code,
computed with the <a href="http://closure-compiler.appspot.com/home" target="_blank">closure compiler</a>.

View File

@ -2,48 +2,48 @@
Dependency Injection
@intro
Techniques for Dependency Injection
Techniques for Dependency Injection.
@description
Dependency Injection is a powerful pattern for managing code dependencies.
In this cookbook we will explore many of the features of Dependency Injection (DI) in Angular.
<a id="toc"></a>## Table of contents
[Application-wide dependencies](#app-wide-dependencies)
[Application-wide dependencies](guide/cb-dependency-injection#app-wide-dependencies)
[External module configuration](#external-module-configuration)
[External module configuration](guide/cb-dependency-injection#external-module-configuration)
[*@Injectable* and nested service dependencies](#nested-dependencies)
[*@Injectable* and nested service dependencies](guide/cb-dependency-injection#nested-dependencies)
[Limit service scope to a component subtree](#service-scope)
[Limit service scope to a component subtree](guide/cb-dependency-injection#service-scope)
[Multiple service instances (sandboxing)](#multiple-service-instances)
[Multiple service instances (sandboxing)](guide/cb-dependency-injection#multiple-service-instances)
[Qualify dependency lookup with *@Optional* and *@Host*](#qualify-dependency-lookup)
[Qualify dependency lookup with *@Optional* and *@Host*](guide/cb-dependency-injection#qualify-dependency-lookup)
[Inject the component's DOM element](#component-element)
[Inject the component's DOM element](guide/cb-dependency-injection#component-element)
[Define dependencies with providers](#providers)
* [The *provide* object literal](#provide)
* [useValue - the *value provider*](#usevalue)
* [useClass - the *class provider*](#useclass)
* [useExisting - the *alias provider*](#useexisting)
* [useFactory - the *factory provider*](#usefactory)
[Define dependencies with providers](guide/cb-dependency-injection#providers)
* [The *provide* object literal](guide/cb-dependency-injection#provide)
* [useValue - the *value provider*](guide/cb-dependency-injection#usevalue)
* [useClass - the *class provider*](guide/cb-dependency-injection#useclass)
* [useExisting - the *alias provider*](guide/cb-dependency-injection#useexisting)
* [useFactory - the *factory provider*](guide/cb-dependency-injection#usefactory)
[Provider token alternatives](#tokens)
* [class-interface](#class-interface)
* [OpaqueToken](#opaque-token)
[Provider token alternatives](guide/cb-dependency-injection#tokens)
* [class-interface](guide/cb-dependency-injection#class-interface)
* [OpaqueToken](guide/cb-dependency-injection#opaque-token)
[Inject into a derived class](#di-inheritance)
[Inject into a derived class](guide/cb-dependency-injection#di-inheritance)
[Find a parent component by injection](#find-parent)
* [Find parent with a known component type](#known-parent)
* [Cannot find a parent by its base class](#base-parent)
* [Find a parent by its class-interface](#class-interface-parent)
* [Find a parent in a tree of parents (*@SkipSelf*)](#parent-tree)
* [A *provideParent* helper function](#provideparent)
[Find a parent component by injection](guide/cb-dependency-injection#find-parent)
* [Find parent with a known component type](guide/cb-dependency-injection#known-parent)
* [Cannot find a parent by its base class](guide/cb-dependency-injection#base-parent)
* [Find a parent by its class-interface](guide/cb-dependency-injection#class-interface-parent)
* [Find a parent in a tree of parents (*@SkipSelf*)](guide/cb-dependency-injection#parent-tree)
* [A *provideParent* helper function](guide/cb-dependency-injection#provideparent)
[Break circularities with a forward class reference (*forwardRef*)](#forwardref)
[Break circularities with a forward class reference (*forwardRef*)](guide/cb-dependency-injection#forwardref)
**See the <live-example name="cb-dependency-injection"></live-example>**
of the code supporting this cookbook.
@ -62,7 +62,7 @@ Service classes can act as their own providers which is why listing them in the
is all the registration we need.
A *provider* is something that can create or deliver a service.
Angular creates a service instance from a class provider by "new-ing" it.
Learn more about providers [below](#providers).Now that we've registered these services,
Learn more about providers [below](guide/cb-dependency-injection#providers).Now that we've registered these services,
Angular can inject them into the constructor of *any* component or service, *anywhere* in the application.
{@example 'cb-dependency-injection/ts/src/app/hero-bios.component.ts' region='ctor'}
@ -79,7 +79,7 @@ We do this when (a) we expect the service to be injectable everywhere
or (b) we must configure another application global service _before it starts_.
We see an example of the second case here, where we configure the Component Router with a non-default
[location strategy](../guide/router.html#location-strategy) by listing its provider
[location strategy](guide/router) by listing its provider
in the `providers` list of the `AppModule`.
@ -136,7 +136,7 @@ Technically, the `@Injectable()`decorator is only _required_ for a service class
The `LoggerService` doesn't depend on anything. The logger would work if we omitted `@Injectable()`
and the generated code would be slightly smaller.
But the service would break the moment we gave it a dependency and we'd have to go back and
But the service would break the moment we gave it a dependency and we'd have to go back
and add `@Injectable()` to fix it. We add `@Injectable()` from the start for the sake of consistency and to avoid future pain.
@ -264,7 +264,7 @@ But when this component is projected into a *parent* component, that parent comp
We look at this second, more interesting case in our next example.
### Demonstration
The `HeroBiosAndContactsComponent` is a revision of the `HeroBiosComponent` that we looked at [above](#hero-bios-component).
The `HeroBiosAndContactsComponent` is a revision of the `HeroBiosComponent` that we looked at [above](guide/cb-dependency-injection#hero-bios-component).
{@example 'cb-dependency-injection/ts/src/app/hero-bios.component.ts' region='hero-bios-and-contacts'}
@ -325,7 +325,7 @@ Although we strive to avoid it, many visual effects and 3rd party tools (such as
require DOM access.
To illustrate, we've written a simplified version of the `HighlightDirective` from
the [Attribute Directives](../guide/attribute-directives.html) chapter.
the [Attribute Directives](guide/attribute-directives) chapter.
{@example 'cb-dependency-injection/ts/src/app/highlight.directive.ts'}
@ -362,7 +362,7 @@ Here's a typical example:
{@example 'cb-dependency-injection/ts/src/app/hero-bios.component.ts' region='ctor'}
Angular asks the injector for the service associated with the `LoggerService` and
Angular asks the injector for the service associated with the `LoggerService`
and assigns the returned value to the `logger` parameter.
Where did the injector get that value?
@ -371,7 +371,7 @@ If it doesn't, it may be able to make one with the help of a ***provider***.
A *provider* is a recipe for delivering a service associated with a *token*.
If the injector doesn't have a provider for the requested *token*, it delegates the request
to its parent injector, where the process repeats until there are no more injectors.
If the search is futile, the injector throws an error ... unless the request was [optional](#optional).
If the search is futile, the injector throws an error ... unless the request was [optional](guide/cb-dependency-injection#optional).
Let's return our attention to providers themselves.A new injector has no providers.
Angular initializes the injectors it creates with some providers it cares about.
@ -408,7 +408,7 @@ It's visually simple: a few properties and the output of a logger. The code behi
#### The *provide* object literal
The `provide` object literal takes a *token* and a *definition object*.
The *token* is usually a class but [it doesn't have to be](#tokens).
The *token* is usually a class but [it doesn't have to be](guide/cb-dependency-injection#tokens).
The *definition* object has one main property, (e.g. `useValue`) that indicates how the provider
should create or return the provided value.
@ -433,7 +433,7 @@ The `Hero` provider token is a class which makes sense because the value is a `H
and the consumer of the injected hero would want the type information.
The `TITLE` provider token is *not a class*.
It's a special kind of provider lookup key called an [OpaqueToken](#opaquetoken).
It's a special kind of provider lookup key called an [OpaqueToken](guide/cb-dependency-injection#opaquetoken).
We often use an `OpaqueToken` when the dependency is a simple value like a string, a number, or a function.
The value of a *value provider* must be defined *now*. We can't create the value later.
@ -486,7 +486,7 @@ creating ***two ways to access the same service object***.
Narrowing an API through an aliasing interface is _one_ important use case for this technique.
We're aliasing for that very purpose here.
Imagine that the `LoggerService` had a large API (it's actually only three methods and a property).
We want to shrink that API surface to just the two members exposed by the `MinimalLogger` [*class-interface*](#class-interface):
We want to shrink that API surface to just the two members exposed by the `MinimalLogger` [*class-interface*](guide/cb-dependency-injection#class-interface):
{@example 'cb-dependency-injection/ts/src/app/date-logger.service.ts' region='minimal-logger'}
@ -718,7 +718,7 @@ after injecting an `AlexComponent` into her constructor:
{@example 'cb-dependency-injection/ts/src/app/parent-finder.component.ts' region='cathy'}
We added the [@Optional](#optional) qualifier for safety but
We added the [@Optional](guide/cb-dependency-injection#optional) qualifier for safety but
the <live-example name="cb-dependency-injection"></live-example>
confirms that the `alex` parameter is set.
@ -741,7 +741,7 @@ That's not possible because TypeScript interfaces disappear from the transpiled
which doesn't support interfaces. There's no artifact we could look for.We're not claiming this is good design.
We are asking *can a component inject its parent via the parent's base class*?
The sample's `CraigComponent` explores this question. [Looking back](#alex)
The sample's `CraigComponent` explores this question. [Looking back](guide/cb-dependency-injection#alex)
we see that the `Alex` component *extends* (*inherits*) from a class named `Base`.
{@example 'cb-dependency-injection/ts/src/app/parent-finder.component.ts' region='alex-class-signature'}
@ -758,14 +758,14 @@ confirms that the `alex` parameter is null.
<a id="class-interface-parent"></a>
### Find a parent by its class-interface
We can find a parent component with a [class-interface](#class-interface).
We can find a parent component with a [class-interface](guide/cb-dependency-injection#class-interface).
The parent must cooperate by providing an *alias* to itself in the name of a *class-interface* token.
Recall that Angular always adds a component instance to its own injector;
that's why we could inject *Alex* into *Cathy* [earlier](#known-parent).
that's why we could inject *Alex* into *Cathy* [earlier](guide/cb-dependency-injection#known-parent).
We write an [*alias provider*](#useexisting) &mdash; a `provide` object literal with a `useExisting` definition &mdash;
We write an [*alias provider*](guide/cb-dependency-injection#useexisting) &mdash; a `provide` object literal with a `useExisting` definition &mdash;
that creates an *alternative* way to inject the same component instance
and add that provider to the `providers` array of the `@Component` metadata for the `AlexComponent`:
@ -774,8 +774,8 @@ and add that provider to the `providers` array of the `@Component` metadata for
{@example 'cb-dependency-injection/ts/src/app/parent-finder.component.ts' region='alex-providers'}
[Parent](#parent-token) is the provider's *class-interface* token.
The [*forwardRef*](#forwardref) breaks the circular reference we just created by having the `AlexComponent` refer to itself.
[Parent](guide/cb-dependency-injection#parent-token) is the provider's *class-interface* token.
The [*forwardRef*](guide/cb-dependency-injection#forwardref) breaks the circular reference we just created by having the `AlexComponent` refer to itself.
*Carol*, the third of *Alex*'s child components, injects the parent into its `parent` parameter, the same way we've done it before:
@ -802,8 +802,8 @@ Here's *Barry*:
{@example 'cb-dependency-injection/ts/src/app/parent-finder.component.ts' region='barry'}
*Barry*'s `providers` array looks just like [*Alex*'s](#alex-providers).
If we're going to keep writing [*alias providers*](#useexisting) like this we should create a [helper function](#provideparent).
*Barry*'s `providers` array looks just like [*Alex*'s](guide/cb-dependency-injection#alex-providers).
If we're going to keep writing [*alias providers*](guide/cb-dependency-injection#useexisting) like this we should create a [helper function](guide/cb-dependency-injection#provideparent).
For now, focus on *Barry*'s constructor:
<md-tab-group>
@ -841,7 +841,7 @@ Here's *Alice*, *Barry* and family in action:
{@a parent-token}
### The *Parent* class-interface
We [learned earlier](#class-interface) that a *class-interface* is an abstract class used as an interface rather than as a base class.
We [learned earlier](guide/cb-dependency-injection#class-interface) that a *class-interface* is an abstract class used as an interface rather than as a base class.
Our example defines a `Parent` *class-interface* .
@ -870,7 +870,7 @@ It doesn't in this example *only* to demonstrate that the code will compile and
### A *provideParent* helper function
Writing variations of the same parent *alias provider* gets old quickly,
especially this awful mouthful with a [*forwardRef*](#forwardref):
especially this awful mouthful with a [*forwardRef*](guide/cb-dependency-injection#forwardref):
{@example 'cb-dependency-injection/ts/src/app/parent-finder.component.ts' region='alex-providers'}

View File

@ -2,7 +2,7 @@
Cookbook
@intro
A collection of recipes for common Angular application scenarios
A collection of recipes for common Angular application scenarios.
@description
The *Cookbook* offers answers to common implementation questions.

View File

@ -13,18 +13,18 @@ Now you can download the sample code for any guide and run it locally.
Look for the new download links next to the "live example" links.
## Template Syntax/Structural Directives: refreshed (2017-02-06)
The [_Template-Syntax_](template-syntax.html) and [_Structural Directives_](structural-directives.html)
The [_Template-Syntax_](guide/template-syntax) and [_Structural Directives_](guide/structural-directives)
guides were significantly revised for clarity, accuracy, and current recommended practices.
Discusses `<ng-container>`.
Revised samples are more clear and cover all topics discussed.
## NEW: Samples re-structured with `src/` folder (2017-02-02)
All documentation samples have been realigned with the default folder structure of the angular-cli.
That's a step along the road to basing our sample in the angular-cli.
All documentation samples have been realigned with the default folder structure of the Angular CLI.
That's a step along the road to basing the sample in the Angular CLI.
But it's also good in its own right.
It helps clearly separate app code from setup and configuration files.
We've updated all samples with an `src/` folder at the project root.
All samples now have a `src/` folder at the project root.
The former `app/` folder moves under `src/`.
Read about moving your existing project to this structure in
<a href="https://github.com/angular/quickstart#updating-to-a-newer-version-of-the-quickstart-repo" target="_blank" target="Migrating samples/quickstart app to the src folder">
@ -38,83 +38,83 @@ Notably:
* Added `lite-server` configuration (`bs-config.json`) to serve `src/`.
## NEW: Reactive Forms guide (2017-01-31)
The new [**Reactive Forms**](reactive-forms.html) guide explains how and why to build a "reactive form".
The new [**Reactive Forms**](guide/reactive-forms) guide explains how and why to build a "reactive form".
"Reactive Forms" are the code-based counterpart to the declarative "Template Driven" forms approach
introduced in the [Forms](forms.html) guide.
introduced in the [Forms](guide/forms) guide.
Check it out before you decide how to add forms to your app.
Remember also that you can use both techniques in the same app,
choosing the approach that best fits each scenario.
## NEW: Deployment guide (2017-01-30)
The new [Deployment](deployment.html) guide describes techniques for putting your application on a server.
The new [Deployment](guide/deployment) guide describes techniques for putting your application on a server.
It includes important advice on optimizing for production.
## Hierarchical Dependency Injection: refreshed (2017-01-13)
[Hierarchical Dependency Injection](hierarchical-dependency-injection.html) guide significantly revised.
Closes issue #3086
Revised samples are more clear and cover all topics discussed.
[Hierarchical Dependency Injection](guide/hierarchical-dependency-injection) guide is significantly revised.
Closes issue #3086.
Revised samples are clearer and cover all topics discussed.
## Miscellaneous (2017-01-05)
* [Setup](setup.html) guide:
* [Setup](guide/setup) guide:
added (optional) instructions on how to remove _non-essential_ files.
* No longer consolidate RxJS operator imports in `rxjs-extensions` file; each file should import what it needs.
* All samples prepend template/style URLS URLs w/ `./` ... and so should you.
* [Style Guide](style-guide.html): copy edits and revised rules.
* All samples prepend template/style URLs with `./` as a best practice.
* [Style Guide](guide/style-guide): copy edits and revised rules.
## Router: more detail (2016-12-21)
Added more information to the [Router](router.html) guide
Added more information to the [Router](guide/router) guide
including sections named outlets, wildcard routes, and preload strategies.
## Http: how to set default request headers (and other request options) (2016-12-14)
## HTTP: how to set default request headers (and other request options) (2016-12-14)
Added section on how to set default request headers (and other request options) to
[Http](server-communication.html#override-default-request-options) guide.
[HTTP](guide/server-communication) guide.
## Testing: added component test plunkers (2016-12-02)
Added two plunkers that each test _one simple component_ so you can write a component test plunker of your own: <live-example name="setup" plnkr="quickstart-specs">one</live-example> for the QuickStart seed's `AppComponent` and <live-example name="testing" plnkr="banner-specs">another</live-example> for the Testing guide's `BannerComponent`.
Linked to these plunkers in [Testing](testing.html#live-examples) and [Setup anatomy](setup-systemjs-anatomy) guides.
Linked to these plunkers in [Testing](guide/testing) and [Setup anatomy](guide/setup-systemjs-anatomy) guides.
## Internationalization: pluralization and _select_ (2016-11-30)
The [Internationalization (i18n)](../cookbook/i18n.html) guide explains how to handle pluralization and
The [Internationalization (i18n)](cookbook/i18n) guide explains how to handle pluralization and
translation of alternative texts with `select`.
The sample demonstrates these features too.
## Testing: karma file updates (2016-11-30)
* karma.config + karma-test-shim can handle multiple spec source paths;
see quickstart issue: [angular/quickstart#294](https://github.com/angular/quickstart/issues/294)
* Displays Jasmine Runner output in the karma-launched browser
* `karma.config` + `karma-test-shim` can handle multiple spec source paths;
see quickstart issue: [angular/quickstart#294](https://github.com/angular/quickstart/issues/294).
* Displays Jasmine Runner output in the karma-launched browser.
## QuickStart Rewrite (2016-11-18)
The QuickStart is completely rewritten so that it actually is quick.
It references a minimal "Hello Angular" app running in Plunker.
The new [Setup](setup.html) page tells you how to install a local development environment
The new [Setup](guide/setup) page tells you how to install a local development environment
by downloading (or cloning) the QuickStart github repository.
You are no longer asked to copy-and-paste code into setup files that were not explained anyway.
## Sync with Angular v.2.2.0 (2016-11-14)
Docs and code samples updated and tested with Angular v.2.2.0
Docs and code samples updated and tested with Angular v.2.2.0.
## UPDATE: NgUpgrade Guide for the AOT friendly _upgrade/static_ module (2016-11-14)
The updated [NgUpgrade Guide](upgrade.html) guide covers the
The updated [NgUpgrade Guide](guide/upgrade) guide covers the
new AOT friendly `upgrade/static` module
released in v.2.2.0, which is the recommended
facility for migrating from AngularJS to Angular.
The documentation for the version prior to v.2.2.0 has been removed.
## ES6 described in "TypeScript to JavaScript" (2016-11-14)
The updated "[TypeScript to JavaScript](../cookbook/ts-to-js.html)" cookbook
The updated [TypeScript to JavaScript](cookbook/ts-to-js) cookbook
now explains how to write apps in ES6/7
by translating the common idioms in the TypeScript documentation examples
(and elsewhere on the web) to ES6/7 and ES5.
## Sync with Angular v.2.1.1 (2016-10-21)
Docs and code samples updated and tested with Angular v.2.1.0
Docs and code samples updated and tested with Angular v.2.1.1.
## npm _@types_ packages replace _typings_ (2016-10-20)
Documentation samples now get TypeScript type information for 3rd party libraries
from npm `@types` packages rather than with the _typings_ tooling.
The `typings.json` file is gone.
The "[AngularJS Upgrade](upgrade.html)" guide reflects this change.
The [AngularJS Upgrade](guide/upgrade) guide reflects this change.
The `package.json` installs `@types/angular` and several `@types/angular-...`
packages in support of upgrade; these are not needed for pure Angular development.
@ -135,29 +135,29 @@ _before_ the user navigates to them for improved perceived performance.
New `:enter` and `:leave` aliases make animation more natural.
## Sync with Angular v.2.1.0 (2016-10-12)
Docs and code samples updated and tested with Angular v.2.1.0
Docs and code samples updated and tested with Angular v.2.1.0.
## NEW "Ahead of time (AOT) Compilation" cookbook (2016-10-11)
The NEW [Ahead of time (AOT) Compilation](../cookbook/aot-compiler.html) cookbook
The NEW [Ahead of time (AOT) Compilation](cookbook/aot-compiler) cookbook
explains what AOT compilation is and why you'd want it.
It demonstrates the basics with a QuickStart app
followed by the more advanced considerations of compiling and bundling the Tour of Heroes.
## Sync with Angular v.2.0.2 (2016-10-6)
Docs and code samples updated and tested with Angular v.2.0.2
Docs and code samples updated and tested with Angular v.2.0.2.
## "Routing and Navigation" guide with the _Router Module_ (2016-10-5)
The [Routing and Navigation](router.html) guide now locates route configuration
The [Routing and Navigation](guide/router) guide now locates route configuration
in a _Routing Module_.
The _Routing Module_ replaces the previous _routing object_ involving the `ModuleWithProviders`.
All guided samples with routing use the _Routing Module_ and prose content has been updated,
most conspicuously in the
[NgModule](ngmodule.html) guide and [NgModule FAQ](../cookbook/ngmodule-faq.html) cookbook.
[NgModule](guide/ngmodule) guide and [NgModule FAQ](cookbook/ngmodule-faq) cookbook.
## New "Internationalization" Cookbook (2016-09-30)
Added a new [Internationalization (i18n)](../cookbook/i18n.html) cookbook that shows how
Added a new [Internationalization (i18n)](cookbook/i18n) cookbook that shows how
to use Angular "i18n" facilities to translate template text into multiple languages.
## "angular-in-memory-web-api" package rename (2016-09-27)
@ -171,21 +171,21 @@ The new "angular-in-memory-web-api" has new features.
## "Style Guide" with _NgModules_ (2016-09-27)
[StyleGuide](style-guide.html) explains our recommended conventions for Angular modules (NgModule).
[StyleGuide](guide/style-guide) explains recommended conventions for Angular modules (NgModule).
Barrels now are far less useful and have been removed from the style guide;
they remain valuable but are not a matter of Angular style.
We also relaxed the rule that discouraged use of the `@Component.host` property.
Also relaxed the rule that discouraged use of the `@Component.host` property.
## _moduleId: module.id_ everywhere (2016-09-25)
Sample components that get their templates or styles with `templateUrl` or `styleUrls`
have been converted to _module-relative_ URLs.
We added the `moduleId: module.id` property-and-value to their `@Component` metadata.
Added the `moduleId: module.id` property-and-value to their `@Component` metadata.
This change is a requirement for compilation with AOT compiler when the app loads
modules with SystemJS as the samples currently do.
## "Lifecycle Hooks" guide simplified (2016-09-24)
The [Lifecycle Hooks](lifecycle-hooks.html) guide is shorter, simpler, and
The [Lifecycle Hooks](guide/lifecycle-hooks) guide is shorter, simpler, and
draws more attention to the order in which Angular calls the hooks.

View File

@ -2,32 +2,32 @@
Component Interaction
@intro
Share information between different directives and components
Share information between different directives and components.
@description
<a id="top"></a>This cookbook contains recipes for common component communication scenarios
in which two or more components share information.
<a id="toc"></a>## Table of contents
[Pass data from parent to child with input binding](#parent-to-child)
[Pass data from parent to child with input binding](guide/component-communication#parent-to-child)
[Intercept input property changes with a setter](#parent-to-child-setter)
[Intercept input property changes with a setter](guide/component-communication#parent-to-child-setter)
[Intercept input property changes with *ngOnChanges*](#parent-to-child-on-changes)
[Intercept input property changes with *ngOnChanges*](guide/component-communication#parent-to-child-on-changes)
[Parent listens for child event](#child-to-parent)
[Parent listens for child event](guide/component-communication#child-to-parent)
[Parent interacts with child via a *local variable*](#parent-to-child-local-var)
[Parent interacts with child via a *local variable*](guide/component-communication#parent-to-child-local-var)
[Parent calls a *ViewChild*](#parent-to-view-child)
[Parent calls a *ViewChild*](guide/component-communication#parent-to-view-child)
[Parent and children communicate via a service](#bidirectional-service)
[Parent and children communicate via a service](guide/component-communication#bidirectional-service)
**See the <live-example name="cb-component-communication"></live-example>**.
<a id="parent-to-child"></a>## Pass data from parent to child with input binding
`HeroChildComponent` has two ***input properties***,
typically adorned with [@Input decorations](../guide/template-syntax.html#inputs-outputs).
typically adorned with [@Input decorations](guide/template-syntax).
{@example 'cb-component-communication/ts/src/app/hero-child.component.ts'}
@ -54,7 +54,7 @@ E2E test that all children were instantiated and displayed as expected:
{@example 'cb-component-communication/e2e-spec.ts' region='parent-to-child'}
[Back to top](#top)
[Back to top](guide/component-communication#top)
<a id="parent-to-child-setter"></a>## Intercept input property changes with a setter
@ -83,14 +83,14 @@ E2E tests of input property setter with empty and non-empty names:
{@example 'cb-component-communication/e2e-spec.ts' region='parent-to-child-setter'}
[Back to top](#top)
[Back to top](guide/component-communication#top)
<a id="parent-to-child-on-changes"></a>## Intercept input property changes with *ngOnChanges*
Detect and act upon changes to input property values with the `ngOnChanges` method of the `OnChanges` lifecycle hook interface.
May prefer this approach to the property setter when watching multiple, interacting input properties.
Learn about `ngOnChanges` in the [LifeCycle Hooks](../guide/lifecycle-hooks.html) chapter.This `VersionChildComponent` detects changes to the `major` and `minor` input properties and composes a log message reporting these changes:
Learn about `ngOnChanges` in the [LifeCycle Hooks](guide/lifecycle-hooks) chapter.This `VersionChildComponent` detects changes to the `major` and `minor` input properties and composes a log message reporting these changes:
{@example 'cb-component-communication/ts/src/app/version-child.component.ts'}
@ -114,15 +114,15 @@ the expected `ngOnChanges` calls and values:
{@example 'cb-component-communication/e2e-spec.ts' region='parent-to-child-onchanges'}
[Back to top](#top)
[Back to top](guide/component-communication#top)
<a id="child-to-parent"></a>## Parent listens for child event
The child component exposes an `EventEmitter` property with which it `emits`events when something happens.
The child component exposes an `EventEmitter` property with which it `emits` events when something happens.
The parent binds to that event property and reacts to those events.
The child's `EventEmitter` property is an ***output property***,
typically adorned with an [@Output decoration](../guide/template-syntax.html#inputs-outputs)
typically adorned with an [@Output decoration](guide/template-syntax)
as seen in this `VoterComponent`:
@ -150,7 +150,7 @@ Test that clicking the *Agree* and *Disagree* buttons update the appropriate cou
{@example 'cb-component-communication/e2e-spec.ts' region='child-to-parent'}
[Back to top](#top)
[Back to top](guide/component-communication#top)
## Parent interacts with child via *local variable*
@ -200,7 +200,7 @@ Test also that clicking the *Stop* button pauses the countdown timer:
{@example 'cb-component-communication/e2e-spec.ts' region='countdown-timer-tests'}
[Back to top](#top)
[Back to top](guide/component-communication#top)
<a id="parent-to-view-child"></a>## Parent calls a *ViewChild*
@ -214,9 +214,9 @@ must read or write child component values or must call child component methods.
When the parent component *class* requires that kind of access,
we ***inject*** the child component into the parent as a *ViewChild*.
We'll illustrate this technique with the same [Countdown Timer](#countdown-timer-example) example.
We'll illustrate this technique with the same [Countdown Timer](guide/component-communication#countdown-timer-example) example.
We won't change its appearance or behavior.
The child [CountdownTimerComponent](#countdown-timer-example) is the same as well.
The child [CountdownTimerComponent](guide/component-communication#countdown-timer-example) is the same as well.
We are switching from the *local variable* to the *ViewChild* technique
solely for the purpose of demonstration.Here is the parent, `CountdownViewChildParentComponent`:
@ -248,7 +248,7 @@ We use `setTimeout` to wait one tick and then revise the `seconds` method so
that it takes future values from the timer component.
### Test it
Use [the same countdown timer tests](#countdown-tests) as before.[Back to top](#top)
Use [the same countdown timer tests](guide/component-communication#countdown-tests) as before.[Back to top](guide/component-communication#top)
<a id="bidirectional-service"></a>## Parent and children communicate via a service
@ -298,4 +298,4 @@ and verify that the *History* meets expectations:
{@example 'cb-component-communication/e2e-spec.ts' region='bidirectional-service'}
[Back to top](#top)
[Back to top](guide/component-communication#top)

View File

@ -33,7 +33,7 @@ It would be much easier to write and maintain our application components if we c
We can if we build our application as `commonjs` modules and load those modules
with a suitable package loader such as `systemjs` or `webpack`.
Learn why [below](#why-default).
Learn why [below](guide/component-relative-paths#why-default).
The Angular CLI uses these technologies and defaults to the
*component-relative path* approach described here.
@ -98,7 +98,7 @@ The result looks like this:
~~~ {.alert.is-helpful}
Webpack users may prefer [an alternative approach](#webpack).
Webpack users may prefer [an alternative approach](guide/component-relative-paths#webpack).
~~~
@ -189,6 +189,6 @@ properties that reference *component-relative URLS.
{@example 'webpack/ts/src/app/app.component.ts'}
Webpack will do a `require` behind the scenes to load the templates and styles. Read more [here](../guide/webpack.html#highlights).
Webpack will do a `require` behind the scenes to load the templates and styles. Read more [here](guide/webpack).
See the [Introduction to Webpack](../guide/webpack.html).
See the [Introduction to Webpack](guide/webpack).

View File

@ -16,12 +16,12 @@ This page describes how to load and apply these component styles.
## Table Of Contents
* [Using component styles](#using-component-styles)
* [Special selectors](#special-selectors)
* [Loading styles into components](#loading-styles)
* [Controlling view encapsulation: native, emulated, and none](#view-encapsulation)
* [Appendix 1: Inspecting the CSS generated in emulated view encapsulation](#inspect-generated-css)
* [Appendix 2: Loading styles with relative URLs](#relative-urls)
* [Using component styles](guide/component-styles#using-component-styles)
* [Special selectors](guide/component-styles#special-selectors)
* [Loading styles into components](guide/component-styles#loading-styles)
* [Controlling view encapsulation: native, emulated, and none](guide/component-styles#view-encapsulation)
* [Appendix 1: Inspecting the CSS generated in emulated view encapsulation](guide/component-styles#inspect-generated-css)
* [Appendix 2: Loading styles with relative URLs](guide/component-styles#relative-urls)
You can run the <live-example></live-example> in Plunker and download the code from there.
@ -120,7 +120,7 @@ The `/deep/` selector also has the alias `>>>`. You can use either interchangeab
Use the `/deep/` and `>>>` selectors only with *emulated* view encapsulation.
Emulated is the default and most commonly used view encapsulation. For more information, see the
[Controlling view encapsulation](#view-encapsulation) section.
[Controlling view encapsulation](guide/component-styles#view-encapsulation) section.
~~~
@ -201,7 +201,7 @@ Choose from the following modes:
view inside that shadow DOM. The component's styles are included within the shadow DOM.
* `Emulated` view encapsulation (the default) emulates the behavior of shadow DOM by preprocessing
(and renaming) the CSS code to effectively scope the CSS to the component's view.
For details, see [Appendix 1](#inspect-generated-css).
For details, see [Appendix 1](guide/component-styles#inspect-generated-css).
* `None` means that Angular does no view encapsulation.
Angular adds the CSS to the global styles.
The scoping rules, isolations, and protections discussed earlier don't apply.

View File

@ -11,13 +11,13 @@ we really can't build an Angular application without it.
It's used so widely that almost everyone just calls it _DI_.
In this chapter we'll learn what DI is and why we want it.
Then we'll learn [how to use it](#angular-di) in an Angular app.
Then we'll learn [how to use it](guide/dependency-injection#angular-di) in an Angular app.
- [Why dependency injection?](#why-dependency-injection)
- [Angular dependency injection](#angular-dependency-injection)
- [Injector providers](#injector-providers)
- [Dependency injection tokens](#dependency-injection-tokens)
- [Summary](#summary)
- [Why dependency injection?](guide/dependency-injection#why-dependency-injection)
- [Angular dependency injection](guide/dependency-injection#angular-dependency-injection)
- [Injector providers](guide/dependency-injection#injector-providers)
- [Dependency injection tokens](guide/dependency-injection#dependency-injection-tokens)
- [Summary](guide/dependency-injection#summary)
Run the <live-example></live-example>.
@ -170,7 +170,7 @@ That sounds nice. What does it do for us when building components in Angular?
Let's see, one step at a time.
We'll begin with a simplified version of the `HeroesComponent`
that we built in the [The Tour of Heroes](../tutorial/).
that we built in the [The Tour of Heroes](tutorial/).
<md-tab-group>
@ -219,7 +219,7 @@ write the service code in its own file.
Our `HeroService` exposes a `getHeroes` method that returns
the same mock data as before, but none of its consumers need to know that.
Notice the `@Injectable()` #{_decorator} above the service class.
We'll discuss its purpose [shortly](#injectable).
We'll discuss its purpose [shortly](guide/dependency-injection#injectable).
We aren't even pretending this is a real service.
If we were actually getting data from a remote server, the API would have to be
@ -239,7 +239,7 @@ We don't have to create an Angular injector.
Angular creates an application-wide injector for us during the bootstrap process.
We do have to configure the injector by registering the **providers**
that create the services our application requires.
We'll explain what [providers](#providers) are later in this chapter.
We'll explain what [providers](guide/dependency-injection#providers) are later in this chapter.
### Registering providers in a component
Here's a revised `HeroesComponent` that registers the `HeroService`.
@ -251,7 +251,7 @@ Here's a revised `HeroesComponent` that registers the `HeroService`.
The `HeroListComponent` should get heroes from the injected `HeroService`.
Per the dependency injection pattern, the component must ask for the service in its
constructor, [as we explained earlier](#ctor-injection).
constructor, [as we explained earlier](guide/dependency-injection#ctor-injection).
It's a small change:
<md-tab-group>
@ -301,10 +301,10 @@ would be explicitly created:
{@example 'dependency-injection/ts/src/app/car/car-injector.ts' region='injector-create-and-call'}
We won't find code like that in the Tour of Heroes or any of our other samples.
We *could* write code that [explicitly creates an injector](#explicit-injector) if we *had* to, but we rarely do.
We *could* write code that [explicitly creates an injector](guide/dependency-injection#explicit-injector) if we *had* to, but we rarely do.
Angular takes care of creating and calling injectors
when it creates components for us &mdash; whether through HTML markup, as in `<hero-list></hero-list>`,
or after navigating to a component with the [router](./router.html).
or after navigating to a component with the [router](guide/router).
If we let Angular do its job, we'll enjoy the benefits of automated dependency injection.
### Singleton services
@ -314,7 +314,7 @@ In our example, a single `HeroService` instance is shared among the
However, Angular DI is an hierarchical injection
system, which means that nested injectors can create their own service instances.
Learn more about that in the [Hierarchical Injectors](./hierarchical-dependency-injection.html) chapter.
Learn more about that in the [Hierarchical Injectors](guide/hierarchical-dependency-injection) chapter.
### Testing the component
We emphasized earlier that designing a class for dependency injection makes the class easier to test.
@ -327,7 +327,7 @@ under test:
{@example 'dependency-injection/ts/src/app/test.component.ts' region='spec'}
Learn more in [Testing](./testing.html).
Learn more in [Testing](guide/testing).
### When the service needs a service
Our `HeroService` is very simple. It doesn't have any dependencies of its own.
@ -453,7 +453,7 @@ We wrote the `providers` #{_array} like this:
{@example 'dependency-injection/ts/src/app/providers.component.ts' region='providers-3'}
The first is the [token](#token) that serves as the key for both locating a dependency value
The first is the [token](guide/dependency-injection#token) that serves as the key for both locating a dependency value
and registering the provider.
The second is a !{_secondParam},
@ -528,8 +528,8 @@ which makes this object play the logger role.
{@example 'dependency-injection/ts/src/app/providers.component.ts' region='providers-7'}
See more `useValue` examples in the
[Non-class dependencies](#non-class-dependencies) and
[OpaqueToken](#opaquetoken) sections.
[Non-class dependencies](guide/dependency-injection#non-class-dependencies) and
[OpaqueToken](guide/dependency-injection#opaquetoken) sections.
<div id='factory-provider'>
@ -583,7 +583,7 @@ We inject both the `Logger` and the `UserService` into the factory provider and
The `useFactory` field tells Angular that the provider is a factory function
whose implementation is the `heroServiceFactory`.
The `deps` property is #{_an} #{_array} of [provider tokens](#token).
The `deps` property is #{_an} #{_array} of [provider tokens](guide/dependency-injection#token).
The `Logger` and `UserService` classes serve as tokens for their own class providers.
The injector resolves these tokens and injects the corresponding services into the matching factory function parameters.
Notice that we captured the factory provider in #{_an} #{exportedvar}, `heroServiceProvider`.
@ -647,7 +647,7 @@ This is especially convenient when we consider that most dependency values are p
{@example 'dependency-injection/ts/src/app/app.config.ts' region='config'}
We'd like to make this configuration object available for injection.
We know we can register an object with a [value provider](#value-provider).
We know we can register an object with a [value provider](guide/dependency-injection#value-provider).
### OpaqueToken
One solution to choosing a provider token for non-class dependencies is
@ -700,7 +700,7 @@ adding a parameter to a constructor.
Angular dependency injection is more capable than we've described.
We can learn more about its advanced features, beginning with its support for
nested injectors, in the
[Hierarchical Dependency Injection](hierarchical-dependency-injection.html) chapter.
[Hierarchical Dependency Injection](guide/hierarchical-dependency-injection) chapter.
## Appendix: Working with injectors directly

View File

@ -10,21 +10,21 @@ This page describes tools and techniques for deploy and optimize your Angular ap
{@a toc}
## Table of contents
* [Overview](#overview)
* [Simplest deployment possible](#dev-deploy)
* [Optimize for production](#optimize)
* [Ahead-of-Time (AOT) compilation](#aot)
* [Webpack](#webpack)
* [Tree shaking with _rollup_](#rollup)
* [Pruned libraries](#prune)
* [Measure performance first](#measure)
* [Angular configuration](#angular-configuration)
* [The `base` tag](#base-tag)
* [Enable production mode](#enable-prod-mode)
* [Lazy loading](#lazy-loading)
* [Server configuration](#server-configuration)
* [Routed apps must fallback to `index.html`](#fallback)
* [CORS: requesting services from a different server](#cors)
* [Overview](guide/deployment#overview)
* [Simplest deployment possible](guide/deployment#dev-deploy)
* [Optimize for production](guide/deployment#optimize)
* [Ahead-of-Time (AOT) compilation](guide/deployment#aot)
* [Webpack](guide/deployment#webpack)
* [Tree shaking with _rollup_](guide/deployment#rollup)
* [Pruned libraries](guide/deployment#prune)
* [Measure performance first](guide/deployment#measure)
* [Angular configuration](guide/deployment#angular-configuration)
* [The `base` tag](guide/deployment#base-tag)
* [Enable production mode](guide/deployment#enable-prod-mode)
* [Lazy loading](guide/deployment#lazy-loading)
* [Server configuration](guide/deployment#server-configuration)
* [Routed apps must fallback to `index.html`](guide/deployment#fallback)
* [CORS: requesting services from a different server](guide/deployment#cors)
{@a overview}
@ -34,20 +34,20 @@ This page describes tools and techniques for deploy and optimize your Angular ap
This guide describes techniques for preparing and deploying an Angular application to a server running remotely.
The techniques progress from _easy but suboptimal_ to _more optimal and more involved_.
* The [simple way](#dev-deploy "Simplest deployment possible") is to copy the development environment to the server.
* The [simple way](guide/deployment#dev-deploy "Simplest deployment possible") is to copy the development environment to the server.
* [_Ahead of Time_ compilation (AOT)](#aot "AOT Compilation") is the first of
[several optimization strategies](#optimize).
You'll also want to read the [detailed instructions in the AOT Cookbook](../cookbook/aot-compiler.html "AOT Cookbook").
* [_Ahead of Time_ compilation (AOT)](guide/deployment#aot "AOT Compilation") is the first of
[several optimization strategies](guide/deployment#optimize).
You'll also want to read the [detailed instructions in the AOT Cookbook](cookbook/aot-compiler).
* [Webpack](#webpack "Webpack Optimization") is a popular general purpose packaging tool with a rich ecosystem, including plugins for AOT.
The Angular [webpack guide](webpack.html "Webpack: an introduction") can get you started and
* [Webpack](guide/deployment#webpack "Webpack Optimization") is a popular general purpose packaging tool with a rich ecosystem, including plugins for AOT.
The Angular [webpack guide](guide/webpack) can get you started and
_this_ page provides additional optimization advice, but you'll probably have to learn more about webpack on your own.
* The [Angular configuration](#angular-configuration "Angular configuration") section calls attention to
* The [Angular configuration](guide/deployment#angular-configuration "Angular configuration") section calls attention to
specific client application changes that could improve performance.
* The [Server configuration](#server-configuration "Server configuration") section describes
* The [Server configuration](guide/deployment#server-configuration "Server configuration") section describes
server-side changes that may be necessary, _no matter how you deploy the application_.
@ -61,7 +61,7 @@ directly out of the development environment.
It's already running locally. You'll just copy it, almost _as is_,
to a non-local server that others can reach.
1. Copy _everything_ (or [_almost_ everything](#node-modules "Loading npm packages from the web"))
1. Copy _everything_ (or [_almost_ everything](guide/deployment#node-modules "Loading npm packages from the web"))
from the local project folder to a folder on the server.
1. If you're serving the app out of a subfolder,
@ -69,12 +69,12 @@ edit a version of `index.html` to set the `<base href>` appropriately.
For example, if the URL to `index.html` is `www.mysite.com/my/app/`, set the _base href_ to
`<base href="/my/app/">`.
Otherwise, leave it alone.
[More on this below](#base-tag).
[More on this below](guide/deployment#base-tag).
1. Configure the server to redirect requests for missing files to `index.html`.
[More on this below](#fallback).
[More on this below](guide/deployment#fallback).
1. Enable production mode as [described below](#enable-prod-mode) (optional).
1. Enable production mode as [described below](guide/deployment#enable-prod-mode) (optional).
That's the simplest deployment you can do.
@ -83,7 +83,7 @@ That's the simplest deployment you can do.
This is _not_ a production deployment. It's not optimized and it won't be fast for users.
It might be good enough for sharing your progress and ideas internally with managers, teammates, and other stakeholders.
Be sure to read about [optimizing for production](#optimize "Optimizing for production") below.
Be sure to read about [optimizing for production](guide/deployment#optimize "Optimizing for production") below.
@ -184,7 +184,7 @@ The following trivial router sample app shows these changes.
Practice with this sample before attempting these techniques on your application.
1. Follow the [setup instructions](../guide/setup.html "Angular QuickStart setup") for creating a new project
1. Follow the [setup instructions](guide/setup) for creating a new project
named <ngio-ex path="simple-deployment"></ngio-ex>.
1. Add the "Simple deployment" sample files shown above.
@ -254,9 +254,9 @@ Apps compiled with AOT launch faster for several reasons.
* You don't download the Angular compiler, which is pretty big on its own.
* The compiler discards unused Angular directives that a tree-shaking tool can then exclude.
Learn more about AOT Compilation in the [AOT Cookbook](../cookbook/aot-compiler.html "AOT Cookbook")
Learn more about AOT Compilation in the [AOT Cookbook](cookbook/aot-compiler)
which describes running the AOT compiler from the command line
and using [_rollup_](#rollup) for bundling, minification, uglification and tree shaking.
and using [_rollup_](guide/deployment#rollup) for bundling, minification, uglification and tree shaking.
{@a webpack}
@ -264,7 +264,7 @@ and using [_rollup_](#rollup) for bundling, minification, uglification and tree
<a href="https://webpack.js.org/" target="_blank" title="Webpack 2">Webpack 2</a> is another
great option for inlining templates and style-sheets, for bundling, minifying, and uglifying the application.
The "[Webpack: an introduction](webpack.html "Webpack: an introduction")" guide will get you started
The "[Webpack: an introduction](guide/webpack)" guide will get you started
using webpack with Angular.
Consider configuring _Webpack_ with the official
@ -338,7 +338,7 @@ For example, given the `<base href="/my/app/">`, the browser resolves a URL such
into a server request for `my/app/some/place/foo.jpg`.
During navigation, the Angular router uses the _base href_ as the base path to component, template, and module files.
See also the [*APP_BASE_HREF*](../api/common/index/APP_BASE_HREF-let.html "API: APP_BASE_HREF") alternative.In development, you typically start the server in the folder that holds `index.html`.
See also the [*APP_BASE_HREF*](api/common/index/APP_BASE_HREF-let) alternative.In development, you typically start the server in the folder that holds `index.html`.
That's the root folder and you'd add `<base href="/">` near the top of `index.html` because `/` is the root of the app.
But on the shared or production server, you might serve the app from a subfolder.
@ -361,7 +361,7 @@ console:
Switching to production mode can make it run faster by disabling development specific checks such as the dual change detection cycles.
To enable [production mode](../api/core/index/enableProdMode-function.html) when running remotely, add the following code to the `main.ts`.
To enable [production mode](api/core/index/enableProdMode-function) when running remotely, add the following code to the `main.ts`.
{@example 'deployment/ts/src/main.ts' region='enableProdMode'}
@ -375,8 +375,8 @@ You can dramatically reduce launch time by only loading the application modules
absolutely must be present when the app starts.
Configure the Angular Router to defer loading of all other modules (and their associated code), either by
[waiting until the app has launched](router.html#preloading "Preloading")
or by [_lazy loading_](router.html#asynchronous-routing "Lazy loading")
[waiting until the app has launched](guide/router)
or by [_lazy loading_](guide/router)
them on demand.
#### Don't eagerly import something from a lazy loaded module
@ -545,5 +545,5 @@ Read about how to enable CORS for specific servers at
{@a next-steps}
## Next steps
If you want to go beyond the [simple _copy-deploy_](#dev-deploy "Simplest deployment possible") approach,
read the [AOT Cookbook](../cookbook/aot-compiler.html "AOT Cookbook") next.
If you want to go beyond the [simple _copy-deploy_](guide/deployment#dev-deploy "Simplest deployment possible") approach,
read the [AOT Cookbook](cookbook/aot-compiler) next.

View File

@ -19,9 +19,9 @@ The final UI looks like this:
# Contents
* [Showing component properties with interpolation](#interpolation).
* [Showing !{_an} !{_array} property with NgFor](#ngFor).
* [Conditional display with NgIf](#ngIf).
* [Showing component properties with interpolation](guide/displaying-data#interpolation).
* [Showing !{_an} !{_array} property with NgFor](guide/displaying-data#ngFor).
* [Conditional display with NgIf](guide/displaying-data#ngIf).
The <live-example></live-example> demonstrates all of the syntax and code
snippets described in this page.
@ -31,7 +31,7 @@ The easiest way to display a component property
is to bind the property name through interpolation.
With interpolation, you put the property name in the view template, enclosed in double curly braces: `{{myHero}}`.
Follow the [setup](setup.html) instructions for creating a new project
Follow the [setup](guide/setup) instructions for creating a new project
named <ngio-ex path="displaying-data"></ngio-ex>.
Then modify the <ngio-ex path="app.component.ts"></ngio-ex> file by
@ -93,22 +93,22 @@ It marks that `<li>` element (and its children) as the "repeater template":
~~~ {.alert.is-important}
Don't forget the leading asterisk (\*) in `*ngFor`. It is an essential part of the syntax.
For more information, see the [Template Syntax](./template-syntax.html#ngFor) page.
For more information, see the [Template Syntax](guide/template-syntax) page.
~~~
Notice the `hero` in the `ngFor` double-quoted instruction;
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.
more about template input variables in the [microsyntax](guide/template-syntax) section of
the [Template Syntax](guide/template-syntax) page.
Angular duplicates the `<li>` 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
context for the interpolation in the double curly braces.
In this case, `ngFor` is displaying !{_an} !{_array}, but `ngFor` can
repeat items for any [iterable](!{_iterableUrl}) object.Now the heroes appear in an unordered list.
repeat items for any [iterable](guide/!{_iterableUrl}) object.Now the heroes appear in an unordered list.
<figure class='image-display'>
<img src="assets/images/devguide/displaying-data/hero-names-list.png" alt="After ngfor"> </img>
@ -150,7 +150,7 @@ To see it in action, add the following paragraph at the bottom of the template:
~~~ {.alert.is-important}
Don't forget the leading asterisk (\*) in `*ngIf`. It is an essential part of the syntax.
Read more about `ngIf` and `*` in the [ngIf section](./template-syntax.html#ngIf) of the [Template Syntax](./template-syntax.html) page.
Read more about `ngIf` and `*` in the [ngIf section](guide/template-syntax) of the [Template Syntax](guide/template-syntax) page.
~~~
@ -160,8 +160,8 @@ The template expression inside the double quotes,
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.
see the [template expressions](guide/template-syntax) section of the
[Template Syntax](guide/template-syntax) page.
~~~ {.alert.is-helpful}

View File

@ -2,7 +2,7 @@
Dynamic Component Loader
@intro
Load components dynamically
Load components dynamically.
@description
Component templates are not always fixed. An application may need to load new components at runtime.
@ -11,11 +11,11 @@ In this cookbook we show how to use `ComponentFactoryResolver` to add components
<a id="toc"></a>## Table of contents
[Dynamic Component Loading](#dynamic-loading)
[Dynamic Component Loading](guide/dynamic-component-loader#dynamic-loading)
[Where to load the component](#where-to-load)
[Where to load the component](guide/dynamic-component-loader#where-to-load)
[Loading components](#loading-components)
[Loading components](guide/dynamic-component-loader#loading-components)
<a id="dynamic-loading"></a>## Dynamic Component Loading

View File

@ -2,7 +2,7 @@
Dynamic Forms
@intro
Render dynamic forms with FormGroup
Render dynamic forms with FormGroup.
@description
We can't always justify the cost and time to build handcrafted forms,
@ -21,15 +21,15 @@ The agency is constantly tinkering with the application process.
We can create the forms on the fly *without changing our application code*.
<a id="toc"></a>## Table of contents
[Bootstrap](#bootstrap)
[Bootstrap](guide/dynamic-form#bootstrap)
[Question Model](#object-model)
[Question Model](guide/dynamic-form#object-model)
[Form Component](#form-component)
[Form Component](guide/dynamic-form#form-component)
[Questionnaire Metadata](#questionnaire-metadata)
[Questionnaire Metadata](guide/dynamic-form#questionnaire-metadata)
[Dynamic Template](#dynamic-template)
[Dynamic Template](guide/dynamic-form#dynamic-template)
**See the <live-example name="cb-dynamic-form"></live-example>**.
<a id="bootstrap"></a>## Bootstrap
@ -129,7 +129,7 @@ The `ngSwitch` determines which type of question to display.
In both components we're relying on Angular's **formGroup** to connect the template HTML to the
underlying control objects, populated from the question model with display and validation rules.
`formControlName` and `formGroup` are directives defined in `ReactiveFormsModule`. Our templates can can access these directives directly since we imported `ReactiveFormsModule` from `AppModule`.
`formControlName` and `formGroup` are directives defined in `ReactiveFormsModule`. Our templates can access these directives directly since we imported `ReactiveFormsModule` from `AppModule`.
<a id="questionnaire-metadata"></a>## Questionnaire data`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`.
@ -165,4 +165,4 @@ The final form looks like this:
<img src="assets/images/cookbooks/dynamic-form/dynamic-form.png" alt="Dynamic-Form"> </img>
</figure>
[Back to top](#top)
[Back to top](guide/dynamic-form#top)

View File

@ -2,7 +2,7 @@
Form Validation
@intro
Validate user's form entries
Validate user's form entries.
@description
@ -12,21 +12,21 @@ We can improve overall data quality by validating user input for accuracy and co
In this cookbook we show how to validate user input in the UI and display useful validation messages
using first the template-driven forms and then the reactive forms approach.
Learn more about these choices in the [Forms chapter.](../guide/forms.html)
Learn more about these choices in the [Forms chapter.](guide/forms)
{@a toc}
## Table of Contents
[Simple Template-Driven Forms](#template1)
[Simple Template-Driven Forms](guide/form-validation#template1)
[Template-Driven Forms with validation messages in code](#template2)
[Template-Driven Forms with validation messages in code](guide/form-validation#template2)
[Reactive Forms with validation in code](#reactive)
[Reactive Forms with validation in code](guide/form-validation#reactive)
[Custom validation](#custom-validation)
[Custom validation](guide/form-validation#custom-validation)
[Testing](#testing)
[Testing](guide/form-validation#testing)
{@a live-example}
@ -85,7 +85,7 @@ The full template repeats this kind of layout for each data entry control on the
We shouldn't show errors for a new hero before the user has had a chance to edit the value.
The checks for `dirty` and `touched` prevent premature display of errors.
Learn about `dirty` and `touched` in the [Forms](../guide/forms.html) chapter.The component class manages the hero model used in the data binding
Learn about `dirty` and `touched` in the [Forms](guide/forms) chapter.The component class manages the hero model used in the data binding
as well as other code to support the view.
@ -148,8 +148,8 @@ The `<input>` element HTML is almost the same. There are noteworthy differences:
- The hard-code error message `<divs>` are gone.
- There's a new attribute, `forbiddenName`, that is actually a custom validation directive.
It invalidates the control if the user enters "bob" anywhere in the name ([try it](#live-example)).
We discuss [custom validation directives](#custom-validation) later in this cookbook.
It invalidates the control if the user enters "bob" anywhere in the name ([try it](guide/form-validation#live-example)).
We discuss [custom validation directives](guide/form-validation#custom-validation) later in this cookbook.
- The `#name` template variable is gone because we no longer refer to the Angular control for this element.
@ -179,7 +179,7 @@ the name of that variable as a string (`'heroForm'` in this case).
- The `heroForm` object changes several times during the life of the component, most notably when we add a new hero.
We'll have to re-inspect it periodically.
- Angular calls the `ngAfterViewChecked` [lifecycle hook method](../guide/lifecycle-hooks.html#afterview)
- Angular calls the `ngAfterViewChecked` [lifecycle hook method](guide/lifecycle-hooks)
when anything changes in the view.
That's the right time to see if there's a new `heroForm` object.
@ -245,7 +245,7 @@ Here's how we imported it in the `HeroFormTemplateModule`.
We haven't talked about the `SharedModule` or its `SubmittedComponent` which appears at the bottom of every
form template in this cookbook.
They're not germane to the validation story. Look at the [live example](#live-example) if you're interested.
They're not germane to the validation story. Look at the [live example](guide/form-validation#live-example) if you're interested.
@ -258,7 +258,7 @@ At runtime, Angular interprets the template and derives its _form control model_
**Reactive Forms** takes a different approach.
You create the form control model in code. You write the template with form elements
and`form...` directives from the Angular `ReactiveFormsModule`.
and `form...` directives from the Angular `ReactiveFormsModule`.
At runtime, Angular binds the template elements to your control model based on your instructions.
This approach requires a bit more effort. *You have to write the control model and manage it*.
@ -266,7 +266,7 @@ This approach requires a bit more effort. *You have to write the control model a
In return, you can
* add, change, and remove validation functions on the fly
* manipulate the control model dynamically from within the component
* [test](#testing) validation and control logic with isolated unit tests.
* [test](guide/form-validation#testing) validation and control logic with isolated unit tests.
The third cookbook sample re-writes the hero form in _reactive forms_ style.
@ -346,7 +346,7 @@ Here's the section of code devoted to that process, paired with the template-dri
- we inject the `FormBuilder` in a constructor.
- we call a `buildForm` method in the `ngOnInit` [lifecycle hook method](../guide/lifecycle-hooks.html#hooks-overview)
- we call a `buildForm` method in the `ngOnInit` [lifecycle hook method](guide/lifecycle-hooks)
because that's when we'll have the hero data. We'll call it again in the `addHero` method.
A real app would retrieve the hero asynchronously from a data service, a task best performed in the `ngOnInit` hook.- the `buildForm` method uses the `FormBuilder` (`fb`) to declare the form control model.
Then it attaches the same `onValueChanged` handler (there's a one line difference)
@ -363,9 +363,9 @@ Most of the validator functions are stock validators provided by Angular as stat
Angular has stock validators that correspond to the standard HTML validation attributes.
The `forbiddenNames` validator on the `"name"` control is a custom validator,
discussed in a separate [section below](#custom-validation).
discussed in a separate [section below](guide/form-validation#custom-validation).
Learn more about `FormBuilder` in a _forthcoming_ chapter on reactive forms.
Learn more about `FormBuilder` in the [Introduction to FormBuilder](guide/reactive-forms) section of Reactive Forms guide.
#### Committing hero value changes
In two-way data binding, the user's changes flow automatically from the controls back to the data model properties.
@ -410,7 +410,7 @@ Here's the complete reactive component file, compared to the two template-driven
</md-tab-group>
Run the [live example](#live-example) to see how the reactive form behaves
Run the [live example](guide/form-validation#live-example) to see how the reactive form behaves
and to compare all of the files in this cookbook sample.
@ -461,7 +461,7 @@ The rest of the directive is unremarkable and we present it here without further
{@example 'cb-form-validation/ts/src/app/shared/forbidden-name.directive.ts' region='directive'}
See the [Attribute Directives](../guide/attribute-directives.html) chapter.
See the [Attribute Directives](guide/attribute-directives) chapter.

View File

@ -29,7 +29,7 @@ You can run the <live-example></live-example> in Plunker and download the code f
## Template-driven forms
You can build forms by writing templates in the Angular [template syntax](./template-syntax.html) with
You can build forms by writing templates in the Angular [template syntax](guide/template-syntax) with
the form-specific directives and techniques described in this page.
You can also use a reactive (or model-driven) approach to build forms.
@ -74,7 +74,7 @@ You'll build this form in small steps:
1. Disable the forms *Submit* button until the form is valid.
## Setup
Follow the [setup](setup.html) instructions for creating a new project
Follow the [setup](guide/setup) instructions for creating a new project
named <span ngio-ex>angular-forms</span>.
## Create the Hero model class
@ -119,8 +119,8 @@ Understanding this component requires only the Angular concepts covered in previ
- You defined dummy data for `model` and `powers`, as befits a demo.
Down the road, you can inject a data service to get and save real data
or perhaps expose these properties as inputs and outputs
(see [Input and output properties](./template-syntax.html#inputs-outputs) on the
[Template Syntax](./template-syntax.html) page) for binding to a
(see [Input and output properties](guide/template-syntax) on the
[Template Syntax](guide/template-syntax) page) for binding to a
parent component. This is not a concern now and these future changes won't affect the form.
- You added a `diagnostic` property to return a JSON representation of the model.
It'll help you see what you're doing during development; you've left yourself a cleanup note to discard it later.
@ -230,7 +230,7 @@ You maintain that list internally (in `HeroFormComponent`).
You'll add a `select` to the
form and bind the options to the `powers` list using `ngFor`,
a technique seen previously in the [Displaying Data](./displaying-data.html) page.
a technique seen previously in the [Displaying Data](guide/displaying-data) page.
Add the following HTML *immediately below* the *Alter Ego* group:
This code repeats the `<option>` tag for each power in the list of powers.
@ -247,8 +247,8 @@ Running the app right now would be disappointing.
You don't see hero data because you're not binding to the `Hero` yet.
You know how to do that from earlier pages.
[Displaying Data](./displaying-data.html) teaches property binding.
[User Input](./user-input.html) shows how to listen for DOM events with an
[Displaying Data](guide/displaying-data) teaches property binding.
[User Input](guide/user-input) shows how to listen for DOM events with an
event binding and how to update a component property with the displayed value.
Now you need to display, listen, and extract at the same time.
@ -278,8 +278,8 @@ back again.
That's *two-way data binding*.
For more information, see
[Two-way binding with NgModel](template-syntax.html#ngModel) on the
the [Template Syntax](template-syntax.html) page.
[Two-way binding with NgModel](guide/template-syntax) on the
the [Template Syntax](guide/template-syntax) page.
Notice that you also added a `name` attribute to the `<input>` tag and set it to "name",
which makes sense for the hero's name. Any unique value will do, but using a descriptive name is helpful.
Defining a `name` attribute is a requirement when using `[(ngModel)]` in combination with a form.
@ -287,7 +287,7 @@ Defining a `name` attribute is a requirement when using `[(ngModel)]` in combina
Internally, Angular creates `FormControl` instances and
registers them with an `NgForm` directive that Angular attached to the `<form>` tag.
Each `FormControl` is registered under the name you assigned to the `name` attribute.
Read more in [The NgForm directive](#ngForm), later in this page.
Read more in [The NgForm directive](guide/forms#ngForm), later in this page.
Add similar `[(ngModel)]` bindings and `name` attributes to *Alter Ego* and *Hero Power*.
You'll ditch the input box binding message
and add a new binding (at the top) to the component's `diagnostic` property.
@ -401,7 +401,7 @@ You can leverage those class names to change the appearance of the control.
</table>
Temporarily add a [template reference variable](./template-syntax.html#ref-vars) named `spy`
Temporarily add a [template reference variable](guide/template-syntax) named `spy`
to the _Name_ `<input>` tag and use it to display the input's CSS classes.
Now run the app and look at the _Name_ input box.
Follow these steps *precisely*:
@ -458,7 +458,7 @@ When the user deletes the name, the form should look like this:
</figure>
To achieve this effect, extend the `<input>` tag with the following:
- A [template reference variable](./template-syntax.html#ref-vars).
- A [template reference variable](guide/template-syntax).
- The "*is required*" message in a nearby `<div>`, which you'll display only if the control is invalid.
Here's an example of an error message added to the _name_ input box:
@ -466,7 +466,7 @@ You need a template reference variable to access the input box's Angular control
Here you created a variable called `name` and gave it the value "ngModel".
Why "ngModel"?
A directive's [exportAs](../api/core/index/Directive-decorator.html) property
A directive's [exportAs](api/core/index/Directive-decorator) property
tells Angular how to link the reference variable to the directive.
You set `name` to `ngModel` because the `ngModel` directive's `exportAs` property happens to be "ngModel".
You control visibility of the name error message by binding properties of the `name`
@ -481,7 +481,7 @@ you'll see the error message immediately, before you've done anything.
Some developers want to the message to display only when the user makes an invalid change.
Hiding the message while the control is "pristine" achieves that goal.
You'll see the significance of this choice when you [add a new hero](#new-hero) to the form.
You'll see the significance of this choice when you [add a new hero](guide/forms#new-hero) to the form.
The hero *Alter Ego* is optional so you can leave that be.
@ -540,7 +540,7 @@ The variable `heroForm` is now a reference to the `NgForm` directive that govern
### The _NgForm_ directive
What `NgForm` directive?
You didn't add an [NgForm](../api/forms/index/NgForm-directive.html) directive.
You didn't add an [NgForm](api/forms/index/NgForm-directive) directive.
Angular did. Angular automatically creates and attaches an `NgForm` directive to the `<form>` tag.

View File

@ -2,5 +2,5 @@
Glossary
@intro
Brief definitions of the most important words in the Angular vocabulary
Brief definitions of the most important words in the Angular vocabulary.

View File

@ -6,7 +6,7 @@ Angular's hierarchical dependency injection system supports nested injectors in
@description
You learned the basics of Angular Dependency injection in the
[Dependency Injection](./dependency-injection.html) guide.
[Dependency Injection](guide/dependency-injection) guide.
Angular has a _Hierarchical Dependency Injection_ system.
There is actually a tree of injectors that parallel an application's component tree.
@ -18,7 +18,7 @@ Try the <live-example></live-example>.
## The injector tree
In the [Dependency Injection](./dependency-injection.html) guide,
In the [Dependency Injection](guide/dependency-injection) guide,
you learned how to configure a dependency injector and how to retrieve dependencies where you need them.
In fact, there is no such thing as ***the*** injector.
@ -51,8 +51,9 @@ If it runs out of ancestors, Angular throws an error.
You can cap the bubbling. An intermediate component can declare that it is the "host" component.
The hunt for providers will climb no higher than the injector for that host component.
This a topic for another day.
This is a topic for another day.
### Re-providing a service at different levels
You can re-register a provider for a particular dependency token at multiple levels of the injector tree.
You don't *have* to re-register providers. You shouldn't do so unless you have a good reason.
But you *can*.
@ -67,6 +68,7 @@ All requests bubble up to the root <span if-docs="ts"><code>NgModule</code></spa
## Component injectors
The ability to configure one or more providers at different levels opens up interesting and useful possibilities.
### Scenario: service isolation
Architectural reasons may lead you to restrict access to a service to the application domain where it belongs.
@ -74,27 +76,23 @@ Architectural reasons may lead you to restrict access to a service to the applic
The guide sample includes a `VillainsListComponent` that displays a list of villains.
It gets those villains from a `VillainsService`.
While you could provide `VillainsService` in the root `AppModule` (that's where you'll find the `HeroesService`),
While you _could_ provide `VillainsService` in the root `AppModule` (that's where you'll find the `HeroesService`),
that would make the `VillainsService` available everywhere in the application, including the _Hero_ workflows.
If you later modify the `VillainsService`, you could break something in a hero component somewhere.
That's not supposed to happen but the way you've provided the service creates that risk.
If you later modified the `VillainsService`, you could break something in a hero component somewhere.
That's not supposed to happen but providing the service in the root `AppModule` creates that risk.
Instead, provide the `VillainsService` in the `providers` metadata of the `VillainsListComponent` like this:
{@example 'hierarchical-dependency-injection/ts/src/app/villains-list.component.ts' region='metadata'}
By providing `VillainsService` in the `VillainsListComponent` metadata &mdash; and nowhere else &mdash;,
By providing `VillainsService` in the `VillainsListComponent` metadata and nowhere else,
the service becomes available only in the `VillainsListComponent` and its sub-component tree.
It's still a singleton, but it's a singleton that exist solely in the _villain_ domain.
You are confident that a hero component can't access it. You've reduced your exposure to error.
Now you know that a hero component can't access it. You've reduced your exposure to error.
### Scenario: multiple edit sessions
Many applications allow users to work on several open tasks at the same time.
For example, in a tax preparation application, the preparer could be working several tax returns,
For example, in a tax preparation application, the preparer could be working on several tax returns,
switching from one to the other throughout the day.
This guide demonstrates that scenario with an example in the Tour of Heroes theme.
@ -103,28 +101,30 @@ Imagine an outer `HeroListComponent` that displays a list of super heroes.
To open a hero's tax return, the preparer clicks on a hero name, which opens a component for editing that return.
Each selected hero tax return opens in its own component and multiple returns can be open at the same time.
Each tax return component
* is its own tax return editing session.
* can change a tax return without affecting a return in another component.
* has the ability to save the changes to its tax return or cancel them.
Each tax return component has the following characteristics:
* Is its own tax return editing session.
* Can change a tax return without affecting a return in another component.
* Has the ability to save the changes to its tax return or cancel them.
<figure class='image-display'>
<img src="assets/images/devguide/dependency-injection/hid-heroes-anim.gif" width="400" alt="Heroes in action"> </img>
</figure>
One might suppose that the `TaxReturnComponent` has logic to manage and restore changes.
One might suppose that the `HeroTaxReturnComponent` has logic to manage and restore changes.
That would be a pretty easy task for a simple hero tax return.
In the real world, with a rich tax return data model, the change management would be tricky.
You might delegate that management to a helper service, as this example does.
Here is the `HeroTaxReturnService`.
It caches a single `HeroTaxReturn`, tracks changes to that return, and can save or restore it.
It also delegates to the application-wide, singleton `HeroService`, which it gets by injection.
It also delegates to the application-wide singleton `HeroService`, which it gets by injection.
{@example 'hierarchical-dependency-injection/ts/src/app/hero-tax-return.service.ts'}
Here is the `HeroTaxReturnComponent` that makes use of it.
{@example 'hierarchical-dependency-injection/ts/src/app/hero-tax-return.component.ts'}
The _tax-return-to-edit_ arrives via the input property which is implemented with getters and setters.
@ -138,23 +138,19 @@ Each component would overwrite the tax return that belonged to another hero.
What a mess!
Look closely at the metadata for the `HeroTaxReturnComponent`. Notice the `providers` property.
{@example 'hierarchical-dependency-injection/ts/src/app/hero-tax-return.component.ts' region='providers'}
The `HeroTaxReturnComponent` has its own provider of the `HeroTaxReturnService`.
Recall that every component _instance_ has its own injector.
Providing the service at the component level ensures that _every_ instance of the component gets its own, private instance of the service.
No tax return overwriting. No mess.
The rest of the scenario code relies on other Angular features and techniques that you can learn about elsewhere in the documentation.
You can review it and download it from the <live-example></live-example>
You can review it and download it from the <live-example></live-example>.
### Scenario: specialized providers
Another reason to re-provide a service is to substitute a _more specialized_ implementation of that service,
deeper in the component tree.
Consider again the Car example from the [Dependency Injection](./dependency-injection.html) guide.
Consider again the Car example from the [Dependency Injection](guide/dependency-injection) guide.
Suppose you configured the root injector (marked as A) with _generic_ providers for
`CarService`, `EngineService` and `TiresService`.
@ -181,4 +177,4 @@ its injector produces an instance of `Car` resolved by injector (C) with an `Eng
The code for this _cars_ scenario is in the `car.components.ts` and `car.services.ts` files of the sample
which you can review and download from the <live-example></live-example>
which you can review and download from the <live-example></live-example>.

View File

@ -12,17 +12,17 @@ Angular's _internationalization_ (_i18n_) tools help make your app available in
## Table of contents
* [Angular and i18n template translation](#angular-i18n)
* [Mark text with the _i18n_ attribute](#i18n-attribute)
* [Add _i18n-..._ translation attributes](#translate-attributes)
* [Handle singular and plural](#cardinality)
* [Select among alternative texts](#select)
* [Create a translation source file with the **_ng-xi18n_ extraction tool**](#ng-xi18n)
* [Translate text messages](#translate)
* [Merge the completed translation file into the app](#merge)
* [Merge with the JIT compiler](#jit)
* [Internationalization with the AOT compiler](#aot)
* [Translation file maintenance and _id_ changes](#maintenance)
* [Angular and i18n template translation](guide/i18n#angular-i18n)
* [Mark text with the _i18n_ attribute](guide/i18n#i18n-attribute)
* [Add _i18n-..._ translation attributes](guide/i18n#translate-attributes)
* [Handle singular and plural](guide/i18n#cardinality)
* [Select among alternative texts](guide/i18n#select)
* [Create a translation source file with the **_ng-xi18n_ extraction tool**](guide/i18n#ng-xi18n)
* [Translate text messages](guide/i18n#translate)
* [Merge the completed translation file into the app](guide/i18n#merge)
* [Merge with the JIT compiler](guide/i18n#jit)
* [Internationalization with the AOT compiler](guide/i18n#aot)
* [Translation file maintenance and _id_ changes](guide/i18n#maintenance)
**Try this** <live-example name="cb-i18n" title="i18n Example in Spanish">live example</live-example>
of a JIT-compiled app, translated into Spanish.
@ -346,7 +346,7 @@ replace the `<target/>` tag with the Spanish greeting:
Note that the tool generates the `id`. **Don't touch it.**
Its value depends on the content of the message and its assigned meaning.
Change either factor and the `id` changes as well.
See the **[translation file maintenance discussion](#maintenance)**.
See the **[translation file maintenance discussion](guide/i18n#maintenance)**.
~~~
@ -465,8 +465,8 @@ You provide the Angular compiler with three new pieces of information:
_How_ you provide this information depends upon whether you compile with
the JIT (_Just-in-Time_) compiler or the AOT (_Ahead-of-Time_) compiler.
* With [JIT](#jit), you provide the information at bootstrap time.
* With [AOT](#aot), you pass the information as `ngc` options.
* With [JIT](guide/i18n#jit), you provide the information at bootstrap time.
* With [AOT](guide/i18n#aot), you pass the information as `ngc` options.
{@a jit}
@ -524,10 +524,10 @@ and the corresponding translation file:
It must return a `Promise` because this function could read a translation file asynchronously from the server.
1. It creates a transaction filename from the locale according to the name and location convention
[described earlier](#localization-folder).
[described earlier](guide/i18n#localization-folder).
1. The `getTranslationsWithSystemJs` method reads the translation and returns the contents as a string.
Notice that it appends `!text` to the filename, telling SystemJS to use the [text plugin](#text-plugin).
Notice that it appends `!text` to the filename, telling SystemJS to use the [text plugin](guide/i18n#text-plugin).
1. The callback composes a providers array with the three translation providers.
@ -574,8 +574,8 @@ It does explain the few steps necessary to tell the AOT compiler to apply a tran
Internationalization with the AOT compiler requires
some setup specifically for AOT compilation.
Start with the application project as shown
[just before merging the translation file](#app-pre-translation)
and refer to the [AOT cookbook](aot-compiler.html) to make it _AOT-ready_.
[just before merging the translation file](guide/i18n#app-pre-translation)
and refer to the [AOT cookbook](guide/aot-compiler) to make it _AOT-ready_.
Next, issue an `ngc` compile command for each supported language (including English).
The result is a separate version of the application for each language.

View File

@ -2,11 +2,11 @@
Documentation Overview
@intro
How to read and use this documentation
How to read and use this documentation.
@description
This page describes the Angular documentation at a high level.
If you're new to Angular, you may want to visit "[Learning Angular](learning-angular.html)" first.
If you're new to Angular, you may want to visit "[Learning Angular](guide/learning-angular)" first.
## Themes
@ -132,7 +132,7 @@ Each page includes code snippets from a sample application that accompanies the
You can reuse these snippets in your applications.
Look for a link to a running version of that sample, often near the top of the page,
such as this <live-example nodownload name="architecture"></live-example> from the [Architecture](architecture.html) page.
such as this <live-example nodownload name="architecture"></live-example> from the [Architecture](guide/architecture) page.
<span if-docs="ts">
The link launches a browser-based, code editor where you can inspect, modify, save, and download the code.
</span>
@ -142,10 +142,10 @@ Just download, unzip, run `npm install` to install the dependencies and run it w
## Reference pages
* The [Cheat Sheet](cheatsheet.html) lists Angular syntax for common scenarios.
* The [Glossary](glossary.html) defines terms that Angular developers should know.
<li if-docs="ts">The [Change Log](change-log.html) announces what's new and changed in the documentation.</li>
* The [API Reference](../api/) is the authority on every public-facing member of the Angular libraries.
* The [Cheat Sheet](guide/cheatsheet) lists Angular syntax for common scenarios.
* The [Glossary](guide/glossary) defines terms that Angular developers should know.
<li if-docs="ts">The [Change Log](guide/change-log) announces what's new and changed in the documentation.</li>
* The [API Reference](api/) is the authority on every public-facing member of the Angular libraries.
## Feedback

View File

@ -2,7 +2,7 @@
Learning Angular
@intro
A suggested path through the documentation for Angular newcomers
A suggested path through the documentation for Angular newcomers.
@description
@ -15,32 +15,32 @@ You don't have to read the documentation straight through. Most pages stand on
Those new to Angular may wish to follow this popular learning path.
<br class="l-clear-left">
1. [Setup](setup.html "Setup locally withe Quickstart seed") for local Angular development, if you haven't already done so.
1. [Setup](guide/setup) for local Angular development, if you haven't already done so.
1. Take the [*Tour of Heroes* tutorial](../tutorial "Tour of Heroes").
1. Take the [*Tour of Heroes* tutorial](tutorial "Tour of Heroes").
The *Tour of Heroes* takes you step-by-step from [setup](setup.html)
The *Tour of Heroes* takes you step-by-step from [setup](guide/setup)
to a full-featured example that demonstrates the essential characteristics of a professional application:
a sensible project structure, data binding, master/detail, services, dependency injection, navigation, and remote data access.
1. <a id="architecture"></a>Read the [Architecture](architecture.html) overview for the big picture.
1. <a id="architecture"></a>Read the [Architecture](guide/architecture) overview for the big picture.
1. [The Root Module](appmodule.html) introduces the `NgModule` class that tells Angular how to compile and run your application.
1. [The Root Module](guide/appmodule) introduces the `NgModule` class that tells Angular how to compile and run your application.
1. [Displaying Data](displaying-data.html) shows how data binding puts component property values on screen.
1. [Displaying Data](guide/displaying-data) shows how data binding puts component property values on screen.
1. [User Input](user-input.html) explains how to respond to user-initiated DOM events.
1. [User Input](guide/user-input) explains how to respond to user-initiated DOM events.
1. [Forms](forms.html) covers data entry and validation within the UI.
1. [Forms](guide/forms) covers data entry and validation within the UI.
1. [Dependency Injection](dependency-injection.html) is the way to build large, maintainable applications
1. [Dependency Injection](guide/dependency-injection) is the way to build large, maintainable applications
from small, single-purpose parts.
1. [Template Syntax](template-syntax.html) is a comprehensive study of Angular template HTML.
1. [Template Syntax](guide/template-syntax) is a comprehensive study of Angular template HTML.
After reading the above sections, feel free to skip around among the other pages on this site.
### Next Step
Try the [tutorial](../tutorial "Tour of Heroes") if you're ready to start coding or
visit the [Architecture](architecture.html "Basic Concepts") page if you prefer to learn the basic concepts first.
Try the [tutorial](tutorial "Tour of Heroes") if you're ready to start coding or
visit the [Architecture](guide/architecture) page if you prefer to learn the basic concepts first.

View File

@ -492,7 +492,7 @@ 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
[Tutorial](tutorial/toh-pt4) and [HTTP](guide/server-communication) chapter
show how.
@ -523,7 +523,7 @@ This example monitors the `OnChanges` hook.
{@example 'lifecycle-hooks/ts/src/app/on-changes.component.ts' region='ng-on-changes'}
The `ngOnChanges` method takes an object that maps each changed property name to a
[SimpleChange](../api/core/index/SimpleChange-class.html) object holding the current and previous property values.
[SimpleChange](api/core/index/SimpleChange-class) object holding the current and previous property values.
This hook iterates over the changed properties and logs them.
The example component, `OnChangesComponent`, has two input properties: `hero` and `power`.
@ -588,7 +588,7 @@ The `AfterViewComponent` displays this child view *within its template*:
The following hooks take action based on changing values *within the child view*
which can only be reached by querying for the child view via the property decorated with
[@ViewChild](../api/core/index/ViewChild-decorator.html).
[@ViewChild](api/core/index/ViewChild-decorator).
{@example 'lifecycle-hooks/ts/src/app/after-view.component.ts' region='hooks'}
@ -626,7 +626,7 @@ The *AfterContent* sample explores the `AfterContentInit` and `AfterContentCheck
into the component's template in a designated spot.
AngularJS developers know this technique as *transclusion*.
Consider this variation on the [previous _AfterView_](#afterview) example.
Consider this variation on the [previous _AfterView_](guide/lifecycle-hooks#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.
@ -661,7 +661,7 @@ projected into the component.
The following *AfterContent* hooks take action based on changing values in a *content child*
which can only be reached by querying for it via the property decorated with
[@ContentChild](../api/core/index/ContentChild-decorator.html).
[@ContentChild](api/core/index/ContentChild-decorator).
{@example 'lifecycle-hooks/ts/src/app/after-content.component.ts' region='hooks'}
@ -672,7 +672,7 @@ which can only be reached by querying for it via the property decorated with
### 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).
There's no [need to wait](guide/lifecycle-hooks#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.

View File

@ -8,5 +8,5 @@
This guide has been withdrawn.
The essential information about this feature
is in the [Structural Directives](structural-directives.html#ngcontainer) guide.
is in the [Structural Directives](guide/structural-directives) guide.
The original draft has been retained for possible future use.

View File

@ -17,7 +17,7 @@ making some of them public so external components can use them.
And there are many more options covered here.
Before reading this page, read the
[The Root Module](appmodule.html) page, which introduces NgModules and the essentials
[The Root Module](guide/appmodule) page, which introduces NgModules and the essentials
of creating and maintaining a single root `AppModule` for the entire application.
This page covers NgModules in greater depth.
@ -29,21 +29,21 @@ This page covers NgModules in greater depth.
- some pages don't have tables of contents
I didn't make changes here as I'm not sure what the correct style is.
-->
* [Angular modularity](#angular-modularity "Add structure to the app with NgModule")
* [The application root module](#root-module "The startup module that every app requires")
* [Bootstrap](#bootstrap "Launch the app in a browser with the root module as the entry point") the root module
* [Declarations](#declarations "Declare the components, directives, and pipes that belong to a module")
* [Providers](#providers "Extend the app with additional services")
* [Imports](#imports "Import components, directives, and pipes for use in component templates")
* [Resolve conflicts](#resolve-conflicts "When two directives have the same selector")
* [Angular modularity](guide/ngmodule#angular-modularity "Add structure to the app with NgModule")
* [The application root module](guide/ngmodule#root-module "The startup module that every app requires")
* [Bootstrap](guide/ngmodule#bootstrap "Launch the app in a browser with the root module as the entry point") the root module
* [Declarations](guide/ngmodule#declarations "Declare the components, directives, and pipes that belong to a module")
* [Providers](guide/ngmodule#providers "Extend the app with additional services")
* [Imports](guide/ngmodule#imports "Import components, directives, and pipes for use in component templates")
* [Resolve conflicts](guide/ngmodule#resolve-conflicts "When two directives have the same selector")
<!-- CF: See my comment in the "Resolve diretive conflicts" section below proposing renaming or reorganizing that section. -->
* [Feature modules](#feature-modules "Partition the app into feature modules")
* [Lazy loaded modules](#lazy-load "Load modules asynchronously") with the router
* [Shared modules](#shared-module "Create modules for commonly used components, directives, and pipes")
* [The Core module](#core-module "Create a core module with app-wide singleton services and single-use components")
* [Configure core services with _forRoot_](#core-for-root "Configure providers during module import")
* [Prevent reimport of the _CoreModule_](#prevent-reimport "because bad things happen if a lazy loaded module imports Core")
* [NgModule metadata properties](#ngmodule-properties "A technical summary of the @NgModule metadata properties")
* [Feature modules](guide/ngmodule#feature-modules "Partition the app into feature modules")
* [Lazy loaded modules](guide/ngmodule#lazy-load "Load modules asynchronously") with the router
* [Shared modules](guide/ngmodule#shared-module "Create modules for commonly used components, directives, and pipes")
* [The Core module](guide/ngmodule#core-module "Create a core module with app-wide singleton services and single-use components")
* [Configure core services with _forRoot_](guide/ngmodule#core-for-root "Configure providers during module import")
* [Prevent reimport of the _CoreModule_](guide/ngmodule#prevent-reimport "because bad things happen if a lazy loaded module imports Core")
* [NgModule metadata properties](guide/ngmodule#ngmodule-properties "A technical summary of the @NgModule metadata properties")
<!-- CF: This link goes to the top of this page. I would expect it to go to an "NgModule metadata properties"
section at the end of this page, but that section doesn't exist. -->
@ -61,7 +61,7 @@ Here's an index to live examples at key moments in the evolution of the sample:
This page covers NgModule concepts in a tutorial fashion.
The companion [NgModule FAQs](../cookbook/ngmodule-faq.html "NgModule FAQs") cookbook
The companion [NgModule FAQs](cookbook/ngmodule-faq) cookbook
offers answers to specific design and implementation questions.
Read this page before reading those FAQs.
@ -119,7 +119,7 @@ Later in this page, you'll read about this process. For now, you'll start with t
Every Angular app has a *root module* class.
By convention, the *root module* class is called `AppModule` and it exists in a file named `app.module.ts`.
The `AppModule` from the QuickStart seed on the [Setup](setup.html) page is as minimal as possible:
The `AppModule` from the QuickStart seed on the [Setup](guide/setup) page is as minimal as possible:
{@example 'setup/ts/src/app/app.module.ts'}
@ -153,7 +153,7 @@ Angular offers a variety of bootstrapping options targeting multiple platforms.
This page describes two options, both targeting the browser.
### Dynamic bootstrapping with the just-in-time (JIT) compiler
In the first, _dynamic_ option, the [Angular compiler](../cookbook/ngmodule-faq.html#q-angular-compiler "About the Angular Compiler")
In the first, _dynamic_ option, the [Angular compiler](cookbook/ngmodule-faq)
compiles the application in the browser and then launches the app.
@ -206,7 +206,7 @@ This is the last time you'll look at `main.ts`.
## Declare directives and components
As the app evolves,
the first addition is a `HighlightDirective`, an [attribute directive](attribute-directives.html)
the first addition is a `HighlightDirective`, an [attribute directive](guide/attribute-directives)
that sets the background color of the attached element.
{@example 'ngmodule/ts/src/app/highlight.directive.ts'}
@ -251,9 +251,9 @@ Import the `TitleComponent` class and add it to the module's `declarations`:
Modules are a great way to provide services for all of the module's components.
The [Dependency Injection](dependency-injection.html) page describes
The [Dependency Injection](guide/dependency-injection) page describes
the Angular hierarchical dependency-injection system and how to configure that system
with [providers](dependency-injection.html#providers) at different levels of the
with [providers](guide/dependency-injection) at different levels of the
application's component tree.
A module can add providers to the application's root dependency injector, making those services
@ -306,7 +306,7 @@ More accurately, `NgIf` is declared in `CommonModule` from `@angular/common`.
`CommonModule` contributes many of the common directives that applications need, including `ngIf` and `ngFor`.
`BrowserModule` imports `CommonModule` and [re-exports](../cookbook/ngmodule-faq.html#q-re-export) it.
`BrowserModule` imports `CommonModule` and [re-exports](cookbook/ngmodule-faq) it.
The net effect is that an importer of `BrowserModule` gets `CommonModule` directives automatically.Many familiar Angular directives don't belong to `CommonModule`.
For example, `NgModel` and `RouterLink` belong to Angular's `FormsModule` and `RouterModule` respectively.
You must import those modules before you can use their directives.
@ -316,16 +316,16 @@ a form component that imports form support from the Angular `FormsModule`.
### Add the _ContactComponent_
[Angular forms](forms.html) are a great way to manage user data entry.
[Angular forms](guide/forms) are a great way to manage user data entry.
The `ContactComponent` presents a "contact editor,"
implemented with Angular forms in the [template-driven form](forms.html#template-driven) style.
implemented with Angular forms in the [template-driven form](guide/forms) style.
### Angular form styles
You can write Angular form components in
template-driven or
[reactive](../cookbook/dynamic-form.html) style.
[reactive](cookbook/dynamic-form) style.
<!-- CF: this link goes to a page titled "Dynamic Forms". Should the link text be "dynamic" instead of "reactive"? -->
The following sample imports the `FormsModule` from `@angular/forms` because
@ -338,7 +338,7 @@ Add an element with that name to the `AppComponent` template, just below the `<a
{@example 'ngmodule/ts/src/app/app.component.1b.ts' region='template'}
Form components are often complex. The `ContactComponent` has its own `ContactService`
and [custom pipe](pipes.html#custom-pipes) (called `Awesome`),
and [custom pipe](guide/pipes) (called `Awesome`),
and an alternative version of the `HighlightDirective`.
To make it manageable, place all contact-related material in an `src/app/contact` folder
@ -434,7 +434,7 @@ To work around this, create an alias for the contact version using the `as` Java
This solves the immediate issue of referencing both directive _types_ in the same file but
leaves another issue unresolved.
You'll learn more about that issue later in this page, in [Resolve directive conflicts](#resolve-conflicts).
You'll learn more about that issue later in this page, in [Resolve directive conflicts](guide/ngmodule#resolve-conflicts).
### Provide the _ContactService_
The `ContactComponent` displays contacts retrieved by the `ContactService`,
which Angular injects into its constructor.
@ -473,8 +473,8 @@ Now you can inject `ContactService` (like `UserService`) into any component in t
To inject `ContactService`, you must first import its _type_.
Only Contact components should import the `ContactService` type.
Read more in the [How do I restrict service scope to a module?](../cookbook/ngmodule-faq.html#q-component-scoped-providers) section
of the [NgModule FAQs](../cookbook/ngmodule-faq.html) page.
Read more in the [How do I restrict service scope to a module?](cookbook/ngmodule-faq) section
of the [NgModule FAQs](cookbook/ngmodule-faq) page.
### Run the app
Everything is in place to run the application with its contact editor.
@ -549,7 +549,7 @@ Try the example:
This section seems like more of an introduction to the next section, "Feature modules".
Consider moving this section to be a child section of "Feature modules", or striking "Resolve" from this title. -->
An issue arose [earlier](#import-name-conflict) when you declared the contact's `HighlightDirective` because
An issue arose [earlier](guide/ngmodule#import-name-conflict) when you declared the contact's `HighlightDirective` because
you already had a `HighlightDirective` class at the application level.
The selectors of the two directives both highlight the attached element with a different color.
@ -670,8 +670,8 @@ Before `ContactComponent` can bind with `[(ngModel)]`, its `ContactModule` must
~~~
You also replaced `BrowserModule` by `CommonModule`, for reasons explained in the
[Should I import BrowserModule or CommonModule?](../cookbook/ngmodule-faq.html#q-browser-vs-common-module)
section of the [NgModule FAQs](../cookbook/ngmodule-faq.html) page.
[Should I import BrowserModule or CommonModule?](cookbook/ngmodule-faq)
section of the [NgModule FAQs](cookbook/ngmodule-faq) page.
You _declare_ the contact component, directive, and pipe in the module `declarations`.
@ -762,14 +762,14 @@ The module does _not_ import `HeroModule` or `CrisisModule`.
They'll be fetched and mounted asynchronously when the user navigates to one of their routes.
The significant change from version 2 is the addition of the *AppRoutingModule* to the module `imports`.
The `AppRoutingModule` is a [routing module](../guide/router.html#routing-module)
The `AppRoutingModule` is a [routing module](guide/router)
that handles the app's routing concerns.
### App routing
{@example 'ngmodule/ts/src/app/app-routing.module.ts'}
The router is the subject of the [Routing & Navigation](router.html) page, so this section skips many of the details and
The router is the subject of the [Routing & Navigation](guide/router) page, so this section skips many of the details and
concentrates on the intersection of NgModules and routing.
The `app-routing.module.ts` file defines three routes.
@ -839,8 +839,8 @@ _forRoot_ and _forChild_ are conventional names for methods that
deliver different `import` values to root and feature modules.
Angular doesn't recognize them but Angular developers do.
[Follow this convention](../cookbook/ngmodule-faq.html#q-for-root) if you write a similar module
that has both shared [declarables](../cookbook/ngmodule-faq.html#q-declarable) and services.
[Follow this convention](cookbook/ngmodule-faq) if you write a similar module
that has both shared [declarables](cookbook/ngmodule-faq) and services.
~~~
@ -866,7 +866,7 @@ that has both shared [declarables](../cookbook/ngmodule-faq.html#q-declarable) a
Now that you navigate to `ContactComponent` with the router, there's no reason to make it public.
Also, `ContactComponent` doesn't need a selector.
No template will ever again reference this `ContactComponent`.
It's gone from the [AppComponent template](#app-component-template).
It's gone from the [AppComponent template](guide/ngmodule#app-component-template).
{@a hero-module}
@ -923,15 +923,15 @@ a more interesting and useful example. Its file structure is as follows:
</aio-filetree>
This is the child routing scenario familiar to readers of the
[Child routing component](router.html#child-routing-component) section of the
[Routing & Navigation](router.html#child-routing-component) page.
[Child routing component](guide/router) section of the
[Routing & Navigation](guide/router) page.
The `HeroComponent` is the feature's top component and routing host.
Its template has a `<router-outlet>` that displays either a list of heroes (`HeroList`)
or an editor of a selected hero (`HeroDetail`).
Both components delegate to the `HeroService` to fetch and save data.
Yet another `HighlightDirective` colors elements in yet a different shade.
In the next section, [Shared modules](#shared-module "Shared modules"), you'll resolve the repetition and inconsistencies.
In the next section, [Shared modules](guide/ngmodule#shared-module "Shared modules"), you'll resolve the repetition and inconsistencies.
The `HeroModule` is a feature module like any other.
@ -1006,7 +1006,7 @@ and only one provider of it.
`UserService` is an application-wide singleton.
You don't want each module to have its own separate instance.
Yet there is [a real danger](../cookbook/ngmodule-faq.html#q-why-it-is-bad) of that happening
Yet there is [a real danger](cookbook/ngmodule-faq) of that happening
<!-- CF: This link goes to the top of the NgModule FAQs page.
It looks like it is supposed to go to a specific question/section within the page. -->
if the `SharedModule` provides the `UserService`.
@ -1140,7 +1140,7 @@ A module that adds providers to the application can offer a facility for configu
By convention, the `forRoot` static method both provides and configures services at the same time.
It takes a service configuration object and returns a
[ModuleWithProviders](../api/core/index/ModuleWithProviders-interface.html), which is
[ModuleWithProviders](api/core/index/ModuleWithProviders-interface), which is
a simple object with the following properties:
* `ngModule`: the `CoreModule` class
* `providers`: the configured providers
@ -1189,7 +1189,7 @@ Remember to _import_ the result; don't add it to any other `@NgModule` list.
## Prevent reimport of the _CoreModule_
Only the root `AppModule` should import the `CoreModule`.
[Bad things happen](../cookbook/ngmodule-faq.html#q-why-it-is-bad) if a lazy-loaded module imports it.
[Bad things happen](cookbook/ngmodule-faq) if a lazy-loaded module imports it.
<!-- CF: Again, this link goes to the top of the NgModule FAQs page.
It looks like it is supposed to go to a specific question/section within the page. -->
@ -1226,5 +1226,5 @@ You made it! You can examine and download the complete source for this final ver
### Frequently asked questions
Now that you understand NgModules, you may be interested
in the companion [NgModule FAQs](../cookbook/ngmodule-faq.html "NgModule FAQs") page
in the companion [NgModule FAQs](cookbook/ngmodule-faq) page
with its ready answers to specific design and implementation questions.

View File

@ -2,7 +2,7 @@
Npm Packages
@intro
Recommended npm packages, and how to specify package dependencies
Recommended npm packages, and how to specify package dependencies.
@description
Angular applications and Angular itself depend upon features and functionality provided by a variety of third-party packages.
@ -16,12 +16,17 @@ Get them now</a> if they're not already installed on your machine.
by running the commands `node -v` and `npm -v` in a terminal/console window.
Older versions produce errors.
We recommend [nvm](https://github.com/creationix/nvm) for managing multiple versions of node and npm. You may need [nvm](https://github.com/creationix/nvm) if you already have projects running on your machine that use other versions of node and npm.
We recommend a comprehensive starter-set of packages as specified in the `dependencies` and `devDependencies`
sections of the <a href="https://docs.npmjs.com/files/package.json" target="_blank">package.json</a> file
installed as described during [Setup](setup.html).You can use other packages but we recommend *this particular set* to start with because (a) they work well together and
(b) they include everything you'll need to build and run the sample applications in this series.
Note: A cookbook or guide page may require an additional library such as *jQuery*.You'll install more than you need for QuickStart.
Consider using [nvm](https://github.com/creationix/nvm) for managing multiple
versions of node and npm. You may need [nvm](https://github.com/creationix/nvm) if
you already have projects running on your machine that use other versions of node and npm.
During [Setup](guide/setup), a <a href="https://docs.npmjs.com/files/package.json" target="_blank">package.json</a>
file is installed with a comprehensive starter set of
packages as specified in the `dependencies` and `devDependencies` sections.
You can use other packages but the packages in _this particular set_ work well together and include
everything you need to build and run the sample applications in this series.
Note: A cookbook or guide page may require an additional library such as *jQuery*.You'll install more than you need for the QuickStart guide.
No worries!
You only serve to the client those packages that the application actually requests.
@ -29,7 +34,7 @@ This page explains what each package does. You can make substitutions later to s
## *dependencies* and *devDependencies*
The `package.json` includes two sets of packages,
[dependencies](#dependencies) and [devDependencies](#dev-dependencies).
[dependencies](guide/npm-packages#dependencies) and [devDependencies](guide/npm-packages#dev-dependencies).
The *dependencies* are essential to *running* the application.
The *devDependencies* are only necessary to *develop* the application.
@ -46,37 +51,40 @@ You can exclude them from production installations by adding `--production` to t
## *dependencies*
The `dependencies` section of `package.json` contains:
* ***Features*** - Feature packages give the application framework and utility capabilities.
* ***Features***: Feature packages give the application framework and utility capabilities.
* ***Polyfills*** - Polyfills plug gaps in the browser's JavaScript implementation.
* ***Polyfills***: Polyfills plug gaps in the browser's JavaScript implementation.
* ***Other*** - Other libraries that support the application such as `bootstrap` for HTML widgets and styling.
* ***Other***: Other libraries that support the application such as `bootstrap` for HTML widgets and styling.
### Feature Packages
***@angular/core*** - Critical runtime parts of the framework needed by every application.
***@angular/core***: Critical runtime parts of the framework needed by every application.
Includes all metadata decorators, `Component`, `Directive`, dependency injection, and the component lifecycle hooks.
***@angular/common*** - The commonly needed services, pipes, and directives provided by the Angular team.
***@angular/common***: The commonly needed services, pipes, and directives provided by the Angular team.
***@angular/compiler*** - Angular's *Template Compiler*.
***@angular/compiler***: Angular's *Template Compiler*.
It understands templates and can convert them to code that makes the application run and render.
Typically you dont interact with the compiler directly; rather, you use it indirectly via `platform-browser-dynamic` or the offline template compiler.
***@angular/platform-browser*** - Everything DOM and browser related, especially the pieces that help render into DOM.
This package also includes the bootstrapStatic method for bootstrapping applications for production builds that pre-compile templates offline.
***@angular/platform-browser***: Everything DOM and browser related, especially
the pieces that help render into the DOM.
This package also includes the `bootstrapStatic()` method
for bootstrapping applications for production builds that pre-compile templates offline.
***@angular/platform-browser-dynamic*** - Includes [Providers](../api/core/index/Provider-type-alias.html) and a [bootstrap](ngmodule.html#bootstrap) method for applications that
***@angular/platform-browser-dynamic***: Includes [Providers](api/core/index/Provider-type-alias)
and a [bootstrap](guide/ngmodule) method for applications that
compile templates on the client. Dont use offline compilation.
Use this package for bootstrapping during development and for bootstrapping plunker samples.
***@angular/http*** - Angular's http client.
***@angular/http***: Angular's HTTP client.
***@angular/router*** - Component router.
***@angular/router***: Component router.
***@angular/upgrade*** - Set of utilities for upgrading AngularJS applications to Angular.
***@angular/upgrade***: Set of utilities for upgrading AngularJS applications to Angular.
***[system.js](https://github.com/systemjs/systemjs)*** - A dynamic module loader compatible with the
***[system.js](https://github.com/systemjs/systemjs)***: A dynamic module loader compatible with the
[ES2015 module](http://www.2ality.com/2014/09/es6-modules-final.html) specification.
Other viable choices include the well-regarded [webpack](https://webpack.github.io/).
@ -94,16 +102,16 @@ Install these polyfills using the npm packages that Angular lists in the *peerDe
You must list these packages in the `dependencies` section of your own `package.json`.
For background on this requirement, see [Why peerDependencies?](#why-peer-dependencies).***core-js*** - Patches the global context (window) with essential features of ES2015 (ES6).
For background on this requirement, see [Why peerDependencies?](guide/npm-packages#why-peer-dependencies).***core-js***: Patches the global context (window) with essential features of ES2015 (ES6).
You may substitute an alternative polyfill that provides the same core APIs.
When these APIs are implemented by the major browsers, this dependency will become unnecessary.
***rxjs*** - A polyfill for the [Observables specification](https://github.com/zenparsing/es-observable) currently before the
***rxjs***: A polyfill for the [Observables specification](https://github.com/zenparsing/es-observable) currently before the
[TC39](http://www.ecma-international.org/memento/TC39.htm) committee that determines standards for the JavaScript language.
You can pick a preferred version of *rxjs* (within a compatible version range)
without waiting for Angular updates.
***zone.js*** - A polyfill for the [Zone specification](https://gist.github.com/mhevery/63fdcdf7c65886051d55) currently before the
***zone.js***: A polyfill for the [Zone specification](https://gist.github.com/mhevery/63fdcdf7c65886051d55) currently before the
[TC39](http://www.ecma-international.org/memento/TC39.htm) committee that determines standards for the JavaScript language.
You can pick a preferred version of *zone.js* to use (within a compatible version range)
without waiting for Angular updates.
@ -113,12 +121,12 @@ without waiting for Angular updates.
### Other helper libraries
***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.
***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 you even have a server).
Read about it in the [HTTP Client](guide/server-communication) page.
***bootstrap*** - [Bootstrap](http://getbootstrap.com/) is a popular HTML and CSS framework for designing responsive web apps.
***bootstrap***: [Bootstrap](http://getbootstrap.com/) is a popular HTML and CSS framework for designing responsive web apps.
Some of the samples improve their appearance with *bootstrap*.
@ -128,33 +136,32 @@ Some of the samples improve their appearance with *bootstrap*.
The packages listed in the *devDependencies* section of the `package.json` help you develop the application.
You don't have to deploy them with the production application although there is no harm in doing so.
***[concurrently](https://www.npmjs.com/package/concurrently)*** -
***[concurrently](https://www.npmjs.com/package/concurrently)***:
A utility to run multiple *npm* commands concurrently on OS/X, Windows, and Linux operating systems.
***[lite-server](https://www.npmjs.com/package/lite-server)*** -
***[lite-server](https://www.npmjs.com/package/lite-server)***:
A light-weight, static file server, by [John Papa](http://johnpapa.net/)
with excellent support for Angular apps that use routing.
***[typescript](https://www.npmjs.com/package/typescript)*** -
***[typescript](https://www.npmjs.com/package/typescript)***:
the TypeScript language server, including the *tsc* TypeScript compiler.
***@types/\**** - TypeScript definition files.
Learn more about it in the [TypeScript Configuration](typescript-configuration.html#typings) chapter.
***@types/\****: TypeScript definition files.
Learn more about it in the [TypeScript Configuration](guide/typescript-configuration) guide.
{@a why-peer-dependencies}
## Why *peerDependencies*?
There isn't a *peerDependencies* section in the QuickStart `package.json`.
There isn't a [*peerDependencies*](https://nodejs.org/en/blog/npm/peer-dependencies/) section in the QuickStart `package.json`.
But Angular has a *peerDependencies* section in
*its* package.json, which has important consequences for your application.
*its* `package.json`, which has important consequences for your application.
It explains why you load the [polyfill](#polyfills) *dependency* packages in the QuickStart `package.json`,
This section explains why you load the [polyfill](guide/npm-packages#polyfills) *dependency*
packages in the QuickStart application's `package.json`,
and why you'll need those packages in your own applications.
An explanation of [peer dependencies](https://nodejs.org/en/blog/npm/peer-dependencies/) follows.
Packages depend on other packages. For example, your application depends on the Angular package.
Two packages, "A" and "B", could depend on the same third package "C".
@ -178,7 +185,7 @@ The difference between a `dependency` and a `peerDependency` is roughly this:
The Angular `package.json` specifies several *peer dependency* packages,
each pinned to a particular version of a third-party package.
### We must install Angular's *peerDependencies* ourselves.
### You must install Angular's *peerDependencies* yourself.
When *npm* installs packages listed in *your* `dependencies` section,
it also installs the packages listed within *their* packages `dependencies` sections.

View File

@ -12,23 +12,23 @@ This guide explains reactive forms as you follow the steps to build a "Hero Deta
{@a toc}
## Contents
- [Introduction to reactive forms](#intro)
- [Setup](#setup)
- [Create a data model](#data-model)
- [Create a _reactive forms_ component](#create-component)
- [Create its template file](#create-template)
- [Import the _ReactiveFormsModule_](#import)
- [Display the _HeroDetailComponent_](#update)
- [Add a FormGroup](#formgroup)
- [Taking a look at the form model](#json)
- [Introduction to _FormBuilder_](#formbuilder)
- [Validators.required](#validators)
- [Nested FormGroups](#grouping)
- [Inspect _FormControl_ properties](#properties)
- [Set form model data using _setValue_ and _patchValue_](#set-data)
- [Use _FormArray_ to present an array of _FormGroups_](#form-array)
- [Observe control changes](#observe-control)
- [Save form data](#save)
- [Introduction to reactive forms](guide/reactive-forms#intro)
- [Setup](guide/reactive-forms#setup)
- [Create a data model](guide/reactive-forms#data-model)
- [Create a _reactive forms_ component](guide/reactive-forms#create-component)
- [Create its template file](guide/reactive-forms#create-template)
- [Import the _ReactiveFormsModule_](guide/reactive-forms#import)
- [Display the _HeroDetailComponent_](guide/reactive-forms#update)
- [Add a FormGroup](guide/reactive-forms#formgroup)
- [Taking a look at the form model](guide/reactive-forms#json)
- [Introduction to _FormBuilder_](guide/reactive-forms#formbuilder)
- [Validators.required](guide/reactive-forms#validators)
- [Nested FormGroups](guide/reactive-forms#grouping)
- [Inspect _FormControl_ properties](guide/reactive-forms#properties)
- [Set form model data using _setValue_ and _patchValue_](guide/reactive-forms#set-data)
- [Use _FormArray_ to present an array of _FormGroups_](guide/reactive-forms#form-array)
- [Observe control changes](guide/reactive-forms#observe-control)
- [Save form data](guide/reactive-forms#save)
Try the <live-example plnkr="final" title="Reactive Forms (final) in Plunker">Reactive Forms live-example</live-example>.
@ -65,7 +65,7 @@ the form controls and pull user-changed values back out. The component can
observe changes in form control state and react to those changes.
One advantage of working with form control objects directly is that value and validity updates
are [always synchronous and under your control](#async-vs-sync "Async vs sync").
are [always synchronous and under your control](guide/reactive-forms#async-vs-sync "Async vs sync").
You won't encounter the timing issues that sometimes plague a template-driven form
and reactive forms can be easier to unit test.
@ -82,7 +82,7 @@ but it does facilitate the reactive programming approach should you choose to us
### _Template-driven_ forms
_Template-driven_ forms, introduced in the [Template guide](forms.html), take a completely different approach.
_Template-driven_ forms, introduced in the [Template guide](guide/forms), take a completely different approach.
You place HTML form controls (such as `<input>` and `<select>`) in the component template and
bind them to _data model_ properties in the component, using directives
@ -96,7 +96,7 @@ Angular updates the mutable _data model_ with user changes as they happen.
For this reason, the `ngModel` directive is not part of the ReactiveFormsModule.
While this means less code in the component class,
[template-driven forms are asynchronous](#async-vs-sync "Async vs sync")
[template-driven forms are asynchronous](guide/reactive-forms#async-vs-sync "Async vs sync")
which may complicate development in more advanced scenarios.
@ -116,7 +116,7 @@ That means you must wait a tick before manipulating any of the controls
from within the component class.
For example, if you inject the form control with a `@ViewChild(NgForm)` query and examine it in the
[`ngAfterViewInit` lifecycle hook](lifecycle-hooks.html#afterview "Lifecycle hooks guide: AfterView"),
[`ngAfterViewInit` lifecycle hook](guide/lifecycle-hooks),
you'll discover that it has no children.
You must wait a tick, using `setTimeout`, before you can
extract a value from a control, test its validity, or set it to a new value.
@ -136,17 +136,17 @@ You may decide to use both in the same application.
The balance of this _reactive forms_ guide explores the _reactive_ paradigm and
concentrates exclusively on reactive forms techniques.
For information on _template-driven forms_, see the [_Forms_](forms.html) guide.
For information on _template-driven forms_, see the [_Forms_](guide/forms) guide.
In the next section, you'll set up your project for the reactive form demo.
Then you'll learn about the [Angular form classes](#essentials) and how to use them in a reactive form.
Then you'll learn about the [Angular form classes](guide/reactive-forms#essentials) and how to use them in a reactive form.
{@a setup}
## Setup
Follow the steps in the [_Setup_ guide](../setup.html "Setup guide")
Follow the steps in the [_Setup_ guide](setup)
for creating a new project folder (perhaps called `reactive-forms`)
based on the _QuickStart seed_.
@ -181,7 +181,7 @@ Now enter the `@Component` decorator that specifies the `HeroDetailComponent` me
{@example 'reactive-forms/ts/src/app/hero-detail.component.ts' region='metadata'}
The `moduleId: module.id` lets you use
[component-relative paths](../cookbook/component-relative-paths.html) in file URLs
[component-relative paths](cookbook/component-relative-paths) in file URLs
such as when specifying the `templateUrl`.
Next, create an exported `HeroDetailComponent` class with a `FormControl`.
@ -202,7 +202,7 @@ This simple control doesn't have data or validators.
In real apps, most form controls have both.
This guide touches only briefly on `Validators`. For an in-depth look at them,
read the [Form Validation](../cookbook/form-validation.html) cookbook.
read the [Form Validation](cookbook/form-validation) cookbook.
@ -256,21 +256,21 @@ Revise the `AppComponent` template so it displays the `HeroDetailComponent`.
### Essential form classes
It may be helpful to read a brief description of the core form classes.
* [_AbstractControl_](../api/forms/index/AbstractControl-class.html "API Reference: AbstractControl")
* [_AbstractControl_](api/forms/index/AbstractControl-class)
is the abstract base class for the three concrete form control classes:
`FormControl`, `FormGroup`, and `FormArray`.
It provides their common behaviors and properties, some of which are _observable_.
* [_FormControl_](../api/forms/index/FormControl-class.html "API Reference: FormControl")
* [_FormControl_](api/forms/index/FormControl-class)
tracks the value and validity status of an _individual_ form control.
It corresponds to an HTML form control such as an input box or selector.
* [_FormGroup_](../api/forms/index/FormGroup-class.html "API Reference: FormGroup")
* [_FormGroup_](api/forms/index/FormGroup-class)
tracks the value and validity state of a _group_ of `AbstractControl` instances.
The group's properties include its child controls.
The top-level form in your component is a `FormGroup`.
* [_FormArray_](../api/forms/index/FormArray-class.html "API Reference: FormArray")
* [_FormArray_](api/forms/index/FormArray-class)
tracks the value and validity state of a numerically indexed _array_ of `AbstractControl` instances.
You'll learn more about these classes as you work through this guide.
@ -440,7 +440,7 @@ Using `Validators.required` is optional for the rest of the guide.
It remains in each of the following examples with the same configuration.
For more on validating Angular forms, see the
[Form Validation](../cookbook/form-validation.html) guide.
[Form Validation](cookbook/form-validation) guide.
### More FormControls
A hero has more than a name.
A hero has an address, a super power and sometimes a sidekick too.
@ -487,9 +487,9 @@ You tie these controls to the template HTML elements in the same way,
specifiying the `FormControl` name with the `formControlName` directive.
See the API reference for more information about
[radio buttons](../api/forms/index/RadioControlValueAccessor-directive.html "API: RadioControlValueAccessor"),
[selects](../api/forms/index/SelectControlValueAccessor-directive.html "API: SelectControlValueAccessor"), and
[checkboxes](../api/forms/index/CheckboxControlValueAccessor-directive.html "API: CheckboxControlValueAccessor").
[radio buttons](api/forms/index/RadioControlValueAccessor-directive),
[selects](api/forms/index/SelectControlValueAccessor-directive), and
[checkboxes](api/forms/index/CheckboxControlValueAccessor-directive).
@ -654,12 +654,12 @@ such as one of the following:
</table>
Learn about other `FormControl` properties in the
[_AbstractControl_](../api/forms/index/AbstractControl-class.html) API reference.
[_AbstractControl_](api/forms/index/AbstractControl-class) API reference.
One common reason for inspecting `FormControl` properties is to
make sure the user entered valid values.
Read more about validating Angular forms in the
[Form Validation](../cookbook/form-validation.html) guide.
[Form Validation](cookbook/form-validation) guide.
@ -704,7 +704,7 @@ There are two significant differences between these models:
1. The `Hero` has an `id`. The form model does not because you generally don't show primary keys to users.
1. The `Hero` has an array of addresses. This form model presents only one address,
a choice [revisited below](#form-array "Form arrays").
a choice [revisited below](guide/reactive-forms#form-array "Form arrays").
Nonetheless, the two models are pretty close in shape and you'll see in a moment how this alignment facilitates copying the _data model_ properties
to the _form model_ with the `patchValue` and `setValue` methods.
@ -767,7 +767,7 @@ values and does not throw helpful errors.
Now you know _how_ to set the _form model_ values. But _when_ do you set them?
The answer depends upon when the component gets the _data model_ values.
The `HeroDetailComponent` in this reactive forms sample is nested within a _master/detail_ `HeroListComponent` ([discussed below](#hero-list)).
The `HeroDetailComponent` in this reactive forms sample is nested within a _master/detail_ `HeroListComponent` ([discussed below](guide/reactive-forms#hero-list)).
The `HeroListComponent` displays hero names to the user.
When the user clicks on a hero, the list component passes the selected hero into the `HeroDetailComponent`
by binding to its `hero` input property.
@ -777,7 +777,7 @@ by binding to its `hero` input property.
In this approach, the value of `hero` in the `HeroDetailComponent` changes
every time the user selects a new hero.
You should call _setValue_ in the [ngOnChanges](lifecyle-hooks.html#onchanges)
You should call _setValue_ in the [ngOnChanges](guide/lifecyle-hooks)
hook, which Angular calls whenever the input `hero` property changes
as the following steps demonstrate.
@ -839,11 +839,11 @@ A "Refresh" button clears the hero list and the current selected hero before ref
The remaining `HeroListComponent` and `HeroService` implementation details are not relevant to understanding reactive forms.
The techniques involved are covered elsewhere in the documentation, including the _Tour of Heroes_
[here](../tutorial/toh-pt3.html "ToH: Multiple Components") and [here](../tutorial/toh-pt4.html "ToH: Services").
[here](tutorial/toh-pt3) and [here](tutorial/toh-pt4).
If you're coding along with the steps in this reactive forms tutorial,
create the pertinent files based on the
[source code displayed below](#source-code "Reactive Forms source code").
[source code displayed below](guide/reactive-forms#source-code "Reactive Forms source code").
Notice that `hero-list.component.ts` imports `Observable` and `finally` while `hero.service.ts` imports `Observable`, `of`,
and `delay` from `rxjs`.
Then return here to learn about _form array_ properties.

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
Security
@intro
Developing for content security in Angular applications
Developing for content security in Angular applications.
@description
This page describes Angular's built-in
@ -18,7 +18,7 @@ You can run the <live-example></live-example> in Plunker and download the code f
Reporting vulnerabilities
</h2>
To report vulnerabilities in Angular itself, email us at [security@angular.io](mailto:security@angular.io).
To report vulnerabilities in Angular itself, email us at [security@angular.io](guide/mailto:security@angular).
For more information about how Google handles security issues, see [Google's security
philosophy](https://www.google.com/about/appsecurity/).
@ -39,7 +39,7 @@ important security fixes and enhancements. Instead, share your Angular improveme
community and make a pull request.
* **Avoid Angular APIs marked in the documentation as “_Security Risk_.”**
For more information, see the [Trusting safe values](#bypass-security-apis) section of this page.
For more information, see the [Trusting safe values](guide/security#bypass-security-apis) section of this page.
<h2 id='xss'>
@ -68,7 +68,7 @@ _Angular templates are the same as executable code_: HTML, attributes, and bindi
prevent values that an attacker can control from ever making it into the source code of a
template. Never generate template source code by concatenating user input and templates.
To prevent these vulnerabilities, use
the [offline template compiler](#offline-template-compiler), also known as _template injection_.
the [offline template compiler](guide/security#offline-template-compiler), also known as _template injection_.
### Sanitization and security contexts
@ -124,7 +124,7 @@ and greatly improves application performance. Use the offline template compiler
deployments; don't dynamically generate templates. Angular trusts template code, so generating
templates, in particular templates containing user data, circumvents Angular's built-in protections.
For information about dynamically constructing forms in a safe way, see the
[Dynamic Forms](../cookbook/dynamic-form.html) cookbook page.
[Dynamic Forms](cookbook/dynamic-form) cookbook page.
### Server-side XSS protection
@ -142,5 +142,5 @@ carries a high risk of introducing template-injection vulnerabilities.
Angular applications must follow the same security principles as regular web applications, and
must be audited as such. Angular-specific APIs that should be audited in a security review,
such as the [_bypassSecurityTrust_](#bypass-security-apis) methods, are marked in the documentation
such as the [_bypassSecurityTrust_](guide/security#bypass-security-apis) methods, are marked in the documentation
as security sensitive.

View File

@ -13,27 +13,50 @@ it isn't covered in this page.Modern browsers support two HTTP-based APIs:
[Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API).
The !{_Angular_http_library} simplifies application programming with the **XHR** and **JSONP** APIs.
This page covers:
- [The Tour of Heroes *HTTP* client demo](#http-client).
- [Fetch data with http.get](#fetch-data).
<li if-docs="ts"> [RxJS library](#rxjs).</li>
<li if-docs="ts"> [Enable RxJS operators](#enable-rxjs-operators).</li>
- [Process the response object](#extract-data).
- [Always handle errors](#error-handling).
- [Send data to the server](#update).
<li if-docs="ts"> [Fall back to promises](#promises).</li>
- [Cross-Origin Requests: Wikipedia example](#cors).
<ul if-docs="ts">
<li> [Search parameters](#search-parameters).</li>
<li> [More fun with observables](#more-observables).</li>
# Contents
* [Demos](guide/server-communication#demos)
* [Providing HTTP Services](guide/server-communication#http-providers)
* [The Tour of Heroes *HTTP* client demo](guide/server-communication#http-client)
- [The `HeroListComponent` class](guide/server-communication#HeroListComponent)
* [Fetch data with `http.get()`](guide/server-communication#fetch-data)
<li if-docs="ts"> [RxJS library](guide/server-communication#rxjs-library)
<ul>
<li> [Enable RxJS operators](guide/server-communication#enable-rxjs-operators)</li>
</ul>
- [Guarding against Cross-Site Request Forgery](#xsrf).
- [Override default request headers (and other request options)](#override-default-request-options).
- [Appendix: Tour of Heroes _in-memory web api_](#in-mem-web-api).
</li>
* [Process the response object](guide/server-communication#extract-data)
- [Parse to `JSON`](guide/server-communication#parse-to-json)
- [Do not return the response object](guide/server-communication#no-return-response-object)
- [Always handle errors](guide/server-communication#error-handling)
- [`HeroListComponent` error handling](guide/server-communication#hero-list-component)
* [Send data to the server](guide/server-communication#update)
- [Headers](guide/server-communication#headers)
- [JSON results](guide/server-communication#json-results)
<ul><li if-docs="ts"> [Fall back to promises](guide/server-communication#promises)</ul>
* [Cross-Origin Requests: Wikipedia example](guide/server-communication#cors)
<ul if-docs="ts">
<li> [Search Wikipedia](guide/server-communication#search-wikipedia)</li>
<li> [Search parameters](guide/server-communication#search-parameters)</li>
<li> [The WikiComponent](guide/server-communication#wikicomponent)</li>
</ul>
* [A wasteful app](guide/server-communication#wasteful-app)
<li if-docs="ts"> [More fun with Observables](guide/server-communication#more-observables)
<ul>
<li> [Create a stream of search terms](guide/server-communication#create-stream)</li>
<li> [Listen for search terms](guide/server-communication#listen-for-search-terms)</li>
</ul>
</li>
* [Guarding against Cross-Site Request Forgery](guide/server-communication#xsrf)
* [Override default request headers (and other request options)](guide/server-communication#override-default-request-options)
* [Appendix: Tour of Heroes _in-memory web api_](guide/server-communication#in-mem-web-api)
A <live-example>live example</live-example> illustrates these topics.
{@a demos}
# Demos
This page describes server communication with the help of the following demos:
@ -50,7 +73,7 @@ The !{_Angular_Http} client communicates with the server using a familiar HTTP r
The `!{_Http}` client is one of a family of services in the !{_Angular_http_library}.
Before you can use the `!{_Http}` client, you need to register it as a service provider with the dependency injection system.
Read about providers in the [Dependency Injection](dependency-injection.html) page.
Read about providers in the [Dependency Injection](guide/dependency-injection) page.
Register providers by importing other NgModules to the root NgModule in `app.module.ts`.
@ -58,12 +81,12 @@ Register providers by importing other NgModules to the root NgModule in `app.mod
The `HttpModule` is necessary for making HTTP calls.
Though the JsonpModule isn't necessary for plain HTTP,
Though the `JsonpModule` isn't necessary for plain HTTP,
there is a JSONP demo later in this page.
Loading its module now saves time.
## The Tour of Heroes HTTP client demo
The first demo is a mini-version of the [tutorial](../tutorial)'s "Tour of Heroes" (ToH) application.
The first demo is a mini-version of the [tutorial](tutorial)'s "Tour of Heroes" (ToH) application.
This version gets some heroes from the server, displays them in a list, lets the user add new heroes, and saves them to the server.
The app uses the !{_Angular_Http} client to communicate via `XMLHttpRequest (XHR)`.
@ -79,7 +102,7 @@ This demo has a single component, the `HeroListComponent`. Here's its template:
It presents the list of heroes with an `ngFor`.
Below the list is an input box and an *Add Hero* button where you can enter the names of new heroes
and add them to the database.
A [template reference variable](template-syntax.html#ref-vars), `newHeroName`, accesses the
A [template reference variable](guide/template-syntax), `newHeroName`, accesses the
value of the input box in the `(click)` event binding.
When the user clicks the button, that value passes to the component's `addHero` method and then
the event binding clears it to make it ready for a new hero name.
@ -96,7 +119,7 @@ Here's the component class:
{@example 'server-communication/ts/src/app/toh/hero-list.component.ts' region='component'}
Angular [injects](dependency-injection.html) a `HeroService` into the constructor
Angular [injects](guide/dependency-injection) a `HeroService` into the constructor
and the component calls that service to fetch and save data.
The component **does not talk directly to the !{_Angular_Http} client**.
@ -107,7 +130,7 @@ This is a golden rule: **always delegate data access to a supporting service cla
Although _at runtime_ the component requests heroes immediately after creation,
you **don't** call the service's `get` method in the component's constructor.
Instead, call it inside the `ngOnInit` [lifecycle hook](lifecycle-hooks.html)
Instead, call it inside the `ngOnInit` [lifecycle hook](guide/lifecycle-hooks)
and rely on Angular to call `ngOnInit` when it instantiates this component.
This is a *best practice*.
Components are easier to test and debug when their constructors are simple, and all real work
@ -116,7 +139,7 @@ Components are easier to test and debug when their constructors are simple, and
{@a HeroService}
## Fetch data with http.get
## Fetch data with _http.get()_
In many of the previous samples the app faked the interaction with the server by
returning mock heroes in a service like this one:
@ -128,7 +151,7 @@ You can revise that `HeroService` to get the heroes from the server using the !{
{@example 'server-communication/ts/src/app/toh/hero.service.ts' region='v1'}
Notice that the !{_Angular_Http} client service is
[injected](dependency-injection.html) into the `HeroService` constructor.
[injected](guide/dependency-injection) into the `HeroService` constructor.
{@example 'server-communication/ts/src/app/toh/hero.service.ts' region='ctor'}
@ -138,7 +161,7 @@ Look closely at how to call `!{_priv}http.get`:
You pass the resource URL to `get` and it calls the server which returns heroes.
The server returns heroes once you've set up the [in-memory web api](#in-mem-web-api)
The server returns heroes once you've set up the [in-memory web api](guide/server-communication#in-mem-web-api)
described in the appendix below.
Alternatively, you can temporarily target a JSON file by changing the endpoint URL:
@ -149,13 +172,15 @@ Alternatively, you can temporarily target a JSON file by changing the endpoint U
{@a extract-data}
## Process the response object
Remember that the `getHeroes()` method used an `!{_priv}extractData` helper method to map the `!{_priv}http.get` response object to heroes:
Remember that the `getHeroes()` method used an `!{_priv}extractData()` helper method to map the `!{_priv}http.get` response object to heroes:
{@example 'server-communication/ts/src/app/toh/hero.service.ts' region='extract-data'}
The `response` object doesn't hold the data in a form the app can use directly.
You must parse the response data into a JSON object.
{@a parse-to-json}
### Parse to JSON
Don't expect the decoded JSON to be the heroes !{_array} directly.
This server always wraps JSON results in an object with a `data`
@ -169,8 +194,12 @@ This is conventional web API behavior, driven by
Make no assumptions about the server API.
Not all servers return an object with a `data` property.
~~~
{@a no-return-response-object}
### Do not return the response object
The `getHeroes()` method _could_ have returned the HTTP response but this wouldn't
be a best practice.
@ -225,7 +254,7 @@ just the name of a new hero and returns an `Observable` of `Hero`. It begins lik
To implement it, you must know the server's API for creating heroes.
[This sample's data server](#server) follows typical REST guidelines.
[This sample's data server](guide/server-communication#in-mem-web-api) follows typical REST guidelines.
It expects a [`POST`](http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5) request
at the same endpoint as `GET` heroes.
It expects the new hero data to arrive in the body of the request,
@ -240,17 +269,23 @@ The server generates the `id` and returns the entire `JSON` representation
of the new hero including its generated id. The hero arrives tucked inside a response object
with its own `data` property.
Now that you know how the API works, implement `addHero()`as follows:
Now that you know how the API works, implement `addHero()` as follows:
{@example 'server-communication/ts/src/app/toh/hero.service.ts' region='addhero'}
{@a headers}
### Headers
In the `headers` object, the `Content-Type` specifies that the body represents JSON.
{@a json-results}
### JSON results
As with `getHeroes()`, use the `!{_priv}extractData()` helper to [extract the data](#extract-data)
As with `getHeroes()`, use the `!{_priv}extractData()` helper to [extract the data](guide/server-communication#extract-data)
from the response.
@ -270,10 +305,13 @@ This is called the [same-origin policy](https://en.wikipedia.org/wiki/Same-origi
Modern browsers do allow `XHR` requests to servers from a different origin if the server supports the
[CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) protocol.
If the server requires user credentials, you'll enable them in the [request headers](#headers).
If the server requires user credentials, enable them in the [request headers](guide/server-communication#headers).
Some servers do not support CORS but do support an older, read-only alternative called [JSONP](https://en.wikipedia.org/wiki/JSONP).
Wikipedia is one such server.
This [Stack Overflow answer](http://stackoverflow.com/questions/2067472/what-is-jsonp-all-about/2067584#2067584) covers many details of JSONP.### Search wikipedia
This [Stack Overflow answer](http://stackoverflow.com/questions/2067472/what-is-jsonp-all-about/2067584#2067584) covers many details of JSONP.
{@a search-wikipedia}
### Search Wikipedia
Here is a simple search that shows suggestions from Wikipedia as the user
types in a text box:
@ -289,7 +327,7 @@ types in a text box:
## Guarding against Cross-Site Request Forgery
In a cross-site request forgery (CSRF or XSRF), an attacker tricks the user into visiting
a different web page with malignant code that secretly sends a malicious request to your application's web server,
a different web page with malignant code that secretly sends a malicious request to your application's web server.
The server and client application must work together to thwart this attack.
Angular's `Http` client does its part by applying a default `CookieXSRFStrategy` automatically to all requests.
@ -299,7 +337,7 @@ generated authentication token in a cookie named `XSRF-TOKEN`.
The HTTP client adds an `X-XSRF-TOKEN` header with that token value to subsequent requests.
The server receives both the cookie and the header, compares them, and processes the request only if the cookie and header match.
See the [XSRF topic on the Security page](security.html#xsrf) for more information about XSRF and Angular's `XSRFStrategy` counter measures.
See the [XSRF topic on the Security page](guide/security) for more information about XSRF and Angular's `XSRFStrategy` counter measures.
{@a override-default-request-options}
@ -311,7 +349,7 @@ Request options (such as headers) are merged into the
before the request is processed.
The `HttpModule` provides these default options via the `RequestOptions` token.
You can override these defaults to suit your application needs.
You can override these defaults to suit your application needs
by creating a custom sub-class of `RequestOptions`
that sets the default options for the application.
@ -326,13 +364,13 @@ Then it registers the provider in the root `AppModule`.
{@example 'server-communication/ts/src/app/app.module.ts' region='provide-default-request-options'}
Remember to include this provider during setup when unit testing the app's HTTP services.After this change, the `header` option setting in `HeroService.addHero` is no longer necessary,
Remember to include this provider during setup when unit testing the app's HTTP services.After this change, the `header` option setting in `HeroService.addHero()` is no longer necessary,
{@example 'server-communication/ts/src/app/toh/hero.service.ts' region='addhero'}
You can confirm that `DefaultRequestOptions` is working by examing HTTP requests in the browser developer tools' network tab.
If you're short-circuiting the server call with something like the [_in-memory web api_](#in-mem-web-api),
If you're short-circuiting the server call with something like the [_in-memory web api_](guide/server-communication#in-mem-web-api),
try commenting-out the `addHero` header option,
set a breakpoint on the POST call, and step through the request processing
to verify the header is there.

View File

@ -51,7 +51,7 @@ inside a Web Worker to improve your app's responsiveness by using multiple threa
means that you could run your app inside Electron.js or Windows Universal to deliver it to the desktop.
## Use the *Title* service
Fortunately, Angular bridges the gap by providing a `Title` service as part of the *Browser platform*.
The [Title](../api/platform-browser/index/Title-class.html) service is a simple class that provides an API
The [Title](api/platform-browser/index/Title-class) service is a simple class that provides an API
for getting and setting the current HTML document title:
* `getTitle() : string` &mdash; Gets the title of the current HTML document.
@ -100,4 +100,4 @@ That's exactly what we're doing.
The `Title` service is part of the Angular *browser platform*.
If we bootstrap our application into a different platform,
we'll have to provide a different `Title` service that understands the concept of a "document title" for that specific platform.
Ideally the application itself neither knows nor cares about the runtime environment.[Back to top](#top)
Ideally the application itself neither knows nor cares about the runtime environment.[Back to top](guide/set-document-title#top)

View File

@ -2,7 +2,7 @@
Setup for local development
@intro
Install the Angular QuickStart seed for faster, more efficient development on your machine
Install the Angular QuickStart seed for faster, more efficient development on your machine.
@description
@ -13,16 +13,16 @@ Install the Angular QuickStart seed for faster, more efficient development on yo
<span if-docs="ts">
The <live-example name=quickstart>QuickStart live-coding</live-example> example is an Angular _playground_.
It's not where you'd develop a real application.
You [should develop locally](#why-locally "Why develop locally") on your own machine ... and that's also how we think you should learn Angular.
You [should develop locally](guide/setup#why-locally "Why develop locally") on your own machine ... and that's also how we think you should learn Angular.
</span>
Setting up a new project on your machine is quick and easy with the **QuickStart seed**,
maintained [on github](!{_qsRepo} "Install the github QuickStart repo").
Make sure you have [!{_prereq} installed](#install-prerequisites "What if you don't have !{_prereq}?").
maintained [on github](guide/!{_qsRepo} "Install the github QuickStart repo").
Make sure you have [!{_prereq} installed](guide/setup#install-prerequisites "What if you don't have !{_prereq}?").
Then ...
1. Create a project folder (you can call it `quickstart` and rename it later).
1. [Clone](#clone "Clone it from github") or [download](#download "download it from github") the **QuickStart seed** into your project folder.
1. !{_Install} [!{_npm}](#install-prerequisites "What if you don't have !{_prereq}?") packages.
1. [Clone](guide/setup#clone "Clone it from github") or [download](guide/setup#download "download it from github") the **QuickStart seed** into your project folder.
1. !{_Install} [!{_npm}](guide/setup#install-prerequisites "What if you don't have !{_prereq}?") packages.
1. Run `!{_npm} !{_start}` to launch the sample application.
@ -180,7 +180,7 @@ The following are all in `src/`
<td>
Defines `AppModule`, the [root module](appmodule.html "AppModule: the root module") that tells Angular how to assemble the application.
Defines `AppModule`, the [root module](guide/appmodule) that tells Angular how to assemble the application.
Right now it declares only the `AppComponent`.
Soon there will be more components to declare.
</td>
@ -197,12 +197,12 @@ The following are all in `src/`
<td>
Compiles the application with the [JIT compiler](../glossary.html#jit) and
[bootstraps](appmodule.html#main "bootstrap the application")
Compiles the application with the [JIT compiler](glossary) and
[bootstraps](guide/appmodule)
the application's main module (`AppModule`) to run in the browser.
The JIT compiler is a reasonable choice during the development of most projects and
it's the only viable choice for a sample running in a _live-coding_ environment like Plunker.
You'll learn about alternative compiling and [deployment](deployment.html) options later in the documentation.
You'll learn about alternative compiling and [deployment](guide/deployment) options later in the documentation.
</td>
@ -215,7 +215,7 @@ The following are all in `src/`
### Next Step
If you're new to Angular, we recommend staying on the [learning path](learning-angular.html "Angular learning path").
If you're new to Angular, we recommend staying on the [learning path](guide/learning-angular).
<br></br><br></br>
{@a install-prerequisites}

View File

@ -17,18 +17,18 @@ how you can write your own structural directives to do the same thing.
### Table of contents
- [What are structural directives?](#definition)
- [*NgIf* case study](#ngIf)
- [Group sibling elements with &lt;ng-container&gt;](#ng-container)
- [The asterisk (\*) prefix](#asterisk)
- [Inside *NgFor*](#ngfor)
- [microsyntax](#microsyntax)
- [template input variables](#template-input-variable)
- [one structural directive per element](#one-per-element)
- [Inside the *NgSwitch* directives](#ngSwitch)
- [Prefer the (\*) prefix](#prefer-asterisk)
- [The &lt;template> element](#template)
- [Write a structural directive](#unless)
- [What are structural directives?](guide/structural-directives#definition)
- [*NgIf* case study](guide/structural-directives#ngIf)
- [The asterisk (*) prefix](guide/structural-directives#asterisk)
- [Inside *NgFor*](guide/structural-directives#ngFor)
- [microsyntax](guide/structural-directives#microsyntax)
- [template input variables](guide/structural-directives#template-input-variable)
- [one structural directive per element](guide/structural-directives#one-per-element)
- [Inside the *NgSwitch* directives](guide/structural-directives#ngSwitch)
- [Prefer the (*) prefix](guide/structural-directives#prefer-asterisk)
- [The &lt;template> element](guide/structural-directives#template)
- [Group sibling elements with &lt;ng-container&gt;](guide/structural-directives#ng-container)
- [Write a structural directive](guide/structural-directives#unless)
Try the <live-example></live-example>.
@ -45,28 +45,22 @@ As with other directives, you apply a structural directive to a _host element_.
The directive then does whatever it's supposed to do with that host element and its descendents.
Structural directives are easy to recognize.
An asterisk (\*) precedes the directive attribute name as in this example.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngif'}
An asterisk (*) precedes the directive attribute name as in this example.
No brackets. No parentheses. Just `*ngIf` set to a string.
You'll learn in this guide that the [asterisk (\*) is a convenience notation](#asterisk)
and the string is a [_microsyntax_](#microsyntax) rather than the usual [template expression](template-syntax.html#template-expressions).
Angular "de-sugars" this notation into a marked-up `<template>` that surrounds the
You'll learn in this guide that the [asterisk (*) is a convenience notation](guide/structural-directives#asterisk)
and the string is a [_microsyntax_](guide/structural-directives#microsyntax) rather than the usual
[template expression](guide/template-syntax).
Angular desugars this notation into a marked-up `<template>` that surrounds the
host element and its descendents.
Each structural directive does something different with that template.
Three of the common, built-in structural directives&mdash;[NgIf](template-syntax.html#ngIf),
[NgFor](template-syntax.html#ngFor), and [NgSwitch...](template-syntax.html#ngSwitch)&mdash;are
described in the [_Template Syntax_](template-syntax.html) guide and seen in samples throughout the Angular documentation.
Three of the common, built-in structural directives&mdash;[NgIf](guide/template-syntax),
[NgFor](guide/template-syntax), and [NgSwitch...](guide/template-syntax)&mdash;are
described in the [_Template Syntax_](guide/template-syntax) guide and seen in samples throughout the Angular documentation.
Here's an example of them in a template:
{@example 'structural-directives/ts/src/app/app.component.html' region='built-in'}
This guide won't repeat how to _use_ them. But it does explain _how they work_
and how to [write your own](#unless) structural directive.
and how to [write your own](guide/structural-directives#unless) structural directive.
~~~ {.callout.is-helpful}
@ -91,30 +85,27 @@ you apply the directive to an element in the HTML template.
~~~
There are two other kinds of Angular directives, described extensively elsewhere: (1)&nbsp;components and (2)&nbsp;attribute directives.
There are two other kinds of Angular directives, described extensively elsewhere:
(1)&nbsp;components and (2)&nbsp;attribute directives.
A *component* manages a region of HTML in the manner of a native HTML element.
Technically it's a directive with a template.
An [*attribute* directive](attribute-directives.html) changes the appearance or behavior
An [*attribute* directive](guide/attribute-directives) changes the appearance or behavior
of an element, component, or another directive.
For example, the built-in [`NgStyle`](template-syntax.html#ngStyle) directive
For example, the built-in [`NgStyle`](guide/template-syntax) directive
changes several element styles at the same time.
You can apply many _attribute_ directives to one host element.
You can [only apply one](#one-per-element) _structural_ directive to a host element.
You can [only apply one](guide/structural-directives#one-per-element) _structural_ directive to a host element.
{@a ngIf}
## NgIf Case Study
## NgIf case study
`NgIf` is the simplest structural directive and the easiest to understand.
It takes a boolean value and makes an entire chunk of the DOM appear or disappear.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngif-true'}
It takes a boolean expression and makes an entire chunk of the DOM appear or disappear.
The `ngIf` directive doesn't hide elements with CSS. It adds and removes them physically from the DOM.
Confirm that fact using browser developer tools to inspect the DOM.
@ -123,7 +114,7 @@ Confirm that fact using browser developer tools to inspect the DOM.
</figure>
The top paragraph is in the DOM. The bottom, disused paragraph is not;
in its place is a comment about "template bindings" (more about that [later](#asterisk)).
in its place is a comment about "template bindings" (more about that [later](guide/structural-directives#asterisk)).
When the condition is false, `NgIf` removes its host element from the DOM,
detaches it from DOM events (the attachments that it made),
@ -133,9 +124,6 @@ The component and DOM nodes can be garbage-collected and free up memory.
### Why *remove* rather than *hide*?
A directive could hide the unwanted paragraph instead by setting its `display` style to `none`.
{@example 'structural-directives/ts/src/app/app.component.html' region='display-none'}
While invisible, the element remains in the DOM.
<figure class='image-display'>
@ -166,128 +154,24 @@ Before applying a structural directive, you might want to pause for a moment
to consider the consequences of adding and removing elements and of creating and destroying components.
{@a ngcontainer}
{@a ng-container}
## Group sibling elements with &lt;ng-container&gt;
There's often a _root_ element that can and should host the structural directive.
The list element (`<li>`) is a typical host element of an `NgFor` repeater.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngfor-li'}
When there isn't a host element, you can usually wrap the content in a native HTML container element,
such as a `<div>`, and attach the directive to that wrapper.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngif'}
Introducing another container element&mdash;typically a `<span>` or `<div>`&mdash;to
group the elements under a single _root_ is usually harmless.
_Usually_ ... but not _always_.
The grouping element may break the template appearance because CSS styles
neither expect nor accommodate the new layout.
For example, suppose you have the following paragraph layout.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngif-span'}
You also have a CSS style rule that happens to apply to a `<span>` within a `<p>`aragraph.
{@example 'structural-directives/ts/src/app/app.component.css' region='p-span'}
The constructed paragraph renders strangely.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/bad-paragraph.png' alt="spanned paragraph with bad style"> </img>
</figure>
The `p span` style, intended for use elsewhere, was inadvertently applied here.
Another problem: some HTML elements require all immediate children to be of a specific type.
For example, the `<select>` tag requires `<option>` children.
You can't wrap the _options_ in a conditional `<div>` or a `<span>`.
When you try this,
{@example 'structural-directives/ts/src/app/app.component.html' region='select-span'}
the drop down is empty.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/bad-select.png' alt="spanned options don't work"> </img>
</figure>
The browser won't display an `<option>` within a `<span>`.
### &lt;ng-container&gt; to the rescue
The Angular `<ng-container>` is a grouping element that doesn't interfere with styles or layout
because Angular _doesn't put it in the DOM_.
Here's the conditional paragraph again, this time using `<ng-container>`.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngif-ngcontainer'}
It renders properly.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/good-paragraph.png' alt="ngcontainer paragraph with proper style"> </img>
</figure>
Now conditionally exclude a _select_ `<option>` with `<ng-container>`.
{@example 'structural-directives/ts/src/app/app.component.html' region='select-ngcontainer'}
The drop down works properly.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/select-ngcontainer-anim.gif' alt="ngcontainer options work properly"> </img>
</figure>
The `<ng-container>` is a syntax element recognized by the Angular parser.
It's not a directive, component, class, or interface.
It's more like the curly braces in a JavaScript `if`-block:
<code-example language="javascript">
if (someCondition) {
statement1;
statement2;
statement3;
}
</code-example>
Without those braces JavaScript could only execute the first statement
when you intend to conditionally execute all of them as a single block.
The `<ng-container>` satisfies a similar need in Angular templates.
{@a asterisk}
## The asterisk (\*) prefix
## The asterisk (*) prefix
Surely you noticed the asterisk (\*) prefix to the directive name
Surely you noticed the asterisk (*) prefix to the directive name
and wondered why it is necessary and what it does.
Here is `*ngIf` displaying the hero's name if `hero` exists.
{@example 'structural-directives/ts/src/app/app.component.html' region='asterisk'}
The asterisk is "syntactic sugar" for something a bit more complicated.
Internally, Angular "de-sugars" it in two stages.
Internally, Angular desugars it in two stages.
First, it translates the `*ngIf="..."` into a template _attribute_, `template="ngIf ..."`,&nbsp; like this.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngif-template-attr'}
Then it translates the template _attribute_ into a template _element_, wrapped around the host element, like this.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngif-template'}
* The `*ngIf` directive moved to the `<template>` tag where it became a property binding,`[ngIf]`.
* The rest of the `<div>`, including its class attribute, moved inside the `<template>` tag.
* The `*ngIf` directive moved to the `<template>` element where it became a property binding,`[ngIf]`.
* The rest of the `<div>`, including its class attribute, moved inside the `<template>` element.
None of these forms are actually rendered.
Only the finished product ends up in the DOM.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/hero-div-in-dom.png' alt="hero div in DOM"> </img>
</figure>
@ -295,25 +179,22 @@ Only the finished product ends up in the DOM.
Angular consumed the `<template>` content during its actual rendering and
replaced the `<template>` with a diagnostic comment.
The [`NgFor`](#ngfor) and [`NgSwitch...`](#ngswitch) directives follow the same pattern.
The [`NgFor`](guide/structural-directives#ngFor) and [`NgSwitch...`](guide/structural-directives#ngSwitch) directives follow the same pattern.
{@a ngfor}
{@a ngFor}
## Inside _*ngFor_
Angular transforms the `*ngFor` in similar fashion from asterisk (\*) syntax through
Angular transforms the `*ngFor` in similar fashion from asterisk (*) syntax through
template _attribute_ to template _element_.
Here's a full-featured application of `NgFor`, written all three ways:
{@example 'structural-directives/ts/src/app/app.component.html' region='inside-ngfor'}
This is manifestly more complicated than `ngIf` and rightly so.
The `NgFor` directive has more features, both required and optional, than the `NgIf` shown in this guide.
At minimum `NgFor` needs a looping variable (`let hero`) and a list (`heroes`).
You enable these features in the string assigned to `ngFor`, which you write in Angular's [microsyntax](microsyntax).
You enable these features in the string assigned to `ngFor`, which you write in Angular's [microsyntax](guide/structural-directives#microsyntax).
~~~ {.alert.is-helpful}
@ -328,11 +209,12 @@ In this example, the `[ngClass]="odd"` stays on the `<div>`.
{@a microsyntax}
### microsyntax
### Microsyntax
The Angular microsyntax lets you configure a directive in a compact, friendly string.
The microsyntax parser translates that string into attributes on the `<template>`:
* The `let` keyword declares a [_template input variable_](#template-input-variable)
* The `let` keyword declares a [_template input variable_](guide/structural-directives#template-input-variable)
that you reference within the template. The input variables in this example are `hero`, `i`, and `odd`.
The parser translates `let hero`, `let i`, and `let odd` into variables named,
`let-hero`, `let-i`, and `let-odd`.
@ -353,7 +235,7 @@ It's intended source is implicit.
Angular sets `let-hero` to the value of the context's `$implicit` property
which `NgFor` has initialized with the hero for the current iteration.
* The [API guide](../api/common/index/NgFor-directive.html "API: NgFor")
* The [API guide](api/common/index/NgFor-directive)
describes additional `NgFor` directive properties and context properties.
These microsyntax mechanisms are available to you when you write your own structural directives.
@ -368,18 +250,18 @@ Studying the source code for `NgIf` and `NgFor` is a great way to learn more.
### Template input variable
A _template input variable_ is a variable whose value you can reference _within_ a single instance of the template.
There are several such variables in this example: `hero`, `li`, and `odd`.
There are several such variables in this example: `hero`, `i`, and `odd`.
All are preceded by the keyword `let`.
A _template input variable_ is **_not_** the same as a
[template _reference_ variable](template-syntax.html#ref-vars),
[template _reference_ variable](guide/template-syntax),
neither _semantically_ nor _syntactically_.
You declare a template _input_ variable declaration with the `let` keyword (`let hero`).
You declare a template _input_ variable using the `let` keyword (`let hero`).
The variable's scope is limited to a _single instance_ of the repeated template.
You can use the same variable name again in the definition of other structural directives.
You declare a template _reference_ variable declaration by prefixing the variable name with `#` (`#var`).
You declare a template _reference_ variable by prefixing the variable name with `#` (`#var`).
A _reference_ variable refers to its attached element, component or directive.
It can be accessed _anywhere_ in the _entire template_.
@ -401,19 +283,16 @@ If so (and it seems like it should be so), how should Angular generalize the abi
There are no easy answers to these questions. Prohibiting multiple structural directives makes them moot.
There's an easy solution for this use case: put the `*ngIf` on a container element that wraps the `*ngFor` element.
One or both elements can be an [`ng-container`](#ngcontainer) so you don't have to introduce extra levels of HTML.
One or both elements can be an [`ng-container`](guide/structural-directives#ngcontainer) so you don't have to introduce extra levels of HTML.
{@a ngswitch}
{@a ngSwitch}
## Inside the _NgSwitch_ directives
## Inside _NgSwitch_ directives
The Angular _NgSwitch_ is actually a set of cooperating directives: `NgSwitch`, `NgSwitchCase`, and `NgSwitchDefault`.
Here's an example.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngswitch'}
The switch value assigned to `NgSwitch` (`hero.emotion`) determines which
(if any) of the switch cases are displayed.
@ -422,7 +301,7 @@ It's an _attribute_ directive that controls the behavior of the other two switch
That's why you write `[ngSwitch]`, never `*ngSwitch`.
`NgSwitchCase` and `NgSwitchDefault` _are_ structural directives.
You attach them to elements using the asterisk (\*) prefix notation.
You attach them to elements using the asterisk (*) prefix notation.
An `NgSwitchCase` displays its host element when its value matches the switch value.
The `NgSwitchDefault` displays its host element when no sibling `NgSwitchCase` matches the switch value.
@ -430,26 +309,20 @@ The element to which you apply a directive is its _host_ element.
The `<happy-hero>` is the host element for the happy `*ngSwitchCase`.
The `<unknown-hero>` is the host element for the `*ngSwitchDefault`.
As with other structural directives, the `NgSwitchCase` and `NgSwitchDefault`
can be "de-sugared" into the template _attribute_ form.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngswitch-template-attr'}
That, in turn, can be "de-sugared" into the `<template>` element form.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngswitch-template'}
can be desugared into the template _attribute_ form.
That, in turn, can be desugared into the `<template>` element form.
{@a prefer-asterisk}
## Prefer the asterisk (\*) syntax.
## Prefer the asterisk (*) syntax.
The asterisk (\*) syntax is more clear than the other "de-sugared" forms.
Use [&lt;ng-container&gt;](#ng-container) when there's no single element
The asterisk (*) syntax is more clear than the other desugared forms.
Use [&lt;ng-container&gt;](guide/structural-directives#ng-container) when there's no single element
to host the directive.
While there's rarely a good reason to apply a structural directive in template _attribute_ or _element_ form,
it's still important to know that Angular creates a `<template>` and to understand how it works.
You'll refer to the `<template>` when you [write your own structural directive](#unless).
You'll refer to the `<template>` when you [write your own structural directive](guide/structural-directives#unless).
{@a template}
@ -461,37 +334,116 @@ is a formula for rendering HTML.
It is never displayed directly.
In fact, before rendering the view, Angular _replaces_ the `<template>` and its contents with a comment.
If there is no structural directive, if you merely wrap some elements in a `<template>` and do nothing with it,
If there is no structural directive and you merely wrap some elements in a `<template>`,
those elements disappear.
That's the fate of the middle "hip" in the phrase "Hip! Hip! Hooray!".
That's the fate of the middle "Hip!" in the phrase "Hip! Hip! Hooray!".
Angular erases the middle "Hip!", leaving the cheer a bit less enthusiastic.
{@example 'structural-directives/ts/src/app/app.component.html' region='template-tag'}
Angular erases the middle "hip", leaving the cheer a bit less enthusiastic.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/template-rendering.png' width="350" alt="template tag rendering"> </img>
</figure>
A structural directive puts a `<template>` to work
as you'll see when you write your own structural directive.
as you'll see when you [write your own structural directive](guide/structural-directives#unless).
{@a ngcontainer}
{@a ng-container}
## Group sibling elements with &lt;ng-container&gt;
There's often a _root_ element that can and should host the structural directive.
The list element (`<li>`) is a typical host element of an `NgFor` repeater.
When there isn't a host element, you can usually wrap the content in a native HTML container element,
such as a `<div>`, and attach the directive to that wrapper.
Introducing another container element&mdash;typically a `<span>` or `<div>`&mdash;to
group the elements under a single _root_ is usually harmless.
_Usually_ ... but not _always_.
The grouping element may break the template appearance because CSS styles
neither expect nor accommodate the new layout.
For example, suppose you have the following paragraph layout.
You also have a CSS style rule that happens to apply to a `<span>` within a `<p>`aragraph.
The constructed paragraph renders strangely.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/bad-paragraph.png' alt="spanned paragraph with bad style"> </img>
</figure>
The `p span` style, intended for use elsewhere, was inadvertently applied here.
Another problem: some HTML elements require all immediate children to be of a specific type.
For example, the `<select>` element requires `<option>` children.
You can't wrap the _options_ in a conditional `<div>` or a `<span>`.
When you try this,
the drop down is empty.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/bad-select.png' alt="spanned options don't work"> </img>
</figure>
The browser won't display an `<option>` within a `<span>`.
### &lt;ng-container&gt; to the rescue
The Angular `<ng-container>` is a grouping element that doesn't interfere with styles or layout
because Angular _doesn't put it in the DOM_.
Here's the conditional paragraph again, this time using `<ng-container>`.
It renders properly.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/good-paragraph.png' alt="ngcontainer paragraph with proper style"> </img>
</figure>
Now conditionally exclude a _select_ `<option>` with `<ng-container>`.
The drop down works properly.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/select-ngcontainer-anim.gif' alt="ngcontainer options work properly"> </img>
</figure>
The `<ng-container>` is a syntax element recognized by the Angular parser.
It's not a directive, component, class, or interface.
It's more like the curly braces in a JavaScript `if`-block:
<code-example language="javascript">
if (someCondition) {
statement1;
statement2;
statement3;
}
</code-example>
Without those braces, JavaScript would only execute the first statement
when you intend to conditionally execute all of them as a single block.
The `<ng-container>` satisfies a similar need in Angular templates.
{@a unless}
## Write a structural directive
In this section, you write a `UnlessDirective` structural directive
In this section, you write an `UnlessDirective` structural directive
that does the opposite of `NgIf`.
`NgIf` displays the template content when the condition is `true`.
`UnlessDirective` displays the content when the condition is ***false***.
Creating a directive is similar to creating a component.
* Import the `Directive` decorator (instead of the `Component` decorator).
{@example 'structural-directives/ts/src/app/app.component.html' region='myUnless-1'}
* Import the `Input`, `TemplateRef`, and `ViewContainerRef` symbols; you'll need them for _any_ structural directive.
* Apply the decorator to the directive class.
* Set the CSS *attribute selector* that identifies the directive when applied to an element in a template.
{@example 'structural-directives/ts/src/app/unless.directive.ts' region='skeleton'}
The directive's _selector_ is typically the directive's **attribute name** in square brackets.`[myUnless]`.
Here's how you might begin:
The directive's _selector_ is typically the directive's **attribute name** in square brackets, `[myUnless]`.
The brackets define a CSS
<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors" target="_blank" title="MDN: Attribute selectors">attribute selector</a>.
@ -499,36 +451,29 @@ The directive _attribute name_ should be spelled in _lowerCamelCase_ and begin w
Don't use `ng`. That prefix belongs to Angular.
Pick something short that fits you or your company.
In this example, the prefix is `my`.
The directive _class_ name ends in `Directive` per the [style guide](style-guide.html#02-03 "Angular Style Guide").
The directive _class_ name ends in `Directive` per the [style guide](guide/style-guide).
Angular's own directives do not.
### _TemplateRef_ and _ViewContainerRef_
A simple structural directive like this one creates an
[_embedded view_](../api/core/index/EmbeddedViewRef-class.html "API: EmbeddedViewRef")
[_embedded view_](api/core/index/EmbeddedViewRef-class)
from the Angular-generated `<template>` and inserts that view in a
[_view container_](../api/core/index/ViewContainerRef-class.html "API: ViewContainerRef")
[_view container_](api/core/index/ViewContainerRef-class)
adjacent to the directive's original `<p>` host element.
You'll acquire the `<template>` contents with a
[`TemplateRef`](../api/core/index/TemplateRef-class.html "API: TemplateRef")
[`TemplateRef`](api/core/index/TemplateRef-class)
and access the _view container_ through a
[`ViewContainerRef`](../api/core/index/ViewContainerRef-class.html "API: ViewContainerRef").
[`ViewContainerRef`](api/core/index/ViewContainerRef-class).
You inject both in the directive constructor as private variables of the class.
{@example 'structural-directives/ts/src/app/unless.directive.ts' region='ctor'}
### The _myUnless_ property
The directive consumer expects to bind a true/false condition to `[myUnless]`.
That means the directive needs a `myUnless` property, decorated with `@Input`
Read about `@Input` in the [_Template Syntax_](template-syntax.html#inputs-outputs) guide.
{@example 'structural-directives/ts/src/app/unless.directive.ts' region='set'}
Read about `@Input` in the [_Template Syntax_](guide/template-syntax) guide.
Angular sets the `myUnless` property whenever the value of the condition changes.
Because the `myUnless` property does work, it needs a setter.
@ -541,18 +486,12 @@ clear the container which also destroys the view.
Nobody reads the `myUnless` property so it doesn't need a getter.
The completed directive code looks like this:
{@example 'structural-directives/ts/src/app/unless.directive.ts' region='no-docs'}
Add this directive to the `!{_declsVsDirectives}` !{_array} of the !{_AppModuleVsAppComp}.
Then create some HTML to try it.
{@example 'structural-directives/ts/src/app/app.component.html' region='myUnless'}
When the `condition` is falsy, the top (A) paragraph appears and the bottom (B) paragraph disappears.
When the `condition` is truthy, the top (A) paragraph is removed and the bottom (B) paragraph appears.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/unless-anim.gif' alt="UnlessDirective in action"> </img>
</figure>
@ -562,9 +501,10 @@ When the `condition` is truthy, the top (A) paragraph is removed and the bottom
{@a summary}
## Summary
You can both try and download the source code for this guide in the <live-example></live-example>.
Here is the source from the `app/` folder.
Here is the source from the `src/app/` folder.
<md-tab-group>
@ -606,9 +546,10 @@ Here is the source from the `app/` folder.
</md-tab-group>
You learned
* that structural directives manipulate HTML layout.
* to use [`<ng-container>`](#ngcontainer) as a grouping element when there is no suitable host element.
* that the angular "de-sugars" [asterisk (\*) syntax](#asterisk) into a `<template>`.
* to use [`<ng-container>`](guide/structural-directives#ngcontainer) as a grouping element when there is no suitable host element.
* that the Angular desugars [asterisk (*) syntax](guide/structural-directives#asterisk) into a `<template>`.
* how that works for the `NgIf`, `NgFor` and `NgSwitch` built-in directives.
* about the [_microsyntax_](#microsyntax) that expands into a [`<template>`](#template).
* to write a [custom structural directive](#unless), `UnlessDirective`.
* about the [_microsyntax_](guide/structural-directives#microsyntax) that expands into a [`<template>`](guide/structural-directives#template).
* to write a [custom structural directive](guide/structural-directives#unless), `UnlessDirective`.

View File

@ -60,16 +60,16 @@ The guideline will use the shortcut `hero.component.ts|html|css|spec` to represe
{@a toc}
## Table of contents
1. [Single responsibility](#single-responsibility)
1. [Naming](#naming)
1. [Coding conventions](#coding-conventions)
1. [App structure and Angular modules](#application-structure-and-angular-modules)
1. [Components](#components)
1. [Directives](#directives)
1. [Services](#services)
1. [Data services](#data-services)
1. [Lifecycle hooks](#lifecycle-hooks)
1. [Appendix](#appendix)
1. [Single responsibility](guide/style-guide#single-responsibility)
1. [Naming](guide/style-guide#naming)
1. [Coding conventions](guide/style-guide#coding-conventions)
1. [App structure and Angular modules](guide/style-guide#application-structure-and-angular-modules)
1. [Components](guide/style-guide#components)
1. [Directives](guide/style-guide#directives)
1. [Services](guide/style-guide#services)
1. [Data services](guide/style-guide#data-services)
1. [Lifecycle hooks](guide/style-guide#lifecycle-hooks)
1. [Appendix](guide/style-guide#appendix)
## Single responsibility
@ -3225,7 +3225,7 @@ A typical *lazy loaded folder* contains a *routing component*, its child compone
<div class='s-why' class='s-why-last'>
**Why?** Angular allows for an [alternative syntax](template-syntax.html#binding-syntax) `on-*`. If the event itself was prefixed with `on` this would result in an `on-onEvent` binding expression.
**Why?** Angular allows for an [alternative syntax](guide/template-syntax) `on-*`. If the event itself was prefixed with `on` this would result in an `on-onEvent` binding expression.
</div>

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
TypeScript to JavaScript
@intro
Convert Angular TypeScript examples into ES6 and ES5 JavaScript
Convert Angular TypeScript examples into ES6 and ES5 JavaScript.
@description
Anything you can do with Angular in _TypeScript_, you can also do
@ -19,16 +19,16 @@ can read and write Angular apps in their preferred dialect.
{@a toc}
## Table of contents
[_TypeScript_ to _ES6_ to _ES5_](#from-ts)<br>
[Modularity: imports and exports](#modularity)<br>
[Classes and Class Metadata](#class-metadata)<br>
[_ES5_ DSL](#dsl)<br>
[Interfaces](#interfaces)<br>
[Input and Output Metadata](#io-decorators)<br>
[Dependency Injection](#dependency-injection)<br>
[Host Binding](#host-binding)<br>
[View and Child Decorators](#view-child-decorators)<br>
[AOT compilation in _TypeScript_ Only](#aot)<br>
[_TypeScript_ to _ES6_ to _ES5_](guide/ts-to-js#from-ts)<br>
[Modularity: imports and exports](guide/ts-to-js#modularity)<br>
[Classes and Class Metadata](guide/ts-to-js#class-metadata)<br>
[_ES5_ DSL](guide/ts-to-js#dsl)<br>
[Interfaces](guide/ts-to-js#interfaces)<br>
[Input and Output Metadata](guide/ts-to-js#io-decorators)<br>
[Dependency Injection](guide/ts-to-js#dependency-injection)<br>
[Host Binding](guide/ts-to-js#host-binding)<br>
[View and Child Decorators](guide/ts-to-js#view-child-decorators)<br>
[AOT compilation in _TypeScript_ Only](guide/ts-to-js#aot)<br>
**Run and compare the live <live-example name="cb-ts-to-js">_TypeScript_</live-example> and <live-example name="cb-ts-to-js" lang="js">JavaScript</live-example>
code shown in this cookbook.**
@ -40,7 +40,7 @@ code shown in this cookbook.**
_TypeScript_
<a href="https://www.typescriptlang.org" target="_blank" title='"TypeScript is a typed, superset of JavaScript"'>is a typed superset of _ES6 JavaScript_</a>.
&nbsp; _ES6 JavaScript_ is a superset of _ES5 JavaScript_. &nbsp; _ES5_ is the kind of JavaScript that runs natively in all modern browsers.
_ES6 JavaScript_ is a superset of _ES5 JavaScript_. _ES5_ is the kind of JavaScript that runs natively in all modern browsers.
The transformation of _TypeScript_ code all the way down to _ES5_ code can be seen as "shedding" features.
The downgrade progression is
@ -81,7 +81,7 @@ To use decorators and annotations with Babel, install the
In both _TypeScript_ and _ES6_, you import Angular classes, functions, and other members with _ES6_ `import` statements.
In _ES5_, you access the Angular entities of the [the Angular packages](../glossary.html#scoped-package)
In _ES5_, you access the Angular entities of the [the Angular packages](glossary)
through the global `ng` object.
Anything you can import from `@angular` is a nested member of this `ng` object:
@ -260,7 +260,7 @@ Use the constructor function pattern instead, adding methods to the prototype.
When writing in _TypeScript_ or _ES6-with-decorators_,
provide configuration and metadata by adorning a class with one or more *decorators*.
For example, you supply metadata to a component class by preceding its definition with a
[`@Component`](../api/core/index/Component-decorator.html) decorator function whose
[`@Component`](api/core/index/Component-decorator) decorator function whose
argument is an object literal with metadata properties.
In _plain ES6_, you provide metadata by attaching an `annotations` array to the _class_.
@ -477,7 +477,7 @@ Just implement the methods and ignore interfaces when translating code samples f
### Input and Output Decorators
In _TypeScript_ and _ES6-with-decorators_, you often add metadata to class _properties_ with _property decorators_.
For example, you apply [`@Input` and `@Output` property decorators](../guide/template-syntax.html#inputs-outputs)
For example, you apply [`@Input` and `@Output` property decorators](guide/template-syntax)
to public class properties that will be the target of data binding expressions in parent components.
There is no equivalent of a property decorator in _ES5_ or _plain ES6_.
@ -529,7 +529,7 @@ you specify the special binding name in the argument to the property decorator.
In _ES5_ and _plain ES6_ code, convey this pairing with the `propertyName: bindingName` syntax in the class metadata.
## Dependency Injection
Angular relies heavily on [Dependency Injection](../guide/dependency-injection.html) to provide services to the objects it creates.
Angular relies heavily on [Dependency Injection](guide/dependency-injection) to provide services to the objects it creates.
When Angular creates a new component, directive, pipe or another service,
it sets the class constructor parameters to instances of services provided by an _Injector_.
@ -642,12 +642,12 @@ You can qualify injection behavior with injection decorators from `@angular/core
In _TypeScript_ and _ES6-with-decorators_,
you precede the constructor parameters with injection qualifiers such as:
* [`@Optional`](../api/core/index/Optional-decorator.html) sets the parameter to `null` if the service is missing
* [`@Attribute`](../api/core/index/Attribute-interface.html) to inject a host element attribute value
* [`@ContentChild`](../api/core/index/ContentChild-decorator.html) to inject a content child
* [`@ViewChild`](../api/core/index/ViewChild-decorator.html) to inject a view child
* [`@Host`](../api/core/index/Host-decorator.html) to inject a service in this component or its host
* [`@SkipSelf`](../api/core/index/SkipSelf-decorator.html) to inject a service provided in an ancestor of this component
* [`@Optional`](api/core/index/Optional-decorator) sets the parameter to `null` if the service is missing
* [`@Attribute`](api/core/index/Attribute-interface) to inject a host element attribute value
* [`@ContentChild`](api/core/index/ContentChild-decorator) to inject a content child
* [`@ViewChild`](api/core/index/ViewChild-decorator) to inject a view child
* [`@Host`](api/core/index/Host-decorator) to inject a service in this component or its host
* [`@SkipSelf`](api/core/index/SkipSelf-decorator) to inject a service provided in an ancestor of this component
In _plain ES6_ and _ES5_, create an instance of the equivalent injection qualifier in a nested array within the `parameters` array.
For example, you'd write `new Optional()` in _plain ES6_ and `new ng.core.Optional()` in _ES5_.
@ -702,9 +702,9 @@ element whose tag matches the component selector.
In _TypeScript_ and _ES6-with-decorators_, you can use host property decorators to bind a host
element to a component or directive.
The [`@HostBinding`](../api/core/index/HostBinding-interface.html) decorator
The [`@HostBinding`](api/core/index/HostBinding-interface) decorator
binds host element properties to component data properties.
The [`@HostListener`](../api/core/index/HostListener-interface.html) decorator binds
The [`@HostListener`](api/core/index/HostListener-interface) decorator binds
host element events to component event handlers.
In _plain ES6_ or _ES5_, add a `host` attribute to the component metadata to achieve the
@ -778,8 +778,8 @@ Several _property_ decorators query a component's nested view and content compon
_View_ children are associated with element tags that appear _within_ the component's template.
_Content_ children are associated with elements that appear _between_ the component's element tags;
they are projected into an `<ng-content>` slot in the component's template. The [`@ViewChild`](../api/core/index/ViewChild-decorator.html) and
[`@ViewChildren`](../api/core/index/ViewChildren-decorator.html) property decorators
they are projected into an `<ng-content>` slot in the component's template. The [`@ViewChild`](api/core/index/ViewChild-decorator) and
[`@ViewChildren`](api/core/index/ViewChildren-decorator) property decorators
allow a component to query instances of other components that are used in
its view.
@ -813,13 +813,13 @@ The `queries` property value is a hash map.
</md-tab-group>
The [`@ContentChild`](../api/core/index/ContentChild-decorator.html) and
[`@ContentChildren`](../api/core/index/ContentChildren-decorator.html) property decorators
The [`@ContentChild`](api/core/index/ContentChild-decorator) and
[`@ContentChildren`](api/core/index/ContentChildren-decorator) property decorators
allow a component to query instances of other components that have been projected
into its view from elsewhere.
They can be added in the same way as [`@ViewChild`](../api/core/index/ViewChild-decorator.html) and
[`@ViewChildren`](../api/core/index/ViewChildren-decorator.html).
They can be added in the same way as [`@ViewChild`](api/core/index/ViewChild-decorator) and
[`@ViewChildren`](api/core/index/ViewChildren-decorator).
<md-tab-group>
@ -862,7 +862,7 @@ instead of the `@ViewChild` and `@ContentChild` property decorators.
## AOT Compilation in _TypeScript_ only
Angular offers two modes of template compilation, JIT (_Just-in-Time_) and
[AOT (_Ahead-of-Time_)](aot-compiler.html).
[AOT (_Ahead-of-Time_)](guide/aot-compiler).
Currently the AOT compiler only works with _TypeScript_ applications because, in part, it generates
_TypeScript_ files as an intermediate result.
**AOT is not an option for pure JavaScript applications** at this time.

View File

@ -30,32 +30,32 @@ business, because the work can be done collaboratively and spread over
a period of time. The `upgrade` module in Angular has been designed to
make incremental upgrading seamless.
1. [Preparation](#preparation)
1. [Follow the Angular Style Guide](#follow-the-angular-style-guide)
2. [Using a Module Loader](#using-a-module-loader)
3. [Migrating to TypeScript](#migrating-to-typescript)
4. [Using Component Directives](#using-component-directives)
2. [Upgrading with The Upgrade Module](#upgrading-with-the-upgrade-module)
1. [How The Upgrade Module Works](#how-the-upgrade-module-works)
2. [Bootstrapping hybrid](#bootstrapping-hybrid-applications)
3. [Using Angular Components from AngularJS Code](#using-angular-components-from-angularjs-code)
4. [Using AngularJS Component Directives from Angular Code](#using-angularjs-component-directives-from-angular-code)
5. [Projecting AngularJS Content into Angular Components](#projecting-angularjs-content-into-angular-components)
6. [Transcluding Angular Content into AngularJS Component Directives](#transcluding-angular-content-into-angularjs-component-directives)
7. [Making AngularJS Dependencies Injectable to Angular](#making-angularjs-dependencies-injectable-to-angular)
8. [Making Angular Dependencies Injectable to AngularJS](#making-angular-dependencies-injectable-to-angularjs)
9. [Using Ahead-of-time compilation with hybrid apps](#using-ahead-of-time-compilation-with-hybrid-apps)
10. [Dividing routes between Angular and AngularJS](#dividing-routes-between-angular-and-angularjs)
3. [PhoneCat Upgrade Tutorial](#phonecat-upgrade-tutorial)
1. [Switching to TypeScript](#switching-to-typescript)
2. [Installing Angular](#installing-angular)
3. [Bootstrapping a hybrid PhoneCat](#bootstrapping-a-hybrid-phonecat)
4. [Upgrading the Phone service](#upgrading-the-phone-service)
5. [Upgrading Components](#upgrading-components)
6. [AoT compile the hybrid app](#aot-compile-the-hybrid-app)
7. [Adding The Angular Router And Bootstrap](#adding-the-angular-router-and-bootstrap)
8. [Say Goodbye to AngularJS](#say-goodbye-to-angularjs)
3. [Appendix: Upgrading PhoneCat Tests](#appendix-upgrading-phonecat-tests)
1. [Preparation](guide/upgrade#preparation)
1. [Follow the Angular Style Guide](guide/upgrade#follow-the-angular-style-guide)
2. [Using a Module Loader](guide/upgrade#using-a-module-loader)
3. [Migrating to TypeScript](guide/upgrade#migrating-to-typescript)
4. [Using Component Directives](guide/upgrade#using-component-directives)
2. [Upgrading with The Upgrade Module](guide/upgrade#upgrading-with-the-upgrade-module)
1. [How The Upgrade Module Works](guide/upgrade#how-the-upgrade-module-works)
2. [Bootstrapping hybrid](guide/upgrade#bootstrapping-hybrid-applications)
3. [Using Angular Components from AngularJS Code](guide/upgrade#using-angular-components-from-angularjs-code)
4. [Using AngularJS Component Directives from Angular Code](guide/upgrade#using-angularjs-component-directives-from-angular-code)
5. [Projecting AngularJS Content into Angular Components](guide/upgrade#projecting-angularjs-content-into-angular-components)
6. [Transcluding Angular Content into AngularJS Component Directives](guide/upgrade#transcluding-angular-content-into-angularjs-component-directives)
7. [Making AngularJS Dependencies Injectable to Angular](guide/upgrade#making-angularjs-dependencies-injectable-to-angular)
8. [Making Angular Dependencies Injectable to AngularJS](guide/upgrade#making-angular-dependencies-injectable-to-angularjs)
9. [Using Ahead-of-time compilation with hybrid apps](guide/upgrade#using-ahead-of-time-compilation-with-hybrid-apps)
10. [Dividing routes between Angular and AngularJS](guide/upgrade#dividing-routes-between-angular-and-angularjs)
3. [PhoneCat Upgrade Tutorial](guide/upgrade#phonecat-upgrade-tutorial)
1. [Switching to TypeScript](guide/upgrade#switching-to-typescript)
2. [Installing Angular](guide/upgrade#installing-angular)
3. [Bootstrapping a hybrid PhoneCat](guide/upgrade#bootstrapping-a-hybrid-phonecat)
4. [Upgrading the Phone service](guide/upgrade#upgrading-the-phone-service)
5. [Upgrading Components](guide/upgrade#upgrading-components)
6. [AoT compile the hybrid app](guide/upgrade#aot-compile-the-hybrid-app)
7. [Adding The Angular Router And Bootstrap](guide/upgrade#adding-the-angular-router-and-bootstrap)
8. [Say Goodbye to AngularJS](guide/upgrade#say-goodbye-to-angularjs)
3. [Appendix: Upgrading PhoneCat Tests](guide/upgrade#appendix-upgrading-phonecat-tests)
## Preparation
@ -207,7 +207,7 @@ using the component API:
Controller lifecycle hook methods `$onInit()`, `$onDestroy()`, and `$onChanges()`
are another convenient feature that AngularJS 1.5 introduces. They all have nearly
exact [equivalents in Angular](lifecycle-hooks.html), so organizing component lifecycle
exact [equivalents in Angular](guide/lifecycle-hooks), so organizing component lifecycle
logic around them will ease the eventual Angular upgrade process.
## Upgrading with The Upgrade Module
@ -266,7 +266,7 @@ frameworks in how it actually works.
<td>
Tokens [can have different types](../guide/dependency-injection.html).
Tokens [can have different types](guide/dependency-injection).
They are often classes. They may also be strings.
</td>
@ -283,7 +283,7 @@ frameworks in how it actually works.
<td>
There is a [tree hierarchy of injectors](../guide/hierarchical-dependency-injection.html),
There is a [tree hierarchy of injectors](guide/hierarchical-dependency-injection),
with a root injector and an additional injector for each component.
</td>
@ -379,7 +379,7 @@ bindings get updated.
In Angular things are different. While change detection still
occurs after every event, no one needs to call `scope.$apply()` for
that to happen. This is because all Angular code runs inside something
called the [Angular zone](../api/core/index/NgZone-class.html). Angular always
called the [Angular zone](api/core/index/NgZone-class). Angular always
knows when the code finishes, so it also knows when it should kick off
change detection. The code itself doesn't have to call `scope.$apply()`
or anything like it.
@ -408,7 +408,7 @@ When we downgrade an Angular component and then use it from AngularJS,
the component's inputs will be watched using AngularJS change detection.
When those inputs change, the corresponding properties in the component
are set. We can also hook into the changes by implementing the
[OnChanges](../api/core/index/OnChanges-class.html) interface in the component,
[OnChanges](api/core/index/OnChanges-class) interface in the component,
just like we could if it hadn't been downgraded.
Correspondingly, when we upgrade an AngularJS component and use it from Angular,
@ -432,7 +432,7 @@ That means that we need at least one module each from both AngularJS and Angular
We will import `UpgradeModule` inside our Angular module, and then use it for
bootstrapping our AngularJS module. Let's see how.
Learn more about Angular modules at the [NgModule guide](ngmodule.html).
Learn more about Angular modules at the [NgModule guide](guide/ngmodule).
### Bootstrapping hybrid applications
The first step to upgrading an application using the `UpgradeModule` is
@ -460,7 +460,7 @@ will result in the same thing:
{@example 'upgrade-module/ts/src/app/ajs-bootstrap/app.module.ts' region='bootstrap'}
Now introduce Angular to the project. Inspired by instructions in
[the Setup](setup.html), you can selectively copy in material from the
[the Setup](guide/setup), you can selectively copy in material from the
<a href="https://github.com/angular/quickstart" target="_blank">QuickStart github repository</a>.
Next, create an `app.module.ts` file and add the following `NgModule` class:
@ -615,7 +615,7 @@ Angular.
Not all kinds of AngularJS directives can be upgraded. The directive
really has to be a *component directive*, with the characteristics
[described in the preparation guide above](#using-component-directives).
[described in the preparation guide above](guide/upgrade#using-component-directives).
Our safest bet for ensuring compatibility is using the
[component API](https://docs.angularjs.org/api/ng/type/angular.Module)
introduced in AngularJS 1.5.
@ -860,7 +860,7 @@ code. For example, we might have a service called `HeroesService` in AngularJS:
{@example 'upgrade-module/ts/src/app/ajs-to-a-providers/heroes.service.ts'}
We can upgrade the service using a Angular [Factory provider](./dependency-injection.html#factory-providers)
We can upgrade the service using a Angular [Factory provider](guide/dependency-injection)
that requests the service from the AngularJS `$injector`.
We recommend declaring the Factory Provider in a separate `ajs-upgraded-providers.ts` file
@ -929,7 +929,7 @@ After this, the service is injectable anywhere in our AngularJS code:
We can take advantage of Ahead-of-time (AoT) compilation on hybrid apps just like on any other
Angular application.
The setup for an hybrid app is mostly the same as described in
[the Ahead-of-time Compilation chapter](../cookbook/aot-compiler.html)
[the Ahead-of-time Compilation chapter](cookbook/aot-compiler)
save for differences in `index.html` and `main-aot.ts`
Our `index.html` will likely have script tags loading AngularJS files, so the `index.html` we
@ -986,7 +986,7 @@ Next we declare both AngularJS and Angular routes as normal:
In our `app.module.ts` we need to add `AppComponent` to the declarations and boostrap array.
Next we configure the router itself.
We want to use [hash navigation](./router.html#-hashlocationstrategy-) in Angular
We want to use [hash navigation](guide/router) in Angular
because that's what we're also using in AngularJS.
Lastly, and most importantly, we want to use a custom `UrlHandlingStrategy` that will tell
@ -1008,7 +1008,7 @@ which is where many of us began our Angular adventures. Now we'll see how to
bring that application to the brave new world of Angular.
During the process we'll learn how to apply the steps outlined in the
[preparation guide](#preparation) in practice: We'll align the application
[preparation guide](guide/upgrade#preparation) in practice: We'll align the application
with Angular and also take TypeScript into use.
To follow along with the tutorial, clone the
@ -1204,7 +1204,7 @@ In terms of project structure, this is where our work begins:
This is actually a pretty good starting point. The code uses the AngularJS 1.5
component API and the organization follows the
[AngularJS Style Guide](https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md),
which is an important [preparation step](#following-the-angular-style-guide) before
which is an important [preparation step](guide/upgrade#following-the-angular-style-guide) before
a successful upgrade.
* Each component, service, and filter is in its own source file, as per the
@ -1246,7 +1246,7 @@ Jasmine unit test framework.
We should also configure the TypeScript compiler so that it can understand our
project. We'll add a `tsconfig.json` file to the project directory, just like we do
in the documentation [setup](setup.html). It instructs the TypeScript compiler how
in the documentation [setup](guide/setup). It instructs the TypeScript compiler how
to interpret our source files.
We are telling the TypeScript compiler to turn our TypeScript files to ES5 code
bundled into CommonJS modules.
@ -1362,7 +1362,7 @@ We'll instead turn it directly into an Angular service.
Having completed our preparation work, let's get going with the Angular
upgrade of PhoneCat. We'll do this incrementally with the help of the
[upgrade module](#upgrading-with-the-upgrade-module) that comes with Angular.
[upgrade module](guide/upgrade#upgrading-with-the-upgrade-module) that comes with Angular.
By the time we're done, we'll be able to remove AngularJS from the project
completely, but the key is to do this piece by piece without breaking the application.
@ -1374,7 +1374,7 @@ The project also contains some animations, which we are not yet upgrading in thi
~~~
Let's install Angular into the project, along with the SystemJS module loader.
Take a look at the results of the [Setup](setup.html) instructions
Take a look at the results of the [Setup](guide/setup) instructions
and get the following configurations from there:
* Add Angular and the other new dependencies to `package.json`
@ -1411,7 +1411,7 @@ to load the actual application:
{@example 'upgrade-phonecat-2-hybrid/ts/index.html' region='angular'}
We also need to make a couple of adjustments
to the `systemjs.config.js` file installed during [setup](setup.html).
to the `systemjs.config.js` file installed during [setup](guide/setup).
We want to point the browser to the project root when loading things through SystemJS,
instead of using the `<base>` URL.
@ -1443,7 +1443,7 @@ What we'll do next is bootstrap the application as a *hybrid application*
that supports both AngularJS and Angular components. Once we've done that
we can start converting the individual pieces to Angular.
To [bootstrap a hybrid application](#bootstrapping-hybrid-applications),
To [bootstrap a hybrid application](guide/upgrade#bootstrapping-hybrid-applications),
we first need to import `UpgradeModule` in our `AppModule`, and override it's bootstrap method:
@ -1514,7 +1514,7 @@ service in `phone.service.ts` with a TypeScript class decorated as `@Injectable`
The `@Injectable` decorator will attach some dependency injection metadata
to the class, letting Angular know about its dependencies. As described
by our [Dependency Injection Guide](./dependency-injection.html),
by our [Dependency Injection Guide](guide/dependency-injection),
this is a marker decorator we need to use for classes that have no other
Angular decorators but still need to have their dependencies injected.
@ -1614,7 +1614,7 @@ with Angular's two-way `[(ngModel)]` binding syntax:
{@example 'upgrade-phonecat-2-hybrid/ts/app/phone-list/phone-list.template.html' region='controls'}
Replace the list's `ng-repeat` with an `*ngFor` as
[described in the Template Syntax page](../guide/template-syntax.html#directives).
[described in the Template Syntax page](guide/template-syntax).
Replace the image tag's `ng-src` with a binding to the native `src` property.
@ -1662,7 +1662,7 @@ which was injected into `PhoneDetails` when it was still an AngularJS controller
We intend to inject it into the new `PhoneDetailsComponent`.
Unfortunately, AngularJS dependencies are not automatically available to Angular components.
We must use a [Factory provider](#making-angularjs-dependencies-injectable-to-angular)
We must use a [Factory provider](guide/upgrade#making-angularjs-dependencies-injectable-to-angular)
to make `$routeParams` an Angular provider.
Do that in a new file called `ajs-upgraded-providers.ts` and import it in `app.module.ts`:
@ -1684,7 +1684,7 @@ There are several notable changes here:
* Just like we did in the phone list, we've replaced `ng-src` with property
bindings for the standard `src` property.
* We're using the property binding syntax around `ng-class`. Though Angular
does have [a very similar `ngClass`](../guide/template-syntax.html#directives)
does have [a very similar `ngClass`](guide/template-syntax)
as AngularJS does, its value is not magically evaluated as an expression.
In Angular we always specify in the template when an attribute's value is
a property expression, as opposed to a literal string.
@ -1727,7 +1727,7 @@ remove the filter &lt;script&gt; tag from `index.html`:
## AoT compile the hybrid app
To use AoT with our hybrid app we have to first set it up like any other Angular application,
as shown in [the Ahead-of-time Compilation chapter](../cookbook/aot-compiler.html).
as shown in [the Ahead-of-time Compilation chapter](cookbook/aot-compiler).
Then we have to change `main-aot.ts` bootstrap also bootstrap the AngularJS app
via `UpgradeModule`:
@ -1764,7 +1764,7 @@ while keeping `/phones/:phoneId` in the AngularJS router.
#### Add the Angular router
Angular has an [all-new router](router.html).
Angular has an [all-new router](guide/router).
Like all routers, it needs a place in the UI to display routed views.
For Angular that's the `<router-outlet>` and it belongs in a *root component*
@ -1792,7 +1792,7 @@ It replaces the old AngularJS `ng-view` directive:
#### Create the _Routing Module_
A router needs configuration whether it's the AngularJS or Angular or any other router.
The details of Angular router configuration are best left to the [Routing documentation](router.html)
The details of Angular router configuration are best left to the [Routing documentation](guide/router)
which recommends that you create a `NgModule` dedicated to router configuration
(called a _Routing Module_).
@ -1838,7 +1838,7 @@ and let that directive construct the appropriate URL to the `PhoneDetailComponen
{@example 'upgrade-phonecat-3-router/ts/app/phone-list/phone-list.template.html' region='list'}
See the [Routing](router.html) page for details.
See the [Routing](guide/router) page for details.
We are now running both routers at the same time!
Angular is handling the initial `/` url, redirecting to `/phones`.
Meanwhile when we click a link to the phone detail, AngularJS takes over.
@ -1881,7 +1881,7 @@ to the Angular way.
{@example 'upgrade-phonecat-4-final/ts/app/main.ts'}
If you haven't already, remove all references to the `UpgradeModule` from `app.module.ts`,
as well as any [Factory provider](#making-angularjs-dependencies-injectable-to-angular)
as well as any [Factory provider](guide/upgrade#making-angularjs-dependencies-injectable-to-angular)
for AngularJS services, and the `app/ajs-upgraded-providers.ts` file.
Also remove any `downgradeInjectable()` or `downgradeComponent()` you find,

View File

@ -13,13 +13,13 @@ event binding syntax.
Run the <live-example></live-example>.
## Binding to user input events
You can use [Angular event bindings](./template-syntax.html#event-binding)
You can use [Angular event bindings](guide/template-syntax)
to respond to any [DOM event](https://developer.mozilla.org/en-US/docs/Web/Events).
Many DOM events are triggered by user input. Binding to these events provides a way to
get input from the user.
To bind to a DOM event, surround the DOM event name in parentheses and assign a quoted
[template statement](./template-syntax.html#template-statements) to it.
[template statement](guide/template-syntax) to it.
The following example shows an event binding that implements a click handler:
@ -63,7 +63,7 @@ In this case, `target` refers to the [`<input>` element](https://developer.mozil
After each call, the `onKey()` method appends the contents of the input box value to the list
in the component's `values` property, followed by a separator character (|).
The [interpolation](./template-syntax.html#interpolation)
The [interpolation](guide/template-syntax)
displays the accumulating input box changes from the `values` property.
Suppose the user enters the letters "abc", and then backspaces to remove them one by one.
@ -114,7 +114,7 @@ The next section shows how to use template reference variables to address this p
## Get user input from a template reference variable
There's another way to get the user data: use Angular
[**template reference variables**](./template-syntax.html#ref-vars).
[**template reference variables**](guide/template-syntax).
These variables provide direct access to an element from within the template.
To declare a template reference variable, precede an identifier with a hash (or pound) character (#).
@ -184,7 +184,7 @@ To fix this issue, listen to both the _Enter_ key and the _blur_ event.
## Put it all together
The previous page showed how to [display data](./displaying-data.html).
The previous page showed how to [display data](guide/displaying-data).
This page demonstrated event binding techniques.
Now, put it all together in a micro-app

View File

@ -2,7 +2,7 @@
Visual Studio 2015 QuickStart
@intro
Use Visual Studio 2015 with the QuickStart files
Use Visual Studio 2015 with the QuickStart files.
@description
<a id="top"></a>Some developers prefer Visual Studio as their Integrated Development Environment (IDE).
@ -21,15 +21,15 @@ then consider the _experimental_
Note that the resulting code does not map to the docs. Adjust accordingly.
The steps are as follows:
- [Prerequisite](#prereq1): Install Node.js
- [Prerequisite](#prereq2): Install Visual Studio 2015 Update 3
- [Prerequisite](#prereq3): Configure External Web tools
- [Prerequisite](#prereq4): Install TypeScript 2 for Visual Studio 2015
- [Step 1](#download): Download the QuickStart files
- [Step 2](#create-project): Create the Visual Studio ASP.NET project
- [Step 3](#copy): Copy the QuickStart files into the ASP.NET project folder
- [Step 4](#restore): Restore required packages
- [Step 5](#build-and-run): Build and run the app
- [Prerequisite](guide/visual-studio-2015#prereq1): Install Node.js
- [Prerequisite](guide/visual-studio-2015#prereq2): Install Visual Studio 2015 Update 3
- [Prerequisite](guide/visual-studio-2015#prereq3): Configure External Web tools
- [Prerequisite](guide/visual-studio-2015#prereq4): Install TypeScript 2 for Visual Studio 2015
- [Step 1](guide/visual-studio-2015#download): Download the QuickStart files
- [Step 2](guide/visual-studio-2015#create-project): Create the Visual Studio ASP.NET project
- [Step 3](guide/visual-studio-2015#copy): Copy the QuickStart files into the ASP.NET project folder
- [Step 4](guide/visual-studio-2015#restore): Restore required packages
- [Step 5](guide/visual-studio-2015#build-and-run): Build and run the app
<h2 id='prereq1'>

View File

@ -2,7 +2,7 @@
Webpack: an introduction
@intro
Create Angular applications with a Webpack based tooling
Create Angular applications with a Webpack based tooling.
@description
@ -22,22 +22,22 @@ This guide offers a taste of Webpack and explains how to use it with Angular app
<a id="top"></a>
## Table of contents
[What is Webpack?](#what-is-webpack)
[What is Webpack?](guide/webpack#what-is-webpack)
* [Entries and outputs](#entries-outputs)
* [Loaders](#loaders)
* [Plugins](#plugins)
* [Entries and outputs](guide/webpack#entries-outputs)
* [Loaders](guide/webpack#loaders)
* [Plugins](guide/webpack#plugins)
[Configuring Webpack](#configure-webpack)
[Configuring Webpack](guide/webpack#configure-webpack)
* [Common configuration](#common-configuration)
* [Development configuration](#development-configuration)
* [Production configuration](#production-configuration)
* [Test configuration](#test-configuration)
* [Common configuration](guide/webpack#common-configuration)
* [Development configuration](guide/webpack#development-configuration)
* [Production configuration](guide/webpack#production-configuration)
* [Test configuration](guide/webpack#test-configuration)
[Trying it out](#try)
[Trying it out](guide/webpack#try)
[Conclusions](#conclusions)
[Conclusions](guide/webpack#conclusions)
You can also <a href="/resources/zips/webpack/webpack.zip">download the final result.</a>
@ -95,7 +95,7 @@ and emits *two* bundle files, one called `app.js` containing only the applicatio
another called `vendor.js` with all the vendor dependencies.
The `[name]` in the output name is a *placeholder* that a Webpack plugin replaces with the entry names,
`app` and `vendor`. Plugins are [covered later](#commons-chunk-plugin) in the guide.
`app` and `vendor`. Plugins are [covered later](guide/webpack#commons-chunk-plugin) in the guide.
To tell Webpack what belongs in the vendor bundle,
add a `vendor.ts` file that only imports the application's third-party modules:
@ -191,8 +191,8 @@ Add these files:
Many of these files should be familiar from other Angular documentation guides,
especially the [_Typescript configuration_](../guide/typescript-configuration.html) and
[_npm packages_](../guide/npm-packages.html) guides.
especially the [_Typescript configuration_](guide/typescript-configuration) and
[_npm packages_](guide/npm-packages) guides.
Webpack, the plugins, and the loaders are also installed as packages.
They are listed in the updated `packages.json`.
@ -209,7 +209,7 @@ Open a terminal window and (re)install the *npm* packages
### Polyfills
You'll need polyfills to run an Angular application in most browsers as explained
in the [_Browser Support_](browser-support.html) guide.
in the [_Browser Support_](guide/browser-support) guide.
Polyfills should be bundled separately from the application and vendor bundles.
Add a `polyfills.ts` like this one to the `src/` folder.
@ -253,10 +253,10 @@ Webpack is a NodeJS-based tool that reads configuration from a JavaScript _commo
The configuration imports dependencies with `require` statements
and exports several objects as properties of a `module.exports` object.
* [`entries`](#common-entries) - the entry-point files that define the bundles.
* [`resolve`](#common-resolve) - how to resolve file names when they lack extensions.
* [`module.rules`](#common-rules) - `module` is an object with `rules` for deciding how files are loaded.
* [`plugins`](#common-plugins) - creates instances of the plugins.
* [`entries`](guide/webpack#common-entries) - the entry-point files that define the bundles.
* [`resolve`](guide/webpack#common-resolve) - how to resolve file names when they lack extensions.
* [`module.rules`](guide/webpack#common-rules) - `module` is an object with `rules` for deciding how files are loaded.
* [`plugins`](guide/webpack#common-plugins) - creates instances of the plugins.
{@a common-entries}
@ -370,7 +370,7 @@ The development build relies on the Webpack development server, configured near
Although you tell Webpack to put output bundles in the `dist` folder,
the dev server keeps all bundles in memory; it doesn't write them to disk.
You won't find any files in the `dist` folder (at least not any generated from `this development build`).
You won't find any files in the `dist` folder (at least not any generated from *this development build*).
The `HtmlWebpackPlugin` (added in `webpack.common.js`) use the *publicPath* and the *filename* settings to generate
@ -567,4 +567,4 @@ for a small Angular application.
_You could always do more_. Search the web for expert advice and expand your Webpack knowledge.
[Back to top](#top)
[Back to top](guide/webpack#top)

View File

@ -1,9 +1,5 @@
{
"TopBar": [
{
"url": "/",
"title": "Home"
},
{
"url": "api",
"title": "API"

View File

@ -2,13 +2,13 @@
The Hero Editor
@intro
We build a simple hero editor
We build a simple hero editor.
@description
## Setup to develop locally
Real application development takes place in a local development environment like your machine.
Follow the [setup](../guide/setup.html) instructions for creating a new project
Follow the [setup](guide/setup) instructions for creating a new project
named <ngio-ex path="angular-tour-of-heroes"></ngio-ex>
after which the file structure should look like this:
@ -109,7 +109,7 @@ The browser should refresh and display our title and hero.
The double curly braces tell our app to read the `title` and `hero` properties from the component and render them.
This is the "interpolation" form of one-way data binding.
Learn more about interpolation in the [Displaying Data chapter](../guide/displaying-data.html).### Hero object
Learn more about interpolation in the [Displaying Data chapter](guide/displaying-data).### Hero object
At the moment, our hero is just a name. Our hero needs more properties.
Let's convert the `hero` from a literal string to a class.
@ -189,8 +189,8 @@ Now we have included the forms package which includes `ngModel`.
Learn more about the `FormsModule` and `ngModel` in the
[Forms](../guide/forms.html#ngModel) and
[Template Syntax](../guide/template-syntax.html#ngModel) chapters.
[Forms](guide/forms) and
[Template Syntax](guide/template-syntax) chapters.
Lets update the template to use the **`ngModel`** built-in directive for two-way binding.
Replace the `<input>` with the following HTML
@ -226,4 +226,4 @@ Our Tour of Heroes only displays one hero and we really want to display a list o
We also want to allow the user to select a hero and display their details.
Well learn more about how to retrieve lists, bind them to the
template, and allow a user to select a hero in the
[next tutorial chapter](./toh-pt2.html).
[next tutorial chapter](tutorial/toh-pt2).

View File

@ -2,7 +2,7 @@
Master/Detail
@intro
We build a master/detail page with a list of heroes
We build a master/detail page with a list of heroes.
@description
Our story needs more heroes.
@ -17,7 +17,7 @@ so well need a way to do that.
## Where We Left Off
Before we continue with Part 2 of the Tour of Heroes,
lets verify we have the following structure after [Part 1](./toh-pt1.html).
lets verify we have the following structure after [Part 1](tutorial/toh-pt1).
If not, well need to go back to Part 1 and figure out what we missed.
<aio-filetree>
@ -160,8 +160,8 @@ The `let` keyword before "hero" identifies `hero` as a template input variable.
We can reference this variable within the template to access a heros properties.
Learn more about `ngFor` and template input variables in the
[Displaying Data](../guide/displaying-data.html#ngFor) and
[Template Syntax](../guide/template-syntax.html#ngFor) chapters.
[Displaying Data](guide/displaying-data) and
[Template Syntax](guide/template-syntax) chapters.
Now we insert some content between the `<li>` tags
that uses the `hero` template variable to display the heros properties.
@ -219,8 +219,8 @@ The expression to the right of the equal sign calls the `AppComponent` method,
passing the template input variable `hero` as an argument.
Thats the same `hero` variable we defined previously in the `ngFor`.
Learn more about Event Binding in the
[User Input](../guide/user-input.html) and
[Templating Syntax](../guide/template-syntax.html#event-binding) chapters.### Add the click handler
[User Input](guide/user-input) and
[Templating Syntax](guide/template-syntax) chapters.### Add the click handler
Our event binding refers to an `onSelect` method that doesnt exist yet.
Well add that method to our component now.
@ -291,8 +291,8 @@ structure of portions of the DOM.
In other words, they give structure to the way Angular displays content in the DOM.
Learn more about `ngIf`, `ngFor` and other structural directives in the
[Structural Directives](../guide/structural-directives.html) and
[Template Syntax](../guide/template-syntax.html#directives) chapters.
[Structural Directives](guide/structural-directives) and
[Template Syntax](guide/template-syntax) chapters.
The browser refreshes and we see the list of heroes but not the selected hero detail.
The `ngIf` keeps it out of the DOM as long as the `selectedHero` is undefined.
When we click on a hero in the list, the selected hero displays in the hero details.
@ -323,7 +323,7 @@ from the data source (the expression `hero === selectedHero`) to a property of `
{@example 'toh-2/ts-snippets/app.component.snippets.pt2.ts' region='class-selected-2'}
Learn more about [property bindings](../guide/template-syntax.html#property-binding)
Learn more about [property bindings](guide/template-syntax)
in the Template Syntax chapter.
The browser reloads our app.
We select the hero Magneta and the selection is clearly identified by the background color.
@ -353,4 +353,4 @@ Run the <live-example></live-example> for this part.
Our Tour of Heroes has grown, but its far from complete.
We can't put the entire app into a single component.
We need to break it up into sub-components and teach them to work together
as we learn in the [next chapter](toh-pt3.html).
as we learn in the [next chapter](tutorial/toh-pt3).

View File

@ -2,7 +2,7 @@
Multiple Components
@intro
We refactor the master/detail view into separate components
We refactor the master/detail view into separate components.
@description
Our app is growing.
@ -117,8 +117,8 @@ Notice that we have an `AppComponent` in a file named `app.component.ts` and ou
All of our component names end in "Component". All of our component file names end in ".component".
We spell our file names in lower **[dash case](../guide/glossary.html#dash-case)**
(AKA **[kebab-case](../guide/glossary.html#kebab-case)**) so we don't worry about
We spell our file names in lower **[dash case](guide/glossary)**
(AKA **[kebab-case](guide/glossary)**) so we don't worry about
case sensitivity on the server or in source control.
<!-- TODO
@ -182,7 +182,7 @@ Notice that the `hero` property is the ***target*** of a property binding &mdash
Angular insists that we declare a ***target*** property to be an ***input*** property.
If we don't, Angular rejects the binding and throws an error.
We explain input properties in more detail [here](../guide/attribute-directives.html#why-input)
We explain input properties in more detail [here](guide/attribute-directives)
where we also explain why *target* properties require this special treatment and
*source* properties do not.There are a couple of ways we can declare that `hero` is an *input*.
We'll do it the way we *prefer*, by annotating the `hero` property with the `@Input` decorator that we imported earlier.
@ -191,7 +191,7 @@ We'll do it the way we *prefer*, by annotating the `hero` property with the `@In
Learn more about the `@Input()` decorator in the
[Attribute Directives](../guide/attribute-directives.html#input) chapter.
[Attribute Directives](guide/attribute-directives) chapter.
## Refresh the AppModule
We return to the `AppModule`, the application's root module, and teach it to use the `HeroDetailComponent`.
@ -362,4 +362,4 @@ That's not sustainable.
We should refactor data access to a separate service
and share it among the components that need data.
Well learn to create services in the [next tutorial](toh-pt4.html) chapter.
Well learn to create services in the [next tutorial](tutorial/toh-pt4) chapter.

View File

@ -2,7 +2,7 @@
Services
@intro
We create a reusable service to manage our hero data calls
We create a reusable service to manage our hero data calls.
@description
The Tour of Heroes is evolving and we anticipate adding more components in the near future.
@ -127,7 +127,7 @@ share that service with all components that need heroes.
### Create the HeroService
Create a file in the `app` folder called `hero.service.ts`.
We've adopted a convention in which we spell the name of a service in lowercase followed by `.service`.
If the service name were multi-word, we'd spell the base filename in lower [dash-case](../guide/glossary.html#dash-case).
If the service name were multi-word, we'd spell the base filename in lower [dash-case](guide/glossary).
The `SpecialSuperHeroService` would be defined in the `special-super-hero.service.ts` file.We name the class `HeroService` and export it for others to import.
@ -234,7 +234,7 @@ Here's the constructor:
The constructor itself does nothing. The parameter simultaneously
defines a private `heroService` property and identifies it as a `HeroService` injection site.Now Angular will know to supply an instance of the `HeroService` when it creates a new `AppComponent`.
Learn more about Dependency Injection in the [Dependency Injection](../guide/dependency-injection.html) chapter.The *injector* does not know yet how to create a `HeroService`.
Learn more about Dependency Injection in the [Dependency Injection](guide/dependency-injection) chapter.The *injector* does not know yet how to create a `HeroService`.
If we ran our code now, Angular would fail with an error:
<code-example format="nocode">
EXCEPTION: No provider for HeroService! (AppComponent -> HeroService)
@ -272,7 +272,7 @@ Angular offers a number of interfaces for tapping into critical moments in the c
at creation, after each change, and at its eventual destruction.
Each interface has a single method. When the component implements that method, Angular calls it at the appropriate time.
Learn more about lifecycle hooks in the [Lifecycle Hooks](../guide/lifecycle-hooks.html) chapter.Here's the essential outline for the `OnInit` interface:
Learn more about lifecycle hooks in the [Lifecycle Hooks](guide/lifecycle-hooks) chapter.Here's the essential outline for the `OnInit` interface:
{@example 'toh-4/ts/src/app/app.component.1.ts' region='on-init'}
@ -332,7 +332,7 @@ in the callback is more succinct than the equivalent function expression and gra
Our app should still be running, still showing a list of heroes, and still
responding to a name selection with a detail view.
Checkout the "[Take it slow](#slow)" appendix to see what the app might be like with a poor connection.### Review the App Structure
Checkout the "[Take it slow](tutorial/toh-pt4#slow)" appendix to see what the app might be like with a poor connection.### Review the App Structure
Lets verify that we have the following structure after all of our good refactoring in this chapter:
<aio-filetree>
@ -456,7 +456,7 @@ Our Tour of Heroes has become more reusable using shared components and services
We want to create a dashboard, add menu links that route between the views, and format data in a template.
As our app evolves, well learn how to design it to make it easier to grow and maintain.
We learn about Angular Component Router and navigation among the views in the [next tutorial](toh-pt5.html) chapter.
We learn about Angular Component Router and navigation among the views in the [next tutorial](tutorial/toh-pt5) chapter.
<a id="slow"></a>### Appendix: Take it slow

View File

@ -2,7 +2,7 @@
Routing
@intro
We add the Angular Router and learn to navigate among the views
We add the Angular Router and learn to navigate among the views.
@description
We received new requirements for our Tour of Heroes application:
@ -20,7 +20,7 @@ When were done, users will be able to navigate the app like this:
We'll add Angulars *Router* to our app to satisfy these requirements.
The [Routing and Navigation](../guide/router.html) chapter covers the router
The [Routing and Navigation](guide/router) chapter covers the router
in more detail than we will in this tutorial.
Run the <live-example></live-example> for this part.
@ -107,7 +107,7 @@ at the top of the `<head>` section.
base href is essential
</header>
See the *base href* section of the [router](../guide/router.html#base-href)
See the *base href* section of the [router](guide/router)
guide to learn why this matters, and what to add if the `base`
element is missing.
@ -131,7 +131,7 @@ This *route definition* has the following parts:
it *must* begin with a capital letter to avoid confusion with the *path* (`Heroes`).</li>
- **component**: the component that the router should create when navigating to this route (`HeroesComponent`).
Learn more about defining routes with `!{_RoutesVsAtRouteConfig}` in the [Routing](../guide/router.html) chapter.
Learn more about defining routes with `!{_RoutesVsAtRouteConfig}` in the [Routing](guide/router) chapter.
### Router Outlet
If we paste the path, `/heroes`, into the browser address bar,
@ -322,7 +322,7 @@ using the `Location` service we injected previously.
Going back too far could take us out of the application.
That's acceptable in a demo. We'd guard against it in a real application,
perhaps with the [!{_CanDeactivateGuard}](../api/!{_CanDeactivateGuardUri}.html).
perhaps with the [!{_CanDeactivateGuard}](api/!{_CanDeactivateGuardUri}).
Then we wire this method with an event binding to a *Back* button that we
add to the bottom of the component template.
Modifying the template to add this button spurs us to take one more
@ -352,7 +352,7 @@ with `<a>` tags. The opening `<a>` tag looks like this:
Notice the `[routerLink]` binding.
Top level navigation in the [`AppComponent`
template](#router-links) has router links set to fixed !{_pathVsName}s of the
template](tutorial/toh-pt5#router-links) has router links set to fixed !{_pathVsName}s of the
destination routes, "/dashboard" and "/heroes".
This time, we're binding to an expression containing a **link parameters !{_array}**.
@ -405,7 +405,7 @@ that we slipped into the interpolation binding. Look for it right after the pipe
Pipes are a good way to format strings, currency amounts, dates and other display data.
Angular ships with several pipes and we can write our own.
Learn about pipes in the [Pipes](../guide/pipes.html) chapter.
Learn about pipes in the [Pipes](guide/pipes) chapter.
### Move content out of the component file
We are not done. We still have to update the component class to support navigation to the
@ -490,10 +490,10 @@ It's pretty easy to package it all up and re-use the component somewhere else.
We can also create styles at the *application level* outside of any component.
Our designers provided some basic styles to apply to elements across the entire app.
These correspond to the full set of master styles that we installed earlier during [setup](../guide/setup.html).
These correspond to the full set of master styles that we installed earlier during [setup](guide/setup).
Here is an excerpt:
Create the file <span ngio-ex>styles.css</span>, if it doesn't exist already.
Ensure that it contains the [master styles given here](!{styles_css}).
Ensure that it contains the [master styles given here](tutorial/!{styles_css}).
If necessary, also edit <span ngio-ex>index.html</span> to refer to this stylesheet.
Look at the app now. Our dashboard, heroes, and navigation links are styling!

View File

@ -2,7 +2,7 @@
HTTP
@intro
We convert our service and components to use Angular's HTTP service
We convert our service and components to use Angular's HTTP service.
@description
Our stakeholders appreciate our progress.
@ -15,7 +15,7 @@ Run the <live-example></live-example> for this part.
## Where We Left Off
In the [previous chapter](toh-pt5.html), we learned to navigate between the dashboard and the fixed heroes list, editing a selected hero along the way.
In the [previous chapter](tutorial/toh-pt5), we learned to navigate between the dashboard and the fixed heroes list, editing a selected hero along the way.
That's our starting point for this chapter.
The application runs and updates automatically as we continue to build the Tour of Heroes.
@ -289,5 +289,5 @@ Here are the files we _added or changed_ in this chapter.
### Next Step
Return to the [learning path](../guide/learning-angular.html#architecture) where
Return to the [learning path](guide/learning-angular) where
you can read about the concepts and practices you discovered in this tutorial.

View File

@ -1,3 +1,4 @@
import { browser, element, by, promise } from 'protractor';
import { SitePage } from './app.po';
describe('site App', function() {
@ -9,10 +10,66 @@ describe('site App', function() {
});
it('should show features text after clicking "Features"', () => {
page.featureLink.click().then(() => {
expect(page.getDocViewerText()).toContain('Progressive web apps');
page.getLink('features').click().then(() => {
expect(page.getDocViewerText()).toMatch(/Progressive web apps/i);
});
});
it('should convert a doc with a code-example');
it('should show the tutorial index page at `/tutorial/`', () => {
// check that we can navigate directly to the tutorial page
page.navigateTo('tutorial/');
expect(page.getDocViewerText()).toMatch(/Tutorial: Tour of Heroes/i);
// navigate to a different page
page.getLink('features').click();
// check that we can navigate to the tutorial page via a link in the navigation
const heading = page.getNavHeading(/tutorial/i);
expect(heading.getText()).toMatch(/tutorial/i);
heading.click();
page.getLink('tutorial/').click();
expect(page.getDocViewerText()).toMatch(/Tutorial: Tour of Heroes/i);
});
it('should render `{@example}` dgeni tags as `<code-example>` elements with HTML escaped content', () => {
page.navigateTo('guide/component-styles');
const codeExample = element.all(by.css('code-example')).first();
expect(page.getInnerHtml(codeExample))
.toContain('@Component({\n selector: \'hero-app\',\n template: `\n &lt;h1&gt;Tour of Heroes&lt;/h1&gt;');
});
describe('api-docs', () => {
it('should show a link to github', () => {
page.navigateTo('api/common/NgClass');
expect(page.ghLink.getAttribute('href'))
.toMatch(/https:\/\/github.com\/angular\/angular\/tree\/.+\/packages\/common\/src\/directives\/ng_class\.ts/);
});
});
describe('google analytics', () => {
beforeEach(done => page.gaReady.then(done));
it('should call ga', done => {
page.ga()
.then(calls => {
expect(calls.length).toBeGreaterThan(2, 'ga calls');
done();
});
});
it('should call ga with initial URL', done => {
let path: string;
page.locationPath()
.then(p => path = p)
.then(() => page.ga().then(calls => {
expect(calls.length).toBeGreaterThan(2, 'ga calls');
expect(calls[1]).toEqual(['set', 'page', path]);
done();
}));
});
// Todo: add test to confirm tracking URL when navigate.
});
});

View File

@ -1,18 +1,63 @@
import { browser, element, by } from 'protractor';
import { browser, element, by, promise, ElementFinder } from 'protractor';
const githubRegex = /https:\/\/github.com\/angular\/angular\//;
export class SitePage {
links = element.all(by.css('md-toolbar a'));
docViewer = element(by.css('aio-doc-viewer'));
codeExample = element.all(by.css('aio-doc-viewer pre > code'));
featureLink = element(by.css('md-toolbar a[href="features"]'));
ghLink = this.docViewer
.all(by.css('a'))
.filter((a: ElementFinder) => a.getAttribute('href').then(href => githubRegex.test(href)))
.first();
gaReady: promise.Promise<any>;
getNavHeading(pattern: RegExp) {
return element.all(by.css('aio-nav-item a'))
.filter(element => element.getText().then(text => pattern.test(text)))
.first();
}
getLink(path) { return element(by.css(`a[href="${path}"]`)); }
ga() { return browser.executeScript('return window["gaCalls"]') as promise.Promise<any[][]>; }
locationPath() { return browser.executeScript('return document.location.pathname') as promise.Promise<string>; }
navigateTo() {
return browser.get('/');
navigateTo(pageUrl = '') {
return browser.get('/' + pageUrl).then(_ => this.replaceGa(_));
}
getDocViewerText() {
return this.docViewer.getText();
}
getInnerHtml(element) {
// `getInnerHtml` was removed from webDriver and this is the workaround.
// See https://github.com/angular/protractor/blob/master/CHANGELOG.md#breaking-changes
return browser.executeScript('return arguments[0].innerHTML;', element);
}
/**
* Replace the ambient Google Analytics tracker with homebrew spy
* don't send commands to GA during e2e testing!
* @param _ - forward's anything passed in
*/
private replaceGa(_: any) {
this.gaReady = browser.driver.executeScript(() => {
// Give ga() a "ready" callback:
// https://developers.google.com/analytics/devguides/collection/analyticsjs/command-queue-reference
window['ga'](() => {
window['gaCalls'] = [];
window['ga'] = function() { window['gaCalls'].push(arguments); };
});
})
.then(() => {
// wait for GaService to start using window.ga after analytics lib loads.
const d = promise.defer();
setTimeout(() => d.fulfill(), 1000); // GaService.initializeDelay
return d.promise;
});
return _;
}
}

View File

@ -4,6 +4,12 @@
},
"hosting": {
"public": "dist",
"cleanUrls": true
"cleanUrls": true,
"rewrites": [
{
"source": "**/!(*.*)",
"destination": "/index.html"
}
]
}
}

24
aio/ngsw-manifest.json Normal file
View File

@ -0,0 +1,24 @@
{
"static.ignore": [
"\\.js\\.map$",
"^\/assets\/images\/(bios|cookbooks|devguide|examples)\/",
"^\/content\/docs\/.*\/"
],
"routing": {
"index": "/index.html",
"routes": {
"/": {
"prefix": false
},
"/about": {
"prefix": true
},
"/tutorial": {
"prefix": true
},
"/guide": {
"prefix": true
}
}
}
}

View File

@ -10,17 +10,19 @@
"ng": "yarn check-env && ng",
"start": "yarn check-env && ng serve",
"build": "yarn check-env && yarn docs && ng build -prod -sm",
"test": "yarn check-env && ng test",
"test": "yarn check-env && ng test --sourcemap=false",
"lint": "yarn check-env && ng lint",
"pree2e": "webdriver-manager update --standalone false --gecko false",
"pree2e": "yarn ~~update-webdriver",
"e2e": "yarn check-env && ng e2e --no-webdriver-update",
"deploy-preview": "scripts/deploy-preview.sh",
"deploy-staging": "firebase use staging --token \"$FIREBASE_TOKEN\" && yarn ~~deploy",
"pre~~deploy": "yarn build",
"~~deploy": "firebase deploy --message \"Commit: $TRAVIS_COMMIT\" --non-interactive --token \"$FIREBASE_TOKEN\"",
"check-env": "node ../tools/check-environment.js",
"predocs": "rimraf src/content",
"docs": "dgeni ./transforms/angular.io-package",
"docs-test": "node ../dist/tools/cjs-jasmine/index-tools ../../transforms/**/*.spec.js"
"docs-test": "node ../dist/tools/cjs-jasmine/index-tools ../../transforms/**/*.spec.js",
"~~update-webdriver": "webdriver-manager update --standalone false --gecko false",
"pre~~deploy": "yarn build",
"~~deploy": "firebase deploy --message \"Commit: $TRAVIS_COMMIT\" --non-interactive --token \"$FIREBASE_TOKEN\""
},
"private": true,
"dependencies": {
@ -35,20 +37,22 @@
"@angular/platform-browser-dynamic": "next",
"@angular/platform-server": "next",
"@angular/router": "next",
"@angular/service-worker": "^1.0.0-beta.7",
"core-js": "^2.4.1",
"rxjs": "^5.1.0",
"rho": "https://github.com/petebacondarwin/rho#heading-fix",
"rxjs": "^5.2.0",
"ts-helpers": "^1.1.1",
"zone.js": "^0.7.6"
"zone.js": "^0.8.4"
},
"devDependencies": {
"@angular/cli": "^1.0.0-rc.0",
"@angular/cli": "^1.0.0-rc.4",
"@angular/compiler-cli": "next",
"@types/jasmine": "2.5.38",
"@types/node": "~6.0.60",
"canonical-path": "^0.0.2",
"codelyzer": "~2.0.0-beta.4",
"dgeni": "^0.4.7",
"dgeni-packages": "^0.16.8",
"dgeni-packages": "0.17.0",
"entities": "^1.1.1",
"firebase-tools": "^3.2.1",
"gulp": "^3.9.1",
@ -62,7 +66,7 @@
"karma-jasmine-html-reporter": "^0.2.2",
"lodash": "^4.17.4",
"protractor": "~5.1.0",
"rho": "^0.3.0",
"rimraf": "^2.6.1",
"ts-node": "~2.0.0",
"tslint": "~4.4.2",
"typescript": "2.1.6"

View File

@ -11,7 +11,7 @@ UPLOAD_URL=$AIO_BUILDS_HOST/create-build/$TRAVIS_PULL_REQUEST/$TRAVIS_PULL_REQUE
cd "`dirname $0`/.."
yarn run build -- --prod
yarn run build
tar --create --gzip --directory "$INPUT_DIR" --file "$OUTPUT_FILE" .
exec 3>&1

Some files were not shown because too many files have changed in this diff Show More