Compare commits
266 Commits
6.1.0-rc.0
...
7.0.0-beta
Author | SHA1 | Date | |
---|---|---|---|
a2593cbfb1 | |||
70a3deb8a5 | |||
843479449d | |||
732026c3f5 | |||
ec6d6175d2 | |||
af9ced9026 | |||
c6e5b971d6 | |||
dbdbbdbe86 | |||
fefc860f35 | |||
02e201ab1a | |||
7bf5a43385 | |||
2fe05abbc4 | |||
2505c077d7 | |||
066fc6a0ca | |||
07ab98bbb0 | |||
16c03c0f38 | |||
3355502f2f | |||
02c15a2448 | |||
6861bc5b06 | |||
b8887ddf16 | |||
4933e103d3 | |||
7d006c5005 | |||
67ad59c245 | |||
397530ab24 | |||
a9881bb18e | |||
c1587029db | |||
2b906f652f | |||
c67f1bb38e | |||
637ae135c5 | |||
4eb8ac6de9 | |||
ba1e25f53f | |||
97b5cb2e3b | |||
795e1e8a38 | |||
aea8832243 | |||
1e7ca22078 | |||
26a15cc534 | |||
b0d86c1c2f | |||
dc0715142f | |||
4e264781ee | |||
79a9c71422 | |||
15cc85c54a | |||
725bae1921 | |||
eb999300d9 | |||
afa6b9e794 | |||
0822dc70f2 | |||
728d98d3a9 | |||
2f4abbf5a1 | |||
1000fb8406 | |||
b38931b484 | |||
1fb7111da1 | |||
c2c12e52fe | |||
28c7a4efbc | |||
4f741e74e1 | |||
6bacd32fbd | |||
183757daa2 | |||
adf510f986 | |||
74bce18190 | |||
3ba5220839 | |||
5982425436 | |||
140248ade0 | |||
e60737f63c | |||
7b89711402 | |||
f1223628a6 | |||
1b4269ad85 | |||
a224df43af | |||
d46a961509 | |||
20b453008f | |||
06a1974a48 | |||
3d7f555044 | |||
06af7943a4 | |||
fa70a2a650 | |||
bde4402675 | |||
7d6b258778 | |||
5342aeaafd | |||
1dd2eaa7d2 | |||
af07ffc2ad | |||
2b6e1f0f4b | |||
7a4fb44f8d | |||
88da8f3d52 | |||
01e6dab544 | |||
a9ecf4b929 | |||
166ddaadca | |||
1e5327872d | |||
367841d237 | |||
d5b73832bf | |||
7075c418f9 | |||
466e026f6f | |||
4976a58780 | |||
bafe1a0d2a | |||
c8a4fb1faf | |||
64516da6b0 | |||
6e2a1877ab | |||
aafd502bcb | |||
4cb1074850 | |||
76d8eb021c | |||
3f6fc00d73 | |||
5254d3447d | |||
4ee9db959a | |||
3f20a2fb5a | |||
e3834b7001 | |||
36648293a8 | |||
cd89eb8404 | |||
e99d860393 | |||
24789e9ad9 | |||
f94f9640d0 | |||
4d5167ec83 | |||
efc6684cd3 | |||
2ef777b0b2 | |||
fe14f180a6 | |||
87419097da | |||
9a6d26e05b | |||
6a797d5401 | |||
89e8b6fc0e | |||
f82b6b2ed7 | |||
a87d44c187 | |||
43d0e3dd72 | |||
5b32aa4486 | |||
844d510d3f | |||
2f70e90493 | |||
45cf5b5dad | |||
4ad2f11919 | |||
d7aa20d912 | |||
a673494412 | |||
07e6de5788 | |||
6f1685ab98 | |||
67588ec606 | |||
ee2c050521 | |||
185b932138 | |||
5e98421d33 | |||
8e65891985 | |||
7f59170f77 | |||
9ea112473b | |||
16f0ac38b8 | |||
15df853622 | |||
d3c0915598 | |||
ce98634dfd | |||
342678486d | |||
e8d4211d5c | |||
6a4d66d432 | |||
a3cf61b7cf | |||
a1b185b723 | |||
601064e41d | |||
e265ccd82c | |||
dd44f63c73 | |||
1d051c5841 | |||
323faf954b | |||
3169edd77a | |||
8de304c15a | |||
0d1d5898e3 | |||
6fe865b080 | |||
e0c0c44d99 | |||
13a0d527f6 | |||
ed7aa1c3e5 | |||
f902b5ec59 | |||
48d7205873 | |||
e1c6fd5453 | |||
968f153491 | |||
1e28495c89 | |||
0bcf20c9fa | |||
cf81823b07 | |||
d4ac9698ba | |||
c205516f0d | |||
777bd412b2 | |||
1e79014fc4 | |||
d0c066a223 | |||
65e18dc1bf | |||
1ceddb6290 | |||
22731a7588 | |||
72dd10f78f | |||
c0e3852384 | |||
2cb0f68a7b | |||
8450e0ab2f | |||
e38b2b502c | |||
445b9a5627 | |||
d523630ea2 | |||
d6016f1d1d | |||
be3cca4fd5 | |||
169e9dd2c8 | |||
13f3157823 | |||
edef58f466 | |||
7c89af34a9 | |||
bd576bb83f | |||
168c2a645b | |||
7729bb2bdc | |||
426324513d | |||
4d6f467fea | |||
6b859daea4 | |||
7960d1879d | |||
f1ab394218 | |||
86203736e9 | |||
41ef75869c | |||
2b8b647006 | |||
ed1db40322 | |||
d3594fc1c5 | |||
9fd70c9715 | |||
b7bbc82e3e | |||
139f5b3672 | |||
6f8ec256ef | |||
5d7005eef5 | |||
2e724ec68b | |||
76f8f78920 | |||
6eb6ac7c12 | |||
9644873023 | |||
ae4563202c | |||
42d4287153 | |||
f9a6a175bf | |||
53a16006d6 | |||
8a986d4642 | |||
e346c3c2f2 | |||
60aeee7abf | |||
1008bb6287 | |||
8a5cd2200a | |||
f58f3dc07a | |||
bb58138579 | |||
b8f740b253 | |||
23766b85e9 | |||
3cd9645daa | |||
2d38fa104b | |||
56b3f1703e | |||
c438b5eeda | |||
70b51a6255 | |||
7ebd8e59a8 | |||
1c533c913d | |||
ead3f926cb | |||
9be222f448 | |||
b137f09345 | |||
453693fd33 | |||
270176bbe4 | |||
5840a86f98 | |||
2aab1c9dd6 | |||
f9669e50ff | |||
99a393e84f | |||
d76531d16e | |||
23dc9a90b0 | |||
0b28732d77 | |||
06a33984af | |||
ba3eb8b654 | |||
c8ad9657c9 | |||
9be8abd012 | |||
74b250b146 | |||
d8c828c9b1 | |||
97277bc9fb | |||
1821b75530 | |||
82004c76ac | |||
a663565403 | |||
85d9c20b1d | |||
80a74b450a | |||
9a6f27c34c | |||
d723a69b31 | |||
d98b1c3bc4 | |||
02b5087685 | |||
48394c64ae | |||
cde0b4b361 | |||
9f20dd937a | |||
a1b630ee8f | |||
d05d28629d | |||
ee50ee493d | |||
161ff5c79d | |||
71e0df039c | |||
0399c6972a | |||
328971ffcc | |||
4d8b8ad372 | |||
0d6b74dd87 | |||
52d11f63cf | |||
a14f25c338 | |||
0b4d85e9f1 |
@ -3,7 +3,10 @@
|
||||
# See remote cache documentation in /docs/BAZEL.md
|
||||
|
||||
# Don't be spammy in the logs
|
||||
build --noshow_progress
|
||||
# TODO(gmagolan): Hide progress again once build performance improves
|
||||
# Presently, CircleCI can timeout during bazel test ... with the following
|
||||
# error: Too long with no output (exceeded 10m0s)
|
||||
# build --noshow_progress
|
||||
|
||||
# Don't run manual tests
|
||||
test --test_tag_filters=-manual
|
||||
|
@ -12,8 +12,8 @@
|
||||
## 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.3.2
|
||||
var_2: &cache_key v2-angular-{{ .Branch }}-{{ checksum "yarn.lock" }}-0.3.2
|
||||
var_1: &docker_image angular/ngcontainer:0.3.3
|
||||
var_2: &cache_key v2-angular-{{ .Branch }}-{{ checksum "yarn.lock" }}-0.3.3
|
||||
|
||||
# Define common ENV vars
|
||||
var_3: &define_env_vars
|
||||
|
197
.pullapprove.yml
197
.pullapprove.yml
@ -8,6 +8,7 @@
|
||||
# alexeagle - Alex Eagle
|
||||
# alxhub - Alex Rickabaugh
|
||||
# andrewseguin - Andrew Seguin
|
||||
# benlesh - Ben Lesh
|
||||
# brandonroberts - Brandon Roberts
|
||||
# brocco - Mike Brocchi
|
||||
# filipesilva - Filipe Silva
|
||||
@ -15,7 +16,7 @@
|
||||
# hansl - Hans Larsen
|
||||
# IgorMinar - Igor Minar
|
||||
# jasonaden - Jason Aden
|
||||
# kapunahelewong - Kapunahele Wong
|
||||
# jenniferfell - Jennifer Fell
|
||||
# kara - Kara Erickson
|
||||
# kyliau - Keen Yee Liau
|
||||
# matsko - Matias Niemelä
|
||||
@ -23,7 +24,6 @@
|
||||
# petebacondarwin - Pete Bacon Darwin
|
||||
# pkozlowski-opensource - Pawel Kozlowski
|
||||
# robwormald - Rob Wormald
|
||||
# tinayuangao - Tina Gao
|
||||
# vicb - Victor Berchet
|
||||
# vikerman - Vikram Subramanian
|
||||
|
||||
@ -92,6 +92,7 @@ groups:
|
||||
- "*.bzl"
|
||||
- "packages/bazel/*"
|
||||
- "tools/bazel.rc"
|
||||
- "/docs/BAZEL.md"
|
||||
users:
|
||||
- alexeagle #primary
|
||||
- kyliau
|
||||
@ -131,42 +132,113 @@ groups:
|
||||
conditions:
|
||||
files:
|
||||
- "packages/core/*"
|
||||
- "aio/content/guide/bootstrapping.md"
|
||||
- "aio/content/examples/bootstrapping/*"
|
||||
- "aio/content/guide/attribute-directives.md"
|
||||
- "aio/content/examples/attribute-directives/*"
|
||||
- "aio/content/images/guide/attribute-directives/*"
|
||||
- "aio/content/guide/structural-directives.md"
|
||||
- "aio/content/examples/structural-directives/*"
|
||||
- "aio/content/images/guide/structural-directives/*"
|
||||
- "aio/content/guide/dynamic-component-loader.md"
|
||||
- "aio/content/examples/dynamic-component-loader/*"
|
||||
- "aio/content/images/guide/dynamic-component-loader/*"
|
||||
- "aio/content/guide/template-syntax.md"
|
||||
- "aio/content/examples/template-syntax/*"
|
||||
- "aio/content/images/guide/template-syntax/*"
|
||||
- "aio/content/guide/dependency-injection.md"
|
||||
- "aio/content/examples/dependency-injection/*"
|
||||
- "aio/content/images/guide/dependency-injection/*"
|
||||
- "aio/content/guide/dependency-injection-in-action.md"
|
||||
- "aio/content/examples/dependency-injection-in-action/*"
|
||||
- "aio/content/images/guide/dependency-injection-in-action/*"
|
||||
- "aio/content/guide/hierarchical-dependency-injection.md"
|
||||
- "aio/content/examples/hierarchical-dependency-injection/*"
|
||||
- "aio/content/guide/singleton-services.md"
|
||||
- "aio/content/guide/dependency-injection-pattern.md"
|
||||
- "aio/content/guide/providers.md"
|
||||
- "aio/content/examples/providers/*"
|
||||
- "aio/content/guide/component-interaction.md"
|
||||
- "aio/content/examples/component-interaction/*"
|
||||
- "aio/content/images/guide/component-interaction/*"
|
||||
- "aio/content/guide/component-styles.md"
|
||||
- "aio/content/examples/component-styles/*"
|
||||
- "aio/content/guide/lifecycle-hooks.md"
|
||||
- "aio/content/examples/lifecycle-hooks/*"
|
||||
- "aio/content/images/guide/lifecycle-hooks/*"
|
||||
- "aio/content/examples/ngcontainer/*"
|
||||
- "aio/content/images/guide/ngcontainer/*"
|
||||
- "aio/content/guide/pipes.md"
|
||||
- "aio/content/examples/pipes/*"
|
||||
- "aio/content/images/guide/pipes/*"
|
||||
- "aio/content/guide/entry-components.md"
|
||||
- "aio/content/guide/set-document-title.md"
|
||||
- "aio/content/examples/set-document-title/*"
|
||||
- "aio/content/images/guide/set-document-title/*"
|
||||
- "aio/content/guide/ngmodules.md"
|
||||
- "aio/content/examples/ngmodules/*"
|
||||
- "aio/content/examples/ngmodule/*"
|
||||
- "aio/content/images/guide/ngmodule/*"
|
||||
- "aio/content/guide/ngmodule-faq.md"
|
||||
- "aio/content/examples/ngmodule-faq/*"
|
||||
- "aio/content/guide/module-types.md"
|
||||
- "aio/content/guide/sharing-ngmodules.md"
|
||||
- "aio/content/guide/frequent-ngmodules.md"
|
||||
- "aio/content/images/guide/frequent-ngmodules/*"
|
||||
- "aio/content/guide/ngmodule-api.md"
|
||||
- "aio/content/guide/ngmodule-vs-jsmodule.md"
|
||||
- "aio/content/guide/feature-modules.md"
|
||||
- "aio/content/examples/feature-modules/*"
|
||||
- "aio/content/images/guide/feature-modules/*"
|
||||
- "aio/content/guide/lazy-loading-ngmodules.md"
|
||||
- "aio/content/examples/lazy-loading-ngmodules/*"
|
||||
- "aio/content/images/guide/lazy-loading-ngmodules"
|
||||
users:
|
||||
- mhevery #primary
|
||||
- jasonaden
|
||||
- kara
|
||||
- vicb
|
||||
- IgorMinar #fallback
|
||||
- IgorMinar
|
||||
- jenniferfell #docs only
|
||||
|
||||
animations:
|
||||
conditions:
|
||||
files:
|
||||
- "packages/animations/*"
|
||||
- "packages/platform-browser/animations/*"
|
||||
- "aio/content/guide/animations.md"
|
||||
- "aio/content/examples/animations/*"
|
||||
- "aio/content/images/guide/animations/*"
|
||||
users:
|
||||
- matsko #primary
|
||||
- mhevery #fallback
|
||||
- IgorMinar #fallback
|
||||
- jenniferfell #docs only
|
||||
|
||||
compiler/i18n:
|
||||
conditions:
|
||||
files:
|
||||
- "packages/compiler/src/i18n/*"
|
||||
- "aio/content/guide/i18n.md"
|
||||
- "aio/content/examples/i18n/*"
|
||||
users:
|
||||
- vicb #primary
|
||||
- alxhub
|
||||
- IgorMinar #fallback
|
||||
- mhevery #fallback
|
||||
- jenniferfell #docs only
|
||||
|
||||
compiler:
|
||||
conditions:
|
||||
files:
|
||||
- "packages/compiler/*"
|
||||
- "aio/content/guide/aot-compiler.md"
|
||||
users:
|
||||
- alxhub #primary
|
||||
- vicb
|
||||
- mhevery
|
||||
- IgorMinar #fallback
|
||||
- jenniferfell #docs only
|
||||
|
||||
compiler-cli/ngtools:
|
||||
conditions:
|
||||
@ -175,7 +247,6 @@ groups:
|
||||
users:
|
||||
- hansl
|
||||
- filipesilva #fallback
|
||||
- brocco #fallback
|
||||
- IgorMinar #fallback
|
||||
|
||||
compiler-cli:
|
||||
@ -211,57 +282,97 @@ groups:
|
||||
files:
|
||||
- "packages/forms/*"
|
||||
- "aio/content/guide/forms.md"
|
||||
- "aio/content/guide/form-validation.md"
|
||||
- "aio/content/guide/reactive-forms.md"
|
||||
- "aio/content/examples/forms/*"
|
||||
- "aio/content/images/guide/forms/*"
|
||||
- "aio/content/guide/form-validation.md"
|
||||
- "aio/content/examples/form-validation/*"
|
||||
- "aio/content/images/guide/form-validation/*"
|
||||
- "aio/content/guide/dynamic-form.md"
|
||||
- "aio/content/examples/dynamic-form/*"
|
||||
- "aio/content/images/guide/dynamic-form/*"
|
||||
- "aio/content/guide/reactive-forms.md"
|
||||
- "aio/content/examples/reactive-forms/*"
|
||||
- "aio/content/images/guide/reactive-forms/*"
|
||||
users:
|
||||
- kara #primary
|
||||
- tinayuangao #secondary
|
||||
- IgorMinar #fallback
|
||||
- mhevery #fallback
|
||||
- jenniferfell #docs only
|
||||
|
||||
http:
|
||||
conditions:
|
||||
files:
|
||||
- "packages/common/http/*"
|
||||
- "packages/http/*"
|
||||
- "aio/content/guide/http.md"
|
||||
- "aio/content/examples/http/*"
|
||||
- "aio/content/images/guide/http/*"
|
||||
users:
|
||||
- alxhub #primary
|
||||
- IgorMinar
|
||||
- mhevery #fallback
|
||||
- jenniferfell #docs only
|
||||
|
||||
language-service:
|
||||
conditions:
|
||||
files:
|
||||
- "packages/language-service/*"
|
||||
- "aio/content/guide/language-service.md"
|
||||
- "aio/content/images/guide/language-service/*"
|
||||
users:
|
||||
- kyliau #primary
|
||||
# needs secondary
|
||||
- vicb
|
||||
- IgorMinar #fallback
|
||||
- mhevery #fallback
|
||||
- jenniferfell #docs only
|
||||
|
||||
router:
|
||||
conditions:
|
||||
files:
|
||||
- "packages/router/*"
|
||||
- "aio/content/guide/router.md"
|
||||
- "aio/content/examples/router/*"
|
||||
- "aio/content/images/guide/router/*"
|
||||
users:
|
||||
- jasonaden #primary
|
||||
- vicb
|
||||
- IgorMinar #fallback
|
||||
- mhevery #fallback
|
||||
- jenniferfell #docs only
|
||||
|
||||
testing:
|
||||
conditions:
|
||||
files:
|
||||
- "*/testing/*"
|
||||
- "aio/content/guide/testing.md"
|
||||
- "aio/content/examples/testing/*"
|
||||
- "aio/content/images/guide/testing/*"
|
||||
users:
|
||||
- vikerman
|
||||
- IgorMinar #fallback
|
||||
- mhevery #fallback
|
||||
- jenniferfell #docs only
|
||||
|
||||
upgrade:
|
||||
conditions:
|
||||
files:
|
||||
- "packages/upgrade/*"
|
||||
- "aio/content/guide/upgrade.md"
|
||||
- "aio/content/examples/upgrade-module/*"
|
||||
- "aio/content/images/guide/upgrade/*"
|
||||
- "aio/content/examples/upgrade-phonecat-1-typescript/*"
|
||||
- "aio/content/examples/upgrade-phonecat-2-hybrid/*"
|
||||
- "aio/content/examples/upgrade-phonecat-3-final/*"
|
||||
- "aio/content/guide/upgrade-performance.md"
|
||||
- "aio/content/guide/ajs-quick-reference.md"
|
||||
- "aio/content/examples/ajs-quick-reference/*"
|
||||
users:
|
||||
- petebacondarwin #primary
|
||||
- gkalpak
|
||||
- IgorMinar #fallback
|
||||
- mhevery #fallback
|
||||
- jenniferfell #docs only
|
||||
|
||||
platform-browser:
|
||||
conditions:
|
||||
@ -277,12 +388,15 @@ groups:
|
||||
conditions:
|
||||
files:
|
||||
- "packages/platform-server/*"
|
||||
- "aio/content/guide/universal.md"
|
||||
- "aio/content/examples/universal/*"
|
||||
users:
|
||||
- vikerman #primary
|
||||
- alxhub #secondary
|
||||
- vicb
|
||||
- IgorMinar #fallback
|
||||
- mhevery #fallback
|
||||
- jenniferfell #docs only
|
||||
|
||||
platform-webworker:
|
||||
conditions:
|
||||
@ -298,22 +412,34 @@ groups:
|
||||
conditions:
|
||||
files:
|
||||
- "packages/service-worker/*"
|
||||
- "aio/content/guide/service-worker-getting-started.md"
|
||||
- "aio/content/examples/service-worker-getting-started/*"
|
||||
- "aio/content/guide/service-worker-communications.md"
|
||||
- "aio/content/guide/service-worker-config.md"
|
||||
- "aio/content/guide/service-worker-devops.md"
|
||||
- "aio/content/guide/service-worker-intro.md"
|
||||
- "aio/content/images/guide/service-worker/*"
|
||||
users:
|
||||
- alxhub #primary
|
||||
- gkalpak
|
||||
- IgorMinar #fallback
|
||||
- gkalpak #primary
|
||||
- alxhub
|
||||
- IgorMinar
|
||||
- mhevery #fallback
|
||||
- jenniferfell #docs only
|
||||
|
||||
elements:
|
||||
conditions:
|
||||
files:
|
||||
- "packages/elements/*"
|
||||
- "aio/content/examples/elements/*"
|
||||
- "aio/content/images/guide/elements/*"
|
||||
- "aio/content/guide/elements.md"
|
||||
users:
|
||||
- andrewseguin #primary
|
||||
- gkalpak
|
||||
- robwormald
|
||||
- IgorMinar #fallback
|
||||
- mhevery #fallback
|
||||
- jenniferfell #docs only
|
||||
|
||||
benchpress:
|
||||
conditions:
|
||||
@ -325,7 +451,7 @@ groups:
|
||||
- IgorMinar #fallback
|
||||
- mhevery #fallback
|
||||
|
||||
angular.io:
|
||||
docs-infra:
|
||||
conditions:
|
||||
files:
|
||||
include:
|
||||
@ -338,7 +464,7 @@ groups:
|
||||
- gkalpak
|
||||
- mhevery #fallback
|
||||
|
||||
angular.io-guide-and-tutorial:
|
||||
docs/guide-and-tutorial:
|
||||
conditions:
|
||||
files:
|
||||
include:
|
||||
@ -348,19 +474,20 @@ groups:
|
||||
- "aio/content/navigation.json"
|
||||
- "aio/content/license.md"
|
||||
users:
|
||||
- kapunahelewong
|
||||
- stephenfluin
|
||||
- jenniferfell
|
||||
- brandonroberts
|
||||
- petebacondarwin
|
||||
- gkalpak
|
||||
- IgorMinar
|
||||
- brandonroberts
|
||||
- mhevery #fallback
|
||||
|
||||
angular.io-marketing:
|
||||
docs/marketing:
|
||||
conditions:
|
||||
files:
|
||||
include:
|
||||
- "aio/content/marketing/*"
|
||||
- "aio/content/images/marketing/*"
|
||||
- "aio/content/navigation.json"
|
||||
- "aio/content/license.md"
|
||||
users:
|
||||
@ -370,3 +497,43 @@ groups:
|
||||
- IgorMinar
|
||||
- robwormald
|
||||
- mhevery #fallback
|
||||
|
||||
docs/observables:
|
||||
conditions:
|
||||
files:
|
||||
- "aio/content/examples/observables/*"
|
||||
- "aio/content/images/guide/observables/*"
|
||||
- "aio/content/guide/observables.md"
|
||||
- "aio/content/guide/comparing-observables.md"
|
||||
- "aio/content/examples/observables-in-angular/*"
|
||||
- "aio/content/images/guide/observables-in-angular/*"
|
||||
- "aio/content/guide/observables-in-angular.md"
|
||||
- "aio/content/examples/practical-observable-usage/*"
|
||||
- "aio/content/guide/practical-observable-usage.md"
|
||||
- "aio/content/examples/rx-library/*"
|
||||
- "aio/content/guide/rx-library.md"
|
||||
users:
|
||||
- jasonaden
|
||||
- benlesh
|
||||
- IgorMinar
|
||||
- mhevery
|
||||
- jenniferfell #docs only
|
||||
|
||||
docs/packaging:
|
||||
conditions:
|
||||
files:
|
||||
- "aio/content/guide/npm-packages.md"
|
||||
- "aio/content/guide/browser-support.md"
|
||||
- "aio/content/guide/typescript-configuration.md"
|
||||
- "aio/content/guide/setup-systemjs-anatomy.md"
|
||||
- "aio/content/examples/setup/*"
|
||||
- "aio/content/guide/setup.md"
|
||||
- "aio/content/guide/deployment.md"
|
||||
- "aio/content/guide/releases.md"
|
||||
- "aio/content/guide/updating.md"
|
||||
users:
|
||||
- IgorMinar #primary
|
||||
- alexeagle
|
||||
- hansl
|
||||
- mhevery #fallback
|
||||
- jenniferfell #docs only
|
||||
|
40
BUILD.bazel
40
BUILD.bazel
@ -5,6 +5,7 @@ load("@build_bazel_rules_nodejs//:defs.bzl", "node_modules_filegroup")
|
||||
exports_files([
|
||||
"tsconfig.json",
|
||||
"LICENSE",
|
||||
"protractor-perf.conf.js",
|
||||
])
|
||||
|
||||
# Developers should always run `bazel run :install`
|
||||
@ -14,36 +15,19 @@ alias(
|
||||
actual = "@nodejs//:yarn",
|
||||
)
|
||||
|
||||
node_modules_filegroup(
|
||||
alias(
|
||||
name = "node_modules",
|
||||
packages = [
|
||||
"bytebuffer",
|
||||
"hammerjs",
|
||||
"jasmine",
|
||||
"minimist",
|
||||
"protobufjs",
|
||||
"reflect-metadata",
|
||||
"source-map-support",
|
||||
"tsickle",
|
||||
"tslib",
|
||||
"tsutils",
|
||||
"typescript",
|
||||
"zone.js",
|
||||
"@angular-devkit/core",
|
||||
"@angular-devkit/schematics",
|
||||
"@types",
|
||||
"@webcomponents/custom-elements",
|
||||
],
|
||||
actual = "@angular_deps//:node_modules",
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "web_test_bootstrap_scripts",
|
||||
# do not sort
|
||||
srcs = [
|
||||
"//:node_modules/reflect-metadata/Reflect.js",
|
||||
"//:node_modules/zone.js/dist/zone.js",
|
||||
"//:node_modules/zone.js/dist/zone-testing.js",
|
||||
"//:node_modules/zone.js/dist/task-tracking.js",
|
||||
"@angular_deps//:node_modules/reflect-metadata/Reflect.js",
|
||||
"@angular_deps//:node_modules/zone.js/dist/zone.js",
|
||||
"@angular_deps//:node_modules/zone.js/dist/zone-testing.js",
|
||||
"@angular_deps//:node_modules/zone.js/dist/task-tracking.js",
|
||||
"//:test-events.js",
|
||||
],
|
||||
)
|
||||
@ -51,9 +35,11 @@ filegroup(
|
||||
filegroup(
|
||||
name = "angularjs_scripts",
|
||||
srcs = [
|
||||
"//:node_modules/angular-1.5/angular.js",
|
||||
"//:node_modules/angular-mocks-1.5/angular-mocks.js",
|
||||
"//:node_modules/angular-mocks/angular-mocks.js",
|
||||
"//:node_modules/angular/angular.js",
|
||||
"@angular_deps//:node_modules/angular-1.5/angular.js",
|
||||
"@angular_deps//:node_modules/angular-1.6/angular.js",
|
||||
"@angular_deps//:node_modules/angular-mocks-1.5/angular-mocks.js",
|
||||
"@angular_deps//:node_modules/angular-mocks-1.6/angular-mocks.js",
|
||||
"@angular_deps//:node_modules/angular-mocks/angular-mocks.js",
|
||||
"@angular_deps//:node_modules/angular/angular.js",
|
||||
],
|
||||
)
|
||||
|
271
CHANGELOG.md
271
CHANGELOG.md
@ -1,33 +1,163 @@
|
||||
<a name="6.1.0-rc.0"></a>
|
||||
# [6.1.0-rc.0](https://github.com/angular/angular/compare/6.1.0-beta.3...6.1.0-rc.0) (2018-07-11)
|
||||
<a name="7.0.0-beta.1"></a>
|
||||
# [7.0.0-beta.1](https://github.com/angular/angular/compare/7.0.0-beta.0...7.0.0-beta.1) (2018-08-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **common:** do not round factional seconds ([#24831](https://github.com/angular/angular/issues/24831)) ([a527c69](https://github.com/angular/angular/commit/a527c69)), closes [#24384](https://github.com/angular/angular/issues/24384)
|
||||
* **common:** properly update collection reference in NgForOf ([#24684](https://github.com/angular/angular/issues/24684)) ([ff84c5c](https://github.com/angular/angular/commit/ff84c5c)), closes [#24155](https://github.com/angular/angular/issues/24155)
|
||||
* **common:** use correct currency format for locale de-AT ([#24658](https://github.com/angular/angular/issues/24658)) ([dcabb05](https://github.com/angular/angular/commit/dcabb05)), closes [#24609](https://github.com/angular/angular/issues/24609)
|
||||
* **compiler:** fix a few non-tree-shakeable code patterns ([#24677](https://github.com/angular/angular/issues/24677)) ([50d4a4f](https://github.com/angular/angular/commit/50d4a4f))
|
||||
* **compiler-cli:** Use typescript to resolve modules for metadata ([#22856](https://github.com/angular/angular/issues/22856)) ([0d5f2d3](https://github.com/angular/angular/commit/0d5f2d3))
|
||||
* **core:** mark NgModule as not the root if APP_ROOT is set to false ([#24814](https://github.com/angular/angular/issues/24814)) ([1089261](https://github.com/angular/angular/commit/1089261))
|
||||
* **core:** use addCustomEqualityTester instead of overriding toEqual ([#22983](https://github.com/angular/angular/issues/22983)) ([0922228](https://github.com/angular/angular/commit/0922228)), closes [#22939](https://github.com/angular/angular/issues/22939)
|
||||
* **language-service:** do not overwrite native `Reflect` ([#24299](https://github.com/angular/angular/issues/24299)) ([6881404](https://github.com/angular/angular/commit/6881404)), closes [#21420](https://github.com/angular/angular/issues/21420)
|
||||
* **platform-browser:** add missing deps for HammerGesturesPlugin ([#24682](https://github.com/angular/angular/issues/24682)) ([13d60ea](https://github.com/angular/angular/commit/13d60ea))
|
||||
* **platform-browser:** mark Meta and Title services as tree shakable providers ([#24815](https://github.com/angular/angular/issues/24815)) ([197387d](https://github.com/angular/angular/commit/197387d))
|
||||
* **platform-browser:** workaround wrong import path generated by ngc for DOCUMENT ([#24830](https://github.com/angular/angular/issues/24830)) ([7d27ecc](https://github.com/angular/angular/commit/7d27ecc))
|
||||
* **router:** add ability to recover from malformed url ([#23283](https://github.com/angular/angular/issues/23283)) ([86d254d](https://github.com/angular/angular/commit/86d254d)), closes [#21468](https://github.com/angular/angular/issues/21468)
|
||||
* **service-worker:** avoid network requests when looking up hashed resources in cache ([#24127](https://github.com/angular/angular/issues/24127)) ([52d43a9](https://github.com/angular/angular/commit/52d43a9))
|
||||
* **compiler-cli:** use the oldProgram option in watch mode ([#21364](https://github.com/angular/angular/issues/21364)) ([c6e5b97](https://github.com/angular/angular/commit/c6e5b97)), closes [#21361](https://github.com/angular/angular/issues/21361)
|
||||
* **core:** In Testability.whenStable update callback, pass more complete ([#25010](https://github.com/angular/angular/issues/25010)) ([16c03c0](https://github.com/angular/angular/commit/16c03c0))
|
||||
* add mappings for ngfactory & ngsummary files to their module names in aot summary resolver ([#25335](https://github.com/angular/angular/issues/25335)) ([02e201a](https://github.com/angular/angular/commit/02e201a))
|
||||
* **router:** take base uri into account in `setUpLocationSync()` ([#20244](https://github.com/angular/angular/issues/20244)) ([ba1e25f](https://github.com/angular/angular/commit/ba1e25f)), closes [#20061](https://github.com/angular/angular/issues/20061)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **core:** add support for ShadowDOM v1 ([#24718](https://github.com/angular/angular/issues/24718)) ([3553977](https://github.com/angular/angular/commit/3553977))
|
||||
* **core:** add support for using async/await with Jasmine ([#24637](https://github.com/angular/angular/issues/24637)) ([71100e6](https://github.com/angular/angular/commit/71100e6))
|
||||
* typescript 2.9 support ([#24652](https://github.com/angular/angular/issues/24652)) ([e3064d5](https://github.com/angular/angular/commit/e3064d5))
|
||||
* **service-worker:** add support for `?` in SW config globbing ([#24105](https://github.com/angular/angular/issues/24105)) ([250527c](https://github.com/angular/angular/commit/250527c))
|
||||
* **core:** add DoBootstrap interface. ([#24558](https://github.com/angular/angular/issues/24558)) ([732026c](https://github.com/angular/angular/commit/732026c)), closes [#24557](https://github.com/angular/angular/issues/24557)
|
||||
|
||||
|
||||
|
||||
<a name="6.1.2"></a>
|
||||
## [6.1.2](https://github.com/angular/angular/compare/6.1.1...6.1.2) (2018-08-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **router:** take base uri into account in `setUpLocationSync()` ([#20244](https://github.com/angular/angular/issues/20244)) ([ae9b4e6](https://github.com/angular/angular/commit/ae9b4e6)), closes [#20061](https://github.com/angular/angular/issues/20061)
|
||||
* add mappings for ngfactory & ngsummary files to their module names in aot summary resolver ([#25335](https://github.com/angular/angular/issues/25335)) ([054fbbe](https://github.com/angular/angular/commit/054fbbe))
|
||||
|
||||
|
||||
<a name="7.0.0-beta.0"></a>
|
||||
# [7.0.0-beta.0](https://github.com/angular/angular/compare/6.1.0...7.0.0-beta.0) (2018-08-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** allow compile_strategy to be (privately) imported ([#25080](https://github.com/angular/angular/issues/25080)) ([0d1d589](https://github.com/angular/angular/commit/0d1d589))
|
||||
* **compiler:** update compiler to flatten nested template fns ([#24943](https://github.com/angular/angular/issues/24943)) ([fe14f18](https://github.com/angular/angular/commit/fe14f18))
|
||||
* **compiler-cli:** correct realPath to realpath. ([#25023](https://github.com/angular/angular/issues/25023)) ([01e6dab](https://github.com/angular/angular/commit/01e6dab))
|
||||
* **core:** throw error message when @Output not initialized ([#19116](https://github.com/angular/angular/issues/19116)) ([adf510f](https://github.com/angular/angular/commit/adf510f)), closes [#3664](https://github.com/angular/angular/issues/3664)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **compiler:** add "original" placeholder value on extracted XMB ([#25079](https://github.com/angular/angular/issues/25079)) ([e99d860](https://github.com/angular/angular/commit/e99d860))
|
||||
|
||||
|
||||
|
||||
<a name="6.1.1"></a>
|
||||
## [6.1.1](https://github.com/angular/angular/compare/6.1.0...6.1.1) (2018-08-02)
|
||||
|
||||
* **compiler-cli:** correct tsickle dependency version to fix typescript 2.9 compatibility ([fec29fa](https://github.com/angular/angular/commit/317c7087c56b72aa74cd6d6a8f719e6e7fec29fa))
|
||||
|
||||
|
||||
|
||||
<a name="6.1.0"></a>
|
||||
# [6.1.0](https://github.com/angular/angular/compare/6.0.0-rc.5...6.1.0) (2018-07-25)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **animations:** always render end-state styles for orphaned DOM nodes ([#24236](https://github.com/angular/angular/issues/24236)) ([dc4a3d0](https://github.com/angular/angular/commit/dc4a3d0))
|
||||
* **animations:** set animations styles properly on platform-server ([#24624](https://github.com/angular/angular/issues/24624)) ([0b356d4](https://github.com/angular/angular/commit/0b356d4))
|
||||
* **animations:** do not throw errors when a destroyed component is animated ([#23836](https://github.com/angular/angular/issues/23836)) ([d2a8687](https://github.com/angular/angular/commit/d2a8687))
|
||||
* **animations:** Fix browser detection logic ([#24188](https://github.com/angular/angular/issues/24188)) ([b492b9e](https://github.com/angular/angular/commit/b492b9e))
|
||||
* **animations:** properly clean up queried element styles in safari/edge ([#23633](https://github.com/angular/angular/issues/23633)) ([da9ff25](https://github.com/angular/angular/commit/da9ff25))
|
||||
* **animations:** retain state styling for nodes that are moved around ([#23534](https://github.com/angular/angular/issues/23534)) ([65211f4](https://github.com/angular/angular/commit/65211f4))
|
||||
* **animations:** retain trigger-state for nodes that are moved around ([#24238](https://github.com/angular/angular/issues/24238)) ([8db928d](https://github.com/angular/angular/commit/8db928d))
|
||||
* **bazel:** Allow ng_module to depend on targets w no deps ([#24446](https://github.com/angular/angular/issues/24446)) ([282d351](https://github.com/angular/angular/commit/282d351))
|
||||
* **benchpress:** Fix promise chain in chrome_driver_extension. ([#23458](https://github.com/angular/angular/issues/23458)) ([d4b6c41](https://github.com/angular/angular/commit/d4b6c41))
|
||||
* **common:** do not round factional seconds ([#24831](https://github.com/angular/angular/issues/24831)) ([a527c69](https://github.com/angular/angular/commit/a527c69)), closes [#24384](https://github.com/angular/angular/issues/24384)
|
||||
* **common:** format fractional seconds ([#24844](https://github.com/angular/angular/issues/24844)) ([0b4d85e](https://github.com/angular/angular/commit/0b4d85e)), closes [#24831](https://github.com/angular/angular/issues/24831)
|
||||
* **common:** properly update collection reference in NgForOf ([#24684](https://github.com/angular/angular/issues/24684)) ([ff84c5c](https://github.com/angular/angular/commit/ff84c5c)), closes [#24155](https://github.com/angular/angular/issues/24155)
|
||||
* **common:** use correct currency format for locale de-AT ([#24658](https://github.com/angular/angular/issues/24658)) ([dcabb05](https://github.com/angular/angular/commit/dcabb05)), closes [#24609](https://github.com/angular/angular/issues/24609)
|
||||
* **common:** use correct ICU plural for locale mk ([#24659](https://github.com/angular/angular/issues/24659)) ([64a8584](https://github.com/angular/angular/commit/64a8584))
|
||||
* **compiler:** fix a few non-tree-shakeable code patterns ([#24677](https://github.com/angular/angular/issues/24677)) ([50d4a4f](https://github.com/angular/angular/commit/50d4a4f))
|
||||
* **compiler:** i18n_extractor now outputs the correct source file name ([#24885](https://github.com/angular/angular/issues/24885)) ([c8ad965](https://github.com/angular/angular/commit/c8ad965)), closes [#24884](https://github.com/angular/angular/issues/24884)
|
||||
* **compiler:** support `.` in import statements. ([#20634](https://github.com/angular/angular/issues/20634)) ([d8f7b29](https://github.com/angular/angular/commit/d8f7b29)), closes [#20363](https://github.com/angular/angular/issues/20363)
|
||||
* **compiler:** avoid a crash in ngc-wrapped. ([#23468](https://github.com/angular/angular/issues/23468)) ([e1c4930](https://github.com/angular/angular/commit/e1c4930))
|
||||
* **compiler:** generate constant array for i18n attributes ([#23837](https://github.com/angular/angular/issues/23837)) ([cfde36d](https://github.com/angular/angular/commit/cfde36d))
|
||||
* **compiler:** generate core-compliant hostBindings property ([#24087](https://github.com/angular/angular/issues/24087)) ([01b5acd](https://github.com/angular/angular/commit/01b5acd)), closes [#24013](https://github.com/angular/angular/issues/24013)
|
||||
* **compiler:** handle undefined annotation metadata ([#23349](https://github.com/angular/angular/issues/23349)) ([ca776c5](https://github.com/angular/angular/commit/ca776c5))
|
||||
* **compiler-cli:** Use typescript to resolve modules for metadata ([#22856](https://github.com/angular/angular/issues/22856)) ([0d5f2d3](https://github.com/angular/angular/commit/0d5f2d3))
|
||||
* **compiler-cli:** don't rely on incompatible TS method ([#23550](https://github.com/angular/angular/issues/23550)) ([b1f040f](https://github.com/angular/angular/commit/b1f040f))
|
||||
* **core:** stop reusing provider definitions across NgModuleRef instances ([#25022](https://github.com/angular/angular/issues/25022)) ([6b859da](https://github.com/angular/angular/commit/6b859da)), closes [#25018](https://github.com/angular/angular/issues/25018)
|
||||
* **core:** mark NgModule as not the root if APP_ROOT is set to false ([#24814](https://github.com/angular/angular/issues/24814)) ([1089261](https://github.com/angular/angular/commit/1089261))
|
||||
* **core:** use addCustomEqualityTester instead of overriding toEqual ([#22983](https://github.com/angular/angular/issues/22983)) ([0922228](https://github.com/angular/angular/commit/0922228)), closes [#22939](https://github.com/angular/angular/issues/22939)
|
||||
* **core:** Injector correctly honors the @Self flag ([#24520](https://github.com/angular/angular/issues/24520)) ([ccbda9d](https://github.com/angular/angular/commit/ccbda9d))
|
||||
* **core:** avoid eager providers re-initialization ([#23559](https://github.com/angular/angular/issues/23559)) ([0c6dc45](https://github.com/angular/angular/commit/0c6dc45))
|
||||
* **core:** call ngOnDestroy on all services that have it ([#23755](https://github.com/angular/angular/issues/23755)) ([fc03427](https://github.com/angular/angular/commit/fc03427)), closes [#22466](https://github.com/angular/angular/issues/22466) [#22240](https://github.com/angular/angular/issues/22240) [#14818](https://github.com/angular/angular/issues/14818)
|
||||
* **docs-infra:** fix table header layout in API pages ([#24919](https://github.com/angular/angular/issues/24919)) ([3cd9645](https://github.com/angular/angular/commit/3cd9645))
|
||||
* **elements:** always check to create strategy ([#23825](https://github.com/angular/angular/issues/23825)) ([b1cda36](https://github.com/angular/angular/commit/b1cda36))
|
||||
* **elements:** prevent closure renaming of platform properties ([#23843](https://github.com/angular/angular/issues/23843)) ([d4b8b24](https://github.com/angular/angular/commit/d4b8b24))
|
||||
* **forms:** properly handle special properties in FormGroup.get ([#22249](https://github.com/angular/angular/issues/22249)) ([9367e91](https://github.com/angular/angular/commit/9367e91)), closes [#17195](https://github.com/angular/angular/issues/17195)
|
||||
* **language-service:** do not overwrite native `Reflect` ([#24299](https://github.com/angular/angular/issues/24299)) ([6881404](https://github.com/angular/angular/commit/6881404)), closes [#21420](https://github.com/angular/angular/issues/21420)
|
||||
* **platform-browser:** add missing deps for HammerGesturesPlugin ([#24682](https://github.com/angular/angular/issues/24682)) ([13d60ea](https://github.com/angular/angular/commit/13d60ea))
|
||||
* **platform-browser:** mark Meta and Title services as tree shakable providers ([#24815](https://github.com/angular/angular/issues/24815)) ([197387d](https://github.com/angular/angular/commit/197387d))
|
||||
* **platform-browser:** workaround wrong import path generated by ngc for DOCUMENT ([#24830](https://github.com/angular/angular/issues/24830)) ([7d27ecc](https://github.com/angular/angular/commit/7d27ecc))
|
||||
* **platform-server:** avoid clash between server and client style encapsulation attributes ([#24158](https://github.com/angular/angular/issues/24158)) ([b96a3c8](https://github.com/angular/angular/commit/b96a3c8))
|
||||
* **platform-server:** avoid dependency cycle when using http interceptor ([#24229](https://github.com/angular/angular/issues/24229)) ([60aa943](https://github.com/angular/angular/commit/60aa943)), closes [#23023](https://github.com/angular/angular/issues/23023)
|
||||
* **platform-server:** don't reflect innerHTML property to attribute ([#24213](https://github.com/angular/angular/issues/24213)) ([6a663a4](https://github.com/angular/angular/commit/6a663a4)), closes [#19278](https://github.com/angular/angular/issues/19278)
|
||||
* **platform-server:** provide Domino DOM types globally ([#24116](https://github.com/angular/angular/issues/24116)) ([c73196e](https://github.com/angular/angular/commit/c73196e)), closes [#23280](https://github.com/angular/angular/issues/23280) [#23133](https://github.com/angular/angular/issues/23133)
|
||||
* **router:** Fix _lastPathIndex in deeply nested empty paths ([#22394](https://github.com/angular/angular/issues/22394)) ([968f153](https://github.com/angular/angular/commit/968f153))
|
||||
* **router:** add ability to recover from malformed url ([#23283](https://github.com/angular/angular/issues/23283)) ([86d254d](https://github.com/angular/angular/commit/86d254d)), closes [#21468](https://github.com/angular/angular/issues/21468)
|
||||
* **router:** fix lazy loading of aux routes ([#23459](https://github.com/angular/angular/issues/23459)) ([5731d07](https://github.com/angular/angular/commit/5731d07)), closes [#10981](https://github.com/angular/angular/issues/10981)
|
||||
* **router:** avoid freezing queryParams in-place ([#22663](https://github.com/angular/angular/issues/22663)) ([89f64e5](https://github.com/angular/angular/commit/89f64e5)), closes [#22617](https://github.com/angular/angular/issues/22617)
|
||||
* **router:** cache route handle if found ([#22475](https://github.com/angular/angular/issues/22475)) ([4cfa571](https://github.com/angular/angular/commit/4cfa571)), closes [#22474](https://github.com/angular/angular/issues/22474)
|
||||
* **router:** correct the segment parsing so it won't break on ampersand ([#23684](https://github.com/angular/angular/issues/23684)) ([553a680](https://github.com/angular/angular/commit/553a680))
|
||||
* **service-worker:** don't include sourceMappingURL in ngsw-worker ([#24877](https://github.com/angular/angular/issues/24877)) ([8620373](https://github.com/angular/angular/commit/8620373)), closes [#23596](https://github.com/angular/angular/issues/23596)
|
||||
* **service-worker:** avoid network requests when looking up hashed resources in cache ([#24127](https://github.com/angular/angular/issues/24127)) ([52d43a9](https://github.com/angular/angular/commit/52d43a9))
|
||||
* **service-worker:** fix `SwPush.unsubscribe()` ([#24162](https://github.com/angular/angular/issues/24162)) ([3ed2d75](https://github.com/angular/angular/commit/3ed2d75)), closes [#24095](https://github.com/angular/angular/issues/24095)
|
||||
* **service-worker:** add badge to NOTIFICATION_OPTION_NAMES ([#23241](https://github.com/angular/angular/issues/23241)) ([fb59b2d](https://github.com/angular/angular/commit/fb59b2d)), closes [#23196](https://github.com/angular/angular/issues/23196)
|
||||
* **service-worker:** check platformBrowser before accessing navigator.serviceWorker ([#21231](https://github.com/angular/angular/issues/21231)) ([0bdd30e](https://github.com/angular/angular/commit/0bdd30e))
|
||||
* **service-worker:** correctly handle requests with empty `clientId` ([#23625](https://github.com/angular/angular/issues/23625)) ([e0ed59e](https://github.com/angular/angular/commit/e0ed59e)), closes [#23526](https://github.com/angular/angular/issues/23526)
|
||||
* **service-worker:** deprecate `versionedFiles` in asset-group resources ([#23584](https://github.com/angular/angular/issues/23584)) ([1d378e2](https://github.com/angular/angular/commit/1d378e2))
|
||||
|
||||
### Features
|
||||
|
||||
* **bazel:** Initial commit of protractor_web_test_suite ([#24787](https://github.com/angular/angular/issues/24787)) ([71e0df0](https://github.com/angular/angular/commit/71e0df0))
|
||||
* **bazel:** protractor_web_test_suite for release ([#24787](https://github.com/angular/angular/issues/24787)) ([161ff5c](https://github.com/angular/angular/commit/161ff5c))
|
||||
* **common:** introduce KeyValuePipe ([#24319](https://github.com/angular/angular/issues/24319)) ([2b49bf7](https://github.com/angular/angular/commit/2b49bf7))
|
||||
* **compiler:** support `// ...` and `// TODO` in mock compiler expectations ([#23441](https://github.com/angular/angular/issues/23441)) ([c6b206e](https://github.com/angular/angular/commit/c6b206e))
|
||||
* **compiler-cli:** update `tsickle` to `0.29.x` ([#24233](https://github.com/angular/angular/issues/24233)) ([f69ac67](https://github.com/angular/angular/commit/f69ac67))
|
||||
* **core:** export defaultKeyValueDiffers to private api ([#24319](https://github.com/angular/angular/issues/24319)) ([92b278c](https://github.com/angular/angular/commit/92b278c))
|
||||
* **core:** expose a Compiler API for accessing module ids from NgModule types ([#24258](https://github.com/angular/angular/issues/24258)) ([bd02b27](https://github.com/angular/angular/commit/bd02b27))
|
||||
* **core:** KeyValueDiffer#diff allows null values ([#24319](https://github.com/angular/angular/issues/24319)) ([52ce9d5](https://github.com/angular/angular/commit/52ce9d5))
|
||||
* **core:** add support for ShadowDOM v1 ([#24718](https://github.com/angular/angular/issues/24718)) ([3553977](https://github.com/angular/angular/commit/3553977))
|
||||
(https://github.com/angular/angular/commit/328971f)), closes [#24616](https://github.com/angular/angular/issues/24616)
|
||||
* **platform-browser:** add HammerJS lazy-loader symbols to public API ([#23943](https://github.com/angular/angular/issues/23943)) ([26fbf1d](https://github.com/angular/angular/commit/26fbf1d))
|
||||
* **platform-browser:** allow lazy-loading HammerJS ([#23906](https://github.com/angular/angular/issues/23906)) ([313bdce](https://github.com/angular/angular/commit/313bdce))
|
||||
* **platform-server:** use EventManagerPlugin on the server ([#24132](https://github.com/angular/angular/issues/24132)) ([d6595eb](https://github.com/angular/angular/commit/d6595eb))
|
||||
* **router:** add urlUpdateStrategy allow updating the browser URL at the beginning of navigation ([#24820](https://github.com/angular/angular/issues/24820)) ([328971f]
|
||||
* **router:** add navigation execution context info to activation hooks ([#24204](https://github.com/angular/angular/issues/24204)) ([20c463e](https://github.com/angular/angular/commit/20c463e)), closes [#24202](https://github.com/angular/angular/issues/24202)
|
||||
* **router:** implement scrolling restoration service ([#20030](https://github.com/angular/angular/issues/20030)) ([49c5234](https://github.com/angular/angular/commit/49c5234)), closes [#13636](https://github.com/angular/angular/issues/13636) [#10929](https://github.com/angular/angular/issues/10929) [#7791](https://github.com/angular/angular/issues/7791) [#6595](https://github.com/angular/angular/issues/6595)
|
||||
* **service-worker:** add support for `?` in SW config globbing ([#24105](https://github.com/angular/angular/issues/24105)) ([250527c](https://github.com/angular/angular/commit/250527c))
|
||||
* typescript 2.9 support ([#24652](https://github.com/angular/angular/issues/24652)) ([e3064d5](https://github.com/angular/angular/commit/e3064d5))
|
||||
|
||||
### build
|
||||
|
||||
* **bazel:** turn on preserve-symlinks ([#24881](https://github.com/angular/angular/issues/24881)) ([c438b5e](https://github.com/angular/angular/commit/c438b5e))
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **bazel:** Use of @angular/bazel rules now requires calling ng_setup_workspace() in your WORKSPACE file.
|
||||
|
||||
For example:
|
||||
|
||||
local_repository(
|
||||
name = "angular",
|
||||
path = "node_modules/@angular/bazel",
|
||||
)
|
||||
|
||||
load("@angular//:index.bzl", "ng_setup_workspace")
|
||||
|
||||
ng_setup_workspace()
|
||||
|
||||
<a name="6.0.9"></a>
|
||||
## [6.0.9](https://github.com/angular/angular/compare/6.0.8...6.0.9) (2018-07-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
* **common:** format fractional seconds ([#24844](https://github.com/angular/angular/issues/24844)) ([3c93d07](https://github.com/angular/angular/commit/3c93d07)), closes [#24831](https://github.com/angular/angular/issues/24831)
|
||||
|
||||
|
||||
<a name="6.0.8"></a>
|
||||
## [6.0.8](https://github.com/angular/angular/compare/6.0.7...6.0.8) (2018-07-11)
|
||||
|
||||
@ -48,15 +178,6 @@
|
||||
|
||||
* **core:** add support for ShadowDOM v1 ([#24718](https://github.com/angular/angular/issues/24718)) ([6c55a13](https://github.com/angular/angular/commit/6c55a13))
|
||||
|
||||
|
||||
<a name="6.1.0-beta.3"></a>
|
||||
# [6.1.0-beta.3](https://github.com/angular/angular/compare/6.1.0-beta.2...6.1.0-beta.3) (2018-06-28)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **animations:** set animations styles properly on platform-server ([#24624](https://github.com/angular/angular/issues/24624)) ([0b356d4](https://github.com/angular/angular/commit/0b356d4))
|
||||
* **common:** use correct ICU plural for locale mk ([#24659](https://github.com/angular/angular/issues/24659)) ([64a8584](https://github.com/angular/angular/commit/64a8584))
|
||||
|
||||
<a name="6.0.7"></a>
|
||||
## [6.0.7](https://github.com/angular/angular/compare/6.0.6...6.0.7) (2018-06-27)
|
||||
|
||||
@ -66,18 +187,6 @@
|
||||
* **animations:** set animations styles properly on platform-server ([#24624](https://github.com/angular/angular/issues/24624)) ([0b356d4](https://github.com/angular/angular/commit/0b356d4))
|
||||
* **common:** use correct ICU plural for locale mk ([#24659](https://github.com/angular/angular/issues/24659)) ([64a8584](https://github.com/angular/angular/commit/64a8584))
|
||||
|
||||
|
||||
|
||||
<a name="6.1.0-beta.2"></a>
|
||||
# [6.1.0-beta.2](https://github.com/angular/angular/compare/6.1.0-beta.1...6.1.0-beta.2) (2018-06-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler:** support `.` in import statements. ([#20634](https://github.com/angular/angular/issues/20634)) ([d8f7b29](https://github.com/angular/angular/commit/d8f7b29)), closes [#20363](https://github.com/angular/angular/issues/20363)
|
||||
* **core:** Injector correctly honors the @Self flag ([#24520](https://github.com/angular/angular/issues/24520)) ([ccbda9d](https://github.com/angular/angular/commit/ccbda9d))
|
||||
|
||||
|
||||
<a name="6.0.6"></a>
|
||||
## [6.0.6](https://github.com/angular/angular/compare/6.0.5...6.0.6) (2018-06-20)
|
||||
|
||||
@ -87,39 +196,6 @@
|
||||
* **compiler:** support `.` in import statements. ([#20634](https://github.com/angular/angular/issues/20634)) ([e543c73](https://github.com/angular/angular/commit/e543c73)), closes [#20363](https://github.com/angular/angular/issues/20363)
|
||||
* **core:** Injector correctly honors the @Self flag ([#24520](https://github.com/angular/angular/issues/24520)) ([f5b3661](https://github.com/angular/angular/commit/f5b3661))
|
||||
|
||||
|
||||
|
||||
<a name="6.1.0-beta.1"></a>
|
||||
# [6.1.0-beta.1](https://github.com/angular/angular/compare/6.1.0-beta.0...6.1.0-beta.1) (2018-06-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **animations:** always render end-state styles for orphaned DOM nodes ([#24236](https://github.com/angular/angular/issues/24236)) ([dc4a3d0](https://github.com/angular/angular/commit/dc4a3d0))
|
||||
* **bazel:** Allow ng_module to depend on targets w no deps ([#24446](https://github.com/angular/angular/issues/24446)) ([282d351](https://github.com/angular/angular/commit/282d351))
|
||||
* **docs-infra:** use script nomodule to load IE polyfills, skip other polyfills ([#24317](https://github.com/angular/angular/issues/24317)) ([8be6892](https://github.com/angular/angular/commit/8be6892)), closes [#23647](https://github.com/angular/angular/issues/23647)
|
||||
* **ivy:** compute transitive scopes from NgModuleDef only ([#24334](https://github.com/angular/angular/issues/24334)) ([1135563](https://github.com/angular/angular/commit/1135563))
|
||||
* **ivy:** correctly handle queries with embedded views ([#24418](https://github.com/angular/angular/issues/24418)) ([014949f](https://github.com/angular/angular/commit/014949f))
|
||||
* **ivy:** remove debugger statement ([#24480](https://github.com/angular/angular/issues/24480)) ([70ef061](https://github.com/angular/angular/commit/70ef061))
|
||||
* **ivy:** special case [style] and [class] bindings for future use ([#23232](https://github.com/angular/angular/issues/23232)) ([1b253e1](https://github.com/angular/angular/commit/1b253e1))
|
||||
* **router:** fix lazy loading of aux routes ([#23459](https://github.com/angular/angular/issues/23459)) ([5731d07](https://github.com/angular/angular/commit/5731d07)), closes [#10981](https://github.com/angular/angular/issues/10981)
|
||||
* **service-worker:** fix `SwPush.unsubscribe()` ([#24162](https://github.com/angular/angular/issues/24162)) ([3ed2d75](https://github.com/angular/angular/commit/3ed2d75)), closes [#24095](https://github.com/angular/angular/issues/24095)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **common:** introduce KeyValuePipe ([#24319](https://github.com/angular/angular/issues/24319)) ([2b49bf7](https://github.com/angular/angular/commit/2b49bf7))
|
||||
* **core:** export defaultKeyValueDiffers to private api ([#24319](https://github.com/angular/angular/issues/24319)) ([92b278c](https://github.com/angular/angular/commit/92b278c))
|
||||
* **core:** expose a Compiler API for accessing module ids from NgModule types ([#24258](https://github.com/angular/angular/issues/24258)) ([bd02b27](https://github.com/angular/angular/commit/bd02b27))
|
||||
* **core:** KeyValueDiffer#diff allows null values ([#24319](https://github.com/angular/angular/issues/24319)) ([52ce9d5](https://github.com/angular/angular/commit/52ce9d5))
|
||||
* **ivy:** a generic visitor which allows prefixing nodes for ngtsc ([#24230](https://github.com/angular/angular/issues/24230)) ([ca79e11](https://github.com/angular/angular/commit/ca79e11))
|
||||
* **ivy:** add support of ApplicationRef.bootstrapModuleFactory ([#23811](https://github.com/angular/angular/issues/23811)) ([e3759f7](https://github.com/angular/angular/commit/e3759f7))
|
||||
* **ivy:** namespaced attributes added to output instructions ([#24386](https://github.com/angular/angular/issues/24386)) ([82c5313](https://github.com/angular/angular/commit/82c5313))
|
||||
* **ivy:** now supports SVG and MathML elements ([#24377](https://github.com/angular/angular/issues/24377)) ([8c1ac28](https://github.com/angular/angular/commit/8c1ac28))
|
||||
* **router:** implement scrolling restoration service ([#20030](https://github.com/angular/angular/issues/20030)) ([49c5234](https://github.com/angular/angular/commit/49c5234)), closes [#13636](https://github.com/angular/angular/issues/13636) [#10929](https://github.com/angular/angular/issues/10929) [#7791](https://github.com/angular/angular/issues/7791) [#6595](https://github.com/angular/angular/issues/6595)
|
||||
|
||||
|
||||
|
||||
<a name="6.0.5"></a>
|
||||
## [6.0.5](https://github.com/angular/angular/compare/6.0.4...6.0.5) (2018-06-13)
|
||||
|
||||
@ -129,53 +205,6 @@
|
||||
* **router:** fix lazy loading of aux routes ([#23459](https://github.com/angular/angular/issues/23459)) ([d20877b](https://github.com/angular/angular/commit/d20877b)), closes [#10981](https://github.com/angular/angular/issues/10981)
|
||||
* **service-worker:** fix `SwPush.unsubscribe()` ([#24162](https://github.com/angular/angular/issues/24162)) ([ea2987c](https://github.com/angular/angular/commit/ea2987c)), closes [#24095](https://github.com/angular/angular/issues/24095)
|
||||
|
||||
|
||||
|
||||
<a name="6.1.0-beta.0"></a>
|
||||
# [6.1.0-beta.0](https://github.com/angular/angular/compare/6.0.0-rc.5...6.1.0-beta.0) (2018-06-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **animations:** do not throw errors when a destroyed component is animated ([#23836](https://github.com/angular/angular/issues/23836)) ([d2a8687](https://github.com/angular/angular/commit/d2a8687))
|
||||
* **animations:** Fix browser detection logic ([#24188](https://github.com/angular/angular/issues/24188)) ([b492b9e](https://github.com/angular/angular/commit/b492b9e))
|
||||
* **animations:** properly clean up queried element styles in safari/edge ([#23633](https://github.com/angular/angular/issues/23633)) ([da9ff25](https://github.com/angular/angular/commit/da9ff25))
|
||||
* **animations:** retain state styling for nodes that are moved around ([#23534](https://github.com/angular/angular/issues/23534)) ([65211f4](https://github.com/angular/angular/commit/65211f4))
|
||||
* **animations:** retain trigger-state for nodes that are moved around ([#24238](https://github.com/angular/angular/issues/24238)) ([8db928d](https://github.com/angular/angular/commit/8db928d))
|
||||
* **benchpress:** Fix promise chain in chrome_driver_extension. ([#23458](https://github.com/angular/angular/issues/23458)) ([d4b6c41](https://github.com/angular/angular/commit/d4b6c41))
|
||||
* **compiler:** avoid a crash in ngc-wrapped. ([#23468](https://github.com/angular/angular/issues/23468)) ([e1c4930](https://github.com/angular/angular/commit/e1c4930))
|
||||
* **compiler:** generate constant array for i18n attributes ([#23837](https://github.com/angular/angular/issues/23837)) ([cfde36d](https://github.com/angular/angular/commit/cfde36d))
|
||||
* **compiler:** generate core-compliant hostBindings property ([#24087](https://github.com/angular/angular/issues/24087)) ([01b5acd](https://github.com/angular/angular/commit/01b5acd)), closes [#24013](https://github.com/angular/angular/issues/24013)
|
||||
* **compiler:** handle undefined annotation metadata ([#23349](https://github.com/angular/angular/issues/23349)) ([ca776c5](https://github.com/angular/angular/commit/ca776c5))
|
||||
* **compiler-cli:** don't rely on incompatible TS method ([#23550](https://github.com/angular/angular/issues/23550)) ([b1f040f](https://github.com/angular/angular/commit/b1f040f))
|
||||
* **core:** avoid eager providers re-initialization ([#23559](https://github.com/angular/angular/issues/23559)) ([0c6dc45](https://github.com/angular/angular/commit/0c6dc45))
|
||||
* **core:** call ngOnDestroy on all services that have it ([#23755](https://github.com/angular/angular/issues/23755)) ([fc03427](https://github.com/angular/angular/commit/fc03427)), closes [#22466](https://github.com/angular/angular/issues/22466) [#22240](https://github.com/angular/angular/issues/22240) [#14818](https://github.com/angular/angular/issues/14818)
|
||||
* **elements:** always check to create strategy ([#23825](https://github.com/angular/angular/issues/23825)) ([b1cda36](https://github.com/angular/angular/commit/b1cda36))
|
||||
* **elements:** prevent closure renaming of platform properties ([#23843](https://github.com/angular/angular/issues/23843)) ([d4b8b24](https://github.com/angular/angular/commit/d4b8b24))
|
||||
* **forms:** properly handle special properties in FormGroup.get ([#22249](https://github.com/angular/angular/issues/22249)) ([9367e91](https://github.com/angular/angular/commit/9367e91)), closes [#17195](https://github.com/angular/angular/issues/17195)
|
||||
* **platform-server:** avoid clash between server and client style encapsulation attributes ([#24158](https://github.com/angular/angular/issues/24158)) ([b96a3c8](https://github.com/angular/angular/commit/b96a3c8))
|
||||
* **platform-server:** avoid dependency cycle when using http interceptor ([#24229](https://github.com/angular/angular/issues/24229)) ([60aa943](https://github.com/angular/angular/commit/60aa943)), closes [#23023](https://github.com/angular/angular/issues/23023)
|
||||
* **platform-server:** don't reflect innerHTML property to attibute ([#24213](https://github.com/angular/angular/issues/24213)) ([6a663a4](https://github.com/angular/angular/commit/6a663a4)), closes [#19278](https://github.com/angular/angular/issues/19278)
|
||||
* **platform-server:** provide Domino DOM types globally ([#24116](https://github.com/angular/angular/issues/24116)) ([c73196e](https://github.com/angular/angular/commit/c73196e)), closes [#23280](https://github.com/angular/angular/issues/23280) [#23133](https://github.com/angular/angular/issues/23133)
|
||||
* **router:** avoid freezing queryParams in-place ([#22663](https://github.com/angular/angular/issues/22663)) ([89f64e5](https://github.com/angular/angular/commit/89f64e5)), closes [#22617](https://github.com/angular/angular/issues/22617)
|
||||
* **router:** cache route handle if found ([#22475](https://github.com/angular/angular/issues/22475)) ([4cfa571](https://github.com/angular/angular/commit/4cfa571)), closes [#22474](https://github.com/angular/angular/issues/22474)
|
||||
* **router:** correct the segment parsing so it won't break on ampersand ([#23684](https://github.com/angular/angular/issues/23684)) ([553a680](https://github.com/angular/angular/commit/553a680))
|
||||
* **service-worker:** add badge to NOTIFICATION_OPTION_NAMES ([#23241](https://github.com/angular/angular/issues/23241)) ([fb59b2d](https://github.com/angular/angular/commit/fb59b2d)), closes [#23196](https://github.com/angular/angular/issues/23196)
|
||||
* **service-worker:** check platformBrowser before accessing navigator.serviceWorker ([#21231](https://github.com/angular/angular/issues/21231)) ([0bdd30e](https://github.com/angular/angular/commit/0bdd30e))
|
||||
* **service-worker:** correctly handle requests with empty `clientId` ([#23625](https://github.com/angular/angular/issues/23625)) ([e0ed59e](https://github.com/angular/angular/commit/e0ed59e)), closes [#23526](https://github.com/angular/angular/issues/23526)
|
||||
* **service-worker:** deprecate `versionedFiles` in asset-group resources ([#23584](https://github.com/angular/angular/issues/23584)) ([1d378e2](https://github.com/angular/angular/commit/1d378e2))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **compiler:** support `// ...` and `// TODO` in mock compiler expectations ([#23441](https://github.com/angular/angular/issues/23441)) ([c6b206e](https://github.com/angular/angular/commit/c6b206e))
|
||||
* **compiler-cli:** update `tsickle` to `0.29.x` ([#24233](https://github.com/angular/angular/issues/24233)) ([f69ac67](https://github.com/angular/angular/commit/f69ac67))
|
||||
* **platform-browser:** add HammerJS lazy-loader symbols to public API ([#23943](https://github.com/angular/angular/issues/23943)) ([26fbf1d](https://github.com/angular/angular/commit/26fbf1d))
|
||||
* **platform-browser:** allow lazy-loading HammerJS ([#23906](https://github.com/angular/angular/issues/23906)) ([313bdce](https://github.com/angular/angular/commit/313bdce))
|
||||
* **platform-server:** use EventManagerPlugin on the server ([#24132](https://github.com/angular/angular/issues/24132)) ([d6595eb](https://github.com/angular/angular/commit/d6595eb))
|
||||
* **router:** add navigation execution context info to activation hooks ([#24204](https://github.com/angular/angular/issues/24204)) ([20c463e](https://github.com/angular/angular/commit/20c463e)), closes [#24202](https://github.com/angular/angular/issues/24202)
|
||||
|
||||
|
||||
<a name="6.0.4"></a>
|
||||
## [6.0.4](https://github.com/angular/angular/compare/6.0.3...6.0.4) (2018-06-06)
|
||||
|
||||
@ -254,7 +283,6 @@ To learn about the release highlights and our new CLI-powered update workflow fo
|
||||
* **animations:** only use the WA-polyfill alongside AnimationBuilder ([#22143](https://github.com/angular/angular/issues/22143)) ([b2f366b](https://github.com/angular/angular/commit/b2f366b)), closes [#17496](https://github.com/angular/angular/issues/17496)
|
||||
* **animations:** expose `element` and `params` within transition matchers ([#22693](https://github.com/angular/angular/issues/22693)) ([58b94e6](https://github.com/angular/angular/commit/58b94e6))
|
||||
* **common:** better error message when non-template element used in NgIf ([#22274](https://github.com/angular/angular/issues/22274)) ([67cf11d](https://github.com/angular/angular/commit/67cf11d)), closes [#16410](https://github.com/angular/angular/issues/16410)
|
||||
* **common:** better error message when non-template element used in NgIf ([#22274](https://github.com/angular/angular/issues/22274)) ([67cf11d](https://github.com/angular/angular/commit/67cf11d)), closes [#16410](https://github.com/angular/angular/issues/16410)
|
||||
* **common:** export functions to format numbers, percents, currencies & dates ([#22423](https://github.com/angular/angular/issues/22423)) ([4180912](https://github.com/angular/angular/commit/4180912)), closes [#20536](https://github.com/angular/angular/issues/20536)
|
||||
* **compiler:** lower @NgModule ids if needed ([#23031](https://github.com/angular/angular/issues/23031)) ([bd024c0](https://github.com/angular/angular/commit/bd024c0))
|
||||
* **compiler:** implement "enableIvy" compiler option ([#21427](https://github.com/angular/angular/issues/21427)) ([64d16de](https://github.com/angular/angular/commit/64d16de))
|
||||
@ -294,7 +322,6 @@ To learn about the release highlights and our new CLI-powered update workflow fo
|
||||
* **animations:** report correct totalTime value even during noOp animations ([#22225](https://github.com/angular/angular/issues/22225)) ([e1bf067](https://github.com/angular/angular/commit/e1bf067))
|
||||
* **animations:** avoid animation insertions during router back/refresh ([#21977](https://github.com/angular/angular/issues/21977)) ([f88fba0](https://github.com/angular/angular/commit/f88fba0)), closes [#19712](https://github.com/angular/angular/issues/19712)
|
||||
* **animations:** treat numeric state name values as strings ([#22923](https://github.com/angular/angular/issues/22923)) ([e5e1b0d](https://github.com/angular/angular/commit/e5e1b0d))
|
||||
* **animations:** report correct totalTime value even during noOp animations ([#22225](https://github.com/angular/angular/issues/22225)) ([e1bf067](https://github.com/angular/angular/commit/e1bf067))
|
||||
* **animations:** fix increment/decrement aliases example ([#18323](https://github.com/angular/angular/issues/18323)) ([d2aa8ac](https://github.com/angular/angular/commit/d2aa8ac))
|
||||
* **common:** NgClass should properly take className changes into account ([#21937](https://github.com/angular/angular/issues/21937)) ([4a42669](https://github.com/angular/angular/commit/4a42669)), closes [#21932](https://github.com/angular/angular/issues/21932)
|
||||
* **common:** fix the titlecase pipe ([#22600](https://github.com/angular/angular/issues/22600)) ([7966744](https://github.com/angular/angular/commit/7966744))
|
||||
|
86
WORKSPACE
86
WORKSPACE
@ -6,23 +6,30 @@ workspace(name = "angular")
|
||||
|
||||
http_archive(
|
||||
name = "build_bazel_rules_nodejs",
|
||||
url = "https://github.com/bazelbuild/rules_nodejs/archive/0.10.1.zip",
|
||||
strip_prefix = "rules_nodejs-0.10.1",
|
||||
sha256 = "634206524d90dc03c52392fa3f19a16637d2bcf154910436fe1d669a0d9d7b9c",
|
||||
urls = ["https://github.com/bazelbuild/rules_nodejs/archive/0.11.2.zip"],
|
||||
strip_prefix = "rules_nodejs-0.11.2",
|
||||
sha256 = "c00d5381adeefb56e0ef959a7b168cae628535dab933cfad1c2cd1870cd7c9de",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "bazel_skylib",
|
||||
urls = ["https://github.com/bazelbuild/bazel-skylib/archive/0.3.1.zip"],
|
||||
strip_prefix = "bazel-skylib-0.3.1",
|
||||
sha256 = "95518adafc9a2b656667bbf517a952e54ce7f350779d0dd95133db4eb5c27fb1",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "io_bazel_rules_webtesting",
|
||||
url = "https://github.com/bazelbuild/rules_webtesting/archive/v0.2.0.zip",
|
||||
strip_prefix = "rules_webtesting-0.2.0",
|
||||
sha256 = "cecc12f07e95740750a40d38e8b14b76fefa1551bef9332cb432d564d693723c",
|
||||
url = "https://github.com/bazelbuild/rules_webtesting/archive/7ffe970bbf380891754487f66c3d680c087d67f2.zip",
|
||||
strip_prefix = "rules_webtesting-7ffe970bbf380891754487f66c3d680c087d67f2",
|
||||
sha256 = "4fb0dca8c9a90547891b7ef486592775a523330fc4555c88cd8f09270055c2ce",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "build_bazel_rules_typescript",
|
||||
url = "https://github.com/rkirov/rules_typescript/archive/v0.16.0.zip",
|
||||
strip_prefix = "rules_typescript-0.16.0",
|
||||
sha256 = "f5aedd3a792e5af19cd0c0f0318cb692e2989e816e896e794152d07808fccacd",
|
||||
url = "https://github.com/bazelbuild/rules_typescript/archive/1d9a4b0087f307e31af91e2b221a6447288994c6.zip",
|
||||
strip_prefix = "rules_typescript-1d9a4b0087f307e31af91e2b221a6447288994c6",
|
||||
sha256 = "e17ac3f33d5d3cd2a0c385c4fd28b814d0ad46c6c67ccaef97160be99d7a24eb",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@ -58,7 +65,7 @@ http_archive(
|
||||
# Even better, things like aspects will visit the entire graph including
|
||||
# ts_library rules in the devkit repository.
|
||||
http_archive(
|
||||
name = "angular_devkit",
|
||||
name = "angular_cli",
|
||||
url = "https://github.com/angular/angular-cli/archive/v6.1.0-rc.0.zip",
|
||||
strip_prefix = "angular-cli-6.1.0-rc.0",
|
||||
sha256 = "8cf320ea58c321e103f39087376feea502f20eaf79c61a4fdb05c7286c8684fd",
|
||||
@ -71,32 +78,6 @@ http_archive(
|
||||
sha256 = "8a517806d2b7c8505ba5c53934e7d7c70d341b68ffd268e9044d35b564a48828",
|
||||
)
|
||||
|
||||
#
|
||||
# Load and install our dependencies downloaded above.
|
||||
#
|
||||
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories", "yarn_install")
|
||||
|
||||
check_bazel_version("0.14.0")
|
||||
node_repositories(package_json = ["//:package.json"])
|
||||
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains")
|
||||
|
||||
go_rules_dependencies()
|
||||
go_register_toolchains()
|
||||
|
||||
load("@io_bazel_rules_webtesting//web:repositories.bzl", "browser_repositories", "web_test_repositories")
|
||||
|
||||
web_test_repositories()
|
||||
browser_repositories(
|
||||
chromium = True,
|
||||
firefox = True,
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")
|
||||
|
||||
ts_setup_workspace()
|
||||
|
||||
#
|
||||
# Point Bazel to WORKSPACEs that live in subdirectories
|
||||
#
|
||||
@ -113,6 +94,39 @@ local_repository(
|
||||
path = "integration/bazel",
|
||||
)
|
||||
|
||||
#
|
||||
# Load and install our dependencies downloaded above.
|
||||
#
|
||||
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories", "yarn_install")
|
||||
|
||||
check_bazel_version("0.15.0")
|
||||
node_repositories(
|
||||
package_json = ["//:package.json"],
|
||||
preserve_symlinks = True,
|
||||
)
|
||||
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains")
|
||||
|
||||
go_rules_dependencies()
|
||||
go_register_toolchains()
|
||||
|
||||
load("@io_bazel_rules_webtesting//web:repositories.bzl", "browser_repositories", "web_test_repositories")
|
||||
|
||||
web_test_repositories()
|
||||
browser_repositories(
|
||||
chromium = True,
|
||||
firefox = True,
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")
|
||||
|
||||
ts_setup_workspace()
|
||||
|
||||
load("@angular//:index.bzl", "ng_setup_workspace")
|
||||
|
||||
ng_setup_workspace()
|
||||
|
||||
#
|
||||
# Ask Bazel to manage these toolchain dependencies for us.
|
||||
# Bazel will run `yarn install` when one of these toolchains is requested during
|
||||
|
@ -43,6 +43,17 @@ Here are the most important tasks you might need to use:
|
||||
|
||||
* `yarn build-ie-polyfills` - generates a js file of polyfills that can be loaded in Internet Explorer.
|
||||
|
||||
## Developing on Windows
|
||||
The `packages/` directory may contain Linux-specific symlinks, which are not recognized by Windows.
|
||||
These unresolved links cause the docs generation process to fail because it cannot locate certain files.
|
||||
|
||||
> Hint: The following steps require administration rights or [Windows Developer Mode](https://docs.microsoft.com/en-us/windows/uwp/get-started/enable-your-device-for-development) enabled!
|
||||
|
||||
To fix this problem, run `scripts/windows/create-symlinks.sh`. This command creates temporary files where the symlinks used to be. Make sure not to commit those files with your documentation changes.
|
||||
When you are done making and testing your documentation changes, you can restore the original symlinks and delete the temporary files by running `scripts/windows/remove-symlinks.sh`.
|
||||
|
||||
It's necessary to remove the temporary files, because otherwise they're displayed as local changes in your git working copy and certain operations are blocked.
|
||||
|
||||
## Using ServiceWorker locally
|
||||
|
||||
Since abb36e3cb, running `yarn start --prod` will no longer set up the ServiceWorker, which
|
||||
|
@ -5,7 +5,7 @@
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { HttpModule } from '@angular/http';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
// #docregion directive-import
|
||||
@ -24,7 +24,7 @@ import { ItemDirective } from './item.directive';
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
HttpModule
|
||||
HttpClientModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
|
@ -1,7 +1,7 @@
|
||||
// #docregion
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { HttpModule } from '@angular/http';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
|
||||
// import { AppRoutingModule } from './app-routing.module';
|
||||
import { LocationStrategy,
|
||||
@ -54,7 +54,7 @@ const c_components = [
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
HttpModule,
|
||||
HttpClientModule,
|
||||
InMemoryWebApiModule.forRoot(HeroData)
|
||||
// AppRoutingModule TODO: add routes
|
||||
],
|
||||
|
@ -1,26 +1,38 @@
|
||||
import { ReflectiveInjector } from '@angular/core';
|
||||
import { Injector } from '@angular/core';
|
||||
|
||||
import { Car, Engine, Tires } from './car';
|
||||
import { Logger } from '../logger.service';
|
||||
|
||||
// #docregion injector
|
||||
export function useInjector() {
|
||||
let injector: ReflectiveInjector;
|
||||
let injector: Injector;
|
||||
// #enddocregion injector
|
||||
/*
|
||||
// #docregion injector-no-new
|
||||
// Cannot instantiate an ReflectiveInjector like this!
|
||||
let injector = new ReflectiveInjector([Car, Engine, Tires]);
|
||||
// Cannot instantiate an Injector like this!
|
||||
let injector = new Injector([
|
||||
{ provide: Car, deps: [Engine, Tires] },
|
||||
{ provide: Engine, deps: [] },
|
||||
{ provide: Tires, deps: [] }
|
||||
]);
|
||||
// #enddocregion injector-no-new
|
||||
*/
|
||||
// #docregion injector, injector-create-and-call
|
||||
injector = ReflectiveInjector.resolveAndCreate([Car, Engine, Tires]);
|
||||
injector = Injector.create({
|
||||
providers: [
|
||||
{ provide: Car, deps: [Engine, Tires] },
|
||||
{ provide: Engine, deps: [] },
|
||||
{ provide: Tires, deps: [] }
|
||||
]
|
||||
});
|
||||
// #docregion injector-call
|
||||
let car = injector.get(Car);
|
||||
// #enddocregion injector-call, injector-create-and-call
|
||||
car.description = 'Injector';
|
||||
|
||||
injector = ReflectiveInjector.resolveAndCreate([Logger]);
|
||||
injector = Injector.create({
|
||||
providers: [{ provide: Logger, deps: [] }]
|
||||
});
|
||||
let logger = injector.get(Logger);
|
||||
logger.log('Injector car.drive() said: ' + car.drive());
|
||||
return car;
|
||||
|
69
aio/content/examples/elements/e2e/src/app.e2e-spec.ts
Normal file
69
aio/content/examples/elements/e2e/src/app.e2e-spec.ts
Normal file
@ -0,0 +1,69 @@
|
||||
'use strict'; // necessary for es6 output in node
|
||||
|
||||
import { browser, by, element } from 'protractor';
|
||||
|
||||
/* tslint:disable:quotemark */
|
||||
describe('Elements', () => {
|
||||
const messageInput = element(by.css('input'));
|
||||
const popupButtons = element.all(by.css('button'));
|
||||
|
||||
beforeEach(() => browser.get(''));
|
||||
|
||||
describe('popup component', () => {
|
||||
const popupComponentButton = popupButtons.get(0);
|
||||
const popupComponent = element(by.css('popup-component'));
|
||||
const closeButton = popupComponent.element(by.css('button'));
|
||||
|
||||
it('should be displayed on button click', () => {
|
||||
expect(popupComponent.isPresent()).toBe(false);
|
||||
|
||||
popupComponentButton.click();
|
||||
expect(popupComponent.isPresent()).toBe(true);
|
||||
});
|
||||
|
||||
it('should display the specified message', () => {
|
||||
messageInput.clear();
|
||||
messageInput.sendKeys('Angular rocks!');
|
||||
|
||||
popupComponentButton.click();
|
||||
expect(popupComponent.getText()).toContain('Popup: Angular rocks!');
|
||||
});
|
||||
|
||||
it('should be closed on "close" button click', () => {
|
||||
popupComponentButton.click();
|
||||
expect(popupComponent.isPresent()).toBe(true);
|
||||
|
||||
closeButton.click();
|
||||
expect(popupComponent.isPresent()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('popup element', () => {
|
||||
const popupElementButton = popupButtons.get(1);
|
||||
const popupElement = element(by.css('popup-element'));
|
||||
const closeButton = popupElement.element(by.css('button'));
|
||||
|
||||
it('should be displayed on button click', () => {
|
||||
expect(popupElement.isPresent()).toBe(false);
|
||||
|
||||
popupElementButton.click();
|
||||
expect(popupElement.isPresent()).toBe(true);
|
||||
});
|
||||
|
||||
it('should display the specified message', () => {
|
||||
messageInput.clear();
|
||||
messageInput.sendKeys('Angular rocks!');
|
||||
|
||||
popupElementButton.click();
|
||||
expect(popupElement.getText()).toContain('Popup: Angular rocks!');
|
||||
});
|
||||
|
||||
it('should be closed on "close" button click', () => {
|
||||
popupElementButton.click();
|
||||
expect(popupElement.isPresent()).toBe(true);
|
||||
|
||||
closeButton.click();
|
||||
expect(popupElement.isPresent()).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
3
aio/content/examples/elements/example-config.json
Normal file
3
aio/content/examples/elements/example-config.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"projectType": "elements"
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
// #docregion
|
||||
import { Component, Injector } from '@angular/core';
|
||||
import { createNgElementConstructor } from '../elements-dist';
|
||||
import { createCustomElement } from '@angular/elements';
|
||||
import { PopupService } from './popup.service';
|
||||
import { PopupComponent } from './popup.component';
|
||||
|
||||
@ -8,19 +7,15 @@ import { PopupComponent } from './popup.component';
|
||||
selector: 'app-root',
|
||||
template: `
|
||||
<input #input value="Message">
|
||||
<button (click)="popup.showAsComponent(input.value)">
|
||||
Show as component </button>
|
||||
<button (click)="popup.showAsElement(input.value)">
|
||||
Show as element </button>
|
||||
`
|
||||
<button (click)="popup.showAsComponent(input.value)">Show as component</button>
|
||||
<button (click)="popup.showAsElement(input.value)">Show as element</button>
|
||||
`,
|
||||
})
|
||||
|
||||
export class AppComponent {
|
||||
constructor(private injector: Injector, public popup: PopupService) {
|
||||
// on init, convert PopupComponent to a custom element
|
||||
const PopupElement =
|
||||
createNgElementConstructor(PopupComponent, {injector: this.injector});
|
||||
// register the custom element with the browser.
|
||||
customElements.define('popup-element', PopupElement);
|
||||
constructor(injector: Injector, public popup: PopupService) {
|
||||
// Convert `PopupComponent` to a custom element.
|
||||
const PopupElement = createCustomElement(PopupComponent, {injector});
|
||||
// Register the custom element with the browser.
|
||||
customElements.define('popup-element', PopupElement);
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,21 @@
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { PopupService } from './popup.service';
|
||||
import { PopupComponent } from './popup.component';
|
||||
import { PopupService } from './popup.service';
|
||||
|
||||
// include the PopupService provider,
|
||||
// but exclude PopupComponent from compilation,
|
||||
// because it will be added dynamically
|
||||
// Include the `PopupService` provider,
|
||||
// but exclude `PopupComponent` from compilation,
|
||||
// because it will be added dynamically.
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent, PopupComponent],
|
||||
imports: [BrowserModule, BrowserAnimationsModule],
|
||||
providers: [PopupService],
|
||||
declarations: [AppComponent, PopupComponent],
|
||||
bootstrap: [AppComponent],
|
||||
entryComponents: [PopupComponent],
|
||||
})
|
||||
|
||||
export class AppModule {}
|
||||
export class AppModule {
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
// #docregion
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { AnimationEvent } from '@angular/animations';
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
|
||||
@Component({
|
||||
selector: 'my-popup',
|
||||
template: 'Popup: {{message}}',
|
||||
template: `
|
||||
<span>Popup: {{message}}</span>
|
||||
<button (click)="closed.next()">✖</button>
|
||||
`,
|
||||
host: {
|
||||
'[@state]': 'state',
|
||||
'(@state.done)': 'onAnimationDone($event)',
|
||||
},
|
||||
animations: [
|
||||
trigger('state', [
|
||||
@ -27,13 +27,17 @@ import { animate, state, style, transition, trigger } from '@angular/animations'
|
||||
height: 48px;
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-top: 1px solid black;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 50%;
|
||||
}
|
||||
`]
|
||||
})
|
||||
|
||||
export class PopupComponent {
|
||||
private state: 'opened' | 'closed' = 'closed';
|
||||
|
||||
@ -41,18 +45,10 @@ export class PopupComponent {
|
||||
set message(message: string) {
|
||||
this._message = message;
|
||||
this.state = 'opened';
|
||||
|
||||
setTimeout(() => this.state = 'closed', 2000);
|
||||
}
|
||||
get message(): string { return this._message; }
|
||||
_message: string;
|
||||
|
||||
@Output()
|
||||
closed = new EventEmitter();
|
||||
|
||||
onAnimationDone(e: AnimationEvent) {
|
||||
if (e.toState === 'closed') {
|
||||
this.closed.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
|
||||
// #docregion
|
||||
import { ApplicationRef, ComponentFactoryResolver, Injectable, Injector } from '@angular/core';
|
||||
|
||||
import { NgElement, WithProperties } from '@angular/elements';
|
||||
import { PopupComponent } from './popup.component';
|
||||
import { NgElementConstructor } from '../elements-dist';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class PopupService {
|
||||
@ -40,7 +39,7 @@ export class PopupService {
|
||||
// This uses the new custom-element method to add the popup to the DOM.
|
||||
showAsElement(message: string) {
|
||||
// Create element
|
||||
const popupEl = document.createElement('popup-element');
|
||||
const popupEl: NgElement & WithProperties<PopupComponent> = document.createElement('popup-element') as any;
|
||||
|
||||
// Listen to the close event
|
||||
popupEl.addEventListener('closed', () => document.body.removeChild(popupEl));
|
||||
|
12
aio/content/examples/elements/src/index.html
Normal file
12
aio/content/examples/elements/src/index.html
Normal file
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<base href="/">
|
||||
<title>Elements</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</html>
|
@ -1,4 +1,3 @@
|
||||
// tslint:disable:no-unused-variable
|
||||
import { enableProdMode } from '@angular/core';
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
@ -10,4 +9,3 @@ if (environment.production) {
|
||||
}
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
|
9
aio/content/examples/elements/stackblitz.json
Normal file
9
aio/content/examples/elements/stackblitz.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"description": "Angular Elements",
|
||||
"files":[
|
||||
"!**/*.d.ts",
|
||||
"!**/*.js",
|
||||
"!**/*.[1].*"
|
||||
],
|
||||
"tags":["cookbook"]
|
||||
}
|
@ -1,15 +1,14 @@
|
||||
// #docplaster
|
||||
// #docregion app-module
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { HttpModule } from '@angular/http';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
// import the feature module here so you can add it to the imports array below
|
||||
import { CustomerDashboardModule } from './customer-dashboard/customer-dashboard.module';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
@ -17,7 +16,7 @@ import { CustomerDashboardModule } from './customer-dashboard/customer-dashboard
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
HttpModule,
|
||||
HttpClientModule,
|
||||
CustomerDashboardModule // add the feature module here
|
||||
],
|
||||
providers: [],
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { HttpModule } from '@angular/http';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
@NgModule({
|
||||
@ -13,7 +13,7 @@ import { AppComponent } from './app.component';
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
HttpModule,
|
||||
HttpClientModule,
|
||||
AppRoutingModule
|
||||
],
|
||||
providers: [],
|
||||
|
@ -1,7 +1,5 @@
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { HttpModule } from '@angular/http';
|
||||
|
||||
/* App Root */
|
||||
import { AppComponent } from './app.component';
|
||||
|
@ -15,7 +15,7 @@ function sequenceSubscriber(observer) {
|
||||
if (idx === arr.length - 1) {
|
||||
observer.complete();
|
||||
} else {
|
||||
doSequence(arr, idx++);
|
||||
doSequence(arr, ++idx);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
@ -95,7 +95,7 @@ function multicastSequenceSubscriber() {
|
||||
},
|
||||
complete() {
|
||||
// Notify all complete callbacks
|
||||
observers.forEach(obs => obs.complete());
|
||||
observers.slice(0).forEach(obs => obs.complete());
|
||||
}
|
||||
}, seq, 0);
|
||||
}
|
||||
@ -121,13 +121,13 @@ function doSequence(observer, arr, idx) {
|
||||
if (idx === arr.length - 1) {
|
||||
observer.complete();
|
||||
} else {
|
||||
doSequence(observer, arr, idx++);
|
||||
doSequence(observer, arr, ++idx);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// Create a new Observable that will deliver the above sequence
|
||||
const multicastSequence = new Observable(multicastSequenceSubscriber);
|
||||
const multicastSequence = new Observable(multicastSequenceSubscriber());
|
||||
|
||||
// Subscribe starts the clock, and begins to emit after 1 second
|
||||
multicastSequence.subscribe({
|
||||
|
@ -1,26 +1,21 @@
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import {
|
||||
FlyingHeroesComponent,
|
||||
FlyingHeroesImpureComponent
|
||||
} from './flying-heroes.component';
|
||||
import { ExponentialStrengthPipe } from './exponential-strength.pipe';
|
||||
import { FetchJsonPipe } from './fetch-json.pipe';
|
||||
import { FlyingHeroesComponent, FlyingHeroesImpureComponent } from './flying-heroes.component';
|
||||
import { FlyingHeroesImpurePipe, FlyingHeroesPipe } from './flying-heroes.pipe';
|
||||
import { HeroAsyncMessageComponent } from './hero-async-message.component';
|
||||
import { HeroBirthdayComponent } from './hero-birthday1.component';
|
||||
import { HeroBirthday2Component } from './hero-birthday2.component';
|
||||
import { HeroListComponent } from './hero-list.component';
|
||||
import { PowerBoosterComponent } from './power-booster.component';
|
||||
import { PowerBoostCalculatorComponent } from './power-boost-calculator.component';
|
||||
import {
|
||||
FlyingHeroesPipe,
|
||||
FlyingHeroesImpurePipe
|
||||
} from './flying-heroes.pipe';
|
||||
import { FetchJsonPipe } from './fetch-json.pipe';
|
||||
import { ExponentialStrengthPipe } from './exponential-strength.pipe';
|
||||
import { PowerBoosterComponent } from './power-booster.component';
|
||||
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@ -43,6 +38,6 @@ import { ExponentialStrengthPipe } from './exponential-strength.pipe';
|
||||
FetchJsonPipe,
|
||||
ExponentialStrengthPipe
|
||||
],
|
||||
bootstrap: [ AppComponent ]
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
||||
|
@ -1,13 +1,14 @@
|
||||
// #docregion
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
|
||||
// #docregion pipe-metadata
|
||||
@Pipe({
|
||||
name: 'fetch',
|
||||
pure: false
|
||||
})
|
||||
// #enddocregion pipe-metadata
|
||||
export class FetchJsonPipe implements PipeTransform {
|
||||
export class FetchJsonPipe implements PipeTransform {
|
||||
private cachedData: any = null;
|
||||
private cachedUrl = '';
|
||||
|
||||
@ -17,7 +18,7 @@ export class FetchJsonPipe implements PipeTransform {
|
||||
if (url !== this.cachedUrl) {
|
||||
this.cachedData = null;
|
||||
this.cachedUrl = url;
|
||||
this.http.get(url).subscribe( result => this.cachedData = result );
|
||||
this.http.get(url).subscribe(result => this.cachedData = result);
|
||||
}
|
||||
|
||||
return this.cachedData;
|
||||
|
@ -1,3 +0,0 @@
|
||||
[1030/162525.401:ERROR:process_reader_win.cc(123)] NtOpenThread: {Acceso denegado} Un proceso ha solicitado acceso a un objeto, pero no se le han concedido esos derechos de acceso. (0xc0000022)
|
||||
[1030/162525.402:ERROR:exception_snapshot_win.cc(87)] thread ID 26896 not found in process
|
||||
[1030/162525.402:WARNING:crash_report_exception_handler.cc(62)] ProcessSnapshotWin::Initialize failed
|
File diff suppressed because it is too large
Load Diff
@ -1,24 +0,0 @@
|
||||
{
|
||||
"description": "Angular Reactive Forms (final)",
|
||||
"files":[
|
||||
"src/styles.css",
|
||||
|
||||
"src/app/app.component.ts",
|
||||
"src/app/app.component.html",
|
||||
"src/app/app.component.css",
|
||||
"src/app/app.module.ts",
|
||||
"src/app/data-model.ts",
|
||||
"src/app/hero.service.ts",
|
||||
"src/app/hero-detail/hero-detail.component.html",
|
||||
"src/app/hero-detail/hero-detail.component.ts",
|
||||
"src/app/hero-detail/hero-detail.component.css",
|
||||
"src/app/hero-list/hero-list.component.html",
|
||||
"src/app/hero-list/hero-list.component.ts",
|
||||
"src/app/hero-list/hero-list.component.css",
|
||||
|
||||
"src/main-final.ts",
|
||||
"src/index-final.html"
|
||||
],
|
||||
"main": "src/index-final.html",
|
||||
"tags": ["reactive", "forms"]
|
||||
}
|
@ -1,4 +1,10 @@
|
||||
<div class="container">
|
||||
<h1>Reactive Forms</h1>
|
||||
<app-hero-detail></app-hero-detail>
|
||||
</div>
|
||||
<!-- #docplaster -->
|
||||
<h1>Reactive Forms</h1>
|
||||
|
||||
<!-- #docregion app-name-editor-->
|
||||
<app-name-editor></app-name-editor>
|
||||
<!-- #enddocregion app-name-editor-->
|
||||
|
||||
<!-- #docregion app-profile-editor -->
|
||||
<app-profile-editor></app-profile-editor>
|
||||
<!-- #enddocregion app-profile-editor -->
|
@ -1,4 +1,17 @@
|
||||
<div class="container">
|
||||
<h1>Reactive Forms</h1>
|
||||
<app-hero-list></app-hero-list>
|
||||
</div>
|
||||
<!-- #docplaster -->
|
||||
<!-- #docregion app-name-editor -->
|
||||
<h1>Reactive Forms</h1>
|
||||
|
||||
<!-- #enddocregion app-name-editor -->
|
||||
<nav>
|
||||
<a (click)="toggleEditor('name')">Name Editor</a>
|
||||
<a (click)="toggleEditor('profile')">Profile Editor</a>
|
||||
</nav>
|
||||
|
||||
<!-- #docregion app-name-editor -->
|
||||
<app-name-editor *ngIf="showNameEditor"></app-name-editor>
|
||||
<!-- #enddocregion app-name-editor -->
|
||||
|
||||
<!-- #docregion app-profile-editor -->
|
||||
<app-profile-editor *ngIf="showProfileEditor"></app-profile-editor>
|
||||
<!-- #enddocregion app-profile-editor -->
|
||||
|
@ -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('app');
|
||||
}));
|
||||
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 reactive-forms!');
|
||||
}));
|
||||
});
|
@ -1,9 +1,24 @@
|
||||
// #docregion
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
export type EditorType = 'name' | 'profile';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
export class AppComponent { }
|
||||
export class AppComponent {
|
||||
editor: EditorType = 'name';
|
||||
|
||||
get showNameEditor() {
|
||||
return this.editor === 'name';
|
||||
}
|
||||
|
||||
get showProfileEditor() {
|
||||
return this.editor === 'profile';
|
||||
}
|
||||
|
||||
toggleEditor(type: EditorType) {
|
||||
this.editor = type;
|
||||
}
|
||||
}
|
||||
|
@ -1,45 +1,34 @@
|
||||
// #docplaster
|
||||
// #docregion
|
||||
// #docregion v1
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { ReactiveFormsModule } from '@angular/forms'; // <-- #1 import module
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
// #docregion imports
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { HeroDetailComponent } from './hero-detail/hero-detail.component';
|
||||
// #enddocregion v1
|
||||
// #docregion hero-service-list
|
||||
// add JavaScript imports
|
||||
import { HeroListComponent } from './hero-list/hero-list.component';
|
||||
import { HeroService } from './hero.service';
|
||||
// #docregion v1
|
||||
// #enddocregion imports
|
||||
import { AppComponent } from './app.component';
|
||||
import { NameEditorComponent } from './name-editor/name-editor.component';
|
||||
import { ProfileEditorComponent } from './profile-editor/profile-editor.component';
|
||||
|
||||
// #docregion imports
|
||||
@NgModule({
|
||||
// #enddocregion imports
|
||||
declarations: [
|
||||
AppComponent,
|
||||
HeroDetailComponent,
|
||||
// #enddocregion v1
|
||||
HeroListComponent // <--declare HeroListComponent
|
||||
// #docregion v1
|
||||
NameEditorComponent,
|
||||
ProfileEditorComponent
|
||||
],
|
||||
// #enddocregion hero-service-list
|
||||
// #docregion imports
|
||||
imports: [
|
||||
// #enddocregion imports
|
||||
BrowserModule,
|
||||
ReactiveFormsModule // <-- #2 add to @NgModule imports
|
||||
// #docregion imports
|
||||
// other imports ...
|
||||
ReactiveFormsModule
|
||||
],
|
||||
// #enddocregion v1
|
||||
// export for the DemoModule
|
||||
// #docregion hero-service-list
|
||||
// ...
|
||||
exports: [
|
||||
AppComponent,
|
||||
HeroDetailComponent,
|
||||
HeroListComponent // <-- export HeroListComponent
|
||||
],
|
||||
providers: [ HeroService ], // <-- provide HeroService
|
||||
// #enddocregion hero-service-list
|
||||
// #docregion v1
|
||||
bootstrap: [ AppComponent ]
|
||||
// #enddocregion imports
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
// #docregion imports
|
||||
})
|
||||
export class AppModule { }
|
||||
// #enddocregion v1
|
||||
// #enddocregion imports
|
||||
|
@ -1,40 +0,0 @@
|
||||
// #docregion
|
||||
// #docregion model-classes
|
||||
export class Hero {
|
||||
id = 0;
|
||||
name = '';
|
||||
addresses: Address[];
|
||||
}
|
||||
|
||||
export class Address {
|
||||
street = '';
|
||||
city = '';
|
||||
state = '';
|
||||
zip = '';
|
||||
}
|
||||
// #enddocregion model-classes
|
||||
|
||||
export const heroes: Hero[] = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Whirlwind',
|
||||
addresses: [
|
||||
{street: '123 Main', city: 'Anywhere', state: 'CA', zip: '94801'},
|
||||
{street: '456 Maple', city: 'Somewhere', state: 'VA', zip: '23226'},
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Bombastic',
|
||||
addresses: [
|
||||
{street: '789 Elm', city: 'Smallville', state: 'OH', zip: '04501'},
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Magneta',
|
||||
addresses: [ ]
|
||||
},
|
||||
];
|
||||
|
||||
export const states = ['CA', 'MD', 'OH', 'VA'];
|
@ -1,40 +0,0 @@
|
||||
<div class="container">
|
||||
<h1>Reactive Forms</h1>
|
||||
<h4><i>Pick a demo:</i>
|
||||
<select [selectedIndex]="demo - 1" (change)="selectDemo($event.target.selectedIndex)">
|
||||
<option *ngFor="let demo of demos">{{demo}}</option>
|
||||
</select>
|
||||
</h4>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="demo">
|
||||
<app-hero-list *ngIf="demo===final"></app-hero-list>
|
||||
<app-hero-detail-1 *ngIf="demo===1"></app-hero-detail-1>
|
||||
<app-hero-detail-2 *ngIf="demo===2"></app-hero-detail-2>
|
||||
<app-hero-detail-3 *ngIf="demo===3"></app-hero-detail-3>
|
||||
<app-hero-detail-4 *ngIf="demo===4"></app-hero-detail-4>
|
||||
<app-hero-detail-5 *ngIf="demo===5"></app-hero-detail-5>
|
||||
|
||||
<div *ngIf="demo >= 6 && demo !== final" >
|
||||
|
||||
<h3 *ngIf="isLoading"><i>Loading heroes ... </i></h3>
|
||||
<h3 *ngIf="!isLoading">Select a hero:</h3>
|
||||
|
||||
<nav>
|
||||
<button (click)="getHeroes()" class="btn btn-primary">Refresh</button>
|
||||
<a *ngFor="let hero of heroes | async" (click)="select(hero)">{{hero.name}}</a>
|
||||
</nav>
|
||||
|
||||
<div *ngIf="selectedHero">
|
||||
<hr>
|
||||
<h2>Hero Detail</h2>
|
||||
<h3>Editing: {{selectedHero.name}}</h3>
|
||||
<app-hero-detail-6 [hero]=selectedHero *ngIf="demo===6"></app-hero-detail-6>
|
||||
<app-hero-detail-7 [hero]=selectedHero *ngIf="demo===7"></app-hero-detail-7>
|
||||
<app-hero-detail-8 [hero]=selectedHero *ngIf="demo===8"></app-hero-detail-8>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,49 +0,0 @@
|
||||
/* tslint:disable:member-ordering */
|
||||
import { Component } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { finalize } from 'rxjs/operators';
|
||||
|
||||
import { Hero } from './data-model';
|
||||
import { HeroService } from './hero.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './demo.component.html'
|
||||
})
|
||||
export class DemoComponent {
|
||||
|
||||
demos: string[] = [
|
||||
'Just a FormControl',
|
||||
'FormControl in a FormGroup',
|
||||
'Simple FormBuilder group',
|
||||
'Group with multiple controls',
|
||||
'Nested FormBuilder group',
|
||||
'PatchValue',
|
||||
'SetValue',
|
||||
'FormArray',
|
||||
'Final'].map(n => n + ' Demo');
|
||||
|
||||
final = this.demos.length;
|
||||
demo = this.final; // current demo
|
||||
|
||||
heroes: Observable<Hero[]>;
|
||||
isLoading = false;
|
||||
selectedHero: Hero;
|
||||
|
||||
constructor(private heroService: HeroService) { }
|
||||
|
||||
getHeroes() {
|
||||
this.isLoading = true;
|
||||
this.heroes = this.heroService.getHeroes().pipe(
|
||||
finalize(() => this.isLoading = false)
|
||||
);
|
||||
this.selectedHero = undefined;
|
||||
}
|
||||
|
||||
select(hero: Hero) { this.selectedHero = hero; }
|
||||
|
||||
selectDemo(demo: number) {
|
||||
this.demo = demo + 1;
|
||||
this.getHeroes();
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
|
||||
import { AppModule } from './app.module';
|
||||
import { DemoComponent } from './demo.component';
|
||||
import { HeroDetailComponent1 } from './hero-detail/hero-detail-1.component';
|
||||
import { HeroDetailComponent2 } from './hero-detail/hero-detail-2.component';
|
||||
import { HeroDetailComponent3 } from './hero-detail/hero-detail-3.component';
|
||||
import { HeroDetailComponent4 } from './hero-detail/hero-detail-4.component';
|
||||
import { HeroDetailComponent5 } from './hero-detail/hero-detail-5.component';
|
||||
import { HeroDetailComponent6 } from './hero-detail/hero-detail-6.component';
|
||||
import { HeroDetailComponent7 } from './hero-detail/hero-detail-7.component';
|
||||
import { HeroDetailComponent8 } from './hero-detail/hero-detail-8.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
ReactiveFormsModule,
|
||||
AppModule,
|
||||
],
|
||||
declarations: [ DemoComponent,
|
||||
HeroDetailComponent1,
|
||||
HeroDetailComponent2,
|
||||
HeroDetailComponent3,
|
||||
HeroDetailComponent4,
|
||||
HeroDetailComponent5,
|
||||
HeroDetailComponent6,
|
||||
HeroDetailComponent7,
|
||||
HeroDetailComponent8],
|
||||
bootstrap: [ DemoComponent ]
|
||||
})
|
||||
export class DemoModule { }
|
@ -1,8 +0,0 @@
|
||||
<!-- #docregion simple-control-->
|
||||
<h2>Hero Detail</h2>
|
||||
<h3><i>Just a FormControl</i></h3>
|
||||
<label class="center-block">Name:
|
||||
<input class="form-control" [formControl]="name">
|
||||
</label>
|
||||
<!-- #enddocregion simple-control-->
|
||||
|
@ -1,15 +0,0 @@
|
||||
/* tslint:disable:component-class-suffix */
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
// #docregion import
|
||||
import { FormControl } from '@angular/forms';
|
||||
// #enddocregion import
|
||||
|
||||
@Component({
|
||||
selector: 'app-hero-detail-1',
|
||||
templateUrl: './hero-detail-1.component.html'
|
||||
})
|
||||
// #docregion v1
|
||||
export class HeroDetailComponent1 {
|
||||
name = new FormControl();
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
<!-- #docregion basic-form-->
|
||||
<h2>Hero Detail</h2>
|
||||
<h3><i>FormControl in a FormGroup</i></h3>
|
||||
<form [formGroup]="heroForm">
|
||||
<div class="form-group">
|
||||
<label class="center-block">Name:
|
||||
<input class="form-control" formControlName="name">
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
<!-- #enddocregion basic-form-->
|
||||
|
||||
<!-- #docregion form-value-json -->
|
||||
<p>Form value: {{ heroForm.value | json }}</p>
|
||||
<!-- #enddocregion form-value-json -->
|
||||
|
||||
|
||||
|
@ -1,17 +0,0 @@
|
||||
/* tslint:disable:component-class-suffix */
|
||||
// #docregion imports
|
||||
import { Component } from '@angular/core';
|
||||
import { FormControl, FormGroup } from '@angular/forms';
|
||||
// #enddocregion imports
|
||||
|
||||
@Component({
|
||||
selector: 'app-hero-detail-2',
|
||||
templateUrl: './hero-detail-2.component.html'
|
||||
})
|
||||
// #docregion v2
|
||||
export class HeroDetailComponent2 {
|
||||
heroForm = new FormGroup ({
|
||||
name: new FormControl()
|
||||
});
|
||||
}
|
||||
// #enddocregion v2
|
@ -1,16 +0,0 @@
|
||||
<!-- #docregion basic-form-->
|
||||
<h2>Hero Detail</h2>
|
||||
<h3><i>A FormGroup with a single FormControl using FormBuilder</i></h3>
|
||||
<form [formGroup]="heroForm">
|
||||
<div class="form-group">
|
||||
<label class="center-block">Name:
|
||||
<input class="form-control" formControlName="name">
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
<!-- #enddocregion basic-form-->
|
||||
|
||||
<!-- #docregion form-value-json -->
|
||||
<p>Form value: {{ heroForm.value | json }}</p>
|
||||
<p>Form status: {{ heroForm.status | json }}</p>
|
||||
<!-- #enddocregion form-value-json -->
|
@ -1,27 +0,0 @@
|
||||
/* tslint:disable:component-class-suffix */
|
||||
// #docregion imports
|
||||
import { Component } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
// #enddocregion imports
|
||||
|
||||
@Component({
|
||||
selector: 'app-hero-detail-3',
|
||||
templateUrl: './hero-detail-3.component.html'
|
||||
})
|
||||
// #docregion v3
|
||||
export class HeroDetailComponent3 {
|
||||
heroForm: FormGroup; // <--- heroForm is of type FormGroup
|
||||
|
||||
constructor(private fb: FormBuilder) { // <--- inject FormBuilder
|
||||
this.createForm();
|
||||
}
|
||||
|
||||
createForm() {
|
||||
// #docregion required
|
||||
this.heroForm = this.fb.group({
|
||||
name: ['', Validators.required ],
|
||||
});
|
||||
// #enddocregion required
|
||||
}
|
||||
}
|
||||
// #enddocregion v3
|
@ -1,25 +0,0 @@
|
||||
/* tslint:disable:component-class-suffix */
|
||||
// #docregion imports
|
||||
import { Component } from '@angular/core';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
// #enddocregion imports
|
||||
|
||||
@Component({
|
||||
selector: 'app-hero-detail-3',
|
||||
templateUrl: './hero-detail-3.component.html'
|
||||
})
|
||||
// #docregion v3a
|
||||
export class HeroDetailComponent3 {
|
||||
heroForm: FormGroup; // <--- heroForm is of type FormGroup
|
||||
|
||||
constructor(private fb: FormBuilder) { // <--- inject FormBuilder
|
||||
this.createForm();
|
||||
}
|
||||
|
||||
createForm() {
|
||||
this.heroForm = this.fb.group({
|
||||
name: '', // <--- the FormControl called "name"
|
||||
});
|
||||
}
|
||||
}
|
||||
// #enddocregion v3a
|
@ -1,46 +0,0 @@
|
||||
<!-- #docregion -->
|
||||
<h2>Hero Detail</h2>
|
||||
<h3><i>A FormGroup with multiple FormControls</i></h3>
|
||||
<form [formGroup]="heroForm">
|
||||
<div class="form-group">
|
||||
<label class="center-block">Name:
|
||||
<input class="form-control" formControlName="name">
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">Street:
|
||||
<input class="form-control" formControlName="street">
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">City:
|
||||
<input class="form-control" formControlName="city">
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">State:
|
||||
<select class="form-control" formControlName="state">
|
||||
<option *ngFor="let state of states" [value]="state">{{state}}</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">Zip Code:
|
||||
<input class="form-control" formControlName="zip">
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group radio">
|
||||
<h4>Super power:</h4>
|
||||
<label class="center-block"><input type="radio" formControlName="power" value="flight">Flight</label>
|
||||
<label class="center-block"><input type="radio" formControlName="power" value="x-ray vision">X-ray vision</label>
|
||||
<label class="center-block"><input type="radio" formControlName="power" value="strength">Strength</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label class="center-block">
|
||||
<input type="checkbox" formControlName="sidekick">I have a sidekick.
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
<p>Form value: {{ heroForm.value | json }}</p>
|
@ -1,34 +0,0 @@
|
||||
/* tslint:disable:component-class-suffix */
|
||||
// #docregion imports
|
||||
import { Component } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
|
||||
import { states } from '../data-model';
|
||||
// #enddocregion imports
|
||||
|
||||
@Component({
|
||||
selector: 'app-hero-detail-4',
|
||||
templateUrl: './hero-detail-4.component.html'
|
||||
})
|
||||
// #docregion v4
|
||||
export class HeroDetailComponent4 {
|
||||
heroForm: FormGroup;
|
||||
states = states;
|
||||
|
||||
constructor(private fb: FormBuilder) {
|
||||
this.createForm();
|
||||
}
|
||||
|
||||
createForm() {
|
||||
this.heroForm = this.fb.group({
|
||||
name: ['', Validators.required ],
|
||||
street: '',
|
||||
city: '',
|
||||
state: '',
|
||||
zip: '',
|
||||
power: '',
|
||||
sidekick: ''
|
||||
});
|
||||
}
|
||||
}
|
||||
// #enddocregion v4
|
@ -1,56 +0,0 @@
|
||||
|
||||
<form [formGroup]="heroForm">
|
||||
<div class="form-group">
|
||||
<label class="center-block">Name:
|
||||
<input class="form-control" formControlName="name">
|
||||
</label>
|
||||
</div>
|
||||
<!-- #docregion add-group-->
|
||||
<div formGroupName="address" class="well well-lg">
|
||||
<h4>Secret Lair</h4>
|
||||
<div class="form-group">
|
||||
<label class="center-block">Street:
|
||||
<input class="form-control" formControlName="street">
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">City:
|
||||
<input class="form-control" formControlName="city">
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">State:
|
||||
<select class="form-control" formControlName="state">
|
||||
<option *ngFor="let state of states" [value]="state">{{state}}</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">Zip Code:
|
||||
<input class="form-control" formControlName="zip">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- #enddocregion add-group-->
|
||||
<div class="form-group radio">
|
||||
<h4>Super power:</h4>
|
||||
<label class="center-block"><input type="radio" formControlName="power" value="flight">Flight</label>
|
||||
<label class="center-block"><input type="radio" formControlName="power" value="x-ray vision">X-ray vision</label>
|
||||
<label class="center-block"><input type="radio" formControlName="power" value="strength">Strength</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label class="center-block">
|
||||
<input type="checkbox" formControlName="sidekick">I have a sidekick.
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p>heroForm value: {{ heroForm.value | json}}</p>
|
||||
<h4>Extra info for the curious:</h4>
|
||||
<!-- #docregion inspect-value -->
|
||||
<p>Name value: {{ heroForm.get('name').value }}</p>
|
||||
<!-- #enddocregion inspect-value -->
|
||||
|
||||
<!-- #docregion inspect-child-control -->
|
||||
<p>Street value: {{ heroForm.get('address.street').value}}</p>
|
||||
<!-- #enddocregion inspect-child-control -->
|
@ -1,35 +0,0 @@
|
||||
/* tslint:disable:component-class-suffix */
|
||||
import { Component } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
|
||||
import { states } from '../data-model';
|
||||
|
||||
@Component({
|
||||
selector: 'app-hero-detail-5',
|
||||
templateUrl: './hero-detail-5.component.html'
|
||||
})
|
||||
// #docregion v5
|
||||
export class HeroDetailComponent5 {
|
||||
heroForm: FormGroup;
|
||||
states = states;
|
||||
|
||||
constructor(private fb: FormBuilder) {
|
||||
this.createForm();
|
||||
}
|
||||
|
||||
createForm() {
|
||||
this.heroForm = this.fb.group({ // <-- the parent FormGroup
|
||||
name: ['', Validators.required ],
|
||||
address: this.fb.group({ // <-- the child FormGroup
|
||||
street: '',
|
||||
city: '',
|
||||
state: '',
|
||||
zip: ''
|
||||
}),
|
||||
power: '',
|
||||
sidekick: ''
|
||||
});
|
||||
}
|
||||
}
|
||||
// #enddocregion v5
|
||||
|
@ -1,46 +0,0 @@
|
||||
<!-- #docregion -->
|
||||
<h2>Hero Detail</h2>
|
||||
<h3><i>PatchValue to initialize a value</i></h3>
|
||||
<form [formGroup]="heroForm">
|
||||
<div class="form-group">
|
||||
<label class="center-block">Name:
|
||||
<input class="form-control" formControlName="name">
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">Street:
|
||||
<input class="form-control" formControlName="street">
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">City:
|
||||
<input class="form-control" formControlName="city">
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">State:
|
||||
<select class="form-control" formControlName="state">
|
||||
<option *ngFor="let state of states" [value]="state">{{state}}</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">Zip Code:
|
||||
<input class="form-control" formControlName="zip">
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group radio">
|
||||
<h4>Super power:</h4>
|
||||
<label class="center-block"><input type="radio" formControlName="power" value="flight">Flight</label>
|
||||
<label class="center-block"><input type="radio" formControlName="power" value="x-ray vision">X-ray vision</label>
|
||||
<label class="center-block"><input type="radio" formControlName="power" value="strength">Strength</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label class="center-block">
|
||||
<input type="checkbox" formControlName="sidekick">I have a sidekick.
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
<p>Form value: {{ heroForm.value | json }}</p>
|
@ -1,66 +0,0 @@
|
||||
/* tslint:disable:component-class-suffix */
|
||||
// #docregion import-input
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
// #enddocregion import-input
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
|
||||
// #docregion import-hero
|
||||
import { Hero, states } from '../data-model';
|
||||
// #enddocregion import-hero
|
||||
|
||||
////////// 6 ////////////////////
|
||||
|
||||
@Component({
|
||||
selector: 'app-hero-detail-6',
|
||||
templateUrl: './hero-detail-5.component.html'
|
||||
})
|
||||
// #docregion v6
|
||||
export class HeroDetailComponent6 implements OnChanges {
|
||||
// #docregion hero
|
||||
@Input() hero: Hero;
|
||||
// #enddocregion hero
|
||||
|
||||
heroForm: FormGroup;
|
||||
states = states;
|
||||
|
||||
constructor(private fb: FormBuilder) {
|
||||
this.createForm();
|
||||
}
|
||||
|
||||
createForm() {
|
||||
// #docregion hero-form-model
|
||||
this.heroForm = this.fb.group({
|
||||
name: ['', Validators.required ],
|
||||
address: this.fb.group({
|
||||
street: '',
|
||||
city: '',
|
||||
state: '',
|
||||
zip: ''
|
||||
}),
|
||||
power: '',
|
||||
sidekick: ''
|
||||
});
|
||||
// #enddocregion hero-form-model
|
||||
}
|
||||
|
||||
// #docregion patch-value-on-changes
|
||||
ngOnChanges() { // <-- call rebuildForm in ngOnChanges
|
||||
this.rebuildForm();
|
||||
}
|
||||
// #enddocregion patch-value-on-changes
|
||||
|
||||
// #docregion patch-value-rebuildform
|
||||
rebuildForm() { // <-- wrap patchValue in rebuildForm
|
||||
this.heroForm.reset();
|
||||
// #docregion patch-value
|
||||
this.heroForm.patchValue({
|
||||
name: this.hero.name
|
||||
});
|
||||
// #enddocregion patch-value
|
||||
}
|
||||
// #enddocregion patch-value-rebuildform
|
||||
}
|
||||
|
||||
|
||||
|
||||
// #enddocregion v6
|
@ -1,46 +0,0 @@
|
||||
<!-- #docregion -->
|
||||
<h2>Hero Detail</h2>
|
||||
<h3><i>A FormGroup with multiple FormControls</i></h3>
|
||||
<form [formGroup]="heroForm">
|
||||
<div class="form-group">
|
||||
<label class="center-block">Name:
|
||||
<input class="form-control" formControlName="name">
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">Street:
|
||||
<input class="form-control" formControlName="street">
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">City:
|
||||
<input class="form-control" formControlName="city">
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">State:
|
||||
<select class="form-control" formControlName="state">
|
||||
<option *ngFor="let state of states" [value]="state">{{state}}</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">Zip Code:
|
||||
<input class="form-control" formControlName="zip">
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group radio">
|
||||
<h4>Super power:</h4>
|
||||
<label class="center-block"><input type="radio" formControlName="power" value="flight">Flight</label>
|
||||
<label class="center-block"><input type="radio" formControlName="power" value="x-ray vision">X-ray vision</label>
|
||||
<label class="center-block"><input type="radio" formControlName="power" value="strength">Strength</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label class="center-block">
|
||||
<input type="checkbox" formControlName="sidekick">I have a sidekick.
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
<p>Form value: {{ heroForm.value | json }}</p>
|
@ -1,68 +0,0 @@
|
||||
/* tslint:disable:component-class-suffix */
|
||||
// #docplaster
|
||||
// #docregion imports
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
|
||||
// #docregion import-address
|
||||
import { Address, Hero, states } from '../data-model';
|
||||
// #enddocregion import-address
|
||||
|
||||
// #enddocregion imports
|
||||
|
||||
@Component({
|
||||
selector: 'app-hero-detail-7',
|
||||
templateUrl: './hero-detail-5.component.html'
|
||||
})
|
||||
// #docregion v7
|
||||
export class HeroDetailComponent7 implements OnChanges {
|
||||
@Input() hero: Hero;
|
||||
|
||||
heroForm: FormGroup;
|
||||
states = states;
|
||||
|
||||
constructor(private fb: FormBuilder) {
|
||||
this.createForm();
|
||||
}
|
||||
|
||||
createForm() {
|
||||
// #docregion address-form-group
|
||||
this.heroForm = this.fb.group({
|
||||
name: ['', Validators.required ],
|
||||
address: this.fb.group(new Address()), // <-- a FormGroup with a new address
|
||||
power: '',
|
||||
sidekick: ''
|
||||
});
|
||||
// #enddocregion address-form-group
|
||||
}
|
||||
|
||||
// #docregion ngOnChanges
|
||||
ngOnChanges() {
|
||||
this.rebuildForm();
|
||||
}
|
||||
// #enddocregion ngOnChanges
|
||||
|
||||
// #docregion rebuildForm
|
||||
rebuildForm() {
|
||||
this.heroForm.reset({
|
||||
name: this.hero.name,
|
||||
// #docregion set-value-address
|
||||
address: this.hero.addresses[0] || new Address()
|
||||
// #enddocregion set-value-address
|
||||
});
|
||||
}
|
||||
// #enddocregion rebuildForm
|
||||
|
||||
/* First version of rebuildForm */
|
||||
rebuildForm1() {
|
||||
// #docregion reset
|
||||
this.heroForm.reset();
|
||||
// #enddocregion reset
|
||||
// #docregion set-value
|
||||
this.heroForm.setValue({
|
||||
name: this.hero.name,
|
||||
address: this.hero.addresses[0] || new Address()
|
||||
});
|
||||
// #enddocregion set-value
|
||||
}
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
<!-- #docplaster-->
|
||||
<h3><i>Using FormArray to add groups</i></h3>
|
||||
|
||||
<form [formGroup]="heroForm">
|
||||
<p>Form Changed: {{ heroForm.dirty }}</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="center-block">Name:
|
||||
<input class="form-control" formControlName="name">
|
||||
</label>
|
||||
</div>
|
||||
<!-- #docregion form-array-->
|
||||
<!-- #docregion form-array-skeleton -->
|
||||
<!-- #docregion form-array-name -->
|
||||
<div formArrayName="secretLairs" class="well well-lg">
|
||||
<!-- #enddocregion form-array-name -->
|
||||
<div *ngFor="let address of secretLairs.controls; let i=index" [formGroupName]="i" >
|
||||
<!-- The repeated address template -->
|
||||
<!-- #enddocregion form-array-skeleton -->
|
||||
<h4>Address #{{i + 1}}</h4>
|
||||
<div style="margin-left: 1em;">
|
||||
<div class="form-group">
|
||||
<label class="center-block">Street:
|
||||
<input class="form-control" formControlName="street">
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">City:
|
||||
<input class="form-control" formControlName="city">
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">State:
|
||||
<select class="form-control" formControlName="state">
|
||||
<option *ngFor="let state of states" [value]="state">{{state}}</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">Zip Code:
|
||||
<input class="form-control" formControlName="zip">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<!-- End of the repeated address template -->
|
||||
<!-- #docregion form-array-skeleton -->
|
||||
</div>
|
||||
<!-- #enddocregion form-array-skeleton -->
|
||||
<!-- #enddocregion form-array-->
|
||||
<!-- #docregion add-lair -->
|
||||
<button (click)="addLair()" type="button">Add a Secret Lair</button>
|
||||
<!-- #enddocregion add-lair -->
|
||||
<!-- #docregion form-array-->
|
||||
<!-- #docregion form-array-skeleton -->
|
||||
</div>
|
||||
<!-- #enddocregion form-array-skeleton -->
|
||||
<!-- #enddocregion form-array-->
|
||||
<div class="form-group radio">
|
||||
<h4>Super power:</h4>
|
||||
<label class="center-block"><input type="radio" formControlName="power" value="flight">Flight</label>
|
||||
<label class="center-block"><input type="radio" formControlName="power" value="x-ray vision">X-ray vision</label>
|
||||
<label class="center-block"><input type="radio" formControlName="power" value="strength">Strength</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label class="center-block">
|
||||
<input type="checkbox" formControlName="sidekick">I have a sidekick.
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p>heroForm value: {{ heroForm.value | json}}</p>
|
@ -1,74 +0,0 @@
|
||||
/* tslint:disable:component-class-suffix */
|
||||
// #docregion imports
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
|
||||
import { Address, Hero, states } from '../data-model';
|
||||
// #enddocregion imports
|
||||
|
||||
@Component({
|
||||
selector: 'app-hero-detail-8',
|
||||
templateUrl: './hero-detail-8.component.html'
|
||||
})
|
||||
// #docregion v8
|
||||
export class HeroDetailComponent8 implements OnChanges {
|
||||
@Input() hero: Hero;
|
||||
|
||||
heroForm: FormGroup;
|
||||
states = states;
|
||||
|
||||
// #docregion ctor
|
||||
constructor(private fb: FormBuilder) {
|
||||
this.createForm();
|
||||
this.logNameChange();
|
||||
}
|
||||
// #enddocregion ctor
|
||||
|
||||
createForm() {
|
||||
// #docregion secretLairs-form-array
|
||||
this.heroForm = this.fb.group({
|
||||
name: ['', Validators.required ],
|
||||
secretLairs: this.fb.array([]), // <-- secretLairs as an empty FormArray
|
||||
power: '',
|
||||
sidekick: ''
|
||||
});
|
||||
// #enddocregion secretLairs-form-array
|
||||
}
|
||||
|
||||
logNameChange() {/* Coming soon */}
|
||||
|
||||
// #docregion onchanges
|
||||
ngOnChanges() {
|
||||
this.rebuildForm();
|
||||
}
|
||||
// #enddocregion onchanges
|
||||
|
||||
// #docregion rebuildform
|
||||
rebuildForm() {
|
||||
this.heroForm.reset({
|
||||
name: this.hero.name
|
||||
});
|
||||
this.setAddresses(this.hero.addresses);
|
||||
}
|
||||
// #enddocregion rebuildform
|
||||
|
||||
// #docregion get-secret-lairs
|
||||
get secretLairs(): FormArray {
|
||||
return this.heroForm.get('secretLairs') as FormArray;
|
||||
};
|
||||
// #enddocregion get-secret-lairs
|
||||
|
||||
// #docregion set-addresses
|
||||
setAddresses(addresses: Address[]) {
|
||||
const addressFGs = addresses.map(address => this.fb.group(address));
|
||||
const addressFormArray = this.fb.array(addressFGs);
|
||||
this.heroForm.setControl('secretLairs', addressFormArray);
|
||||
}
|
||||
// #enddocregion set-addresses
|
||||
|
||||
// #docregion add-lair
|
||||
addLair() {
|
||||
this.secretLairs.push(this.fb.group(new Address()));
|
||||
}
|
||||
// #enddocregion add-lair
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
<!-- #docplaster -->
|
||||
<!-- #docregion -->
|
||||
<!-- #docregion buttons -->
|
||||
<form [formGroup]="heroForm" (ngSubmit)="onSubmit()">
|
||||
<div style="margin-bottom: 1em">
|
||||
<button type="submit"
|
||||
[disabled]="heroForm.pristine" class="btn btn-success">Save</button>
|
||||
<button type="button" (click)="revert()"
|
||||
[disabled]="heroForm.pristine" class="btn btn-danger">Revert</button>
|
||||
</div>
|
||||
|
||||
<!-- Hero Detail Controls -->
|
||||
<!-- #enddocregion buttons -->
|
||||
<div class="form-group">
|
||||
<label class="center-block">Name:
|
||||
<input class="form-control" formControlName="name">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div formArrayName="secretLairs" class="well well-lg">
|
||||
<div *ngFor="let address of secretLairs.controls; let i=index" [formGroupName]="i" >
|
||||
<!-- The repeated address template -->
|
||||
<h4>Address #{{i + 1}}</h4>
|
||||
<div style="margin-left: 1em;">
|
||||
<div class="form-group">
|
||||
<label class="center-block">Street:
|
||||
<input class="form-control" formControlName="street">
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">City:
|
||||
<input class="form-control" formControlName="city">
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">State:
|
||||
<select class="form-control" formControlName="state">
|
||||
<option *ngFor="let state of states" [value]="state">{{state}}</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="center-block">Zip Code:
|
||||
<input class="form-control" formControlName="zip">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<!-- End of the repeated address template -->
|
||||
</div>
|
||||
<button (click)="addLair()" type="button">Add a Secret Lair</button>
|
||||
</div>
|
||||
<!-- #docregion buttons -->
|
||||
<div class="form-group radio">
|
||||
<h4>Super power:</h4>
|
||||
<label class="center-block"><input type="radio" formControlName="power" value="flight">Flight</label>
|
||||
<label class="center-block"><input type="radio" formControlName="power" value="x-ray vision">X-ray vision</label>
|
||||
<label class="center-block"><input type="radio" formControlName="power" value="strength">Strength</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label class="center-block">
|
||||
<input type="checkbox" formControlName="sidekick">I have a sidekick.
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
<!-- #enddocregion buttons -->
|
||||
|
||||
<p>heroForm value: {{ heroForm.value | json}}</p>
|
||||
|
||||
<!-- #docregion name-change-log -->
|
||||
<h4>Name change log</h4>
|
||||
<div *ngFor="let name of nameChangeLog">{{name}}</div>
|
||||
<!-- #enddocregion name-change-log -->
|
@ -1,113 +0,0 @@
|
||||
// #docplaster
|
||||
// #docregion
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
import { FormArray, FormBuilder, FormGroup } from '@angular/forms';
|
||||
|
||||
import { Address, Hero, states } from '../data-model';
|
||||
// #docregion import-service
|
||||
import { HeroService } from '../hero.service';
|
||||
// #enddocregion import-service
|
||||
|
||||
@Component({
|
||||
selector: 'app-hero-detail',
|
||||
templateUrl: './hero-detail.component.html',
|
||||
styleUrls: ['./hero-detail.component.css']
|
||||
})
|
||||
|
||||
// #docregion onchanges-implementation
|
||||
export class HeroDetailComponent implements OnChanges {
|
||||
// #enddocregion onchanges-implementation
|
||||
@Input() hero: Hero;
|
||||
|
||||
heroForm: FormGroup;
|
||||
// #docregion log-name-change
|
||||
nameChangeLog: string[] = [];
|
||||
// #enddocregion log-name-change
|
||||
states = states;
|
||||
|
||||
// #docregion ctor
|
||||
constructor(
|
||||
private fb: FormBuilder,
|
||||
private heroService: HeroService) {
|
||||
|
||||
this.createForm();
|
||||
this.logNameChange();
|
||||
}
|
||||
// #enddocregion ctor
|
||||
|
||||
createForm() {
|
||||
this.heroForm = this.fb.group({
|
||||
name: '',
|
||||
secretLairs: this.fb.array([]),
|
||||
power: '',
|
||||
sidekick: ''
|
||||
});
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
this.rebuildForm();
|
||||
}
|
||||
|
||||
rebuildForm() {
|
||||
this.heroForm.reset({
|
||||
name: this.hero.name
|
||||
});
|
||||
this.setAddresses(this.hero.addresses);
|
||||
}
|
||||
|
||||
get secretLairs(): FormArray {
|
||||
return this.heroForm.get('secretLairs') as FormArray;
|
||||
};
|
||||
|
||||
setAddresses(addresses: Address[]) {
|
||||
const addressFGs = addresses.map(address => this.fb.group(address));
|
||||
const addressFormArray = this.fb.array(addressFGs);
|
||||
this.heroForm.setControl('secretLairs', addressFormArray);
|
||||
}
|
||||
|
||||
addLair() {
|
||||
this.secretLairs.push(this.fb.group(new Address()));
|
||||
}
|
||||
|
||||
// #docregion on-submit
|
||||
onSubmit() {
|
||||
this.hero = this.prepareSaveHero();
|
||||
this.heroService.updateHero(this.hero).subscribe(/* error handling */);
|
||||
this.rebuildForm();
|
||||
}
|
||||
// #enddocregion on-submit
|
||||
|
||||
// #docregion prepare-save-hero
|
||||
prepareSaveHero(): Hero {
|
||||
const formModel = this.heroForm.value;
|
||||
|
||||
// deep copy of form model lairs
|
||||
const secretLairsDeepCopy: Address[] = formModel.secretLairs.map(
|
||||
(address: Address) => Object.assign({}, address)
|
||||
);
|
||||
|
||||
// return new `Hero` object containing a combination of original hero value(s)
|
||||
// and deep copies of changed form model values
|
||||
const saveHero: Hero = {
|
||||
id: this.hero.id,
|
||||
name: formModel.name as string,
|
||||
// addresses: formModel.secretLairs // <-- bad!
|
||||
addresses: secretLairsDeepCopy
|
||||
};
|
||||
return saveHero;
|
||||
}
|
||||
// #enddocregion prepare-save-hero
|
||||
|
||||
// #docregion revert
|
||||
revert() { this.rebuildForm(); }
|
||||
// #enddocregion revert
|
||||
|
||||
// #docregion log-name-change
|
||||
logNameChange() {
|
||||
const nameControl = this.heroForm.get('name');
|
||||
nameControl.valueChanges.forEach(
|
||||
(value: string) => this.nameChangeLog.push(value)
|
||||
);
|
||||
}
|
||||
// #enddocregion log-name-change
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
<!-- #docregion -->
|
||||
<nav>
|
||||
<a *ngFor="let hero of heroes | async" (click)="select(hero)">{{hero.name}}</a>
|
||||
</nav>
|
||||
|
||||
<div *ngIf="selectedHero">
|
||||
<app-hero-detail [hero]="selectedHero"></app-hero-detail>
|
||||
</div>
|
@ -1,17 +0,0 @@
|
||||
<!-- #docregion -->
|
||||
<h3 *ngIf="isLoading"><i>Loading heroes ... </i></h3>
|
||||
<h3 *ngIf="!isLoading">Select a hero:</h3>
|
||||
|
||||
<nav>
|
||||
<button (click)="getHeroes()" class="btn btn-primary">Refresh</button>
|
||||
<a *ngFor="let hero of heroes | async" (click)="select(hero)">{{hero.name}}</a>
|
||||
</nav>
|
||||
|
||||
<div *ngIf="selectedHero">
|
||||
<hr>
|
||||
<h2>Hero Detail</h2>
|
||||
<h3>Editing: {{selectedHero.name}}</h3>
|
||||
<!-- #docregion hero-binding -->
|
||||
<app-hero-detail [hero]="selectedHero"></app-hero-detail>
|
||||
<!-- #enddocregion hero-binding -->
|
||||
</div>
|
@ -1,32 +0,0 @@
|
||||
// #docregion
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { finalize } from 'rxjs/operators';
|
||||
|
||||
import { Hero } from '../data-model';
|
||||
import { HeroService } from '../hero.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-hero-list',
|
||||
templateUrl: './hero-list.component.html',
|
||||
styleUrls: ['./hero-list.component.css']
|
||||
})
|
||||
export class HeroListComponent implements OnInit {
|
||||
heroes: Observable<Hero[]>;
|
||||
isLoading = false;
|
||||
selectedHero: Hero;
|
||||
|
||||
constructor(private heroService: HeroService) { }
|
||||
|
||||
ngOnInit() { this.getHeroes(); }
|
||||
|
||||
getHeroes() {
|
||||
this.isLoading = true;
|
||||
this.heroes = this.heroService.getHeroes()
|
||||
// TODO: error handling
|
||||
.pipe(finalize(() => this.isLoading = false));
|
||||
this.selectedHero = undefined;
|
||||
}
|
||||
|
||||
select(hero: Hero) { this.selectedHero = hero; }
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
// #docregion
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { delay } from 'rxjs/operators';
|
||||
|
||||
import { Hero, heroes } from './data-model';
|
||||
|
||||
@Injectable()
|
||||
export class HeroService {
|
||||
|
||||
delayMs = 500;
|
||||
|
||||
// Fake server get; assume nothing can go wrong
|
||||
getHeroes(): Observable<Hero[]> {
|
||||
return of(heroes).pipe(delay(this.delayMs)); // simulate latency with delay
|
||||
}
|
||||
|
||||
// Fake server update; assume nothing can go wrong
|
||||
updateHero(hero: Hero): Observable<Hero> {
|
||||
const oldHero = heroes.find(h => h.id === hero.id);
|
||||
const newHero = Object.assign(oldHero, hero); // Demo: mutate cached hero
|
||||
return of(newHero).pipe(delay(this.delayMs)); // simulate latency with delay
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 24px;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
width: 6em;
|
||||
margin: .5em 0;
|
||||
color: #607D8B;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
input {
|
||||
height: 2em;
|
||||
font-size: 1em;
|
||||
padding-left: .4em;
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<!-- #docregion control-binding -->
|
||||
<label>
|
||||
Name:
|
||||
<input type="text" [formControl]="name">
|
||||
</label>
|
||||
|
||||
<!-- #enddocregion control-binding -->
|
||||
|
||||
<!-- #docregion display-value -->
|
||||
|
||||
<p>
|
||||
Value: {{ name.value }}
|
||||
</p>
|
||||
<!-- #enddocregion display-value -->
|
||||
|
||||
<!-- #docregion update-value -->
|
||||
|
||||
<p>
|
||||
<button (click)="updateName()">Update Name</button>
|
||||
</p>
|
||||
<!-- #enddocregion update-value -->
|
@ -0,0 +1,22 @@
|
||||
// #docplaster
|
||||
// #docregion create-control
|
||||
import { Component } from '@angular/core';
|
||||
import { FormControl } from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'app-name-editor',
|
||||
templateUrl: './name-editor.component.html',
|
||||
styleUrls: ['./name-editor.component.css']
|
||||
})
|
||||
export class NameEditorComponent {
|
||||
name = new FormControl('');
|
||||
// #enddocregion create-control
|
||||
|
||||
// #docregion update-value
|
||||
updateName() {
|
||||
this.name.setValue('Nancy');
|
||||
}
|
||||
// #enddocregion update-value
|
||||
// #docregion create-control
|
||||
}
|
||||
// #enddocregion create-control
|
@ -0,0 +1,67 @@
|
||||
<!-- #docplaster -->
|
||||
<!-- #docregion formgroup -->
|
||||
<form [formGroup]="profileForm">
|
||||
|
||||
<label>
|
||||
First Name:
|
||||
<input type="text" formControlName="firstName">
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Last Name:
|
||||
<input type="text" formControlName="lastName">
|
||||
</label>
|
||||
|
||||
<!-- #enddocregion formgroup -->
|
||||
<!-- #docregion formgroupname -->
|
||||
<div formGroupName="address">
|
||||
<h3>Address</h3>
|
||||
|
||||
<label>
|
||||
Street:
|
||||
<input type="text" formControlName="street">
|
||||
</label>
|
||||
|
||||
<label>
|
||||
City:
|
||||
<input type="text" formControlName="city">
|
||||
</label>
|
||||
|
||||
<label>
|
||||
State:
|
||||
<input type="text" formControlName="state">
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Zip Code:
|
||||
<input type="text" formControlName="zip">
|
||||
</label>
|
||||
</div>
|
||||
<!-- #enddocregion formgroupname -->
|
||||
|
||||
<!-- #docregion formarrayname -->
|
||||
<div formArrayName="aliases">
|
||||
<h3>Aliases</h3> <button (click)="addAlias()">Add Alias</button>
|
||||
|
||||
<div *ngFor="let address of aliases.controls; let i=index">
|
||||
<!-- The repeated alias template -->
|
||||
<label>
|
||||
Alias:
|
||||
<input type="text" [formControlName]="i">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- #enddocregion formarrayname -->
|
||||
<!-- #docregion formgroup -->
|
||||
</form>
|
||||
<!-- #enddocregion formgroup -->
|
||||
|
||||
<p>
|
||||
Form Value: {{ profileForm.value | json }}
|
||||
</p>
|
||||
|
||||
<!-- #docregion patch-value -->
|
||||
<p>
|
||||
<button (click)="updateProfile()">Update Profile</button>
|
||||
</p>
|
||||
<!-- #enddocregion patch-value -->
|
@ -0,0 +1,40 @@
|
||||
// #docplaster
|
||||
// #docregion formgroup, nested-formgroup
|
||||
import { Component } from '@angular/core';
|
||||
// #docregion imports
|
||||
import { FormGroup, FormControl } from '@angular/forms';
|
||||
// #enddocregion imports
|
||||
|
||||
@Component({
|
||||
selector: 'app-profile-editor',
|
||||
templateUrl: './profile-editor.component.html',
|
||||
styleUrls: ['./profile-editor.component.css']
|
||||
})
|
||||
export class ProfileEditorComponent {
|
||||
// #docregion formgroup-compare
|
||||
profileForm = new FormGroup({
|
||||
firstName: new FormControl(''),
|
||||
lastName: new FormControl(''),
|
||||
// #enddocregion formgroup
|
||||
address: new FormGroup({
|
||||
street: new FormControl(''),
|
||||
city: new FormControl(''),
|
||||
state: new FormControl(''),
|
||||
zip: new FormControl('')
|
||||
})
|
||||
// #docregion formgroup
|
||||
});
|
||||
// #enddocregion formgroup, nested-formgroup, formgroup-compare
|
||||
// #docregion patch-value
|
||||
updateProfile() {
|
||||
this.profileForm.patchValue({
|
||||
firstName: 'Nancy',
|
||||
address: {
|
||||
street: '123 Drew Street'
|
||||
}
|
||||
});
|
||||
}
|
||||
// #enddocregion patch-value
|
||||
// #docregion formgroup, nested-formgroup
|
||||
}
|
||||
// #enddocregion formgroup
|
@ -0,0 +1,58 @@
|
||||
// #docplaster
|
||||
// #docregion form-builder
|
||||
import { Component } from '@angular/core';
|
||||
// #docregion form-builder-imports
|
||||
import { FormBuilder } from '@angular/forms';
|
||||
// #enddocregion form-builder-imports, form-builder
|
||||
// #docregion form-array-imports
|
||||
import { FormArray } from '@angular/forms';
|
||||
// #docregion form-builder-imports, form-builder
|
||||
// #enddocregion form-builder-imports, form-array-imports
|
||||
|
||||
@Component({
|
||||
selector: 'app-profile-editor',
|
||||
templateUrl: './profile-editor.component.html',
|
||||
styleUrls: ['./profile-editor.component.css']
|
||||
})
|
||||
export class ProfileEditorComponent {
|
||||
// #docregion formgroup-compare
|
||||
profileForm = this.fb.group({
|
||||
firstName: [''],
|
||||
lastName: [''],
|
||||
address: this.fb.group({
|
||||
street: [''],
|
||||
city: [''],
|
||||
state: [''],
|
||||
zip: ['']
|
||||
}),
|
||||
// #enddocregion form-builder, formgroup-compare
|
||||
aliases: this.fb.array([
|
||||
this.fb.control('')
|
||||
])
|
||||
// #docregion form-builder, formgroup-compare
|
||||
});
|
||||
// #enddocregion form-builder, formgroup-compare
|
||||
get aliases() {
|
||||
return this.profileForm.get('aliases') as FormArray;
|
||||
}
|
||||
|
||||
// #docregion inject-form-builder, form-builder
|
||||
|
||||
constructor(private fb: FormBuilder) { }
|
||||
// #enddocregion inject-form-builder, form-builder
|
||||
|
||||
updateProfile() {
|
||||
this.profileForm.patchValue({
|
||||
firstName: 'Nancy',
|
||||
address: {
|
||||
street: '123 Drew Street'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
addAlias() {
|
||||
this.aliases.push(this.fb.control(''));
|
||||
}
|
||||
// #docregion form-builder
|
||||
}
|
||||
// #enddocregion form-builder
|
@ -0,0 +1,39 @@
|
||||
/* ProfileEditorComponent's private CSS styles */
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 24px;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
width: 6em;
|
||||
margin: .5em 0;
|
||||
color: #607D8B;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
input {
|
||||
height: 2em;
|
||||
font-size: 1em;
|
||||
padding-left: .4em;
|
||||
}
|
||||
|
||||
button {
|
||||
font-family: Arial;
|
||||
background-color: #eee;
|
||||
border: none;
|
||||
padding: 5px 10px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #cfd8dc;
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
background-color: #eee;
|
||||
color: #ccc;
|
||||
cursor: auto;
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
<!-- #docplaster -->
|
||||
<!-- #docregion ng-submit -->
|
||||
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
|
||||
<!-- #enddocregion ng-submit -->
|
||||
<label>
|
||||
First Name:
|
||||
<!-- #docregion required-attribute -->
|
||||
<input type="text" formControlName="firstName" required>
|
||||
<!-- #enddocregion required-attribute -->
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Last Name:
|
||||
<input type="text" formControlName="lastName">
|
||||
</label>
|
||||
|
||||
<div formGroupName="address">
|
||||
<h3>Address</h3>
|
||||
|
||||
<label>
|
||||
Street:
|
||||
<input type="text" formControlName="street">
|
||||
</label>
|
||||
|
||||
<label>
|
||||
City:
|
||||
<input type="text" formControlName="city">
|
||||
</label>
|
||||
|
||||
<label>
|
||||
State:
|
||||
<input type="text" formControlName="state">
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Zip Code:
|
||||
<input type="text" formControlName="zip">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- #docregion formarrayname -->
|
||||
<div formArrayName="aliases">
|
||||
<h3>Aliases</h3> <button (click)="addAlias()">Add Alias</button>
|
||||
|
||||
<div *ngFor="let address of aliases.controls; let i=index">
|
||||
<!-- The repeated alias template -->
|
||||
<label>
|
||||
Alias:
|
||||
<input type="text" [formControlName]="i">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- #enddocregion formarrayname -->
|
||||
|
||||
<!-- #docregion submit-button -->
|
||||
<button type="submit" [disabled]="!profileForm.valid">Submit</button>
|
||||
<!-- #enddocregion submit-button -->
|
||||
</form>
|
||||
|
||||
<hr>
|
||||
|
||||
<!-- #docregion display-value -->
|
||||
|
||||
<p>
|
||||
Form Value: {{ profileForm.value | json }}
|
||||
</p>
|
||||
<!-- #enddocregion display-value -->
|
||||
|
||||
<!-- #docregion display-status -->
|
||||
|
||||
<p>
|
||||
Form Status: {{ profileForm.status }}
|
||||
</p>
|
||||
<!-- #enddocregion display-status -->
|
||||
|
||||
<!-- #docregion patch-value -->
|
||||
<p>
|
||||
<button (click)="updateProfile()">Update Profile</button>
|
||||
</p>
|
||||
<!-- #enddocregion patch-value -->
|
@ -0,0 +1,73 @@
|
||||
// #docplaster
|
||||
// #docregion form-builder
|
||||
import { Component } from '@angular/core';
|
||||
// #docregion form-builder-imports
|
||||
import { FormBuilder } from '@angular/forms';
|
||||
// #enddocregion form-builder-imports
|
||||
// #docregion validator-imports
|
||||
import { Validators } from '@angular/forms';
|
||||
// #enddocregion validator-imports
|
||||
// #docregion form-array-imports
|
||||
import { FormArray } from '@angular/forms';
|
||||
// #enddocregion form-array-imports
|
||||
|
||||
@Component({
|
||||
selector: 'app-profile-editor',
|
||||
templateUrl: './profile-editor.component.html',
|
||||
styleUrls: ['./profile-editor.component.css']
|
||||
})
|
||||
export class ProfileEditorComponent {
|
||||
// #docregion required-validator, aliases
|
||||
profileForm = this.fb.group({
|
||||
firstName: ['', Validators.required],
|
||||
lastName: [''],
|
||||
address: this.fb.group({
|
||||
street: [''],
|
||||
city: [''],
|
||||
state: [''],
|
||||
zip: ['']
|
||||
}),
|
||||
// #enddocregion form-builder, required-validator
|
||||
aliases: this.fb.array([
|
||||
this.fb.control('')
|
||||
])
|
||||
// #docregion form-builder, required-validator
|
||||
});
|
||||
// #enddocregion form-builder, required-validator, aliases
|
||||
// #docregion aliases-getter
|
||||
|
||||
get aliases() {
|
||||
return this.profileForm.get('aliases') as FormArray;
|
||||
}
|
||||
|
||||
// #enddocregion aliases-getter
|
||||
// #docregion inject-form-builder, form-builder
|
||||
constructor(private fb: FormBuilder) { }
|
||||
|
||||
// #enddocregion inject-form-builder
|
||||
|
||||
updateProfile() {
|
||||
this.profileForm.patchValue({
|
||||
firstName: 'Nancy',
|
||||
address: {
|
||||
street: '123 Drew Street'
|
||||
}
|
||||
});
|
||||
}
|
||||
// #enddocregion form-builder
|
||||
// #docregion add-alias
|
||||
|
||||
addAlias() {
|
||||
this.aliases.push(this.fb.control(''));
|
||||
}
|
||||
// #enddocregion add-alias
|
||||
// #docregion on-submit
|
||||
|
||||
onSubmit() {
|
||||
// TODO: Use EventEmitter with form value
|
||||
console.warn(this.profileForm.value);
|
||||
}
|
||||
// #enddocregion on-submit
|
||||
// #docregion form-builder
|
||||
}
|
||||
// #enddocregion form-builder
|
@ -1,17 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- #docregion -->
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Hero Form</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<!-- #docregion bootstrap -->
|
||||
<link rel="stylesheet" href="https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -2,10 +2,9 @@
|
||||
<!-- #docregion -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Hero Form</title>
|
||||
<title>Angular Reactive Forms</title>
|
||||
<meta charset="UTF-8">
|
||||
<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">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@ -2,12 +2,11 @@
|
||||
import { enableProdMode } from '@angular/core';
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
import { AppModule } from './app/app.module'; // just the final version
|
||||
import { DemoModule } from './app/demo.module'; // demo picker
|
||||
import { AppModule } from './app/app.module';
|
||||
import { environment } from './environments/environment';
|
||||
|
||||
if (environment.production) {
|
||||
enableProdMode();
|
||||
}
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(DemoModule);
|
||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
|
@ -1 +0,0 @@
|
||||
@import url('https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css');
|
@ -3,6 +3,7 @@
|
||||
"files":[
|
||||
"!**/*.d.ts",
|
||||
"!**/*.js",
|
||||
"!**/*.[0-9].*",
|
||||
|
||||
"!src/app/app.component.1.ts",
|
||||
"!src/app/hero-list.component.1.html",
|
||||
|
@ -8,7 +8,7 @@ const nums = of(1, 2, 3, 4, 5);
|
||||
|
||||
// Create a function that accepts an Observable.
|
||||
const squareOddVals = pipe(
|
||||
filter(n => n % 2),
|
||||
filter((n: number) => n % 2 !== 0),
|
||||
map(n => n * n)
|
||||
);
|
||||
|
||||
|
@ -9,6 +9,6 @@ import { HeroService } from './heroes';
|
||||
<toh-heroes></toh-heroes>
|
||||
`,
|
||||
styleUrls: ['./app.component.css'],
|
||||
providers: [ HeroService ]
|
||||
providers: [HeroService]
|
||||
})
|
||||
export class AppComponent { }
|
||||
export class AppComponent {}
|
||||
|
@ -1,9 +1,8 @@
|
||||
// #docregion
|
||||
/* avoid */
|
||||
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
import { Component, NgModule, OnInit } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule, Component, OnInit } from '@angular/core';
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
class Hero {
|
||||
id: number;
|
||||
@ -24,24 +23,24 @@ class AppComponent implements OnInit {
|
||||
heroes: Hero[] = [];
|
||||
|
||||
ngOnInit() {
|
||||
getHeroes().then(heroes => this.heroes = heroes);
|
||||
getHeroes().then(heroes => (this.heroes = heroes));
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [ BrowserModule ],
|
||||
declarations: [ AppComponent ],
|
||||
exports: [ AppComponent ],
|
||||
bootstrap: [ AppComponent ]
|
||||
imports: [BrowserModule],
|
||||
declarations: [AppComponent],
|
||||
exports: [AppComponent],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
||||
export class AppModule {}
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
|
||||
const HEROES: Hero[] = [
|
||||
{id: 1, name: 'Bombasto'},
|
||||
{id: 2, name: 'Tornado'},
|
||||
{id: 3, name: 'Magneta'},
|
||||
{ id: 1, name: 'Bombasto' },
|
||||
{ id: 2, name: 'Tornado' },
|
||||
{ id: 3, name: 'Magneta' }
|
||||
];
|
||||
|
||||
function getHeroes(): Promise<Hero[]> {
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { Hero } from './hero.model';
|
||||
|
||||
export const HEROES: Hero[] = [
|
||||
{id: 1, name: 'Bombasto'},
|
||||
{id: 2, name: 'Tornado'},
|
||||
{id: 3, name: 'Magneta'},
|
||||
{ id: 1, name: 'Bombasto' },
|
||||
{ id: 2, name: 'Tornado' },
|
||||
{ id: 3, name: 'Magneta' }
|
||||
];
|
||||
|
@ -1,6 +1,6 @@
|
||||
// #docregion
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
import { AppModule } from './app/app.module';
|
||||
import { AppModule } from './app/app.module';
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
|
@ -3,9 +3,8 @@
|
||||
/* avoid */
|
||||
|
||||
import { ExceptionService, SpinnerService, ToastService } from '../../core';
|
||||
import { Http } from '@angular/http';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { Hero } from './hero.model';
|
||||
// #enddocregion example
|
||||
|
||||
@ -16,18 +15,15 @@ export class HeroService {
|
||||
private exceptionService: ExceptionService,
|
||||
private spinnerService: SpinnerService,
|
||||
private toastService: ToastService,
|
||||
private http: Http
|
||||
private http: HttpClient
|
||||
) { }
|
||||
|
||||
getHero(id: number) {
|
||||
return this.http.get(`api/heroes/${id}`).pipe(
|
||||
map(response => response.json().data as Hero));
|
||||
return this.http.get<Hero>(`api/heroes/${id}`);
|
||||
}
|
||||
|
||||
getHeroes() {
|
||||
return this.http.get(`api/heroes`).pipe(
|
||||
map(response => response.json().data as Hero[]));
|
||||
return this.http.get<Hero[]>(`api/heroes`);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
// #docregion
|
||||
// #docregion example
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Http } from '@angular/http';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { Hero } from './hero.model';
|
||||
import { ExceptionService, SpinnerService, ToastService } from '../../core';
|
||||
import { Hero } from './hero.model';
|
||||
|
||||
// #enddocregion example
|
||||
|
||||
@Injectable()
|
||||
@ -16,18 +16,15 @@ export class HeroService {
|
||||
private exceptionService: ExceptionService,
|
||||
private spinnerService: SpinnerService,
|
||||
private toastService: ToastService,
|
||||
private http: Http
|
||||
private http: HttpClient
|
||||
) { }
|
||||
|
||||
getHero(id: number) {
|
||||
return this.http.get(`api/heroes/${id}`).pipe(
|
||||
map(response => response.json() as Hero));
|
||||
return this.http.get<Hero>(`api/heroes/${id}`);
|
||||
}
|
||||
|
||||
getHeroes() {
|
||||
return this.http.get(`api/heroes`).pipe(
|
||||
map(response => response.json() as Hero[]));
|
||||
return this.http.get<Hero[]>(`api/heroes`);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// #docplaster
|
||||
// #docregion
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
// #docregion added-imports
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Location } from '@angular/common';
|
||||
@ -17,7 +17,7 @@ import { HeroService } from '../hero.service';
|
||||
styleUrls: [ './hero-detail.component.css' ]
|
||||
})
|
||||
export class HeroDetailComponent implements OnInit {
|
||||
@Input() hero: Hero;
|
||||
hero: Hero;
|
||||
|
||||
// #docregion ctor
|
||||
constructor(
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Location } from '@angular/common';
|
||||
|
||||
@ -11,7 +11,7 @@ import { HeroService } from '../hero.service';
|
||||
styleUrls: [ './hero-detail.component.css' ]
|
||||
})
|
||||
export class HeroDetailComponent implements OnInit {
|
||||
@Input() hero: Hero;
|
||||
hero: Hero;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
|
@ -22,7 +22,7 @@ code uses [AnimationBuilder](/api/animations/AnimationBuilder). If your code doe
|
||||
uncomment the `web-animations-js` polyfill from the `polyfills.ts` file generated by Angular CLI.
|
||||
</div>
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The examples in this page are available as a <live-example></live-example>.
|
||||
|
||||
@ -183,7 +183,7 @@ transition definitions, and not in a separate `state(void)` definition. Thus, th
|
||||
are different on enter and leave: the element enters from the left
|
||||
and leaves to the right.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
These two common animations have their own aliases:
|
||||
|
||||
|
@ -4,7 +4,7 @@ The Angular Ahead-of-Time (AOT) compiler converts your Angular HTML and TypeScri
|
||||
|
||||
This guide explains how to build with the AOT compiler using different compiler options and how to write Angular metadata that AOT can compile.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful>
|
||||
|
||||
<a href="https://www.youtube.com/watch?v=kW9cJsvcsGo">Watch compiler author Tobias Bosch explain the Angular Compiler</a> at AngularConnect 2016.
|
||||
|
||||
@ -39,7 +39,7 @@ For AOT compilation, append the `--aot` flags to the _build-only_ or the _build-
|
||||
ng serve --aot
|
||||
</code-example>
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The `--prod` meta-flag compiles with AOT by default.
|
||||
|
||||
@ -297,7 +297,7 @@ At the same time, the AOT **_collector_** analyzes the metadata recorded in the
|
||||
|
||||
You can think of `.metadata.json` as a diagram of the overall structure of a decorator's metadata, represented as an [abstract syntax tree (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree).
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Angular's [schema.ts](https://github.com/angular/angular/blob/master/packages/compiler-cli/src/metadata/schema.ts)
|
||||
describes the JSON format as a collection of TypeScript interfaces.
|
||||
@ -333,7 +333,7 @@ Parentheses | `(a + b)`
|
||||
If an expression uses unsupported syntax, the _collector_ writes an error node to the `.metadata.json` file. The compiler later reports the error if it needs that
|
||||
piece of metadata to generate the application code.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
If you want `ngc` to report syntax errors immediately rather than produce a `.metadata.json` file with errors, set the `strictMetadataEmit` option in `tsconfig`.
|
||||
|
||||
|
@ -11,7 +11,7 @@ A _component_ controls a patch of screen called a *view*. For example, individua
|
||||
You define a component's application logic—what it does to support the view—inside a class.
|
||||
The class interacts with the view through an API of properties and methods.
|
||||
|
||||
For example, the `HeroListComponent` has a `heroes` property that holds an array of heroes. It also has a `selectHero()` method that sets a `selectedHero` property when the user clicks to choose a hero from that list. The component acquires the heroes from a service, which is a TypeScript [parameter property[(http://www.typescriptlang.org/docs/handbook/classes.html#parameter-properties) on the constructor. The service is provided to the component through the dependency injection system.
|
||||
For example, the `HeroListComponent` has a `heroes` property that holds an array of heroes. It also has a `selectHero()` method that sets a `selectedHero` property when the user clicks to choose a hero from that list. The component acquires the heroes from a service, which is a TypeScript [parameter property](http://www.typescriptlang.org/docs/handbook/classes.html#parameter-properties) on the constructor. The service is provided to the component through the dependency injection system.
|
||||
|
||||
<code-example path="architecture/src/app/hero-list.component.ts" linenums="false" title="src/app/hero-list.component.ts (class)" region="class"></code-example>
|
||||
|
||||
@ -40,7 +40,7 @@ Angular inserts an instance of the `HeroListComponent` view between those tags.
|
||||
|
||||
* `templateUrl`: The module-relative address of this component's HTML template. Alternatively, you can provide the HTML template inline, as the value of the `template` property. This template defines the component's _host view_.
|
||||
|
||||
* `providers`: An array of **dependency injection providers** for services that the component requires. In the example, this tells Angular how provide the `HeroService` instance that the component's constructor uses to get the list of heroes to display.
|
||||
* `providers`: An array of **dependency injection providers** for services that the component requires. In the example, this tells Angular how to provide the `HeroService` instance that the component's constructor uses to get the list of heroes to display.
|
||||
|
||||
<hr/>
|
||||
|
||||
@ -177,4 +177,4 @@ or modify aspects of DOM elements and components
|
||||
|
||||
You can also write your own directives. Components such as `HeroListComponent` are one kind of custom directive. You can also create custom structural and attribute directives.
|
||||
|
||||
<!-- PENDING: link to where to learn more about other kinds! -->
|
||||
<!-- PENDING: link to where to learn more about other kinds! -->
|
||||
|
@ -26,7 +26,7 @@ Here's a simple root NgModule definition:
|
||||
|
||||
<code-example path="architecture/src/app/mini-app.ts" region="module" title="src/app/app.module.ts" linenums="false"></code-example>
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The `export` of `AppComponent` is just to show how to export; it isn't actually necessary in this example. A root NgModule has no reason to _export_ anything because other modules don't need to _import_ the root NgModule.
|
||||
|
||||
@ -56,7 +56,7 @@ A component and its template together define a _view_. A component can contain a
|
||||
|
||||
When you create a component, it is associated directly with a single view, called the _host view_. The host view can be the root of a view hierarchy, which can contain _embedded views_, which are in turn the host views of other components. Those components can be in the same NgModule, or can be imported from other NgModules. Views in the tree can be nested to any depth.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
The hierarchical structure of views is a key factor in the way Angular detects and responds to changes in the DOM and app data.
|
||||
</div>
|
||||
|
||||
@ -72,7 +72,7 @@ Other JavaScript modules use *import statements* to access public objects from o
|
||||
|
||||
<code-example path="architecture/src/app/app.module.ts" region="export" linenums="false"></code-example>
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
<a href="http://exploringjs.com/es6/ch_modules.html">Learn more about the JavaScript module system on the web.</a>
|
||||
</div>
|
||||
|
||||
@ -99,7 +99,7 @@ In the example of the simple root module above, the application module needs mat
|
||||
|
||||
In this way you're using both the Angular and JavaScript module systems _together_. Although it's easy to confuse the two systems, which share the common vocabulary of "imports" and "exports", you will become familiar with the different contexts in which they are used.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Learn more from the [NgModules](guide/ngmodules) page.
|
||||
|
||||
|
@ -27,7 +27,7 @@ Like JavaScript modules, NgModules can import functionality from other NgModules
|
||||
|
||||
Organizing your code into distinct functional modules helps in managing development of complex applications, and in designing for reusability. In addition, this technique lets you take advantage of _lazy-loading_—that is, loading modules on demand—in order to minimize the amount of code that needs to be loaded at startup.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For a more detailed discussion, see [Introduction to modules](guide/architecture-modules).
|
||||
|
||||
@ -39,7 +39,7 @@ Every Angular application has at least one component, the *root component* that
|
||||
|
||||
The `@Component` decorator identifies the class immediately below it as a component, and provides the template and related component-specific metadata.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Decorators are functions that modify JavaScript classes. Angular defines a number of such decorators that attach specific kinds of metadata to classes, so that it knows what those classes mean and how they should work.
|
||||
|
||||
@ -59,7 +59,7 @@ Before a view is displayed, Angular evaluates the directives and resolves the bi
|
||||
|
||||
Your templates can also use *pipes* to improve the user experience by transforming values for display. Use pipes to display, for example, dates and currency values in a way appropriate to the user's locale. Angular provides predefined pipes for common transformations, and you can also define your own.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For a more detailed discussion of these concepts, see [Introduction to components](guide/architecture-components).
|
||||
|
||||
@ -74,7 +74,7 @@ For data or logic that is not associated with a specific view, and that you want
|
||||
|
||||
*Dependency injection* (or DI) lets you keep your component classes lean and efficient. They don't fetch data from the server, validate user input, or log directly to the console; they delegate such tasks to services.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For a more detailed discusssion, see [Introduction to services and DI](guide/architecture-services).
|
||||
|
||||
@ -96,7 +96,7 @@ The router interprets a link URL according to your app's view navigation rules a
|
||||
|
||||
To define navigation rules, you associate *navigation paths* with your components. A path uses a URL-like syntax that integrates your program data, in much the same way that template syntax integrates your views with your program data. You can then apply program logic to choose which views to show or to hide, in response to user input and your own access rules.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For a more detailed discussion, see [Routing and navigation](guide/router).
|
||||
|
||||
@ -128,7 +128,7 @@ Each of these subjects is introduced in more detail in the following pages.
|
||||
* [Pipes](guide/architecture-components#pipes)
|
||||
* [Services and dependency injection](guide/architecture-services)
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Note that the code referenced on these pages is available as a <live-example></live-example>.
|
||||
</div>
|
||||
|
@ -51,7 +51,7 @@ ng generate directive highlight
|
||||
|
||||
The CLI creates `src/app/highlight.directive.ts`, a corresponding test file (`.../spec.ts`, and _declares_ the directive class in the root `AppModule`.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
_Directives_ must be declared in [Angular Modules](guide/ngmodules) in the same manner as _components_.
|
||||
|
||||
@ -71,7 +71,7 @@ Angular locates each element in the template that has an attribute named `appHig
|
||||
|
||||
The _attribute selector_ pattern explains the name of this kind of directive.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
#### Why not "highlight"?
|
||||
|
||||
@ -146,7 +146,7 @@ each adorned by the `HostListener` decorator.
|
||||
The `@HostListener` decorator lets you subscribe to events of the DOM
|
||||
element that hosts an attribute directive, the `<p>` in this case.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Of course you could reach into the DOM with standard JavaScript and attach event listeners manually.
|
||||
There are at least three problems with _that_ approach:
|
||||
|
@ -19,7 +19,7 @@ If you use the CLI to generate an app, the default `AppModule` is as follows:
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { HttpModule } from '@angular/http';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
@ -31,7 +31,7 @@ import { AppComponent } from './app.component';
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
HttpModule
|
||||
HttpClientModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
@ -138,7 +138,7 @@ It tells Angular about other NgModules that this particular module needs to func
|
||||
This list of modules are those that export components, directives, or pipes
|
||||
that the component templates in this module reference. In this case, the component is
|
||||
`AppComponent`, which references components, directives, or pipes in `BrowserModule`,
|
||||
`FormsModule`, or `HttpModule`.
|
||||
`FormsModule`, or `HttpClientModule`.
|
||||
A component template can reference another component, directive,
|
||||
or pipe when the referenced class is declared in this module or
|
||||
the class was imported from another module.
|
||||
|
@ -95,7 +95,7 @@ Angular supports most recent browsers. This includes the following specific vers
|
||||
|
||||
</table>
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Angular's continuous integration process runs unit tests of the framework on all of these browsers for every pull request,
|
||||
using <a href="https://saucelabs.com/">SauceLabs</a> and
|
||||
@ -154,7 +154,7 @@ add it yourself, following the same pattern:
|
||||
1. install the npm package
|
||||
1. `import` the file in `polyfills.ts`
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Non-CLI users should follow the instructions [below](#non-cli).
|
||||
</div>
|
||||
|
@ -44,6 +44,9 @@ is available to <code>declarations</code> of this module.</p>
|
||||
<td><p>List of dependency injection providers visible both to the contents of this module and to importers of this module.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>entryComponents:</b> [SomeComponent, OtherComponent]</code></td>
|
||||
<td><p>List of components not referenced in any reachable template, for example dynamically created from code.</p></td>
|
||||
</tr><tr>
|
||||
<td><code><b>bootstrap:</b> [MyAppComponent]</code></td>
|
||||
<td><p>List of components to bootstrap when this module is bootstrapped.</p>
|
||||
</td>
|
||||
|
@ -89,47 +89,51 @@ promise.then(() => {
|
||||
The following code snippets illustrate how the same kind of operation is defined using observables and promises.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Operation</th>
|
||||
<th>Observable</th>
|
||||
<th>Promise</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Creation</td>
|
||||
<td>
|
||||
<pre>new Observable((observer) => {
|
||||
observer.next(123);
|
||||
});</pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre>new Promise((resolve, reject) => {
|
||||
resolve(123);
|
||||
});</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Transform</td>
|
||||
<td><pre>obs.map((value) => value * 2 );</pre></td>
|
||||
<td><pre>promise.then((value) => value * 2);</pre></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Subscribe</td>
|
||||
<td>
|
||||
<pre>sub = obs.subscribe((value) => {
|
||||
console.log(value)
|
||||
});</pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre>promise.then((value) => {
|
||||
console.log(value);
|
||||
});</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Unsubscribe</td>
|
||||
<td><pre>sub.unsubscribe();</pre></td>
|
||||
<td>Implied by promise resolution.</td>
|
||||
</tr>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Operation</th>
|
||||
<th>Observable</th>
|
||||
<th>Promise</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Creation</td>
|
||||
<td>
|
||||
<pre>new Observable((observer) => {
|
||||
observer.next(123);
|
||||
});</pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre>new Promise((resolve, reject) => {
|
||||
resolve(123);
|
||||
});</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Transform</td>
|
||||
<td><pre>obs.map((value) => value * 2 );</pre></td>
|
||||
<td><pre>promise.then((value) => value * 2);</pre></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Subscribe</td>
|
||||
<td>
|
||||
<pre>sub = obs.subscribe((value) => {
|
||||
console.log(value)
|
||||
});</pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre>promise.then((value) => {
|
||||
console.log(value);
|
||||
});</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Unsubscribe</td>
|
||||
<td><pre>sub.unsubscribe();</pre></td>
|
||||
<td>Implied by promise resolution.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Observables compared to events API
|
||||
|
@ -119,7 +119,7 @@ E2E tests of input property setter with empty and non-empty names:
|
||||
|
||||
Detect and act upon changes to input property values with the `ngOnChanges()` method of the `OnChanges` lifecycle hook interface.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
||||
|
||||
@ -311,7 +311,7 @@ The following example illustrates this technique with the same
|
||||
Neither its appearance nor its behavior will change.
|
||||
The child [CountdownTimerComponent](guide/component-interaction#countdown-timer-example) is the same as well.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
||||
|
||||
@ -400,7 +400,7 @@ Each `AstronautComponent` is a child of the `MissionControlComponent` and theref
|
||||
|
||||
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
||||
|
||||
|
@ -187,7 +187,7 @@ They are _not inherited_ by any components nested within the template nor by any
|
||||
|
||||
</div>
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
You can specify more than one styles file or even a combination of `styles` and `styleUrls`.
|
||||
|
||||
@ -216,11 +216,10 @@ You can also write `<link>` tags into the component's HTML template.
|
||||
|
||||
<div class="alert is-critical">
|
||||
|
||||
The link tag's `href` URL must be relative to the
|
||||
_**application root**_, not relative to the component file.
|
||||
|
||||
When building with the CLI, be sure to include the linked style file among the assets to be copied to the server as described in the [CLI documentation](https://github.com/angular/angular-cli/wiki/stories-asset-configuration).
|
||||
|
||||
Once included, the CLI will include the stylesheet, whether the link tag's href URL is relative to the application root or the component file.
|
||||
|
||||
</div>
|
||||
|
||||
### CSS @imports
|
||||
|
@ -25,7 +25,7 @@ application and don't need to be listed in any module.
|
||||
Service classes can act as their own providers which is why defining them in the `@Injectable` decorator
|
||||
is all the registration you need.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
||||
|
||||
@ -167,7 +167,7 @@ that is visible only to the component and its children, if any.
|
||||
You could also provide the `HeroService` to a *different* component elsewhere in the application.
|
||||
That would result in a *different* instance of the service, living in a *different* injector.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
||||
|
||||
@ -433,7 +433,7 @@ It may already have that value in its internal container.
|
||||
If it doesn't, it may be able to make one with the help of a ***provider***.
|
||||
A *provider* is a recipe for delivering a service associated with a *token*.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
||||
|
||||
@ -577,7 +577,7 @@ The second provider substitutes the `DateLoggerService` for the `LoggerService`.
|
||||
The `LoggerService` is already registered at the `AppComponent` level.
|
||||
When _this component_ requests the `LoggerService`, it receives the `DateLoggerService` instead.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
||||
|
||||
@ -645,7 +645,7 @@ The `HeroOfTheMonthComponent` constructor's `logger` parameter is typed as `Mini
|
||||
Behind the scenes, Angular actually sets the `logger` parameter to the full service registered under the `LoggingService` token which happens to be the `DateLoggerService` that was [provided above](guide/dependency-injection-in-action#useclass).
|
||||
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
||||
|
||||
@ -707,7 +707,7 @@ After some undisclosed work, the function returns the string of names
|
||||
and Angular injects it into the `runnersUp` parameter of the `HeroOfTheMonthComponent`.
|
||||
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
||||
|
||||
@ -769,7 +769,7 @@ A ***class-interface*** should define *only* the members that its consumers are
|
||||
Such a narrowing interface helps decouple the concrete class from its consumers.
|
||||
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
||||
|
||||
@ -866,7 +866,7 @@ and displays them in the order they arrive from the database.
|
||||
|
||||
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
||||
|
||||
@ -982,7 +982,7 @@ If you're lucky, they all implement the same base class
|
||||
whose API your `NewsComponent` understands.
|
||||
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
||||
|
||||
@ -1165,7 +1165,7 @@ its class signature doesn't mention `Parent`:
|
||||
|
||||
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
||||
|
||||
|
@ -81,7 +81,7 @@ now in the constructor.
|
||||
The `Car` class no longer creates an `engine` or `tires`.
|
||||
It just consumes them.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
This example leverages TypeScript's constructor syntax for declaring
|
||||
parameters and properties simultaneously.
|
||||
@ -101,7 +101,7 @@ conform to the general API requirements of an `engine` or `tires`.
|
||||
|
||||
Now, if someone extends the `Engine` class, that is not `Car`'s problem.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The _consumer_ of `Car` has the problem. The consumer must update the car creation code to
|
||||
something like this:
|
||||
|
@ -98,7 +98,7 @@ Without a provider, the injector would not know
|
||||
that it is responsible for injecting the service
|
||||
nor be able to create the service.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
You'll learn much more about _providers_ [below](#providers).
|
||||
For now, it is sufficient to know that they configure where and how services are created.
|
||||
@ -141,7 +141,7 @@ The second registers a value (`HERO_DI_CONFIG`) under the `APP_CONFIG` _injectio
|
||||
With the above registrations, Angular can inject the `UserService` or the `HERO_DI_CONFIG` value
|
||||
into any class that it creates.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
You'll learn about _injection tokens_ and _provider_ syntax [below](#providers).
|
||||
</div>
|
||||
@ -174,7 +174,7 @@ You're likely to inject the `UserService` in many places throughout the app
|
||||
and will want to inject the same service instance every time.
|
||||
Providing the `UserService` with an Angular module is a good choice if an `@Injectable` provider is not an option..
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
To be precise, Angular module providers are registered with the root injector
|
||||
_unless the module is_ [lazy loaded](guide/lazy-loading-ngmodules).
|
||||
@ -199,7 +199,7 @@ and is never destroyed so the `HeroService` created for the `HeroComponent` also
|
||||
If you want to restrict `HeroService` access to the `HeroComponent` and its nested `HeroListComponent`,
|
||||
providing the `HeroService` in the `HeroComponent` may be a good choice.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The scope and lifetime of component-provided services is a consequence of [the way Angular creates component instances](#component-child-injectors).
|
||||
|
||||
@ -375,7 +375,7 @@ and let the injector pass them along to the factory function:
|
||||
<code-example path="dependency-injection/src/app/heroes/hero.service.provider.ts" region="provider" title="src/app/heroes/hero.service.provider.ts (excerpt)" linenums="false">
|
||||
</code-example>
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The `useFactory` field tells Angular that the provider is a factory function
|
||||
whose implementation is the `heroServiceFactory`.
|
||||
@ -410,7 +410,7 @@ Here you see the new and the old implementation side-by-side:
|
||||
|
||||
Tree shaking is the ability to remove code that is not referenced in an application from the final bundle. Tree-shakable providers give Angular the ability to remove services that are not used in your application from the final output. This significantly reduces the size of your bundles.
|
||||
|
||||
Ideally, if an application is not injecting a service, it should not be included in the final output. However, it turns out that the Angular compiler cannot identify at build time if the service will be required or not. Because it's always possible to inject a service directly using `injector.get(Service)`, Angular cannot identify all of the places in your code where this injection could happen, so it has no choice but to include the service in the injector regardless. Thus, services provided in modules are not tree-shakeable.
|
||||
Ideally, if an application is not injecting a service, it should not be included in the final output. However, it turns out that the Angular compiler cannot identify at build time if the service will be required or not. Because it's always possible to inject a service directly using `injector.get(Service)`, Angular cannot identify all of the places in your code where this injection could happen, so it has no choice but to include the service in the injector regardless. Thus, services provided in modules are not tree-shakable.
|
||||
|
||||
Let us consider an example of non-tree-shakable providers in Angular.
|
||||
|
||||
@ -424,13 +424,13 @@ This module can then be imported into your application module, to make the servi
|
||||
|
||||
When `ngc` runs, it compiles AppModule into a module factory, which contains definitions for all the providers declared in all the modules it includes. At runtime, this factory becomes an injector that instantiates these services.
|
||||
|
||||
Tree-shaking doesn't work in the method above because Angular cannot decide to exclude one chunk of code (the provider definition for the service within the module factory) based on whether another chunk of code (the service class) is used. To make services tree-shakeable, the information about how to construct an instance of the service (the provider definition) needs to be a part of the service class itself.
|
||||
Tree-shaking doesn't work in the method above because Angular cannot decide to exclude one chunk of code (the provider definition for the service within the module factory) based on whether another chunk of code (the service class) is used. To make services tree-shakable, the information about how to construct an instance of the service (the provider definition) needs to be a part of the service class itself.
|
||||
|
||||
#### Creating tree-shakable providers
|
||||
|
||||
To create providers that are tree-shakable, the information that used to be specified in the module should be specified in the `@Injectable` decorator on the service itself.
|
||||
|
||||
The following example shows the tree-shakeable equivalent to the `ServiceModule` example above:
|
||||
The following example shows the tree-shakable equivalent to the `ServiceModule` example above:
|
||||
|
||||
<code-example path="dependency-injection/src/app/tree-shaking/service.ts" title="src/app/tree-shaking/service.ts" linenums="false"> </code-example>
|
||||
|
||||
@ -440,7 +440,7 @@ The service can be instantiated by configuring a factory function as shown below
|
||||
|
||||
<code-example path="dependency-injection/src/app/tree-shaking/service.0.ts" title="src/app/tree-shaking/service.0.ts" linenums="false"> </code-example>
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
To override tree-shakable providers, register the provider using the `providers: []` array syntax of any Angular decorator that supports it.
|
||||
|
||||
@ -532,7 +532,7 @@ under test:
|
||||
<code-example path="dependency-injection/src/app/test.component.ts" region="spec" title="src/app/test.component.ts" linenums="false">
|
||||
</code-example>
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Learn more in the [Testing](guide/testing) guide.
|
||||
|
||||
@ -636,7 +636,7 @@ But what should you use as the token?
|
||||
You don't have a class to serve as a token.
|
||||
There is no `AppConfig` class.
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
### TypeScript interfaces aren't valid tokens
|
||||
|
||||
@ -690,9 +690,9 @@ If the factory function needs access to other DI tokens, it can use the inject f
|
||||
|
||||
<code-example>
|
||||
const TOKEN =
|
||||
new InjectionToken('tree-shakeable token',
|
||||
new InjectionToken('tree-shakable token',
|
||||
{ providedIn: 'root', factory: () =>
|
||||
new AppConfig(inject(Parameter1), inject(Paremeter2)), });
|
||||
new AppConfig(inject(Parameter1), inject(Parameter2)), });
|
||||
</code-example>
|
||||
|
||||
{@a optional}
|
||||
@ -742,7 +742,7 @@ You can call `get()` with a second parameter, which is the value to return if th
|
||||
is not found. Angular can't find the service if it's not registered with this or any ancestor injector.
|
||||
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
||||
|
||||
@ -776,7 +776,7 @@ If you define the component before the service,
|
||||
you'll get a runtime null reference error.
|
||||
|
||||
|
||||
<div class="l-sub-section">
|
||||
<div class="alert is-helpful">
|
||||
|
||||
You actually can define the component first with the help of the `forwardRef()` method as explained
|
||||
in this [blog post](http://blog.thoughtram.io/angular/2015/09/03/forward-references-in-angular-2.html).
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user