Compare commits
177 Commits
5.1.0-beta
...
labs/route
Author | SHA1 | Date | |
---|---|---|---|
abca7c0243 | |||
1f5256e745 | |||
6990354047 | |||
135ead6c97 | |||
33c0ee3441 | |||
5efea2f6a0 | |||
5f23a1223f | |||
30208759cd | |||
e4c53f8529 | |||
b61e3e9d20 | |||
f593552cfe | |||
8458647232 | |||
a693c5614c | |||
8ceffd8b48 | |||
2986e25abb | |||
f8fe53aeb0 | |||
74e3115686 | |||
3846f19f22 | |||
057513536b | |||
82bcd83566 | |||
e48f477477 | |||
20e1cc049f | |||
0b2d636b75 | |||
f5bb999319 | |||
a4742763b9 | |||
05ff6c09ca | |||
d91ff17adc | |||
d213a20dfc | |||
2e7e935b02 | |||
b89e7c2cb7 | |||
b4db2e25d6 | |||
a33eaf6e07 | |||
0d47c39609 | |||
cbe7e39bbe | |||
6d57cb04f6 | |||
6e2a8a2ba4 | |||
7874697b6c | |||
767141761a | |||
b3eb1db6dd | |||
ee0dab025b | |||
b7738e1fe5 | |||
634d33f5dd | |||
3401283399 | |||
981947d104 | |||
8c52088346 | |||
add3589451 | |||
81d497ce1f | |||
70cd124ede | |||
7363b3d4b5 | |||
f05937db4d | |||
d684f55423 | |||
db06cb170f | |||
77a1f9f2e8 | |||
13e663c232 | |||
d098cf5a8b | |||
3ce3b4d2af | |||
e7d9cb3e4c | |||
e544742156 | |||
c9ad529afc | |||
75e468494c | |||
ddada6e2be | |||
22ae17bb0b | |||
d546be48e1 | |||
753a130aaa | |||
94e2ea7361 | |||
1539cd8819 | |||
131c8ab6be | |||
7d81309e11 | |||
225baf4686 | |||
70b061be2e | |||
46aa0a1cf6 | |||
661fdcd3e2 | |||
590d93b30d | |||
c26e1bba1d | |||
10771d0bd8 | |||
d8cc09b76c | |||
d41d2c460a | |||
4efc32dabf | |||
ef534c0cc1 | |||
073f485c72 | |||
c2dbc55f11 | |||
9ee2703824 | |||
b78ada198a | |||
6790e02a13 | |||
7cabaa0ae7 | |||
da3563ce19 | |||
9bbec42a6c | |||
be994496cd | |||
77ef527993 | |||
f092a7c824 | |||
5e25d3986d | |||
35977e3830 | |||
f7328c69b3 | |||
25f2211726 | |||
18793c896b | |||
e7cdb9f660 | |||
6911a250ef | |||
7e7ff2e0aa | |||
d34f0bf573 | |||
1f5fa25583 | |||
d507057476 | |||
f582620d5b | |||
3fbcde9048 | |||
f841fbe60f | |||
b9a91a5e74 | |||
65f4fad801 | |||
60a30818ef | |||
b967cbfc66 | |||
8826a8235b | |||
47addd169d | |||
ba6af2a6dd | |||
b9e4d62d5a | |||
71e5de646b | |||
3def2cc552 | |||
4ec4a99f16 | |||
3203069d6c | |||
54bfe14313 | |||
ba850b36de | |||
f3c5481181 | |||
48300067fb | |||
b841e0d530 | |||
65a2cb8307 | |||
0bef021321 | |||
aafa75da84 | |||
503be69af6 | |||
eb01ad583f | |||
15a54df7d3 | |||
eaaae2edf4 | |||
c2b3792a3b | |||
b2a586cee1 | |||
8bb42df47e | |||
add5953aa1 | |||
6b4c24020d | |||
24bf3e2a25 | |||
8ecda94899 | |||
1366762d12 | |||
dd6237ecd9 | |||
6e83204238 | |||
a53a040071 | |||
5bef070e16 | |||
89de98b25e | |||
de78307928 | |||
6293ca23c3 | |||
330bb2a360 | |||
59455ea8d1 | |||
e9e4ffd6e1 | |||
0444e13efb | |||
ffb6dbeefe | |||
0e012c9669 | |||
a0819d3af1 | |||
ffd8c361eb | |||
1594f8c09e | |||
d7a727cc07 | |||
437a0446e2 | |||
ac93f1235e | |||
e2b76bb386 | |||
ae0275e2dd | |||
ecce90718b | |||
c2cb475a2c | |||
7cf5e95ac9 | |||
a740e4f00a | |||
2a9d2bacd5 | |||
4ed04392d3 | |||
23ab83b504 | |||
9332161e01 | |||
816d5ba3fd | |||
69c53c3e03 | |||
365712e2f0 | |||
997336b790 | |||
1861e416a1 | |||
7c44637fbf | |||
68b53c07fd | |||
368cb5ad4e | |||
949836d003 | |||
697fb76960 | |||
0fedb57cb0 | |||
717ac5ac4d |
@ -7,17 +7,25 @@
|
|||||||
# To validate changes, use an online parser, eg.
|
# To validate changes, use an online parser, eg.
|
||||||
# http://yaml-online-parser.appspot.com/
|
# http://yaml-online-parser.appspot.com/
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
|
||||||
|
## IMPORTANT
|
||||||
|
# If you change the `docker_image` version, also change the `cache_key` suffix and the version of
|
||||||
|
# `com_github_bazelbuild_buildtools` in the `/WORKSPACE` file.
|
||||||
|
var_1: &docker_image angular/ngcontainer:0.0.8
|
||||||
|
var_2: &cache_key angular-{{ .Branch }}-{{ checksum "yarn.lock" }}-0.0.8
|
||||||
|
|
||||||
# Settings common to each job
|
# Settings common to each job
|
||||||
anchor_1: &job_defaults
|
anchor_1: &job_defaults
|
||||||
working_directory: ~/ng
|
working_directory: ~/ng
|
||||||
docker:
|
docker:
|
||||||
- image: angular/ngcontainer:0.0.2
|
- image: *docker_image
|
||||||
|
|
||||||
# After checkout, rebase on top of master.
|
# After checkout, rebase on top of master.
|
||||||
# Similar to travis behavior, but not quite the same.
|
# Similar to travis behavior, but not quite the same.
|
||||||
# See https://discuss.circleci.com/t/1662
|
# See https://discuss.circleci.com/t/1662
|
||||||
anchor_2: &post_checkout
|
anchor_2: &post_checkout
|
||||||
post: git pull --ff-only origin "refs/pull/${CI_PULL_REQUEST//*pull\//}/merge"
|
post: git pull --ff-only origin "refs/pull/${CIRCLE_PULL_REQUEST//*pull\//}/merge"
|
||||||
|
|
||||||
version: 2
|
version: 2
|
||||||
jobs:
|
jobs:
|
||||||
@ -26,8 +34,13 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout:
|
- checkout:
|
||||||
<<: *post_checkout
|
<<: *post_checkout
|
||||||
|
# Check BUILD.bazel formatting before we have a node_modules directory
|
||||||
|
# Then we don't need any exclude pattern to avoid checking those files
|
||||||
|
- run: 'buildifier -mode=check $(find . -type f \( -name BUILD.bazel -or -name BUILD \)) ||
|
||||||
|
(echo "BUILD files not formatted. Please run ''yarn buildifier''" ; exit 1)'
|
||||||
|
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: angular-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
key: *cache_key
|
||||||
|
|
||||||
- run: yarn install --frozen-lockfile --non-interactive
|
- run: yarn install --frozen-lockfile --non-interactive
|
||||||
- run: ./node_modules/.bin/gulp lint
|
- run: ./node_modules/.bin/gulp lint
|
||||||
@ -38,13 +51,17 @@ jobs:
|
|||||||
- checkout:
|
- checkout:
|
||||||
<<: *post_checkout
|
<<: *post_checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: angular-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
key: *cache_key
|
||||||
|
|
||||||
|
- run: bazel info release
|
||||||
- run: bazel run @yarn//:yarn
|
- run: bazel run @yarn//:yarn
|
||||||
- run: bazel build packages/...
|
# Use bazel query so that we explicitly ask for all buildable targets to be built as well
|
||||||
- run: bazel test @angular//...
|
# This avoids waiting for a build command to finish before running the first test
|
||||||
|
# See https://github.com/bazelbuild/bazel/issues/4257
|
||||||
|
- run: bazel query --output=label '//packages/... union @angular//...' | xargs bazel test --config=ci
|
||||||
|
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: angular-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
key: *cache_key
|
||||||
paths:
|
paths:
|
||||||
- "node_modules"
|
- "node_modules"
|
||||||
|
|
||||||
|
@ -22,11 +22,9 @@
|
|||||||
# petebacondarwin - Pete Bacon Darwin
|
# petebacondarwin - Pete Bacon Darwin
|
||||||
# pkozlowski-opensource - Pawel Kozlowski
|
# pkozlowski-opensource - Pawel Kozlowski
|
||||||
# robwormald - Rob Wormald
|
# robwormald - Rob Wormald
|
||||||
# tbosch - Tobias Bosch
|
|
||||||
# tinayuangao - Tina Gao
|
# tinayuangao - Tina Gao
|
||||||
# vicb - Victor Berchet
|
# vicb - Victor Berchet
|
||||||
# vikerman - Vikram Subramanian
|
# vikerman - Vikram Subramanian
|
||||||
# wardbell - Ward Bell
|
|
||||||
|
|
||||||
|
|
||||||
version: 2
|
version: 2
|
||||||
@ -45,6 +43,7 @@ groups:
|
|||||||
include:
|
include:
|
||||||
- "*"
|
- "*"
|
||||||
exclude:
|
exclude:
|
||||||
|
- ".circleci/*"
|
||||||
- "aio/*"
|
- "aio/*"
|
||||||
- "integration/*"
|
- "integration/*"
|
||||||
- "modules/*"
|
- "modules/*"
|
||||||
@ -74,6 +73,7 @@ groups:
|
|||||||
users:
|
users:
|
||||||
- alexeagle #primary
|
- alexeagle #primary
|
||||||
- chuckjaz
|
- chuckjaz
|
||||||
|
- IgorMinar
|
||||||
- vikerman #fallback
|
- vikerman #fallback
|
||||||
|
|
||||||
build-and-ci:
|
build-and-ci:
|
||||||
@ -100,7 +100,6 @@ groups:
|
|||||||
users:
|
users:
|
||||||
- alexeagle
|
- alexeagle
|
||||||
- mhevery
|
- mhevery
|
||||||
- tbosch
|
|
||||||
- vicb
|
- vicb
|
||||||
- IgorMinar #fallback
|
- IgorMinar #fallback
|
||||||
|
|
||||||
@ -109,8 +108,7 @@ groups:
|
|||||||
files:
|
files:
|
||||||
- "packages/core/*"
|
- "packages/core/*"
|
||||||
users:
|
users:
|
||||||
- tbosch #primary
|
- chuckjaz #primary
|
||||||
- chuckjaz
|
|
||||||
- mhevery
|
- mhevery
|
||||||
- vicb
|
- vicb
|
||||||
- IgorMinar #fallback
|
- IgorMinar #fallback
|
||||||
@ -132,7 +130,7 @@ groups:
|
|||||||
- "packages/compiler/src/i18n/*"
|
- "packages/compiler/src/i18n/*"
|
||||||
users:
|
users:
|
||||||
- vicb #primary
|
- vicb #primary
|
||||||
- tbosch
|
- chuckjaz
|
||||||
- IgorMinar #fallback
|
- IgorMinar #fallback
|
||||||
- mhevery #fallback
|
- mhevery #fallback
|
||||||
|
|
||||||
@ -141,9 +139,8 @@ groups:
|
|||||||
files:
|
files:
|
||||||
- "packages/compiler/*"
|
- "packages/compiler/*"
|
||||||
users:
|
users:
|
||||||
- tbosch #primary
|
- chuckjaz #primary
|
||||||
- vicb
|
- vicb
|
||||||
- chuckjaz
|
|
||||||
- mhevery
|
- mhevery
|
||||||
- IgorMinar #fallback
|
- IgorMinar #fallback
|
||||||
|
|
||||||
@ -163,12 +160,11 @@ groups:
|
|||||||
- "packages/compiler-cli/*"
|
- "packages/compiler-cli/*"
|
||||||
- "packages/bazel/*"
|
- "packages/bazel/*"
|
||||||
exclude:
|
exclude:
|
||||||
- "packages/compiler-cli/src/ngtools*"
|
- "packages/compiler-cli/src/ngtools*"
|
||||||
users:
|
users:
|
||||||
- alexeagle
|
- alexeagle
|
||||||
- chuckjaz
|
- chuckjaz
|
||||||
- vicb
|
- vicb
|
||||||
- tbosch
|
|
||||||
- IgorMinar #fallback
|
- IgorMinar #fallback
|
||||||
- mhevery #fallback
|
- mhevery #fallback
|
||||||
|
|
||||||
@ -212,7 +208,7 @@ groups:
|
|||||||
- "packages/language-service/*"
|
- "packages/language-service/*"
|
||||||
users:
|
users:
|
||||||
- chuckjaz #primary
|
- chuckjaz #primary
|
||||||
- tbosch #secondary
|
# needs secondary
|
||||||
- vicb
|
- vicb
|
||||||
- IgorMinar #fallback
|
- IgorMinar #fallback
|
||||||
- mhevery #fallback
|
- mhevery #fallback
|
||||||
@ -242,8 +238,8 @@ groups:
|
|||||||
files:
|
files:
|
||||||
- "packages/platform-browser/*"
|
- "packages/platform-browser/*"
|
||||||
users:
|
users:
|
||||||
- tbosch #primary
|
- vicb #primary
|
||||||
- vicb #secondary
|
# needs secondary
|
||||||
- IgorMinar #fallback
|
- IgorMinar #fallback
|
||||||
- mhevery #fallback
|
- mhevery #fallback
|
||||||
|
|
||||||
@ -253,9 +249,9 @@ groups:
|
|||||||
- "packages/platform-server/*"
|
- "packages/platform-server/*"
|
||||||
users:
|
users:
|
||||||
- vikerman #primary
|
- vikerman #primary
|
||||||
|
# needs secondary
|
||||||
- alxhub
|
- alxhub
|
||||||
- vicb
|
- vicb
|
||||||
- tbosch
|
|
||||||
- IgorMinar #fallback
|
- IgorMinar #fallback
|
||||||
- mhevery #fallback
|
- mhevery #fallback
|
||||||
|
|
||||||
@ -265,7 +261,7 @@ groups:
|
|||||||
- "packages/platform-webworker/*"
|
- "packages/platform-webworker/*"
|
||||||
users:
|
users:
|
||||||
- vicb #primary
|
- vicb #primary
|
||||||
- tbosch #secondary
|
# needs secondary
|
||||||
- IgorMinar #fallback
|
- IgorMinar #fallback
|
||||||
- mhevery #fallback
|
- mhevery #fallback
|
||||||
|
|
||||||
@ -284,7 +280,7 @@ groups:
|
|||||||
files:
|
files:
|
||||||
- "packages/benchpress/*"
|
- "packages/benchpress/*"
|
||||||
users:
|
users:
|
||||||
- tbosch #primary
|
# needs primary
|
||||||
# needs secondary
|
# needs secondary
|
||||||
- IgorMinar #fallback
|
- IgorMinar #fallback
|
||||||
- mhevery #fallback
|
- mhevery #fallback
|
||||||
@ -315,7 +311,6 @@ groups:
|
|||||||
- juleskremer #primary
|
- juleskremer #primary
|
||||||
- Foxandxss
|
- Foxandxss
|
||||||
- stephenfluin
|
- stephenfluin
|
||||||
- wardbell
|
|
||||||
- petebacondarwin
|
- petebacondarwin
|
||||||
- gkalpak
|
- gkalpak
|
||||||
- IgorMinar #fallback
|
- IgorMinar #fallback
|
||||||
|
@ -2,7 +2,7 @@ language: node_js
|
|||||||
sudo: false
|
sudo: false
|
||||||
dist: trusty
|
dist: trusty
|
||||||
node_js:
|
node_js:
|
||||||
- '6.9.5'
|
- '8.9.1'
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
# firefox: "38.0"
|
# firefox: "38.0"
|
||||||
@ -54,7 +54,6 @@ env:
|
|||||||
- CI_MODE=browserstack_optional
|
- CI_MODE=browserstack_optional
|
||||||
- CI_MODE=aio_tools_test
|
- CI_MODE=aio_tools_test
|
||||||
- CI_MODE=aio
|
- CI_MODE=aio
|
||||||
- CI_MODE=aio_optional
|
|
||||||
- CI_MODE=aio_e2e AIO_SHARD=0
|
- CI_MODE=aio_e2e AIO_SHARD=0
|
||||||
- CI_MODE=aio_e2e AIO_SHARD=1
|
- CI_MODE=aio_e2e AIO_SHARD=1
|
||||||
- CI_MODE=bazel
|
- CI_MODE=bazel
|
||||||
@ -64,7 +63,6 @@ matrix:
|
|||||||
allow_failures:
|
allow_failures:
|
||||||
- env: "CI_MODE=saucelabs_optional"
|
- env: "CI_MODE=saucelabs_optional"
|
||||||
- env: "CI_MODE=browserstack_optional"
|
- env: "CI_MODE=browserstack_optional"
|
||||||
- env: "CI_MODE=aio_optional"
|
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
# source the env.sh script so that the exported variables are available to other scripts later on
|
# source the env.sh script so that the exported variables are available to other scripts later on
|
||||||
|
15
BUILD.bazel
15
BUILD.bazel
@ -1,4 +1,5 @@
|
|||||||
package(default_visibility = ["//visibility:public"])
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
exports_files(["tsconfig.json"])
|
exports_files(["tsconfig.json"])
|
||||||
|
|
||||||
# This rule belongs in node_modules/BUILD
|
# This rule belongs in node_modules/BUILD
|
||||||
@ -11,17 +12,25 @@ filegroup(
|
|||||||
# bazel query "deps(:node_modules)" | wc -l
|
# bazel query "deps(:node_modules)" | wc -l
|
||||||
# This won't scale in the general case.
|
# This won't scale in the general case.
|
||||||
# TODO(alexeagle): figure out what to do
|
# TODO(alexeagle): figure out what to do
|
||||||
srcs = glob(["/".join(["node_modules", pkg, "**", ext]) for pkg in [
|
srcs = glob(["/".join([
|
||||||
|
"node_modules",
|
||||||
|
pkg,
|
||||||
|
"**",
|
||||||
|
ext,
|
||||||
|
]) for pkg in [
|
||||||
"jasmine",
|
"jasmine",
|
||||||
"typescript",
|
"typescript",
|
||||||
"zone.js",
|
"zone.js",
|
||||||
"rxjs",
|
"tsutils",
|
||||||
"@types",
|
"@types/jasmine",
|
||||||
|
"@types/node",
|
||||||
|
"@types/source-map",
|
||||||
"tsickle",
|
"tsickle",
|
||||||
"hammerjs",
|
"hammerjs",
|
||||||
"protobufjs",
|
"protobufjs",
|
||||||
"bytebuffer",
|
"bytebuffer",
|
||||||
"reflect-metadata",
|
"reflect-metadata",
|
||||||
|
"source-map-support",
|
||||||
"minimist",
|
"minimist",
|
||||||
] for ext in [
|
] for ext in [
|
||||||
"*.js",
|
"*.js",
|
||||||
|
198
CHANGELOG.md
198
CHANGELOG.md
@ -1,3 +1,197 @@
|
|||||||
|
<a name="5.2.0-beta.1"></a>
|
||||||
|
# [5.2.0-beta.1](https://github.com/angular/angular/compare/5.2.0-beta.0...5.2.0-beta.1) (2017-12-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **compiler:** generate the correct imports for summary type-check ([d91ff17](https://github.com/angular/angular/commit/d91ff17))
|
||||||
|
* **forms:** avoid producing an error with hostBindingTypeCheck ([d213a20](https://github.com/angular/angular/commit/d213a20))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **compiler:** allow ngIf to use the ngIf expression directly as a guard ([82bcd83](https://github.com/angular/angular/commit/82bcd83))
|
||||||
|
* **router:** add "paramsInheritanceStrategy" router configuration option ([5efea2f](https://github.com/angular/angular/commit/5efea2f)), closes [#20572](https://github.com/angular/angular/issues/20572)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="5.1.2"></a>
|
||||||
|
## [5.1.2](https://github.com/angular/angular/compare/5.1.1...5.1.2) (2017-12-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **common:** fix a Closure compilation issue. ([267ebf3](https://github.com/angular/angular/commit/267ebf3))
|
||||||
|
* **compiler:** make tsx file aot compatible ([756dd34](https://github.com/angular/angular/commit/756dd34)), closes [#20555](https://github.com/angular/angular/issues/20555)
|
||||||
|
* **compiler:** report an error for recursive module references ([ced575f](https://github.com/angular/angular/commit/ced575f))
|
||||||
|
* **compiler-cli:** do not emit invalid .metadata.json files ([a1d4c2d](https://github.com/angular/angular/commit/a1d4c2d))
|
||||||
|
* **compiler-cli:** do not force type checking on .js files ([3b63e16](https://github.com/angular/angular/commit/3b63e16))
|
||||||
|
* **service-worker:** check for updates on navigation ([a33182c](https://github.com/angular/angular/commit/a33182c)), closes [#20877](https://github.com/angular/angular/issues/20877)
|
||||||
|
* **upgrade:** replaces get/setAngularLib with get/setAngularJSGlobal ([66cc2fa](https://github.com/angular/angular/commit/66cc2fa))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="5.2.0-beta.0"></a>
|
||||||
|
# [5.2.0-beta.0](https://github.com/angular/angular/compare/5.1.0...5.2.0-beta.0) (2017-12-13)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **animations:** re-introduce support for transition matching functions ([#20723](https://github.com/angular/angular/issues/20723)) ([590d93b](https://github.com/angular/angular/commit/590d93b)), closes [#18959](https://github.com/angular/angular/issues/18959)
|
||||||
|
* **compiler:** add a pseudo $any() function to disable type checking ([#20876](https://github.com/angular/angular/issues/20876)) ([70cd124](https://github.com/angular/angular/commit/70cd124))
|
||||||
|
* **compiler:** narrow types of expressions used in *ngIf ([#20702](https://github.com/angular/angular/issues/20702)) ([e7d9cb3](https://github.com/angular/angular/commit/e7d9cb3))
|
||||||
|
* **core:** add source to `StaticInjectorError` message ([#20817](https://github.com/angular/angular/issues/20817)) ([b7738e1](https://github.com/angular/angular/commit/b7738e1)), closes [#19302](https://github.com/angular/angular/issues/19302)
|
||||||
|
* **forms:** allow nulls on setAsyncValidators ([#20327](https://github.com/angular/angular/issues/20327)) ([d41d2c4](https://github.com/angular/angular/commit/d41d2c4)), closes [#20296](https://github.com/angular/angular/issues/20296)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="5.1.1"></a>
|
||||||
|
## [5.1.1](https://github.com/angular/angular/compare/5.1.0...5.1.1) (2017-12-13)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **animations:** ensure multi-level route leave animations are queryable ([#20787](https://github.com/angular/angular/issues/20787)) ([d09d497](https://github.com/angular/angular/commit/d09d497)), closes [#19807](https://github.com/angular/angular/issues/19807)
|
||||||
|
* **animations:** ensure the web-animations driver properly handles empty keyframes ([#20648](https://github.com/angular/angular/issues/20648)) ([c3e8731](https://github.com/angular/angular/commit/c3e8731)), closes [#15858](https://github.com/angular/angular/issues/15858)
|
||||||
|
* **animations:** properly recover and cleanup DOM when CD failures occur ([#20719](https://github.com/angular/angular/issues/20719)) ([e6a2805](https://github.com/angular/angular/commit/e6a2805)), closes [#19093](https://github.com/angular/angular/issues/19093)
|
||||||
|
* **animations:** support webkit-based vendor prefixes for prop validations ([#19055](https://github.com/angular/angular/issues/19055)) ([501f01e](https://github.com/angular/angular/commit/501f01e)), closes [#18921](https://github.com/angular/angular/issues/18921)
|
||||||
|
* **bazel:** don't equate moduleName with fileName ([#20895](https://github.com/angular/angular/issues/20895)) ([0c9f7b0](https://github.com/angular/angular/commit/0c9f7b0))
|
||||||
|
* **compiler:** support referencing enums in namespaces ([#20947](https://github.com/angular/angular/issues/20947)) ([d6da798](https://github.com/angular/angular/commit/d6da798)), closes [#18170](https://github.com/angular/angular/issues/18170)
|
||||||
|
* **compiler-cli:** disable checkTypes in emit. ([#20828](https://github.com/angular/angular/issues/20828)) ([160a154](https://github.com/angular/angular/commit/160a154))
|
||||||
|
* **compiler-cli:** fix swallowed Error messages ([#20846](https://github.com/angular/angular/issues/20846)) ([6727336](https://github.com/angular/angular/commit/6727336))
|
||||||
|
* **compiler-cli:** merge [@fileoverview](https://github.com/fileoverview) comments. ([#20870](https://github.com/angular/angular/issues/20870)) ([be9a737](https://github.com/angular/angular/commit/be9a737))
|
||||||
|
* **router:** NavigatonError and NavigationCancel should be emitted after resetting the URL ([#20803](https://github.com/angular/angular/issues/20803)) ([baeec4d](https://github.com/angular/angular/commit/baeec4d))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="5.1.0"></a>
|
||||||
|
# [5.1.0](https://github.com/angular/angular/compare/5.1.0-rc.1...5.1.0) (2017-12-06)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **animations:** ensure DOM is cleaned up after multiple [@trigger](https://github.com/trigger) leave animations finish ([#20740](https://github.com/angular/angular/issues/20740)) ([b78ada1](https://github.com/angular/angular/commit/b78ada1)), closes [#20541](https://github.com/angular/angular/issues/20541)
|
||||||
|
* **service-worker:** initialize in browser only ([#20782](https://github.com/angular/angular/issues/20782)) ([7cabaa0](https://github.com/angular/angular/commit/7cabaa0)), closes [#20360](https://github.com/angular/angular/issues/20360)
|
||||||
|
* **service-worker:** esm2015 points to wrong path ([#20800](https://github.com/angular/angular/issues/20800)) ([da3563c](https://github.com/angular/angular/commit/da3563c))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="5.1.0-rc.1"></a>
|
||||||
|
# [5.1.0-rc.1](https://github.com/angular/angular/compare/5.1.0-rc.0...5.1.0-rc.1) (2017-12-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **compiler-cli:** propagate ts.SourceFile moduleName into metadata ([f841fbe](https://github.com/angular/angular/commit/f841fbe))
|
||||||
|
* **service-worker:** allow disabling SW while still using services ([65f4fad](https://github.com/angular/angular/commit/65f4fad))
|
||||||
|
* **service-worker:** don't crash if SW not supported ([b9a91a5](https://github.com/angular/angular/commit/b9a91a5))
|
||||||
|
* **service-worker:** send initialization signal from the application ([3fbcde9](https://github.com/angular/angular/commit/3fbcde9))
|
||||||
|
* **service-worker:** use relative path for ngsw.json ([f582620](https://github.com/angular/angular/commit/f582620))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="5.0.5"></a>
|
||||||
|
## [5.0.5](https://github.com/angular/angular/compare/5.0.4...5.0.5) (2017-12-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **compiler-cli:** propagate ts.SourceFile moduleName into metadata ([a2ff4ab](https://github.com/angular/angular/commit/a2ff4ab))
|
||||||
|
* **service-worker:** allow disabling SW while still using services ([f99335b](https://github.com/angular/angular/commit/f99335b))
|
||||||
|
* **service-worker:** don't crash if SW not supported ([ee37d4b](https://github.com/angular/angular/commit/ee37d4b))
|
||||||
|
* **service-worker:** send initialization signal from the application ([6bf07b4](https://github.com/angular/angular/commit/6bf07b4))
|
||||||
|
* **service-worker:** use relative path for ngsw.json ([56c98f7](https://github.com/angular/angular/commit/56c98f7))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="5.1.0-rc.0"></a>
|
||||||
|
# [5.1.0-rc.0](https://github.com/angular/angular/compare/5.1.0-beta.2...5.1.0-rc.0) (2017-12-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **animations:** ensure multi-level enter animations work ([#19455](https://github.com/angular/angular/issues/19455)) ([dd6237e](https://github.com/angular/angular/commit/dd6237e))
|
||||||
|
* **animations:** ensure multi-level enter animations work ([#19455](https://github.com/angular/angular/issues/19455)) ([b2a586c](https://github.com/angular/angular/commit/b2a586c))
|
||||||
|
* **animations:** ensure multi-level leave animations work ([#19455](https://github.com/angular/angular/issues/19455)) ([1366762](https://github.com/angular/angular/commit/1366762))
|
||||||
|
* **animations:** ensure multi-level leave animations work ([#19455](https://github.com/angular/angular/issues/19455)) ([c2b3792](https://github.com/angular/angular/commit/c2b3792))
|
||||||
|
* **bazel:** produce named AMD modules for codegen ([#20547](https://github.com/angular/angular/issues/20547)) ([6e83204](https://github.com/angular/angular/commit/6e83204)), closes [#19422](https://github.com/angular/angular/issues/19422)
|
||||||
|
* **common:** accept falsy values as HTTP bodies ([#19958](https://github.com/angular/angular/issues/19958)) ([15a54df](https://github.com/angular/angular/commit/15a54df)), closes [#19825](https://github.com/angular/angular/issues/19825) [#19195](https://github.com/angular/angular/issues/19195)
|
||||||
|
* **common:** don't strip XSSI prefix for if error isn't JSON ([#19958](https://github.com/angular/angular/issues/19958)) ([aafa75d](https://github.com/angular/angular/commit/aafa75d))
|
||||||
|
* **common:** remove useless guard in HttpClient ([#19958](https://github.com/angular/angular/issues/19958)) ([eb01ad5](https://github.com/angular/angular/commit/eb01ad5)), closes [#19223](https://github.com/angular/angular/issues/19223)
|
||||||
|
* **common:** treat an empty body as null when parsing JSON in HttpClient ([#19958](https://github.com/angular/angular/issues/19958)) ([503be69](https://github.com/angular/angular/commit/503be69)), closes [#18680](https://github.com/angular/angular/issues/18680) [#19413](https://github.com/angular/angular/issues/19413) [#19502](https://github.com/angular/angular/issues/19502) [#19555](https://github.com/angular/angular/issues/19555)
|
||||||
|
* **compiler:** correctly detect when to serialze summary metadata ([#20668](https://github.com/angular/angular/issues/20668)) ([8bb42df](https://github.com/angular/angular/commit/8bb42df))
|
||||||
|
* **compiler-cli:** fix memory leak in program creation ([#20692](https://github.com/angular/angular/issues/20692)) ([71e5de6](https://github.com/angular/angular/commit/71e5de6)), closes [#20691](https://github.com/angular/angular/issues/20691)
|
||||||
|
* **compiler-cli:** normalize sourcepaths for i18n extracted files ([#20417](https://github.com/angular/angular/issues/20417)) ([de78307](https://github.com/angular/angular/commit/de78307)), closes [#20416](https://github.com/angular/angular/issues/20416)
|
||||||
|
* **core:** should use native addEventListener in ngZone ([#20672](https://github.com/angular/angular/issues/20672)) ([65a2cb8](https://github.com/angular/angular/commit/65a2cb8))
|
||||||
|
* **language-service:** Allow empty templates ([#20651](https://github.com/angular/angular/issues/20651)) ([3203069](https://github.com/angular/angular/commit/3203069)), closes [#19406](https://github.com/angular/angular/issues/19406)
|
||||||
|
* **language-service:** Fix crash when no script files are found ([#20550](https://github.com/angular/angular/issues/20550)) ([54bfe14](https://github.com/angular/angular/commit/54bfe14)), closes [#19325](https://github.com/angular/angular/issues/19325)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **common:** add locale id parameter to `registerLocaleData` ([#20623](https://github.com/angular/angular/issues/20623)) ([24bf3e2](https://github.com/angular/angular/commit/24bf3e2))
|
||||||
|
* **compiler-cli:** improve error messages produced during structural errors ([#20459](https://github.com/angular/angular/issues/20459)) ([8ecda94](https://github.com/angular/angular/commit/8ecda94))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="5.0.4"></a>
|
||||||
|
## [5.0.4](https://github.com/angular/angular/compare/5.0.3...5.0.4) (2017-12-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **animations:** ensure multi-level enter animations work ([#19455](https://github.com/angular/angular/issues/19455)) ([22bbd6e](https://github.com/angular/angular/commit/22bbd6e))
|
||||||
|
* **animations:** ensure multi-level leave animations work ([#19455](https://github.com/angular/angular/issues/19455)) ([c7b211c](https://github.com/angular/angular/commit/c7b211c))
|
||||||
|
* **common:** accept falsy values as HTTP bodies ([#19958](https://github.com/angular/angular/issues/19958)) ([66fd1f8](https://github.com/angular/angular/commit/66fd1f8)), closes [#19825](https://github.com/angular/angular/issues/19825) [#19195](https://github.com/angular/angular/issues/19195)
|
||||||
|
* **common:** don't strip XSSI prefix for if error isn't JSON ([#19958](https://github.com/angular/angular/issues/19958)) ([ead7596](https://github.com/angular/angular/commit/ead7596))
|
||||||
|
* **common:** remove useless guard in HttpClient ([#19958](https://github.com/angular/angular/issues/19958)) ([e099911](https://github.com/angular/angular/commit/e099911)), closes [#19223](https://github.com/angular/angular/issues/19223)
|
||||||
|
* **common:** treat an empty body as null when parsing JSON in HttpClient ([#19958](https://github.com/angular/angular/issues/19958)) ([bdaee50](https://github.com/angular/angular/commit/bdaee50)), closes [#18680](https://github.com/angular/angular/issues/18680) [#19413](https://github.com/angular/angular/issues/19413) [#19502](https://github.com/angular/angular/issues/19502) [#19555](https://github.com/angular/angular/issues/19555)
|
||||||
|
* **compiler-cli:** fix memory leak in program creation ([#20692](https://github.com/angular/angular/issues/20692)) ([38be44d](https://github.com/angular/angular/commit/38be44d)), closes [#20691](https://github.com/angular/angular/issues/20691)
|
||||||
|
* **compiler-cli:** normalize sourcepaths for i18n extracted files ([#20417](https://github.com/angular/angular/issues/20417)) ([2b0c896](https://github.com/angular/angular/commit/2b0c896)), closes [#20416](https://github.com/angular/angular/issues/20416)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="5.1.0-beta.2"></a>
|
||||||
|
# [5.1.0-beta.2](https://github.com/angular/angular/compare/5.1.0-beta.1...5.1.0-beta.2) (2017-11-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **animations:** always fire inner trigger callbacks even if blocked by parent animations ([#19753](https://github.com/angular/angular/issues/19753)) ([0e012c9](https://github.com/angular/angular/commit/0e012c9)), closes [#19100](https://github.com/angular/angular/issues/19100)
|
||||||
|
* **animations:** always fire start and done callbacks in order for noop animations ([#20570](https://github.com/angular/angular/issues/20570)) ([ffb6dbe](https://github.com/angular/angular/commit/ffb6dbe))
|
||||||
|
* **animations:** validate against trigger() names that use @ symbols ([#20326](https://github.com/angular/angular/issues/20326)) ([1861e41](https://github.com/angular/angular/commit/1861e41))
|
||||||
|
* **benchpress:** Allow ignoring navigationStart events in perflog metric. ([#20312](https://github.com/angular/angular/issues/20312)) ([717ac5a](https://github.com/angular/angular/commit/717ac5a))
|
||||||
|
* **common:** return ISubscription from Location.subscribe() ([#20429](https://github.com/angular/angular/issues/20429)) ([437a044](https://github.com/angular/angular/commit/437a044)), closes [#20406](https://github.com/angular/angular/issues/20406)
|
||||||
|
* **compiler:** emit correct type-check-blocks with TemplateRef's ([#20463](https://github.com/angular/angular/issues/20463)) ([68b53c0](https://github.com/angular/angular/commit/68b53c0))
|
||||||
|
* **compiler:** support event bindings in `fullTemplateTypeCheck` ([#20490](https://github.com/angular/angular/issues/20490)) ([4ed0439](https://github.com/angular/angular/commit/4ed0439))
|
||||||
|
* **core:** fix [#20532](https://github.com/angular/angular/issues/20532), should be able to cancel listener from mixed zone ([#20538](https://github.com/angular/angular/issues/20538)) ([a740e4f](https://github.com/angular/angular/commit/a740e4f))
|
||||||
|
* **core:** should support event.stopImmediatePropagation ([#20469](https://github.com/angular/angular/issues/20469)) ([997336b](https://github.com/angular/angular/commit/997336b))
|
||||||
|
* **forms:** updateOn should check if change occurred ([#20358](https://github.com/angular/angular/issues/20358)) ([69c53c3](https://github.com/angular/angular/commit/69c53c3)), closes [#20259](https://github.com/angular/angular/issues/20259)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **platform-browser-dynamic:** export `JitCompilerFactory` ([#20478](https://github.com/angular/angular/issues/20478)) ([d7a727c](https://github.com/angular/angular/commit/d7a727c)), closes [#20125](https://github.com/angular/angular/issues/20125)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="5.0.3"></a>
|
||||||
|
## [5.0.3](https://github.com/angular/angular/compare/5.0.2...5.0.3) (2017-11-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **animations:** always fire inner trigger callbacks even if blocked by parent animations ([#19753](https://github.com/angular/angular/issues/19753)) ([814f062](https://github.com/angular/angular/commit/814f062)), closes [#19100](https://github.com/angular/angular/issues/19100)
|
||||||
|
* **animations:** validate against trigger() names that use @ symbols ([#20326](https://github.com/angular/angular/issues/20326)) ([15795d0](https://github.com/angular/angular/commit/15795d0))
|
||||||
|
* **benchpress:** Allow ignoring navigationStart events in perflog metric. ([#20312](https://github.com/angular/angular/issues/20312)) ([9ca6ee9](https://github.com/angular/angular/commit/9ca6ee9))
|
||||||
|
* **common:** return ISubscription from Location.subscribe() ([#20429](https://github.com/angular/angular/issues/20429)) ([bc904b1](https://github.com/angular/angular/commit/bc904b1)), closes [#20406](https://github.com/angular/angular/issues/20406)
|
||||||
|
* **compiler:** emit correct type-check-blocks with TemplateRef's ([#20463](https://github.com/angular/angular/issues/20463)) ([81f1d42](https://github.com/angular/angular/commit/81f1d42))
|
||||||
|
* **compiler:** support event bindings in `fullTemplateTypeCheck` ([#20490](https://github.com/angular/angular/issues/20490)) ([b53ead4](https://github.com/angular/angular/commit/b53ead4))
|
||||||
|
* **core:** fix [#20532](https://github.com/angular/angular/issues/20532), should be able to cancel listener from mixed zone ([#20538](https://github.com/angular/angular/issues/20538)) ([0feba49](https://github.com/angular/angular/commit/0feba49))
|
||||||
|
* **core:** should support event.stopImmediatePropagation ([#20469](https://github.com/angular/angular/issues/20469)) ([82aace6](https://github.com/angular/angular/commit/82aace6))
|
||||||
|
* **forms:** updateOn should check if change occurred ([#20358](https://github.com/angular/angular/issues/20358)) ([f9f2c20](https://github.com/angular/angular/commit/f9f2c20)), closes [#20259](https://github.com/angular/angular/issues/20259)
|
||||||
|
|
||||||
|
|
||||||
<a name="5.1.0-beta.1"></a>
|
<a name="5.1.0-beta.1"></a>
|
||||||
# [5.1.0-beta.1](https://github.com/angular/angular/compare/5.1.0-beta.0...5.1.0-beta.1) (2017-11-16)
|
# [5.1.0-beta.1](https://github.com/angular/angular/compare/5.1.0-beta.0...5.1.0-beta.1) (2017-11-16)
|
||||||
|
|
||||||
@ -15,7 +209,11 @@
|
|||||||
* **router:** 'merge' queryParamHandling strategy should be able to remove query params ([#19733](https://github.com/angular/angular/issues/19733)) ([a622e19](https://github.com/angular/angular/commit/a622e19)), closes [#18463](https://github.com/angular/angular/issues/18463) [#17202](https://github.com/angular/angular/issues/17202)
|
* **router:** 'merge' queryParamHandling strategy should be able to remove query params ([#19733](https://github.com/angular/angular/issues/19733)) ([a622e19](https://github.com/angular/angular/commit/a622e19)), closes [#18463](https://github.com/angular/angular/issues/18463) [#17202](https://github.com/angular/angular/issues/17202)
|
||||||
* Update test code to type-check under TS 2.5 ([#20175](https://github.com/angular/angular/issues/20175)) ([5ec1717](https://github.com/angular/angular/commit/5ec1717))
|
* Update test code to type-check under TS 2.5 ([#20175](https://github.com/angular/angular/issues/20175)) ([5ec1717](https://github.com/angular/angular/commit/5ec1717))
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **typescript:** support TypeScript 2.5 ([a9f3e2b](https://github.com/angular/angular/commit/a9f3e2b)), closes [#20175](https://github.com/angular/angular/issues/20175)
|
||||||
|
|
||||||
|
> Note, if you do `Injector.get(Token)` where `Token` has static members, you'll run into https://github.com/Microsoft/TypeScript/issues/20102 where the returned type is `{}` rather than `Token`. Use `Injector.get<Token>(Token)` to work around.
|
||||||
|
|
||||||
<a name="5.0.2"></a>
|
<a name="5.0.2"></a>
|
||||||
## [5.0.2](https://github.com/angular/angular/compare/5.0.1...5.0.2) (2017-11-16)
|
## [5.0.2](https://github.com/angular/angular/compare/5.0.1...5.0.2) (2017-11-16)
|
||||||
|
40
WORKSPACE
40
WORKSPACE
@ -5,19 +5,51 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
|
|||||||
git_repository(
|
git_repository(
|
||||||
name = "build_bazel_rules_nodejs",
|
name = "build_bazel_rules_nodejs",
|
||||||
remote = "https://github.com/bazelbuild/rules_nodejs.git",
|
remote = "https://github.com/bazelbuild/rules_nodejs.git",
|
||||||
commit = "0.2.1",
|
tag = "0.3.1",
|
||||||
)
|
)
|
||||||
|
|
||||||
load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories")
|
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories")
|
||||||
|
|
||||||
|
check_bazel_version("0.8.1")
|
||||||
node_repositories(package_json = ["//:package.json"])
|
node_repositories(package_json = ["//:package.json"])
|
||||||
|
|
||||||
local_repository(
|
git_repository(
|
||||||
name = "build_bazel_rules_typescript",
|
name = "build_bazel_rules_typescript",
|
||||||
path = "node_modules/@bazel/typescript",
|
remote = "https://github.com/bazelbuild/rules_typescript.git",
|
||||||
|
tag = "0.6.0",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
load("@build_bazel_rules_typescript//:defs.bzl", "ts_repositories")
|
||||||
|
|
||||||
|
ts_repositories()
|
||||||
|
|
||||||
local_repository(
|
local_repository(
|
||||||
name = "angular",
|
name = "angular",
|
||||||
path = "packages/bazel",
|
path = "packages/bazel",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
local_repository(
|
||||||
|
name = "rxjs",
|
||||||
|
path = "node_modules/rxjs/src",
|
||||||
|
)
|
||||||
|
|
||||||
|
git_repository(
|
||||||
|
name = "com_github_bazelbuild_buildtools",
|
||||||
|
remote = "https://github.com/bazelbuild/buildtools.git",
|
||||||
|
# Note, this commit matches the version of buildifier in angular/ngcontainer
|
||||||
|
# If you change this, also check if it matches the version in the angular/ngcontainer
|
||||||
|
# version in /.circleci/config.yml
|
||||||
|
commit = "b3b620e8bcff18ed3378cd3f35ebeb7016d71f71",
|
||||||
|
)
|
||||||
|
|
||||||
|
http_archive(
|
||||||
|
name = "io_bazel_rules_go",
|
||||||
|
url = "https://github.com/bazelbuild/rules_go/releases/download/0.7.1/rules_go-0.7.1.tar.gz",
|
||||||
|
sha256 = "341d5eacef704415386974bc82a1783a8b7ffbff2ab6ba02375e1ca20d9b031c",
|
||||||
|
)
|
||||||
|
|
||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains")
|
||||||
|
|
||||||
|
go_rules_dependencies()
|
||||||
|
|
||||||
|
go_register_toolchains()
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
<hr>
|
<hr>
|
||||||
<h4>{{hero.name}} Detail</h4>
|
<h4>{{hero.name}} Detail</h4>
|
||||||
<div>Id: {{hero.id}}</div>
|
<div>Id: {{hero.id}}</div>
|
||||||
<div>Name:
|
<label>Name:
|
||||||
<!-- #docregion ngModel -->
|
<!-- #docregion ngModel -->
|
||||||
<input [(ngModel)]="hero.name">
|
<input [(ngModel)]="hero.name">
|
||||||
<!-- #enddocregion ngModel -->
|
<!-- #enddocregion ngModel -->
|
||||||
</div>
|
</label>
|
||||||
<div>Power:<input [(ngModel)]="hero.power"></div>
|
<br />
|
||||||
|
<label>Power: <input [(ngModel)]="hero.power"></label>
|
||||||
|
@ -7,7 +7,7 @@ import { TaxRateService } from './tax-rate.service';
|
|||||||
selector: 'app-sales-tax',
|
selector: 'app-sales-tax',
|
||||||
template: `
|
template: `
|
||||||
<h2>Sales Tax Calculator</h2>
|
<h2>Sales Tax Calculator</h2>
|
||||||
Amount: <input #amountBox (change)="0">
|
<label>Amount: <input #amountBox (change)="0"></label>
|
||||||
|
|
||||||
<div *ngIf="amountBox.value">
|
<div *ngIf="amountBox.value">
|
||||||
The sales tax is
|
The sales tax is
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
<!-- #docregion -->
|
<!-- #docregion -->
|
||||||
<h1>My First Attribute Directive</h1>
|
<h1>My First Attribute Directive</h1>
|
||||||
<!-- #docregion applied -->
|
<!-- #docregion applied -->
|
||||||
<p appHightlight>Highlight me!</p>
|
<p appHighlight>Highlight me!</p>
|
||||||
<!-- #enddocregion applied, -->
|
<!-- #enddocregion applied, -->
|
||||||
|
|
||||||
<!-- #docregion color-1 -->
|
<!-- #docregion color-1 -->
|
||||||
<p appHightlight highlightColor="yellow">Highlighted in yellow</p>
|
<p appHighlight highlightColor="yellow">Highlighted in yellow</p>
|
||||||
<p appHightlight [highlightColor]="'orange'">Highlighted in orange</p>
|
<p appHighlight [highlightColor]="'orange'">Highlighted in orange</p>
|
||||||
<!-- #enddocregion color-1 -->
|
<!-- #enddocregion color-1 -->
|
||||||
|
|
||||||
<!-- #docregion color-2 -->
|
<!-- #docregion color-2 -->
|
||||||
<p appHightlight [highlightColor]="color">Highlighted with parent component's color</p>
|
<p appHighlight [highlightColor]="color">Highlighted with parent component's color</p>
|
||||||
<!-- #enddocregion color-2 -->
|
<!-- #enddocregion color-2 -->
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
"!**/*.d.ts",
|
"!**/*.d.ts",
|
||||||
"!**/*.js",
|
"!**/*.js",
|
||||||
"!**/*.[0,1,2].*",
|
"!**/*.[0,1,2].*",
|
||||||
"**/dummy.module.ts"
|
"!**/dummy.module.ts"
|
||||||
],
|
],
|
||||||
"tags": ["dependency", "di"]
|
"tags": ["dependency", "di"]
|
||||||
}
|
}
|
||||||
|
@ -2,5 +2,6 @@
|
|||||||
import { registerLocaleData } from '@angular/common';
|
import { registerLocaleData } from '@angular/common';
|
||||||
import localeFr from '@angular/common/locales/fr';
|
import localeFr from '@angular/common/locales/fr';
|
||||||
|
|
||||||
registerLocaleData(localeFr);
|
// the second parameter 'fr' is optional
|
||||||
|
registerLocaleData(localeFr, 'fr');
|
||||||
// #enddocregion import-locale
|
// #enddocregion import-locale
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// #docregion import-locale-extra
|
// #docregion import-locale-extra
|
||||||
import { registerLocaleData } from '@angular/common';
|
import { registerLocaleData } from '@angular/common';
|
||||||
import localeFrCa from '@angular/common/locales/fr-CA';
|
import localeFr from '@angular/common/locales/fr';
|
||||||
import localeFrCaExtra from '@angular/common/locales/extra/fr-CA';
|
import localeFrExtra from '@angular/common/locales/extra/fr';
|
||||||
|
|
||||||
registerLocaleData(localeFrCa, localeFrCaExtra);
|
registerLocaleData(localeFr, 'fr-FR', localeFrExtra);
|
||||||
// #enddocregion import-locale-extra
|
// #enddocregion import-locale-extra
|
||||||
|
@ -93,22 +93,20 @@ export class AfterContentComponent implements AfterContentChecked, AfterContentI
|
|||||||
|
|
||||||
<h4>-- AfterContent Logs --</h4>
|
<h4>-- AfterContent Logs --</h4>
|
||||||
<p><button (click)="reset()">Reset</button></p>
|
<p><button (click)="reset()">Reset</button></p>
|
||||||
<div *ngFor="let msg of logs">{{msg}}</div>
|
<div *ngFor="let msg of logger.logs">{{msg}}</div>
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
styles: ['.parent {background: burlywood}'],
|
styles: ['.parent {background: burlywood}'],
|
||||||
providers: [LoggerService]
|
providers: [LoggerService]
|
||||||
})
|
})
|
||||||
export class AfterContentParentComponent {
|
export class AfterContentParentComponent {
|
||||||
logs: string[];
|
|
||||||
show = true;
|
show = true;
|
||||||
|
|
||||||
constructor(private logger: LoggerService) {
|
constructor(public logger: LoggerService) {
|
||||||
this.logs = logger.logs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
this.logs.length = 0;
|
this.logger.clear();
|
||||||
// quickly remove and reload AfterContentComponent which recreates it
|
// quickly remove and reload AfterContentComponent which recreates it
|
||||||
this.show = false;
|
this.show = false;
|
||||||
this.logger.tick_then(() => this.show = true);
|
this.logger.tick_then(() => this.show = true);
|
||||||
|
@ -95,22 +95,20 @@ export class AfterViewComponent implements AfterViewChecked, AfterViewInit {
|
|||||||
|
|
||||||
<h4>-- AfterView Logs --</h4>
|
<h4>-- AfterView Logs --</h4>
|
||||||
<p><button (click)="reset()">Reset</button></p>
|
<p><button (click)="reset()">Reset</button></p>
|
||||||
<div *ngFor="let msg of logs">{{msg}}</div>
|
<div *ngFor="let msg of logger.logs">{{msg}}</div>
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
styles: ['.parent {background: burlywood}'],
|
styles: ['.parent {background: burlywood}'],
|
||||||
providers: [LoggerService]
|
providers: [LoggerService]
|
||||||
})
|
})
|
||||||
export class AfterViewParentComponent {
|
export class AfterViewParentComponent {
|
||||||
logs: string[];
|
|
||||||
show = true;
|
show = true;
|
||||||
|
|
||||||
constructor(private logger: LoggerService) {
|
constructor(public logger: LoggerService) {
|
||||||
this.logs = logger.logs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
this.logs.length = 0;
|
this.logger.clear();
|
||||||
// quickly remove and reload AfterViewComponent which recreates it
|
// quickly remove and reload AfterViewComponent which recreates it
|
||||||
this.show = false;
|
this.show = false;
|
||||||
this.logger.tick_then(() => this.show = true);
|
this.logger.tick_then(() => this.show = true);
|
||||||
|
@ -27,7 +27,7 @@ export class MyCounterComponent implements OnChanges {
|
|||||||
// Empty the changeLog whenever counter goes to zero
|
// Empty the changeLog whenever counter goes to zero
|
||||||
// hint: this is a way to respond programmatically to external value changes.
|
// hint: this is a way to respond programmatically to external value changes.
|
||||||
if (this.counter === 0) {
|
if (this.counter === 0) {
|
||||||
this.changeLog.length = 0;
|
this.changeLog = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// A change to `counter` is the only change we care about
|
// A change to `counter` is the only change we care about
|
||||||
|
@ -68,7 +68,7 @@ export class DoCheckComponent implements DoCheck {
|
|||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
this.changeDetected = true;
|
this.changeDetected = true;
|
||||||
this.changeLog.length = 0;
|
this.changeLog = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ export class LoggerService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() { this.logs.length = 0; }
|
clear() { this.logs = []; }
|
||||||
|
|
||||||
// schedules a view refresh to ensure display catches up
|
// schedules a view refresh to ensure display catches up
|
||||||
tick() { this.tick_then(() => { }); }
|
tick() { this.tick_then(() => { }); }
|
||||||
|
@ -43,7 +43,7 @@ export class OnChangesComponent implements OnChanges {
|
|||||||
}
|
}
|
||||||
// #enddocregion ng-on-changes
|
// #enddocregion ng-on-changes
|
||||||
|
|
||||||
reset() { this.changeLog.length = 0; }
|
reset() { this.changeLog = []; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************/
|
/***************************************/
|
||||||
|
@ -12,5 +12,5 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- #enddocregion template -->
|
<!-- #enddocregion template -->
|
||||||
<h4>-- Spy Lifecycle Hook Log --</h4>
|
<h4>-- Spy Lifecycle Hook Log --</h4>
|
||||||
<div *ngFor="let msg of spyLog">{{msg}}</div>
|
<div *ngFor="let msg of logger.logs">{{msg}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -15,10 +15,8 @@ import { LoggerService } from './logger.service';
|
|||||||
export class SpyParentComponent {
|
export class SpyParentComponent {
|
||||||
newName = 'Herbie';
|
newName = 'Herbie';
|
||||||
heroes: string[] = ['Windstorm', 'Magneta'];
|
heroes: string[] = ['Windstorm', 'Magneta'];
|
||||||
spyLog: string[];
|
|
||||||
|
|
||||||
constructor(private logger: LoggerService) {
|
constructor(public logger: LoggerService) {
|
||||||
this.spyLog = logger.logs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addHero() {
|
addHero() {
|
||||||
@ -34,7 +32,7 @@ export class SpyParentComponent {
|
|||||||
}
|
}
|
||||||
reset() {
|
reset() {
|
||||||
this.logger.log('-- reset --');
|
this.logger.log('-- reset --');
|
||||||
this.heroes.length = 0;
|
this.heroes = [];
|
||||||
this.logger.tick();
|
this.logger.tick();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
"app/contact/contact.component.html",
|
"app/contact/contact.component.html",
|
||||||
"app/contact/contact.component.3.ts",
|
"app/contact/contact.component.3.ts",
|
||||||
"app/contact/contact.service.ts",
|
"app/contact/contact.service.ts",
|
||||||
"app/contact/highlight.directive.ts",
|
"app/contact/contact-highlight.directive.ts",
|
||||||
|
|
||||||
"main.1b.ts",
|
"main.1b.ts",
|
||||||
"styles.css",
|
"styles.css",
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
"app/contact/awesome.pipe.ts",
|
"app/contact/awesome.pipe.ts",
|
||||||
"app/contact/contact.component.3.ts",
|
"app/contact/contact.component.3.ts",
|
||||||
"app/contact/contact.module.2.ts",
|
"app/contact/contact.module.2.ts",
|
||||||
"app/contact/highlight.directive.ts",
|
"app/contact/contact-highlight.directive.ts",
|
||||||
|
|
||||||
"main.2.ts",
|
"main.2.ts",
|
||||||
"styles.css",
|
"styles.css",
|
||||||
|
@ -15,7 +15,7 @@ describe('NgModule', function () {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
title: element.all(by.tagName('h1')).get(0),
|
title: element.all(by.tagName('h1')).get(0),
|
||||||
subtitle: element.all(by.css('app-title p i')).get(0),
|
welcome: element.all(by.css('app-title p i')).get(0),
|
||||||
contactButton: buttons.get(0),
|
contactButton: buttons.get(0),
|
||||||
crisisButton: buttons.get(1),
|
crisisButton: buttons.get(1),
|
||||||
heroesButton: buttons.get(2)
|
heroesButton: buttons.get(2)
|
||||||
@ -67,7 +67,7 @@ describe('NgModule', function () {
|
|||||||
|
|
||||||
it('should welcome us', function () {
|
it('should welcome us', function () {
|
||||||
const commons = getCommonsSectionStruct();
|
const commons = getCommonsSectionStruct();
|
||||||
expect(commons.subtitle.getText()).toBe('Welcome, ' + (name || 'Sherlock Holmes'));
|
expect(commons.welcome.getText()).toBe('Welcome, ' + (name || 'Sherlock Holmes'));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
"app/contact/contact.component.3.ts",
|
"app/contact/contact.component.3.ts",
|
||||||
"app/contact/contact.module.3.ts",
|
"app/contact/contact.module.3.ts",
|
||||||
"app/contact/contact-routing.module.3.ts",
|
"app/contact/contact-routing.module.3.ts",
|
||||||
"app/contact/highlight.directive.ts",
|
"app/contact/contact-highlight.directive.ts",
|
||||||
|
|
||||||
"app/crisis/*.ts",
|
"app/crisis/*.ts",
|
||||||
|
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { Routes, RouterModule } from '@angular/router';
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
|
||||||
export const routes: Routes = [
|
import { ContactModule } from './contact/contact.module.3';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
{ path: '', redirectTo: 'contact', pathMatch: 'full'},
|
{ path: '', redirectTo: 'contact', pathMatch: 'full'},
|
||||||
{ path: 'crisis', loadChildren: 'app/crisis/crisis.module#CrisisModule' },
|
{ path: 'crisis', loadChildren: 'app/crisis/crisis.module#CrisisModule' },
|
||||||
{ path: 'heroes', loadChildren: 'app/hero/hero.module.3#HeroModule' }
|
{ path: 'heroes', loadChildren: 'app/hero/hero.module.3#HeroModule' }
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [RouterModule.forRoot(routes)],
|
imports: [
|
||||||
|
ContactModule,
|
||||||
|
RouterModule.forRoot(routes)
|
||||||
|
],
|
||||||
exports: [RouterModule]
|
exports: [RouterModule]
|
||||||
})
|
})
|
||||||
export class AppRoutingModule {}
|
export class AppRoutingModule {}
|
||||||
|
@ -2,18 +2,29 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { Routes, RouterModule } from '@angular/router';
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
|
||||||
export const routes: Routes = [
|
import { ContactModule } from './contact/contact.module';
|
||||||
|
|
||||||
|
// #docregion routes
|
||||||
|
const routes: Routes = [
|
||||||
{ path: '', redirectTo: 'contact', pathMatch: 'full'},
|
{ path: '', redirectTo: 'contact', pathMatch: 'full'},
|
||||||
// #docregion lazy-routes
|
// #docregion lazy-routes
|
||||||
{ path: 'crisis', loadChildren: 'app/crisis/crisis.module#CrisisModule' },
|
{ path: 'crisis', loadChildren: 'app/crisis/crisis.module#CrisisModule' },
|
||||||
{ path: 'heroes', loadChildren: 'app/hero/hero.module#HeroModule' }
|
{ path: 'heroes', loadChildren: 'app/hero/hero.module#HeroModule' }
|
||||||
// #enddocregion lazy-routes
|
// #enddocregion lazy-routes
|
||||||
];
|
];
|
||||||
|
// #enddocregion routes
|
||||||
|
|
||||||
// #docregion forRoot
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [RouterModule.forRoot(routes)],
|
// #docregion imports
|
||||||
|
imports: [
|
||||||
|
ContactModule,
|
||||||
|
// #docregion forRoot
|
||||||
|
RouterModule.forRoot(routes),
|
||||||
|
// #enddocregion forRoot
|
||||||
|
],
|
||||||
|
// #enddocregion imports
|
||||||
|
// #docregion exports
|
||||||
exports: [RouterModule]
|
exports: [RouterModule]
|
||||||
|
// #enddocregion exports
|
||||||
})
|
})
|
||||||
export class AppRoutingModule {}
|
export class AppRoutingModule {}
|
||||||
// #enddocregion forRoot
|
|
||||||
|
@ -6,5 +6,5 @@ import { Component } from '@angular/core';
|
|||||||
template: '<h1>{{title}}</h1>',
|
template: '<h1>{{title}}</h1>',
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
title = 'Minimal NgModule';
|
title = 'Angular Modules';
|
||||||
}
|
}
|
||||||
|
@ -11,9 +11,7 @@ import { Component } from '@angular/core';
|
|||||||
// #enddocregion template
|
// #enddocregion template
|
||||||
*/
|
*/
|
||||||
// #docregion
|
// #docregion
|
||||||
template: '<app-title [subtitle]="subtitle"></app-title>'
|
template: '<app-title></app-title>'
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {}
|
||||||
subtitle = '(v1)';
|
|
||||||
}
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
@ -5,11 +5,9 @@ import { Component } from '@angular/core';
|
|||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
// #docregion template
|
// #docregion template
|
||||||
template: `
|
template: `
|
||||||
<app-title [subtitle]="subtitle"></app-title>
|
<app-title></app-title>
|
||||||
<app-contact></app-contact>
|
<app-contact></app-contact>
|
||||||
`
|
`
|
||||||
// #enddocregion template
|
// #enddocregion template
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {}
|
||||||
subtitle = '(v1)';
|
|
||||||
}
|
|
||||||
|
@ -3,10 +3,8 @@ import { Component } from '@angular/core';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
template: `
|
template: `
|
||||||
<app-title [subtitle]="subtitle"></app-title>
|
<app-title></app-title>
|
||||||
<app-contact></app-contact>
|
<app-contact></app-contact>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {}
|
||||||
subtitle = '(v2)';
|
|
||||||
}
|
|
||||||
|
@ -4,7 +4,7 @@ import { Component } from '@angular/core';
|
|||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
// #docregion template
|
// #docregion template
|
||||||
template: `
|
template: `
|
||||||
<app-title [subtitle]="subtitle"></app-title>
|
<app-title></app-title>
|
||||||
<nav>
|
<nav>
|
||||||
<a routerLink="contact" routerLinkActive="active">Contact</a>
|
<a routerLink="contact" routerLinkActive="active">Contact</a>
|
||||||
<a routerLink="crisis" routerLinkActive="active">Crisis Center</a>
|
<a routerLink="crisis" routerLinkActive="active">Crisis Center</a>
|
||||||
@ -14,6 +14,4 @@ import { Component } from '@angular/core';
|
|||||||
`
|
`
|
||||||
// #enddocregion template
|
// #enddocregion template
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {}
|
||||||
subtitle = '(v3)';
|
|
||||||
}
|
|
||||||
|
@ -5,7 +5,7 @@ import { Component } from '@angular/core';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
template: `
|
template: `
|
||||||
<app-title [subtitle]="subtitle"></app-title>
|
<app-title></app-title>
|
||||||
<nav>
|
<nav>
|
||||||
<a routerLink="contact" routerLinkActive="active">Contact</a>
|
<a routerLink="contact" routerLinkActive="active">Contact</a>
|
||||||
<a routerLink="crisis" routerLinkActive="active">Crisis Center</a>
|
<a routerLink="crisis" routerLinkActive="active">Crisis Center</a>
|
||||||
@ -14,6 +14,4 @@ import { Component } from '@angular/core';
|
|||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {}
|
||||||
subtitle = '(Final)';
|
|
||||||
}
|
|
||||||
|
@ -1,17 +1,7 @@
|
|||||||
// #docplaster
|
|
||||||
// #docregion
|
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
import
|
import { AppComponent } from './app.component.0';
|
||||||
// #enddocregion
|
|
||||||
{ AppComponent } from './app.component.0';
|
|
||||||
/*
|
|
||||||
// #docregion
|
|
||||||
{ AppComponent } from './app.component';
|
|
||||||
// #enddocregion
|
|
||||||
*/
|
|
||||||
// #docregion
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
// #docregion imports
|
// #docregion imports
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion
|
// #docregion
|
||||||
|
/* Angular Imports */
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
import
|
/* App Imports */
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
{ AppComponent } from './app.component.1';
|
import { AppComponent } from './app.component.1';
|
||||||
/*
|
/*
|
||||||
// #docregion
|
// #docregion
|
||||||
{ AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
*/
|
*/
|
||||||
// #docregion
|
// #docregion
|
||||||
@ -21,12 +22,9 @@ import { FormsModule } from '@angular/forms';
|
|||||||
|
|
||||||
import { AwesomePipe } from './contact/awesome.pipe';
|
import { AwesomePipe } from './contact/awesome.pipe';
|
||||||
import { ContactComponent } from './contact/contact.component.3';
|
import { ContactComponent } from './contact/contact.component.3';
|
||||||
|
|
||||||
// #docregion import-contact-directive
|
|
||||||
import {
|
import {
|
||||||
HighlightDirective as ContactHighlightDirective
|
ContactHighlightDirective as ContactHighlightDirective
|
||||||
} from './contact/highlight.directive';
|
} from './contact/contact-highlight.directive';
|
||||||
// #enddocregion import-contact-directive
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
// #docregion imports
|
// #docregion imports
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion
|
// #docregion
|
||||||
|
/* Angular Imports */
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
/* App Root */
|
/* App Imports */
|
||||||
import
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
{ AppComponent } from './app.component.1b';
|
import { AppComponent } from './app.component.1b';
|
||||||
/*
|
/*
|
||||||
// #docregion
|
// #docregion
|
||||||
{ AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
*/
|
*/
|
||||||
// #docregion
|
// #docregion
|
||||||
@ -18,25 +19,17 @@ import { TitleComponent } from './title.component';
|
|||||||
import { UserService } from './user.service';
|
import { UserService } from './user.service';
|
||||||
|
|
||||||
/* Contact Imports */
|
/* Contact Imports */
|
||||||
import
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
{ ContactComponent } from './contact/contact.component.3';
|
import { ContactComponent } from './contact/contact.component.3';
|
||||||
/*
|
/*
|
||||||
// #docregion
|
// #docregion
|
||||||
{ ContactComponent } from './contact/contact.component';
|
import { ContactComponent } from './contact/contact.component';
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
*/
|
*/
|
||||||
// #docregion
|
// #docregion
|
||||||
import { ContactService } from './contact/contact.service';
|
import { AwesomePipe } from './contact/awesome.pipe';
|
||||||
import { AwesomePipe } from './contact/awesome.pipe';
|
import { ContactService } from './contact/contact.service';
|
||||||
|
import { ContactHighlightDirective } from './contact/contact-highlight.directive';
|
||||||
// #docregion import-alias
|
|
||||||
import {
|
|
||||||
HighlightDirective as ContactHighlightDirective
|
|
||||||
} from './contact/highlight.directive';
|
|
||||||
// #enddocregion import-alias
|
|
||||||
|
|
||||||
import { FormsModule } from '@angular/forms';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [ BrowserModule, FormsModule ],
|
imports: [ BrowserModule, FormsModule ],
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion
|
// #docregion
|
||||||
|
/* Angular Imports */
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
/* App Root */
|
/* App Imports */
|
||||||
import
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
{ AppComponent } from './app.component.2';
|
import { AppComponent } from './app.component.2';
|
||||||
/*
|
/*
|
||||||
// #docregion
|
// #docregion
|
||||||
{ AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
*/
|
*/
|
||||||
// #docregion
|
// #docregion
|
||||||
@ -18,12 +18,11 @@ import { TitleComponent } from './title.component';
|
|||||||
import { UserService } from './user.service';
|
import { UserService } from './user.service';
|
||||||
|
|
||||||
/* Contact Imports */
|
/* Contact Imports */
|
||||||
import
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
{ ContactModule } from './contact/contact.module.2';
|
import { ContactModule } from './contact/contact.module.2';
|
||||||
/*
|
/*
|
||||||
// #docregion
|
// #docregion
|
||||||
{ ContactModule } from './contact/contact.module';
|
import { ContactModule } from './contact/contact.module';
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
*/
|
*/
|
||||||
// #docregion
|
// #docregion
|
||||||
|
@ -1,25 +1,36 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion
|
// #docregion
|
||||||
|
/* Angular Imports */
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
/* App Root */
|
/* App Imports */
|
||||||
|
// #enddocregion
|
||||||
import { AppComponent } from './app.component.3';
|
import { AppComponent } from './app.component.3';
|
||||||
|
/*
|
||||||
|
// #docregion
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
// #enddocregion
|
||||||
|
*/
|
||||||
|
// #docregion
|
||||||
import { HighlightDirective } from './highlight.directive';
|
import { HighlightDirective } from './highlight.directive';
|
||||||
import { TitleComponent } from './title.component';
|
import { TitleComponent } from './title.component';
|
||||||
import { UserService } from './user.service';
|
import { UserService } from './user.service';
|
||||||
|
|
||||||
/* Feature Modules */
|
|
||||||
import { ContactModule } from './contact/contact.module.3';
|
|
||||||
|
|
||||||
/* Routing Module */
|
/* Routing Module */
|
||||||
|
// #enddocregion
|
||||||
import { AppRoutingModule } from './app-routing.module.3';
|
import { AppRoutingModule } from './app-routing.module.3';
|
||||||
|
/*
|
||||||
|
// #docregion
|
||||||
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
|
// #enddocregion
|
||||||
|
*/
|
||||||
|
// #docregion
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
// #docregion imports
|
// #docregion imports
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
ContactModule,
|
|
||||||
AppRoutingModule
|
AppRoutingModule
|
||||||
],
|
],
|
||||||
// #enddocregion imports
|
// #enddocregion imports
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion
|
// #docregion
|
||||||
// #docregion v4
|
// #docregion v4
|
||||||
|
/* Angular Imports */
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
/* App Root */
|
/* App Imports */
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
/* Feature Modules */
|
/* Core Modules */
|
||||||
import { ContactModule } from './contact/contact.module';
|
|
||||||
import { CoreModule } from './core/core.module';
|
import { CoreModule } from './core/core.module';
|
||||||
|
|
||||||
/* Routing Module */
|
/* Routing Module */
|
||||||
@ -18,7 +18,6 @@ import { AppRoutingModule } from './app-routing.module';
|
|||||||
// #docregion import-for-root
|
// #docregion import-for-root
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
ContactModule,
|
|
||||||
// #enddocregion v4
|
// #enddocregion v4
|
||||||
// #enddocregion import-for-root
|
// #enddocregion import-for-root
|
||||||
/*
|
/*
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* tslint:disable */
|
// #docplaster
|
||||||
// Same directive name and selector as
|
// Same directive name and selector as
|
||||||
// HighlightDirective in parent AppModule
|
// HighlightDirective in parent AppModule
|
||||||
// It selects for both input boxes and 'highlight' attr
|
// It selects for both input boxes and 'highlight' attr
|
||||||
@ -7,12 +7,14 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Directive, ElementRef } from '@angular/core';
|
import { Directive, ElementRef } from '@angular/core';
|
||||||
|
|
||||||
|
// Highlight the host element or any InputElement in blue
|
||||||
@Directive({ selector: '[highlight], input' })
|
@Directive({ selector: '[highlight], input' })
|
||||||
/** Highlight the attached element or an InputElement in blue */
|
export class ContactHighlightDirective {
|
||||||
export class HighlightDirective {
|
|
||||||
constructor(el: ElementRef) {
|
constructor(el: ElementRef) {
|
||||||
el.nativeElement.style.backgroundColor = 'powderblue';
|
el.nativeElement.style.backgroundColor = 'powderblue';
|
||||||
console.log(
|
// #enddocregion
|
||||||
`* Contact highlight called for ${el.nativeElement.tagName}`);
|
console.log(`* Contact highlight called for ${el.nativeElement.tagName}`);
|
||||||
|
// #docregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// #enddocregion
|
@ -3,10 +3,12 @@ import { RouterModule } from '@angular/router';
|
|||||||
|
|
||||||
import { ContactComponent } from './contact.component.3';
|
import { ContactComponent } from './contact.component.3';
|
||||||
|
|
||||||
|
const routes = [
|
||||||
|
{ path: 'contact', component: ContactComponent}
|
||||||
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [RouterModule.forChild([
|
imports: [ RouterModule.forChild(routes) ],
|
||||||
{ path: 'contact', component: ContactComponent}
|
exports: [ RouterModule ]
|
||||||
])],
|
|
||||||
exports: [RouterModule]
|
|
||||||
})
|
})
|
||||||
export class ContactRoutingModule {}
|
export class ContactRoutingModule {}
|
||||||
|
@ -4,11 +4,13 @@ import { RouterModule } from '@angular/router';
|
|||||||
import { ContactComponent } from './contact.component';
|
import { ContactComponent } from './contact.component';
|
||||||
|
|
||||||
// #docregion routing
|
// #docregion routing
|
||||||
|
const routes = [
|
||||||
|
{ path: 'contact', component: ContactComponent}
|
||||||
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [RouterModule.forChild([
|
imports: [ RouterModule.forChild(routes) ],
|
||||||
{ path: 'contact', component: ContactComponent }
|
exports: [ RouterModule ]
|
||||||
])],
|
|
||||||
exports: [RouterModule]
|
|
||||||
})
|
})
|
||||||
export class ContactRoutingModule {}
|
export class ContactRoutingModule {}
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
@ -21,7 +21,7 @@ export class ContactComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.contactService.getContacts().then(contacts => {
|
this.contactService.getContacts().subscribe(contacts => {
|
||||||
this.msg = '';
|
this.msg = '';
|
||||||
this.contacts = contacts;
|
this.contacts = contacts;
|
||||||
this.contact = contacts[0];
|
this.contact = contacts[0];
|
||||||
|
@ -27,3 +27,6 @@
|
|||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
padding-top: 12px;
|
||||||
|
}
|
||||||
|
@ -6,18 +6,32 @@
|
|||||||
<!-- #docregion awesome -->
|
<!-- #docregion awesome -->
|
||||||
<h3 highlight>{{ contact.name | awesome }}</h3>
|
<h3 highlight>{{ contact.name | awesome }}</h3>
|
||||||
<!-- #enddocregion awesome -->
|
<!-- #enddocregion awesome -->
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="name">Name</label>
|
<label for="name">Name</label>
|
||||||
|
|
||||||
|
<!-- #docregion ngModel -->
|
||||||
<input type="text" class="form-control" required
|
<input type="text" class="form-control" required
|
||||||
[(ngModel)]="contact.name"
|
[(ngModel)]="contact.name"
|
||||||
name="name" #name="ngModel" >
|
name="name" #name="ngModel" >
|
||||||
|
<!-- #enddocregion ngModel -->
|
||||||
|
|
||||||
<div [hidden]="name.valid" class="alert alert-danger">
|
<div [hidden]="name.valid" class="alert alert-danger">
|
||||||
Name is required
|
Name is required
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
|
||||||
<button type="submit" class="btn btn-default" [disabled]="!contactForm.form.valid">Save</button>
|
<div class="button-group">
|
||||||
<button type="button" class="btn" (click)="next()" [disabled]="!contactForm.form.valid">Next Contact</button>
|
<button type="submit" class="btn btn-default"
|
||||||
<button type="button" class="btn" (click)="newContact()">New Contact</button>
|
[disabled]="!contactForm.form.valid">
|
||||||
|
Save</button>
|
||||||
|
|
||||||
|
<button type="button" class="btn" (click)="next()"
|
||||||
|
[disabled]="!contactForm.form.valid">
|
||||||
|
Next Contact</button>
|
||||||
|
|
||||||
|
<button type="button" class="btn" (click)="newContact()">
|
||||||
|
New Contact</button>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<!-- #enddocregion -->
|
<!-- #enddocregion -->
|
||||||
|
@ -22,7 +22,7 @@ export class ContactComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.contactService.getContacts().then(contacts => {
|
this.contactService.getContacts().subscribe(contacts => {
|
||||||
this.msg = '';
|
this.msg = '';
|
||||||
this.contacts = contacts;
|
this.contacts = contacts;
|
||||||
this.contact = contacts[0];
|
this.contact = contacts[0];
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
// #docregion
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule
|
||||||
|
],
|
||||||
|
declarations: []
|
||||||
|
})
|
||||||
|
export class ContactModule { }
|
@ -5,25 +5,32 @@ import { CommonModule } from '@angular/common';
|
|||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
import { AwesomePipe } from './awesome.pipe';
|
import { AwesomePipe } from './awesome.pipe';
|
||||||
|
|
||||||
import
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
{ ContactComponent } from './contact.component.3';
|
import { ContactComponent } from './contact.component.3';
|
||||||
/*
|
/*
|
||||||
// #docregion
|
// #docregion
|
||||||
{ ContactComponent } from './contact.component';
|
import { ContactComponent } from './contact.component';
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
*/
|
*/
|
||||||
// #docregion
|
// #docregion
|
||||||
|
import { ContactHighlightDirective } from './contact-highlight.directive';
|
||||||
import { ContactService } from './contact.service';
|
import { ContactService } from './contact.service';
|
||||||
import { HighlightDirective } from './highlight.directive';
|
|
||||||
|
|
||||||
// #docregion class
|
// #docregion class
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [ CommonModule, FormsModule ],
|
imports: [
|
||||||
declarations: [ ContactComponent, HighlightDirective, AwesomePipe ],
|
CommonModule,
|
||||||
exports: [ ContactComponent ],
|
FormsModule
|
||||||
providers: [ ContactService ]
|
],
|
||||||
|
declarations: [
|
||||||
|
AwesomePipe,
|
||||||
|
ContactComponent,
|
||||||
|
ContactHighlightDirective
|
||||||
|
],
|
||||||
|
// #docregion exports
|
||||||
|
exports: [ ContactComponent ],
|
||||||
|
// #enddocregion exports
|
||||||
|
providers: [ ContactService ]
|
||||||
})
|
})
|
||||||
export class ContactModule { }
|
export class ContactModule { }
|
||||||
// #enddocregion class
|
// #enddocregion class
|
||||||
|
@ -1,21 +1,43 @@
|
|||||||
|
// #docplaster
|
||||||
// #docregion
|
// #docregion
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
import { AwesomePipe } from './awesome.pipe';
|
import { AwesomePipe } from './awesome.pipe';
|
||||||
|
// #enddocregion
|
||||||
import { ContactComponent } from './contact.component.3';
|
import { ContactComponent } from './contact.component.3';
|
||||||
|
/*
|
||||||
|
// #docregion
|
||||||
|
import { ContactComponent } from './contact.component';
|
||||||
|
// #enddocregion
|
||||||
|
*/
|
||||||
|
// #docregion
|
||||||
|
import { ContactHighlightDirective } from './contact-highlight.directive';
|
||||||
import { ContactService } from './contact.service';
|
import { ContactService } from './contact.service';
|
||||||
import { HighlightDirective } from './highlight.directive';
|
|
||||||
|
|
||||||
|
// #enddocregion
|
||||||
import { ContactRoutingModule } from './contact-routing.module.3';
|
import { ContactRoutingModule } from './contact-routing.module.3';
|
||||||
|
/*
|
||||||
|
// #docregion
|
||||||
|
import { ContactRoutingModule } from './contact-routing.module';
|
||||||
|
// #enddocregion
|
||||||
|
*/
|
||||||
|
// #docregion
|
||||||
|
|
||||||
// #docregion class
|
// #docregion class
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [ CommonModule, FormsModule, ContactRoutingModule ],
|
imports: [
|
||||||
declarations: [ ContactComponent, HighlightDirective, AwesomePipe ],
|
CommonModule,
|
||||||
providers: [ ContactService ]
|
FormsModule,
|
||||||
|
ContactRoutingModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
AwesomePipe,
|
||||||
|
ContactComponent,
|
||||||
|
ContactHighlightDirective
|
||||||
|
],
|
||||||
|
providers: [ ContactService ]
|
||||||
})
|
})
|
||||||
export class ContactModule { }
|
export class ContactModule { }
|
||||||
// #enddocregion class
|
// #enddocregion class
|
||||||
|
@ -8,7 +8,10 @@ import { ContactRoutingModule } from './contact-routing.module';
|
|||||||
|
|
||||||
// #docregion class
|
// #docregion class
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [ SharedModule, ContactRoutingModule ],
|
imports: [
|
||||||
|
SharedModule,
|
||||||
|
ContactRoutingModule
|
||||||
|
],
|
||||||
declarations: [ ContactComponent ],
|
declarations: [ ContactComponent ],
|
||||||
providers: [ ContactService ]
|
providers: [ ContactService ]
|
||||||
})
|
})
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
|
// #docplaster
|
||||||
// #docregion
|
// #docregion
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable, OnDestroy } from '@angular/core';
|
||||||
|
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { of } from 'rxjs/observable/of';
|
||||||
|
import { delay } from 'rxjs/operators';
|
||||||
|
|
||||||
export class Contact {
|
export class Contact {
|
||||||
constructor(public id: number, public name: string) { }
|
constructor(public id: number, public name: string) { }
|
||||||
@ -13,17 +18,21 @@ const CONTACTS: Contact[] = [
|
|||||||
|
|
||||||
const FETCH_LATENCY = 500;
|
const FETCH_LATENCY = 500;
|
||||||
|
|
||||||
|
/** Simulate a data service that retrieves contacts from a server */
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ContactService {
|
export class ContactService implements OnDestroy {
|
||||||
|
// #enddocregion
|
||||||
|
constructor() { console.log('ContactService instance created.'); }
|
||||||
|
ngOnDestroy() { console.log('ContactService instance destroyed.'); }
|
||||||
|
|
||||||
getContacts() {
|
// #docregion
|
||||||
return new Promise<Contact[]>(resolve => {
|
getContacts(): Observable<Contact[]> {
|
||||||
setTimeout(() => { resolve(CONTACTS); }, FETCH_LATENCY);
|
return of(CONTACTS).pipe(delay(FETCH_LATENCY));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getContact(id: number | string) {
|
getContact(id: number | string): Observable<Contact> {
|
||||||
return this.getContacts()
|
return of(CONTACTS.find(contact => contact.id === +id))
|
||||||
.then(heroes => heroes.find(hero => hero.id === +id));
|
.pipe(delay(FETCH_LATENCY));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// #enddocregion
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!-- Exact copy from earlier app.component.html -->
|
<!-- Exact copy from earlier app.component.html -->
|
||||||
<h1 highlight>{{title}} {{subtitle}}</h1>
|
<h1 highlight>{{title}}</h1>
|
||||||
<p *ngIf="user">
|
<p *ngIf="user">
|
||||||
<i>Welcome, {{user}}</i>
|
<i>Welcome, {{user}}</i>
|
||||||
<p>
|
<p>
|
||||||
|
@ -7,7 +7,6 @@ import { UserService } from '../core/user.service';
|
|||||||
templateUrl: './title.component.html',
|
templateUrl: './title.component.html',
|
||||||
})
|
})
|
||||||
export class TitleComponent {
|
export class TitleComponent {
|
||||||
@Input() subtitle = '';
|
|
||||||
title = 'Angular Modules';
|
title = 'Angular Modules';
|
||||||
user = '';
|
user = '';
|
||||||
|
|
||||||
|
@ -1,22 +1,21 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
import { Crisis,
|
import { Crisis,
|
||||||
CrisisService } from './crisis.service';
|
CrisisService } from './crisis.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
<h3 highlight>Crisis List</h3>
|
<h3 highlight>Crisis List</h3>
|
||||||
<div *ngFor='let crisis of crisises | async'>
|
<div *ngFor='let crisis of crises | async'>
|
||||||
<a routerLink="{{'../' + crisis.id}}">{{crisis.id}} - {{crisis.name}}</a>
|
<a routerLink="{{'../' + crisis.id}}">{{crisis.id}} - {{crisis.name}}</a>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
export class CrisisListComponent implements OnInit {
|
export class CrisisListComponent {
|
||||||
crisises: Promise<Crisis[]>;
|
crises: Observable<Crisis[]>;
|
||||||
|
|
||||||
constructor(private crisisService: CrisisService) { }
|
constructor(private crisisService: CrisisService) {
|
||||||
|
this.crises = this.crisisService.getCrises();
|
||||||
ngOnInit() {
|
|
||||||
this.crisises = this.crisisService.getCrises();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable, OnDestroy } from '@angular/core';
|
||||||
|
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { of } from 'rxjs/observable/of';
|
||||||
|
import { delay } from 'rxjs/operators';
|
||||||
|
|
||||||
export class Crisis {
|
export class Crisis {
|
||||||
constructor(public id: number, public name: string) { }
|
constructor(public id: number, public name: string) { }
|
||||||
@ -13,18 +17,18 @@ const CRISES: Crisis[] = [
|
|||||||
|
|
||||||
const FETCH_LATENCY = 500;
|
const FETCH_LATENCY = 500;
|
||||||
|
|
||||||
|
/** Simulate a data service that retrieves crises from a server */
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CrisisService {
|
export class CrisisService implements OnDestroy {
|
||||||
|
constructor() { console.log('CrisisService instance created.'); }
|
||||||
|
ngOnDestroy() { console.log('CrisisService instance destroyed.'); }
|
||||||
|
|
||||||
getCrises() {
|
getCrises(): Observable<Crisis[]> {
|
||||||
return new Promise<Crisis[]>(resolve => {
|
return of(CRISES).pipe(delay(FETCH_LATENCY));
|
||||||
setTimeout(() => { resolve(CRISES); }, FETCH_LATENCY);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getCrisis(id: number | string) {
|
getCrisis(id: number | string): Observable<Crisis> {
|
||||||
return this.getCrises()
|
return of(CRISES.find(crisis => crisis.id === +id))
|
||||||
.then(heroes => heroes.find(hero => hero.id === +id));
|
.pipe(delay(FETCH_LATENCY));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,6 @@ export class HeroDetailComponent implements OnInit {
|
|||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
let id = parseInt(this.route.snapshot.paramMap.get('id'), 10);
|
let id = parseInt(this.route.snapshot.paramMap.get('id'), 10);
|
||||||
this.heroService.getHero(id).then(hero => this.hero = hero);
|
this.heroService.getHero(id).subscribe(hero => this.hero = hero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
import { Hero,
|
import { Hero,
|
||||||
HeroService } from './hero.service';
|
HeroService } from './hero.service';
|
||||||
@ -11,11 +12,9 @@ import { Hero,
|
|||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
export class HeroListComponent implements OnInit {
|
export class HeroListComponent {
|
||||||
heroes: Promise<Hero[]>;
|
heroes: Observable<Hero[]>;
|
||||||
constructor(private heroService: HeroService) { }
|
constructor(private heroService: HeroService) {
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.heroes = this.heroService.getHeroes();
|
this.heroes = this.heroService.getHeroes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,10 @@ import { FormsModule } from '@angular/forms';
|
|||||||
import { HeroComponent } from './hero.component.3';
|
import { HeroComponent } from './hero.component.3';
|
||||||
import { HeroDetailComponent } from './hero-detail.component';
|
import { HeroDetailComponent } from './hero-detail.component';
|
||||||
import { HeroListComponent } from './hero-list.component';
|
import { HeroListComponent } from './hero-list.component';
|
||||||
import { HighlightDirective } from './highlight.directive';
|
|
||||||
import { HeroRoutingModule } from './hero-routing.module.3';
|
import { HeroRoutingModule } from './hero-routing.module.3';
|
||||||
|
|
||||||
|
import { HighlightDirective } from './highlight.directive';
|
||||||
|
|
||||||
// #docregion class
|
// #docregion class
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [ CommonModule, FormsModule, HeroRoutingModule ],
|
imports: [ CommonModule, FormsModule, HeroRoutingModule ],
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable, OnDestroy } from '@angular/core';
|
||||||
|
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { of } from 'rxjs/observable/of';
|
||||||
|
import { delay } from 'rxjs/operators';
|
||||||
|
|
||||||
export class Hero {
|
export class Hero {
|
||||||
constructor(public id: number, public name: string) { }
|
constructor(public id: number, public name: string) { }
|
||||||
@ -15,18 +19,19 @@ const HEROES: Hero[] = [
|
|||||||
|
|
||||||
const FETCH_LATENCY = 500;
|
const FETCH_LATENCY = 500;
|
||||||
|
|
||||||
|
/** Simulate a data service that retrieves heroes from a server */
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class HeroService {
|
export class HeroService implements OnDestroy {
|
||||||
|
|
||||||
getHeroes() {
|
constructor() { console.log('HeroService instance created.'); }
|
||||||
return new Promise<Hero[]>(resolve => {
|
ngOnDestroy() { console.log('HeroService instance destroyed.'); }
|
||||||
setTimeout(() => { resolve(HEROES); }, FETCH_LATENCY);
|
|
||||||
});
|
getHeroes(): Observable<Hero[]> {
|
||||||
|
return of(HEROES).pipe(delay(FETCH_LATENCY));
|
||||||
}
|
}
|
||||||
|
|
||||||
getHero(id: number | string) {
|
getHero(id: number | string): Observable<Hero> {
|
||||||
return this.getHeroes()
|
return of(HEROES.find(hero => hero.id === +id))
|
||||||
.then(heroes => heroes.find(hero => hero.id === +id));
|
.pipe(delay(FETCH_LATENCY));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
|
// #docplaster
|
||||||
// #docregion
|
// #docregion
|
||||||
import { Directive, ElementRef } from '@angular/core';
|
import { Directive, ElementRef } from '@angular/core';
|
||||||
|
|
||||||
|
// Highlight the host element in gold
|
||||||
@Directive({ selector: '[highlight]' })
|
@Directive({ selector: '[highlight]' })
|
||||||
/** Highlight the attached element in gold */
|
|
||||||
export class HighlightDirective {
|
export class HighlightDirective {
|
||||||
constructor(el: ElementRef) {
|
constructor(el: ElementRef) {
|
||||||
el.nativeElement.style.backgroundColor = 'gold';
|
el.nativeElement.style.backgroundColor = 'gold';
|
||||||
console.log(
|
// #enddocregion
|
||||||
`* AppRoot highlight called for ${el.nativeElement.tagName}`);
|
console.log(`* AppRoot highlight called for ${el.nativeElement.tagName}`);
|
||||||
|
// #docregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// #enddocregion
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
/* tslint:disable */
|
|
||||||
// Exact copy of contact/highlight.directive except for color and message
|
// Exact copy of contact/highlight.directive except for color and message
|
||||||
import { Directive, ElementRef } from '@angular/core';
|
import { Directive, ElementRef } from '@angular/core';
|
||||||
|
|
||||||
@Directive({ selector: '[highlight], input' })
|
@Directive({ selector: '[highlight], input' })
|
||||||
/** Highlight the attached element or an InputElement in gray */
|
// Highlight the host element or any InputElement in gray
|
||||||
export class HighlightDirective {
|
export class HighlightDirective {
|
||||||
constructor(el: ElementRef) {
|
constructor(el: ElementRef) {
|
||||||
el.nativeElement.style.backgroundColor = 'lightgray';
|
el.nativeElement.style.backgroundColor = 'lightgray';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<!-- #docregion -->
|
<!-- #docregion -->
|
||||||
<!-- #docregion v1 -->
|
<!-- #docregion v1 -->
|
||||||
<h1 highlight>{{title}} {{subtitle}}</h1>
|
<h1 highlight>{{title}}</h1>
|
||||||
<!-- #enddocregion v1 -->
|
<!-- #enddocregion v1 -->
|
||||||
<!-- #docregion ngIf -->
|
<!-- #docregion ngIf -->
|
||||||
<p *ngIf="user">
|
<p *ngIf="user">
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion
|
// #docregion
|
||||||
// #docregion v1
|
// #docregion v1
|
||||||
import { Component, Input } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
// #enddocregion v1
|
// #enddocregion v1
|
||||||
import { UserService } from './user.service';
|
import { UserService } from './user.service';
|
||||||
// #docregion v1
|
// #docregion v1
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-title',
|
selector: 'app-title',
|
||||||
templateUrl: './title.component.html',
|
templateUrl: './title.component.html'
|
||||||
})
|
})
|
||||||
export class TitleComponent {
|
export class TitleComponent {
|
||||||
@Input() subtitle = '';
|
title = 'Angular Modules';
|
||||||
title = 'NgModules';
|
|
||||||
// #enddocregion v1
|
// #enddocregion v1
|
||||||
user = '';
|
user = '';
|
||||||
|
|
||||||
|
@ -5,17 +5,6 @@
|
|||||||
<title>NgModule Minimal</title>
|
<title>NgModule Minimal</title>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="stylesheet" href="styles.css">
|
|
||||||
|
|
||||||
<!-- Polyfills -->
|
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
|
||||||
|
|
||||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
|
||||||
<script src="systemjs.config.js"></script>
|
|
||||||
<script>
|
|
||||||
System.import('main.0.js').catch(function(err){ console.error(err); });
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -5,17 +5,6 @@
|
|||||||
<title>NgModule Minimal</title>
|
<title>NgModule Minimal</title>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="stylesheet" href="styles.css">
|
|
||||||
|
|
||||||
<!-- Polyfills -->
|
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
|
||||||
|
|
||||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
|
||||||
<script src="systemjs.config.js"></script>
|
|
||||||
<script>
|
|
||||||
System.import('main.1.js').catch(function(err){ console.error(err); });
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -5,17 +5,6 @@
|
|||||||
<title>NgModule Minimal</title>
|
<title>NgModule Minimal</title>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="stylesheet" href="styles.css">
|
|
||||||
|
|
||||||
<!-- Polyfills -->
|
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
|
||||||
|
|
||||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
|
||||||
<script src="systemjs.config.js"></script>
|
|
||||||
<script>
|
|
||||||
System.import('main.1b.js').catch(function(err){ console.error(err); });
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -5,17 +5,6 @@
|
|||||||
<title>NgModule Minimal</title>
|
<title>NgModule Minimal</title>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="stylesheet" href="styles.css">
|
|
||||||
|
|
||||||
<!-- Polyfills -->
|
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
|
||||||
|
|
||||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
|
||||||
<script src="systemjs.config.js"></script>
|
|
||||||
<script>
|
|
||||||
System.import('main.2.js').catch(function(err){ console.error(err); });
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -5,17 +5,6 @@
|
|||||||
<title>NgModule Minimal</title>
|
<title>NgModule Minimal</title>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="stylesheet" href="styles.css">
|
|
||||||
|
|
||||||
<!-- Polyfills -->
|
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
|
||||||
|
|
||||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
|
||||||
<script src="systemjs.config.js"></script>
|
|
||||||
<script>
|
|
||||||
System.import('main.3.js').catch(function(err){ console.error(err); });
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -5,13 +5,17 @@
|
|||||||
"styles.css",
|
"styles.css",
|
||||||
|
|
||||||
"app/app.component.ts",
|
"app/app.component.ts",
|
||||||
|
"app/app.component.html",
|
||||||
|
"app/app.component.css",
|
||||||
"app/app.module.ts",
|
"app/app.module.ts",
|
||||||
"app/data-model.ts",
|
"app/data-model.ts",
|
||||||
"app/hero.service.ts",
|
"app/hero.service.ts",
|
||||||
"app/hero-detail.component.html",
|
"app/hero-detail/hero-detail.component.html",
|
||||||
"app/hero-detail.component.ts",
|
"app/hero-detail/hero-detail.component.ts",
|
||||||
"app/hero-list.component.html",
|
"app/hero-detail/hero-detail.component.css",
|
||||||
"app/hero-list.component.ts",
|
"app/hero-list/hero-list.component.html",
|
||||||
|
"app/hero-list/hero-list.component.ts",
|
||||||
|
"app/hero-list/hero-list.component.css",
|
||||||
|
|
||||||
"main-final.ts",
|
"main-final.ts",
|
||||||
"index-final.html"
|
"index-final.html"
|
||||||
|
@ -6,18 +6,6 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="stylesheet" href="https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css">
|
<link rel="stylesheet" href="https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css">
|
||||||
<link rel="stylesheet" href="styles.css">
|
|
||||||
|
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
|
||||||
|
|
||||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
|
||||||
<script src="node_modules/reflect-metadata/Reflect.js"></script>
|
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
|
||||||
|
|
||||||
<script src="systemjs.config.js"></script>
|
|
||||||
<script>
|
|
||||||
System.import('main-final.js').catch(function(err){ console.error(err); });
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
44
aio/content/examples/service-worker-getting-started/e2e/app.e2e-spec.ts
Executable file
44
aio/content/examples/service-worker-getting-started/e2e/app.e2e-spec.ts
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
import { AppPage } from './app.po';
|
||||||
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
|
|
||||||
|
describe('sw-example App', () => {
|
||||||
|
let page: AppPage;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
page = new AppPage();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display welcome message', () => {
|
||||||
|
page.navigateTo();
|
||||||
|
expect(page.getParagraphText()).toEqual('Welcome to Service Workers!');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display the Angular logo', () => {
|
||||||
|
let logo = element(by.css('img'));
|
||||||
|
page.navigateTo();
|
||||||
|
expect(logo.isPresent()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show a header for the list of links', () => {
|
||||||
|
const listHeader = element(by.css('app-root > h2'));
|
||||||
|
expect(listHeader.getText()).toEqual('Here are some links to help you start:');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show a list of links', function () {
|
||||||
|
element.all(by.css('ul > li > h2 > a')).then((items) => {
|
||||||
|
expect(items.length).toBe(4);
|
||||||
|
expect(items[0].getText()).toBe('Angular Service Worker Intro');
|
||||||
|
expect(items[1].getText()).toBe('Tour of Heroes');
|
||||||
|
expect(items[2].getText()).toBe('CLI Documentation');
|
||||||
|
expect(items[3].getText()).toBe('Angular blog');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// Check for a rejected promise as the service worker is not enabled
|
||||||
|
it('SwUpdate.checkForUpdate() should return a rejected promise', () => {
|
||||||
|
const button = element(by.css('button'));
|
||||||
|
const rejectMessage = element(by.css('p'));
|
||||||
|
button.click();
|
||||||
|
expect(rejectMessage.getText()).toContain('rejected: ');
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"name": "angular.io-example",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"ng": "ng",
|
||||||
|
"start": "ng serve",
|
||||||
|
"build": "ng build",
|
||||||
|
"test": "ng test",
|
||||||
|
"lint": "ng lint",
|
||||||
|
"e2e": "ng e2e"
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@angular/animations": "^5.0.0",
|
||||||
|
"@angular/common": "^5.0.0",
|
||||||
|
"@angular/compiler": "^5.0.0",
|
||||||
|
"@angular/core": "^5.0.0",
|
||||||
|
"@angular/forms": "^5.0.0",
|
||||||
|
"@angular/http": "^5.0.0",
|
||||||
|
"@angular/service-worker": "^5.0.0",
|
||||||
|
"@angular/platform-browser": "^5.0.0",
|
||||||
|
"@angular/platform-browser-dynamic": "^5.0.0",
|
||||||
|
"@angular/router": "^5.0.0",
|
||||||
|
"core-js": "^2.4.1",
|
||||||
|
"rxjs": "^5.5.2",
|
||||||
|
"zone.js": "^0.8.14"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@angular/cli": "1.5.4",
|
||||||
|
"@angular/compiler-cli": "^5.0.0",
|
||||||
|
"@angular/language-service": "^5.0.0",
|
||||||
|
"@types/jasmine": "~2.5.53",
|
||||||
|
"@types/jasminewd2": "~2.0.2",
|
||||||
|
"@types/node": "~6.0.60",
|
||||||
|
"codelyzer": "^4.0.1",
|
||||||
|
"jasmine-core": "~2.6.2",
|
||||||
|
"jasmine-spec-reporter": "~4.1.0",
|
||||||
|
"karma": "~1.7.0",
|
||||||
|
"karma-chrome-launcher": "~2.1.1",
|
||||||
|
"karma-cli": "~1.0.1",
|
||||||
|
"karma-coverage-istanbul-reporter": "^1.2.1",
|
||||||
|
"karma-jasmine": "~1.1.0",
|
||||||
|
"karma-jasmine-html-reporter": "^0.2.2",
|
||||||
|
"protractor": "~5.1.2",
|
||||||
|
"ts-node": "~3.2.0",
|
||||||
|
"tslint": "~5.7.0",
|
||||||
|
"typescript": "~2.4.2"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"description": "Service Worker",
|
||||||
|
"basePath": "src/",
|
||||||
|
"tags": ["service worker"]
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
<!--The content below is only a placeholder and can be replaced.-->
|
||||||
|
<div style="text-align:center">
|
||||||
|
<h1>
|
||||||
|
Welcome to {{title}}!
|
||||||
|
</h1>
|
||||||
|
<img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button id="check" (click)="updateCheck()">Check for Update</button>
|
||||||
|
<p id="checkResult">{{updateCheckText}}</p>
|
||||||
|
|
||||||
|
<h2>Here are some links to help you start: </h2>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<h2><a target="_blank" rel="noopener" href="https://angular.io/service-worker-intro">Angular Service Worker Intro</a></h2>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
@ -0,0 +1,27 @@
|
|||||||
|
import { TestBed, async } from '@angular/core/testing';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
describe('AppComponent', () => {
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [
|
||||||
|
AppComponent
|
||||||
|
],
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
it('should create the app', async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.debugElement.componentInstance;
|
||||||
|
expect(app).toBeTruthy();
|
||||||
|
}));
|
||||||
|
it(`should have as title 'app'`, async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.debugElement.componentInstance;
|
||||||
|
expect(app.title).toEqual('Service Workers');
|
||||||
|
}));
|
||||||
|
it('should render title in a h1 tag', async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
const compiled = fixture.debugElement.nativeElement;
|
||||||
|
expect(compiled.querySelector('h1').textContent).toContain('Welcome to Service Workers!');
|
||||||
|
}));
|
||||||
|
});
|
20
aio/content/examples/service-worker-getting-started/src/app/app.component.ts
Executable file
20
aio/content/examples/service-worker-getting-started/src/app/app.component.ts
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { SwUpdate } from '@angular/service-worker';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html'
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
title = 'Service Workers';
|
||||||
|
updateCheckText = '';
|
||||||
|
|
||||||
|
constructor(private update: SwUpdate) {}
|
||||||
|
|
||||||
|
updateCheck(): void {
|
||||||
|
this.update
|
||||||
|
.checkForUpdate()
|
||||||
|
.then(() => this.updateCheckText = 'resolved')
|
||||||
|
.catch(err => this.updateCheckText = `rejected: ${err.message}`);
|
||||||
|
}
|
||||||
|
}
|
31
aio/content/examples/service-worker-getting-started/src/app/app.module.ts
Executable file
31
aio/content/examples/service-worker-getting-started/src/app/app.module.ts
Executable file
@ -0,0 +1,31 @@
|
|||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
|
// #docregion sw-import
|
||||||
|
import { ServiceWorkerModule } from '@angular/service-worker';
|
||||||
|
import { environment } from '../environments/environment';
|
||||||
|
// #enddocregion sw-import
|
||||||
|
|
||||||
|
import { CheckForUpdateService } from './check-for-update.service';
|
||||||
|
import { LogUpdateService } from './log-update.service';
|
||||||
|
import { PromptUpdateService } from './prompt-update.service';
|
||||||
|
|
||||||
|
// #docregion sw-module
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
AppComponent
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
BrowserModule,
|
||||||
|
ServiceWorkerModule.register('/ngsw-worker.js', {enabled: environment.production})
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
CheckForUpdateService,
|
||||||
|
LogUpdateService,
|
||||||
|
PromptUpdateService,
|
||||||
|
],
|
||||||
|
bootstrap: [AppComponent]
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
||||||
|
// #enddocregion sw-module
|
@ -0,0 +1,15 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { SwUpdate } from '@angular/service-worker';
|
||||||
|
|
||||||
|
|
||||||
|
// #docregion sw-check-update
|
||||||
|
import { interval } from 'rxjs/observable/interval';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CheckForUpdateService {
|
||||||
|
|
||||||
|
constructor(updates: SwUpdate) {
|
||||||
|
interval(6 * 60 * 60).subscribe(() => updates.checkForUpdate());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion sw-check-update
|
@ -0,0 +1,19 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { SwUpdate } from '@angular/service-worker';
|
||||||
|
|
||||||
|
// #docregion sw-update
|
||||||
|
@Injectable()
|
||||||
|
export class LogUpdateService {
|
||||||
|
|
||||||
|
constructor(updates: SwUpdate) {
|
||||||
|
updates.available.subscribe(event => {
|
||||||
|
console.log('current version is', event.current);
|
||||||
|
console.log('available version is', event.available);
|
||||||
|
});
|
||||||
|
updates.activated.subscribe(event => {
|
||||||
|
console.log('old version was', event.previous);
|
||||||
|
console.log('new version is', event.current);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion sw-update
|
@ -0,0 +1,20 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { SwUpdate } from '@angular/service-worker';
|
||||||
|
|
||||||
|
function promptUser(event): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #docregion sw-activate
|
||||||
|
@Injectable()
|
||||||
|
export class PromptUpdateService {
|
||||||
|
|
||||||
|
constructor(updates: SwUpdate) {
|
||||||
|
updates.available.subscribe(event => {
|
||||||
|
if (promptUser(event)) {
|
||||||
|
updates.activateUpdate().then(() => document.location.reload());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion sw-activate
|
12
aio/content/examples/service-worker-getting-started/src/index.html
Executable file
12
aio/content/examples/service-worker-getting-started/src/index.html
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>SwExample</title>
|
||||||
|
<base href="/">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<app-root></app-root>
|
||||||
|
</body>
|
||||||
|
</html>
|
12
aio/content/examples/service-worker-getting-started/src/main.ts
Executable file
12
aio/content/examples/service-worker-getting-started/src/main.ts
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
import { enableProdMode } from '@angular/core';
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
|
||||||
|
import { AppModule } from './app/app.module';
|
||||||
|
import { environment } from './environments/environment';
|
||||||
|
|
||||||
|
if (environment.production) {
|
||||||
|
enableProdMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
platformBrowserDynamic().bootstrapModule(AppModule)
|
||||||
|
.catch(err => console.log(err));
|
28
aio/content/examples/service-worker-getting-started/src/ngsw-config.json
Executable file
28
aio/content/examples/service-worker-getting-started/src/ngsw-config.json
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
{
|
||||||
|
"index": "/index.html",
|
||||||
|
"assetGroups": [{
|
||||||
|
"name": "app",
|
||||||
|
"installMode": "prefetch",
|
||||||
|
"resources": {
|
||||||
|
"files": [
|
||||||
|
"/favicon.ico",
|
||||||
|
"/index.html"
|
||||||
|
],
|
||||||
|
"versionedFiles": [
|
||||||
|
"/*.bundle.css",
|
||||||
|
"/*.bundle.js",
|
||||||
|
"/*.chunk.js"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"name": "assets",
|
||||||
|
"installMode": "lazy",
|
||||||
|
"updateMode": "prefetch",
|
||||||
|
"resources": {
|
||||||
|
"files": [
|
||||||
|
"/assets/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
@ -37,7 +37,7 @@ describe('Structural Directives', function () {
|
|||||||
expect(paragraph.count()).toEqual(1);
|
expect(paragraph.count()).toEqual(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('myUnless should show 3 paragraph (A)s and (B)s at the start', function () {
|
it('appUnless should show 3 paragraph (A)s and (B)s at the start', function () {
|
||||||
const paragraph = element.all(by.css('p.unless'));
|
const paragraph = element.all(by.css('p.unless'));
|
||||||
expect(paragraph.count()).toEqual(3);
|
expect(paragraph.count()).toEqual(3);
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
@ -45,7 +45,7 @@ describe('Structural Directives', function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('myUnless should show 1 paragraph (B) after toggling condition', function () {
|
it('appUnless should show 1 paragraph (B) after toggling condition', function () {
|
||||||
const toggleConditionButton = element.all(by.cssContainingText('button', 'Toggle condition')).get(0);
|
const toggleConditionButton = element.all(by.cssContainingText('button', 'Toggle condition')).get(0);
|
||||||
const paragraph = element.all(by.css('p.unless'));
|
const paragraph = element.all(by.css('p.unless'));
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<!-- #docregion built-in, asterisk, ngif -->
|
<!-- #docregion built-in, asterisk, ngif -->
|
||||||
<div *ngIf="hero" >{{hero.name}}</div>
|
<div *ngIf="hero" class="name">{{hero.name}}</div>
|
||||||
<!-- #enddocregion built-in, asterisk, ngif -->
|
<!-- #enddocregion built-in, asterisk, ngif -->
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
@ -51,7 +51,7 @@
|
|||||||
<p><ng-template> element</p>
|
<p><ng-template> element</p>
|
||||||
<!-- #docregion ngif-template -->
|
<!-- #docregion ngif-template -->
|
||||||
<ng-template [ngIf]="hero">
|
<ng-template [ngIf]="hero">
|
||||||
<div>{{hero.name}}</div>
|
<div class="name">{{hero.name}}</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<!-- #enddocregion ngif-template -->
|
<!-- #enddocregion ngif-template -->
|
||||||
|
|
||||||
@ -188,7 +188,7 @@
|
|||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<h2 id="myUnless">UnlessDirective</h2>
|
<h2 id="appUnless">UnlessDirective</h2>
|
||||||
<p>
|
<p>
|
||||||
The condition is currently
|
The condition is currently
|
||||||
<span [ngClass]="{ 'a': !condition, 'b': condition, 'unless': true }">{{condition}}</span>.
|
<span [ngClass]="{ 'a': !condition, 'b': condition, 'unless': true }">{{condition}}</span>.
|
||||||
@ -198,31 +198,31 @@
|
|||||||
Toggle condition to {{condition ? 'false' : 'true'}}
|
Toggle condition to {{condition ? 'false' : 'true'}}
|
||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
<!-- #docregion myUnless-->
|
<!-- #docregion appUnless-->
|
||||||
<p *appUnless="condition" class="unless a">
|
<p *appUnless="condition" class="unless a">
|
||||||
(A) This paragraph is displayed because the condition is false.
|
(A) This paragraph is displayed because the condition is false.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p *appUnless="!condition" class="unless b">
|
<p *appUnless="!condition" class="unless b">
|
||||||
(B) Although the condition is true,
|
(B) Although the condition is true,
|
||||||
this paragraph is displayed because myUnless is set to false.
|
this paragraph is displayed because appUnless is set to false.
|
||||||
</p>
|
</p>
|
||||||
<!-- #enddocregion myUnless-->
|
<!-- #enddocregion appUnless-->
|
||||||
|
|
||||||
|
|
||||||
<h4>UnlessDirective with template</h4>
|
<h4>UnlessDirective with template</h4>
|
||||||
|
|
||||||
<!-- #docregion myUnless-1 -->
|
<!-- #docregion appUnless-1 -->
|
||||||
<p *appUnless="condition">Show this sentence unless the condition is true.</p>
|
<p *appUnless="condition">Show this sentence unless the condition is true.</p>
|
||||||
<!-- #enddocregion myUnless-1 -->
|
<!-- #enddocregion appUnless-1 -->
|
||||||
|
|
||||||
<p *appUnless="condition" class="code unless">
|
<p *appUnless="condition" class="code unless">
|
||||||
(A) <p *myUnless="condition" class="code unless">
|
(A) <p *appUnless="condition" class="code unless">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ng-template [appUnless]="condition">
|
<ng-template [appUnless]="condition">
|
||||||
<p class="code unless">
|
<p class="code unless">
|
||||||
(A) <ng-template [myUnless]="condition">
|
(A) <ng-template [appUnless]="condition">
|
||||||
</p>
|
</p>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
|
|||||||
* Add the template content to the DOM unless the condition is true.
|
* Add the template content to the DOM unless the condition is true.
|
||||||
// #enddocregion no-docs
|
// #enddocregion no-docs
|
||||||
*
|
*
|
||||||
* If the expression assigned to `myUnless` evaluates to a truthy value
|
* If the expression assigned to `appUnless` evaluates to a truthy value
|
||||||
* then the templated elements are removed removed from the DOM,
|
* then the templated elements are removed removed from the DOM,
|
||||||
* the templated elements are (re)inserted into the DOM.
|
* the templated elements are (re)inserted into the DOM.
|
||||||
*
|
*
|
||||||
@ -18,8 +18,8 @@ import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
|
|||||||
*
|
*
|
||||||
* ### Syntax
|
* ### Syntax
|
||||||
*
|
*
|
||||||
* - `<div *myUnless="condition">...</div>`
|
* - `<div *appUnless="condition">...</div>`
|
||||||
* - `<ng-template [myUnless]="condition"><div>...</div></ng-template>`
|
* - `<ng-template [appUnless]="condition"><div>...</div></ng-template>`
|
||||||
*
|
*
|
||||||
// #docregion no-docs
|
// #docregion no-docs
|
||||||
*/
|
*/
|
||||||
|
@ -9,6 +9,6 @@ export class MessageService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
this.messages.length = 0;
|
this.messages = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,6 @@ export class MessageService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
this.messages.length = 0;
|
this.messages = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,6 @@ export class MessageService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
this.messages.length = 0;
|
this.messages = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,6 @@ export class MessageService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
this.messages.length = 0;
|
this.messages = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
The Angular Ahead-of-Time (AOT) compiler converts your Angular HTML and TypeScript code into efficient JavaScript code during the build phase _before_ the browser downloads and runs that code.
|
The Angular Ahead-of-Time (AOT) compiler converts your Angular HTML and TypeScript code into efficient JavaScript code during the build phase _before_ the browser downloads and runs that code.
|
||||||
|
|
||||||
This guide explains how to to build with the AOT compiler and how to write Angular metadata that AOT can compile.
|
This guide explains how to build with the AOT compiler and how to write Angular metadata that AOT can compile.
|
||||||
|
|
||||||
<div class="l-sub-section">
|
<div class="l-sub-section">
|
||||||
|
|
||||||
@ -409,7 +409,7 @@ function; it can only contain a single `return` statement.
|
|||||||
|
|
||||||
The Angular [`RouterModule`](api/router/RouterModule) exports two macro static methods, `forRoot` and `forChild`, to help declare root and child routes.
|
The Angular [`RouterModule`](api/router/RouterModule) exports two macro static methods, `forRoot` and `forChild`, to help declare root and child routes.
|
||||||
Review the [source code](https://github.com/angular/angular/blob/master/packages/router/src/router_module.ts#L139 "RouterModule.forRoot source code")
|
Review the [source code](https://github.com/angular/angular/blob/master/packages/router/src/router_module.ts#L139 "RouterModule.forRoot source code")
|
||||||
for these methods to see how macros can simplify configuration of complex Angular modules.
|
for these methods to see how macros can simplify configuration of complex [NgModules](guide/ngmodule).
|
||||||
|
|
||||||
### Metadata rewriting
|
### Metadata rewriting
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ to a component's `@Component` decorator:
|
|||||||
<code-tabs>
|
<code-tabs>
|
||||||
<code-pane title="src/app/hero-app.component.ts (CSS in file)" path="component-styles/src/app/hero-app.component.1.ts"></code-pane>
|
<code-pane title="src/app/hero-app.component.ts (CSS in file)" path="component-styles/src/app/hero-app.component.1.ts"></code-pane>
|
||||||
<code-pane title="src/app/hero-app.component.css" path="component-styles/src/app/hero-app.component.1.css"></code-pane>
|
<code-pane title="src/app/hero-app.component.css" path="component-styles/src/app/hero-app.component.1.css"></code-pane>
|
||||||
</code-tabs>
|
</code-tabs>
|
||||||
|
|
||||||
<div class="alert is-critical">
|
<div class="alert is-critical">
|
||||||
|
|
||||||
@ -245,7 +245,8 @@ See the [CLI documentation](https://github.com/angular/angular-cli/wiki/stories-
|
|||||||
|
|
||||||
### Non-CSS style files
|
### Non-CSS style files
|
||||||
|
|
||||||
You can write style files in [sass](http://sass-lang.com/), [less](http://lesscss.org/), or [stylus](http://stylus-lang.com/) and specify those files in the `styleUrls` metadata, e.g.,
|
If you're building with the CLI,
|
||||||
|
you can write style files in [sass](http://sass-lang.com/), [less](http://lesscss.org/), or [stylus](http://stylus-lang.com/) and specify those files in the `@Component.styleUrls` metadata with the appropriate extensions (`.scss`, `.less`, `.styl`) as in the following example:
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
@Component({
|
@Component({
|
||||||
@ -256,10 +257,18 @@ You can write style files in [sass](http://sass-lang.com/), [less](http://lesscs
|
|||||||
...
|
...
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
The CLI build process runs the corresponding CSS pre-processors.
|
The CLI build process runs the pertinent CSS preprocessor.
|
||||||
|
|
||||||
You can also configure the CLI to default to your preferred CSS pre-processer
|
When generating a component file with `ng generate component`, the CLI emits an empty CSS styles file (`.css`) by default.
|
||||||
as explained in the [CLI documentation](https://github.com/angular/angular-cli/wiki/stories-css-preprocessors).
|
You can configure the CLI to default to your preferred CSS preprocessor
|
||||||
|
as explained in the [CLI documentation](https://github.com/angular/angular-cli/wiki/stories-css-preprocessors
|
||||||
|
"CSS Preprocessor integration").
|
||||||
|
|
||||||
|
<div class="alert is-important">
|
||||||
|
|
||||||
|
Style strings added to the `@Component.styles` array _must be written in CSS_ because the CLI cannot apply a preprocessor to inline styles.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
{@a view-encapsulation}
|
{@a view-encapsulation}
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ Providing the `UserService` with an Angular module is a good choice.
|
|||||||
<div class="l-sub-section">
|
<div class="l-sub-section">
|
||||||
|
|
||||||
To be precise, Angular module providers are registered with the root injector
|
To be precise, Angular module providers are registered with the root injector
|
||||||
_unless the module is_ [lazy loaded](guide/ngmodule#lazy-load).
|
_unless the module is_ [lazy loaded](guide/ngmodule#lazy-load-DI).
|
||||||
In this sample, all modules are _eagerly loaded_ when the application starts,
|
In this sample, all modules are _eagerly loaded_ when the application starts,
|
||||||
so all module providers are registered with the app's root injector.
|
so all module providers are registered with the app's root injector.
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ See the <live-example downloadOnly name="i18n">i18n Example</live-example> for a
|
|||||||
an AOT-compiled app, translated into French.
|
an AOT-compiled app, translated into French.
|
||||||
|
|
||||||
{@a angular-i18n}
|
{@a angular-i18n}
|
||||||
|
|
||||||
## Angular and i18n
|
## Angular and i18n
|
||||||
|
|
||||||
Angular simplifies the following aspects of internationalization:
|
Angular simplifies the following aspects of internationalization:
|
||||||
@ -62,6 +61,23 @@ For more information about Unicode locale identifiers, see the
|
|||||||
For a complete list of locales supported by Angular, see
|
For a complete list of locales supported by Angular, see
|
||||||
[the Angular repository](https://github.com/angular/angular/tree/master/packages/common/locales).
|
[the Angular repository](https://github.com/angular/angular/tree/master/packages/common/locales).
|
||||||
|
|
||||||
|
The locale identifiers used by CLDR and Angular are based on [BCP47](http://www.rfc-editor.org/rfc/bcp/bcp47.txt).
|
||||||
|
These specifications change over time; the following table maps previous identifiers to current ones at
|
||||||
|
time of writing:
|
||||||
|
|
||||||
|
| Locale name | Old locale id | New locale id |
|
||||||
|
|-------------------------------|-------------------|---------------|
|
||||||
|
| Indonesian | in | id |
|
||||||
|
| Hebrew | iw | he |
|
||||||
|
| Romanian Moldova | mo | ro-MD |
|
||||||
|
| Norwegian Bokmål | no, no-NO | nb |
|
||||||
|
| Serbian Latin | sh | sr-Latn |
|
||||||
|
| Filipino | tl | fil |
|
||||||
|
| Portuguese Brazil | pt-BR | pt |
|
||||||
|
| Chinese Simplified | zh-cn, zh-Hans-CN | zh-Hans |
|
||||||
|
| Chinese Traditional | zh-tw, zh-Hant-TW | zh-Hant |
|
||||||
|
| Chinese Traditional Hong Kong | zh-hk | zh-Hant-HK |
|
||||||
|
|
||||||
|
|
||||||
## i18n pipes
|
## i18n pipes
|
||||||
|
|
||||||
@ -78,6 +94,14 @@ If you want to import locale data for other languages, you can do it manually:
|
|||||||
<code-example path="i18n/doc-files/app.locale_data.ts" region="import-locale" title="src/app/app.module.ts" linenums="false">
|
<code-example path="i18n/doc-files/app.locale_data.ts" region="import-locale" title="src/app/app.module.ts" linenums="false">
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
The first parameter is an object containing the locale data imported from `@angular/common/locales`.
|
||||||
|
By default, the imported locale data is registered with the locale id that is defined in the Angular
|
||||||
|
locale data itself.
|
||||||
|
If you want to register the imported locale data with another locale id, use the second parameter to
|
||||||
|
specify a custom locale id. For example, Angular's locale data defines the locale id for French as
|
||||||
|
"fr". You can use the second parameter to associate the imported French locale data with the custom
|
||||||
|
locale id "fr-FR" instead of "fr".
|
||||||
|
|
||||||
The files in `@angular/common/locales` contain most of the locale data that you
|
The files in `@angular/common/locales` contain most of the locale data that you
|
||||||
need, but some advanced formatting options might only be available in the extra dataset that you can
|
need, but some advanced formatting options might only be available in the extra dataset that you can
|
||||||
import from `@angular/common/locales/extra`. An error message informs you when this is the case.
|
import from `@angular/common/locales/extra`. An error message informs you when this is the case.
|
||||||
@ -118,7 +142,6 @@ in the target language.
|
|||||||
You need to build and deploy a separate version of the app for each supported language.
|
You need to build and deploy a separate version of the app for each supported language.
|
||||||
|
|
||||||
{@a i18n-attribute}
|
{@a i18n-attribute}
|
||||||
|
|
||||||
### Mark text with the i18n attribute
|
### Mark text with the i18n attribute
|
||||||
|
|
||||||
The Angular `i18n` attribute marks translatable content. Place it on every element tag whose fixed
|
The Angular `i18n` attribute marks translatable content. Place it on every element tag whose fixed
|
||||||
@ -144,7 +167,6 @@ To mark the greeting for translation, add the `i18n` attribute to the `<h1>` tag
|
|||||||
|
|
||||||
|
|
||||||
{@a help-translator}
|
{@a help-translator}
|
||||||
|
|
||||||
### Help the translator with a description and meaning
|
### Help the translator with a description and meaning
|
||||||
|
|
||||||
To translate a text message accurately, the translator may need additional information or context.
|
To translate a text message accurately, the translator may need additional information or context.
|
||||||
@ -175,7 +197,6 @@ text messages with different descriptions (not different meanings), then they ar
|
|||||||
|
|
||||||
|
|
||||||
{@a custom-id}
|
{@a custom-id}
|
||||||
|
|
||||||
### Set a custom id for persistence and maintenance
|
### Set a custom id for persistence and maintenance
|
||||||
|
|
||||||
The angular i18n extractor tool generates a file with a translation unit entry for each `i18n`
|
The angular i18n extractor tool generates a file with a translation unit entry for each `i18n`
|
||||||
@ -250,7 +271,6 @@ the same text, `Bonjour`:
|
|||||||
|
|
||||||
|
|
||||||
{@a no-element}
|
{@a no-element}
|
||||||
|
|
||||||
### Translate text without creating an element
|
### Translate text without creating an element
|
||||||
|
|
||||||
If there is a section of text that you would like to translate, you can wrap it in a `<span>` tag.
|
If there is a section of text that you would like to translate, you can wrap it in a `<span>` tag.
|
||||||
@ -262,7 +282,6 @@ The `<ng-container>` is transformed into an html comment:
|
|||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
{@a translate-attributes}
|
{@a translate-attributes}
|
||||||
|
|
||||||
## Add i18n translation attributes
|
## Add i18n translation attributes
|
||||||
|
|
||||||
You also can translate attributes.
|
You also can translate attributes.
|
||||||
@ -286,7 +305,6 @@ You also can assign a meaning, description, and id with the `i18n-x="<meaning>|<
|
|||||||
syntax.
|
syntax.
|
||||||
|
|
||||||
{@a plural-ICU}
|
{@a plural-ICU}
|
||||||
|
|
||||||
## Translate singular and plural
|
## Translate singular and plural
|
||||||
|
|
||||||
Different languages have different pluralization rules.
|
Different languages have different pluralization rules.
|
||||||
@ -342,7 +360,6 @@ for two, three, or any other number if the pluralization rules were different. F
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{@a select-ICU}
|
{@a select-ICU}
|
||||||
|
|
||||||
## Select among alternative text messages
|
## Select among alternative text messages
|
||||||
|
|
||||||
If your template needs to display different text messages depending on the value of a variable, you
|
If your template needs to display different text messages depending on the value of a variable, you
|
||||||
@ -360,7 +377,6 @@ The message maps those values to the appropriate translations:
|
|||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
{@a nesting-ICUS}
|
{@a nesting-ICUS}
|
||||||
|
|
||||||
## Nesting plural and select ICU expressions
|
## Nesting plural and select ICU expressions
|
||||||
|
|
||||||
You can also nest different ICU expressions together, as shown in this example:
|
You can also nest different ICU expressions together, as shown in this example:
|
||||||
@ -369,7 +385,6 @@ You can also nest different ICU expressions together, as shown in this example:
|
|||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
{@a ng-xi18n}
|
{@a ng-xi18n}
|
||||||
|
|
||||||
## Create a translation source file with _ng xi18n_
|
## Create a translation source file with _ng xi18n_
|
||||||
|
|
||||||
Use the `ng xi18n` command provided by the CLI to extract the text messages marked with `i18n` into
|
Use the `ng xi18n` command provided by the CLI to extract the text messages marked with `i18n` into
|
||||||
@ -394,7 +409,6 @@ package, or you can manually use the CLI Webpack plugin `ExtractI18nPlugin` from
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{@a other-formats}
|
{@a other-formats}
|
||||||
|
|
||||||
### Other translation formats
|
### Other translation formats
|
||||||
|
|
||||||
Angular i18n tooling supports three translation formats:
|
Angular i18n tooling supports three translation formats:
|
||||||
@ -422,7 +436,6 @@ The sample in this guide uses the default XLIFF 1.2 format.
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{@a ng-xi18n-options}
|
{@a ng-xi18n-options}
|
||||||
|
|
||||||
### Other options
|
### Other options
|
||||||
|
|
||||||
You can specify the output path used by the CLI to extract your translation source file with
|
You can specify the output path used by the CLI to extract your translation source file with
|
||||||
@ -456,7 +469,6 @@ file. This information is not used by Angular, but external translation tools ma
|
|||||||
|
|
||||||
|
|
||||||
{@a translate}
|
{@a translate}
|
||||||
|
|
||||||
## Translate text messages
|
## Translate text messages
|
||||||
|
|
||||||
The `ng xi18n` command generates a translation source file named `messages.xlf` in the project `src`
|
The `ng xi18n` command generates a translation source file named `messages.xlf` in the project `src`
|
||||||
@ -466,7 +478,6 @@ The next step is to translate this source file into the specific language
|
|||||||
translation files. The example in this guide creates a French translation file.
|
translation files. The example in this guide creates a French translation file.
|
||||||
|
|
||||||
{@a localization-folder}
|
{@a localization-folder}
|
||||||
|
|
||||||
### Create a localization folder
|
### Create a localization folder
|
||||||
|
|
||||||
Most apps are translated into more than one other language. For this reason, it is standard practice
|
Most apps are translated into more than one other language. For this reason, it is standard practice
|
||||||
@ -500,7 +511,6 @@ For this example:
|
|||||||
If you were translating to other languages, you would repeat these steps for each target language.
|
If you were translating to other languages, you would repeat these steps for each target language.
|
||||||
|
|
||||||
{@a translate-text-nodes}
|
{@a translate-text-nodes}
|
||||||
|
|
||||||
### Translate text nodes
|
### Translate text nodes
|
||||||
|
|
||||||
In a large translation project, you would send the `messages.fr.xlf` file to a French translator who
|
In a large translation project, you would send the `messages.fr.xlf` file to a French translator who
|
||||||
@ -544,7 +554,6 @@ This sample file is easy to translate without a special editor or knowledge of F
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{@a translate-plural-select}
|
{@a translate-plural-select}
|
||||||
|
|
||||||
## Translate plural and select expressions
|
## Translate plural and select expressions
|
||||||
|
|
||||||
_Plural_ and _select_ ICU expressions are extracted separately, so they require special attention
|
_Plural_ and _select_ ICU expressions are extracted separately, so they require special attention
|
||||||
@ -555,7 +564,6 @@ elsewhere in the source template. In this example, you know the translation unit
|
|||||||
must be just below the translation unit for the logo.
|
must be just below the translation unit for the logo.
|
||||||
|
|
||||||
{@a translate-plural}
|
{@a translate-plural}
|
||||||
|
|
||||||
### Translate _plural_
|
### Translate _plural_
|
||||||
|
|
||||||
To translate a `plural`, translate its ICU format match values:
|
To translate a `plural`, translate its ICU format match values:
|
||||||
@ -567,7 +575,6 @@ You can add or remove plural cases, with each language having its own cardinalit
|
|||||||
[CLDR plural rules](http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html).)
|
[CLDR plural rules](http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html).)
|
||||||
|
|
||||||
{@a translate-select}
|
{@a translate-select}
|
||||||
|
|
||||||
### Translate _select_
|
### Translate _select_
|
||||||
|
|
||||||
Below is the content of our example `select` ICU expression in the component template:
|
Below is the content of our example `select` ICU expression in the component template:
|
||||||
@ -598,7 +605,6 @@ Here they are together, after translation:
|
|||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
{@a translate-nested}
|
{@a translate-nested}
|
||||||
|
|
||||||
### Translate a nested expression
|
### Translate a nested expression
|
||||||
|
|
||||||
A nested expression is similar to the previous examples. As in the previous example, there are
|
A nested expression is similar to the previous examples. As in the previous example, there are
|
||||||
@ -621,7 +627,6 @@ The entire template translation is complete. The next section describes how to l
|
|||||||
into the app.
|
into the app.
|
||||||
|
|
||||||
{@a app-pre-translation}
|
{@a app-pre-translation}
|
||||||
|
|
||||||
### The app and its translation file
|
### The app and its translation file
|
||||||
|
|
||||||
The sample app and its translation file are now as follows:
|
The sample app and its translation file are now as follows:
|
||||||
@ -640,7 +645,6 @@ The sample app and its translation file are now as follows:
|
|||||||
</code-tabs>
|
</code-tabs>
|
||||||
|
|
||||||
{@a merge}
|
{@a merge}
|
||||||
|
|
||||||
## Merge the completed translation file into the app
|
## Merge the completed translation file into the app
|
||||||
|
|
||||||
To merge the translated text into component templates, compile the app with the completed
|
To merge the translated text into component templates, compile the app with the completed
|
||||||
@ -656,12 +660,11 @@ format that Angular understands, such as `.xtb`.
|
|||||||
How you provide this information depends upon whether you compile with
|
How you provide this information depends upon whether you compile with
|
||||||
the JIT compiler or the AOT compiler.
|
the JIT compiler or the AOT compiler.
|
||||||
|
|
||||||
* With [AOT](guide/i18n#aot), you pass the information as a CLI parameter.
|
* With [AOT](guide/i18n#merge-aot), you pass the information as a CLI parameter.
|
||||||
* With [JIT](guide/i18n#jit), you provide the information at bootstrap time.
|
* With [JIT](guide/i18n#merge-jit), you provide the information at bootstrap time.
|
||||||
|
|
||||||
|
|
||||||
{@a aot}
|
{@a merge-aot}
|
||||||
|
|
||||||
### Merge with the AOT compiler
|
### Merge with the AOT compiler
|
||||||
|
|
||||||
The AOT (_Ahead-of-Time_) compiler is part of a build process that produces a small, fast,
|
The AOT (_Ahead-of-Time_) compiler is part of a build process that produces a small, fast,
|
||||||
@ -685,8 +688,7 @@ guide:
|
|||||||
ng serve --aot --i18nFile=src/locale/messages.fr.xlf --i18nFormat=xlf --locale=fr
|
ng serve --aot --i18nFile=src/locale/messages.fr.xlf --i18nFormat=xlf --locale=fr
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
{@a jit}
|
{@a merge-jit}
|
||||||
|
|
||||||
### Merge with the JIT compiler
|
### Merge with the JIT compiler
|
||||||
|
|
||||||
The JIT compiler compiles the app in the browser as the app loads.
|
The JIT compiler compiles the app in the browser as the app loads.
|
||||||
@ -713,3 +715,29 @@ Then provide the `LOCALE_ID` in the main module:
|
|||||||
|
|
||||||
<code-example path="i18n/doc-files/app.module.ts" title="src/app/app.module.ts" linenums="false">
|
<code-example path="i18n/doc-files/app.module.ts" title="src/app/app.module.ts" linenums="false">
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
{@a missing-translation}
|
||||||
|
### Report missing translations
|
||||||
|
By default, when a translation is missing, the build succeeds but generates a warning such as
|
||||||
|
`Missing translation for message "foo"`. You can configure the level of warning that is generated by
|
||||||
|
the Angular compiler:
|
||||||
|
|
||||||
|
* Error: throw an error. If you are using AOT compilation, the build will fail. If you are using JIT
|
||||||
|
compilation, the app will fail to load.
|
||||||
|
* Warning (default): show a 'Missing translation' warning in the console or shell.
|
||||||
|
* Ignore: do nothing.
|
||||||
|
|
||||||
|
If you use the AOT compiler, specify the warning level by using the CLI parameter
|
||||||
|
`--missingTranslation`. The example below shows how to set the warning level to error:
|
||||||
|
|
||||||
|
<code-example language="sh" class="code-shell">
|
||||||
|
ng serve --aot --missingTranslation=error
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
If you use the JIT compiler, specify the warning level in the compiler config at bootstrap by adding
|
||||||
|
the 'MissingTranslationStrategy' property. The example below shows how to set the warning level to
|
||||||
|
error:
|
||||||
|
|
||||||
|
<code-example path="i18n/doc-files/main.3.ts" title="src/main.ts">
|
||||||
|
</code-example>
|
||||||
|
@ -140,7 +140,7 @@ calls the lifecycle hook methods in the following sequence at specific moments:
|
|||||||
</tr>
|
</tr>
|
||||||
<tr style='vertical-align:top'>
|
<tr style='vertical-align:top'>
|
||||||
<td>
|
<td>
|
||||||
<code>ngOnDestroy</code>
|
<code>ngOnDestroy()</code>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -74,8 +74,8 @@ Generate a new project and skeleton application by running the following command
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Patience please.
|
Patience, please.
|
||||||
It takes time to set up a new project, most of it spent installing npm packages.
|
It takes time to set up a new project; most of it is spent installing npm packages.
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
54
aio/content/guide/service-worker-communications.md
Normal file
54
aio/content/guide/service-worker-communications.md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# Service Worker Communication
|
||||||
|
|
||||||
|
Importing `ServiceWorkerModule` into your `AppModule` doesn't just register the service worker, it also provides a few services you can use to interact with the service worker and control the caching of your app.
|
||||||
|
|
||||||
|
#### Prerequisites
|
||||||
|
|
||||||
|
A basic understanding of the following:
|
||||||
|
* [Getting Started with Service Workers](guide/service-worker-getting-started).
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
|
||||||
|
## `SwUpdate` service
|
||||||
|
|
||||||
|
The `SwUpdate` service gives you access to events that indicate when the service worker has discovered an available update for your app or when it has activated such an update—meaning it is now serving content from that update to your app.
|
||||||
|
|
||||||
|
The `SwUpdate` service supports four separate operations:
|
||||||
|
* Getting notified of *available* updates. These are new versions of the app to be loaded if the page is refreshed.
|
||||||
|
* Getting notified of update *activation*. This is when the service worker starts serving a new version of the app immediately.
|
||||||
|
* Asking the service worker to check the server for new updates.
|
||||||
|
* Asking the service worker to activate the latest version of the app for the current tab.
|
||||||
|
|
||||||
|
### Available and activated updates
|
||||||
|
|
||||||
|
The two update events, `available` and `activated`, are `Observable` properties of `SwUpdate`:
|
||||||
|
|
||||||
|
<code-example path="service-worker-getting-started/src/app/log-update.service.ts" linenums="false" title="log-update.service.ts" region="sw-update"> </code-example>
|
||||||
|
|
||||||
|
|
||||||
|
You can use these events to notify the user of a pending update or to refresh their pages when the code they are running is out of date.
|
||||||
|
|
||||||
|
### Checking for updates
|
||||||
|
|
||||||
|
It's possible to ask the service worker to check if any updates have been deployed to the server. You might choose to do this if you have a site that changes frequently or want updates to happen on a schedule.
|
||||||
|
|
||||||
|
Do this with the `checkForUpdate()` method:
|
||||||
|
|
||||||
|
<code-example path="service-worker-getting-started/src/app/check-for-update.service.ts" linenums="false" title="check-for-update.service.ts" region="sw-check-update"> </code-example>
|
||||||
|
|
||||||
|
|
||||||
|
This method returns a `Promise` which indicates that the update check has completed successfully, though it does not indicate whether an update was discovered as a result of the check. Even if one is found, the service worker must still successfully download the changed files, which can fail. If successful, the `available` event will indicate availability of a new version of the app.
|
||||||
|
|
||||||
|
### Forcing update activation
|
||||||
|
|
||||||
|
If the current tab needs to be updated to the latest app version immediately, it can ask to do so with the `activateUpdate()` method:
|
||||||
|
|
||||||
|
<code-example path="service-worker-getting-started/src/app/prompt-update.service.ts" linenums="false" title="prompt-update.service.ts" region="sw-activate"> </code-example>
|
||||||
|
|
||||||
|
Doing this could break lazy-loading into currently running apps, especially if the lazy-loaded chunks use filenames with hashes, which change every version.
|
||||||
|
|
||||||
|
## More on Angular service workers
|
||||||
|
|
||||||
|
You may also be interested in the following:
|
||||||
|
* [Service Worker in Production](guide/service-worker-devops).
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user