Compare commits
308 Commits
master
...
11.0.0-nex
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4baabf9cd3 | ||
![]() |
7244e1b4e3 | ||
![]() |
b1682526dd | ||
![]() |
75610505c6 | ||
![]() |
ba3f4c26bb | ||
![]() |
c8f056beb6 | ||
![]() |
a2068523fd | ||
![]() |
145ab3d7e0 | ||
![]() |
3082f7378b | ||
![]() |
297b123151 | ||
![]() |
a93605f2a4 | ||
![]() |
15dfd3439a | ||
![]() |
123bff7cb6 | ||
![]() |
6158dc16b4 | ||
![]() |
b0a43872a8 | ||
![]() |
856e74ac98 | ||
![]() |
6ae3b68acf | ||
![]() |
49f27e31ed | ||
![]() |
1a62f74496 | ||
![]() |
2b1b7180db | ||
![]() |
fdd4fa0009 | ||
![]() |
984ed39195 | ||
![]() |
0c0c54d615 | ||
![]() |
dfbfabc052 | ||
![]() |
f3f6a42342 | ||
![]() |
e498ea9b5a | ||
![]() |
a91f0f6b82 | ||
![]() |
d5ddb9f340 | ||
![]() |
b68fab547a | ||
![]() |
16a560119a | ||
![]() |
88d7bb8386 | ||
![]() |
2d6105a784 | ||
![]() |
95b8a8706a | ||
![]() |
d92a0dd72f | ||
![]() |
55485713a3 | ||
![]() |
d3169c533e | ||
![]() |
e4424863c2 | ||
![]() |
d795a00137 | ||
![]() |
7fb388f929 | ||
![]() |
02c6bff9cf | ||
![]() |
ef28e15884 | ||
![]() |
a33d630a21 | ||
![]() |
c4b8964424 | ||
![]() |
dd8d8c8289 | ||
![]() |
129107191c | ||
![]() |
722699fb0c | ||
![]() |
5614258cc7 | ||
![]() |
e62a918542 | ||
![]() |
49ee90b1b5 | ||
![]() |
7849fdde09 | ||
![]() |
97adc27207 | ||
![]() |
41bc2701c4 | ||
![]() |
a765530277 | ||
![]() |
5b33798796 | ||
![]() |
44074499dc | ||
![]() |
ba54671993 | ||
![]() |
a85109fd72 | ||
![]() |
85a2626620 | ||
![]() |
d192c87f6a | ||
![]() |
3817e5f1df | ||
![]() |
171a0d0696 | ||
![]() |
a1c1c450dc | ||
![]() |
fd44d84a33 | ||
![]() |
f0688b4d18 | ||
![]() |
b9ca6d20cc | ||
![]() |
e00535a2a4 | ||
![]() |
593bd594e3 | ||
![]() |
284c70ee9d | ||
![]() |
78e1ecb161 | ||
![]() |
3934f0a833 | ||
![]() |
297c060ae7 | ||
![]() |
077f51685a | ||
![]() |
e162da0753 | ||
![]() |
354138eba9 | ||
![]() |
6768fe9927 | ||
![]() |
57c442f930 | ||
![]() |
f667e374a9 | ||
![]() |
15207e3c9c | ||
![]() |
66129f8ea6 | ||
![]() |
da14b72550 | ||
![]() |
27cc56b359 | ||
![]() |
6acea54f62 | ||
![]() |
2d52c80332 | ||
![]() |
03447ba52f | ||
![]() |
8f349b2375 | ||
![]() |
19598b47ca | ||
![]() |
f56ece4fdc | ||
![]() |
cf2e8b99a8 | ||
![]() |
c4556db9f5 | ||
![]() |
a46e0e48a3 | ||
![]() |
9e77bd3087 | ||
![]() |
26f28200bf | ||
![]() |
ce1efc1af2 | ||
![]() |
d1415162cb | ||
![]() |
db21c4fb44 | ||
![]() |
281865bbcf | ||
![]() |
3406ec15a4 | ||
![]() |
85951a0465 | ||
![]() |
0ae00bb1f7 | ||
![]() |
1373a98e25 | ||
![]() |
1ed6913b8b | ||
![]() |
3c4b8b97c1 | ||
![]() |
f9421184ef | ||
![]() |
c6ebb77cec | ||
![]() |
a69507a0ad | ||
![]() |
886f58d4fe | ||
![]() |
18f84a0328 | ||
![]() |
b0ca3cd0c4 | ||
![]() |
3d77b64fc3 | ||
![]() |
f645d26e3f | ||
![]() |
6d9bfb8368 | ||
![]() |
7997fc5f97 | ||
![]() |
3cb2a79399 | ||
![]() |
d896c33b0e | ||
![]() |
19a484302d | ||
![]() |
ded075a79c | ||
![]() |
ba95b79a21 | ||
![]() |
4faac78e32 | ||
![]() |
4360eed9b7 | ||
![]() |
c880e393e9 | ||
![]() |
b0c79f2373 | ||
![]() |
a32a317ea1 | ||
![]() |
bfb7eec698 | ||
![]() |
7e0b3fd953 | ||
![]() |
7a6a061a9e | ||
![]() |
109555b33a | ||
![]() |
bf31ef29f6 | ||
![]() |
40096bee00 | ||
![]() |
45a73dddfd | ||
![]() |
687477279b | ||
![]() |
4007422cc6 | ||
![]() |
1150649139 | ||
![]() |
7869de6136 | ||
![]() |
2c4a98a285 | ||
![]() |
92ff6d93eb | ||
![]() |
83ace4ed30 | ||
![]() |
926ffcd8ac | ||
![]() |
97475d7408 | ||
![]() |
a29f9a9fb3 | ||
![]() |
9f28f82598 | ||
![]() |
261f689e9b | ||
![]() |
1d9873c44c | ||
![]() |
d9da7e5a18 | ||
![]() |
79d8795633 | ||
![]() |
3e57ca1d98 | ||
![]() |
c2d017de83 | ||
![]() |
7baa7ebfc4 | ||
![]() |
4e5286180b | ||
![]() |
73001b42fe | ||
![]() |
c90eb5450d | ||
![]() |
3e97435f1c | ||
![]() |
1c7e5cef3e | ||
![]() |
2cb3d58b42 | ||
![]() |
44bb85ade4 | ||
![]() |
50f4d8a1ce | ||
![]() |
fdea1804d6 | ||
![]() |
1d8c5d88cd | ||
![]() |
a68f1a78a7 | ||
![]() |
86e11f1110 | ||
![]() |
5da1934115 | ||
![]() |
86e7cd8117 | ||
![]() |
e6ee7c2aeb | ||
![]() |
54687f7765 | ||
![]() |
59c234cfb4 | ||
![]() |
a6f3cd93a9 | ||
![]() |
d9fea857db | ||
![]() |
03dbcc7a56 | ||
![]() |
c142b071eb | ||
![]() |
71acf9dd49 | ||
![]() |
f5a148b1b7 | ||
![]() |
4f28192d62 | ||
![]() |
0fc2bef0cd | ||
![]() |
f5d1e9a2d1 | ||
![]() |
036a2faf02 | ||
![]() |
5be4edfa17 | ||
![]() |
38d6596742 | ||
![]() |
0a7a5e3aff | ||
![]() |
d5fabc303d | ||
![]() |
ebc0e46501 | ||
![]() |
3487b549fd | ||
![]() |
52c7a4bfc6 | ||
![]() |
827ba05914 | ||
![]() |
b2857b4e3a | ||
![]() |
5d5caf21b8 | ||
![]() |
c1bc070b40 | ||
![]() |
930eeaf177 | ||
![]() |
2dd29fbae7 | ||
![]() |
9613660fee | ||
![]() |
c0523fc3b4 | ||
![]() |
de1cffb23b | ||
![]() |
31f4557621 | ||
![]() |
7723bfd9ba | ||
![]() |
e8ea839df8 | ||
![]() |
90cec40cce | ||
![]() |
4036281007 | ||
![]() |
164cd274a4 | ||
![]() |
fedcfec346 | ||
![]() |
618cb32407 | ||
![]() |
4aee0087ea | ||
![]() |
0681a20d28 | ||
![]() |
fb06903237 | ||
![]() |
ecc6fd0d28 | ||
![]() |
80cab26023 | ||
![]() |
841dfa68f9 | ||
![]() |
f0af387f6c | ||
![]() |
14e90bef58 | ||
![]() |
db3a21b382 | ||
![]() |
b8351f3b10 | ||
![]() |
81053d3160 | ||
![]() |
bdba1a062d | ||
![]() |
23f855b300 | ||
![]() |
94a3e0e81d | ||
![]() |
9cbde86534 | ||
![]() |
18e474f522 | ||
![]() |
cb3db0d31b | ||
![]() |
d36828a7a1 | ||
![]() |
f18e2d5898 | ||
![]() |
375f0a6f67 | ||
![]() |
281b647f15 | ||
![]() |
0fc44e0436 | ||
![]() |
201a546af8 | ||
![]() |
6e643d9874 | ||
![]() |
4985267211 | ||
![]() |
b48cc6ead5 | ||
![]() |
874792dc43 | ||
![]() |
e7da4040d6 | ||
![]() |
2a643e1ab6 | ||
![]() |
364284b0dc | ||
![]() |
956b25a100 | ||
![]() |
8017ca4db3 | ||
![]() |
22f1ac3e37 | ||
![]() |
4ee5e730ab | ||
![]() |
6442875c99 | ||
![]() |
8f24bc9443 | ||
![]() |
ac461e1efd | ||
![]() |
f245c6bb15 | ||
![]() |
68a9a01a64 | ||
![]() |
8cd4099db9 | ||
![]() |
0b54c0c6b4 | ||
![]() |
1ec609946f | ||
![]() |
7ad32649c0 | ||
![]() |
9ad69c1503 | ||
![]() |
9af2de821c | ||
![]() |
0270020ac2 | ||
![]() |
6b662d10c1 | ||
![]() |
55fd725e74 | ||
![]() |
f77fd5e02a | ||
![]() |
63ba74fe4e | ||
![]() |
aaa1d8e2fe | ||
![]() |
dbfb50e9f4 | ||
![]() |
bee44b3359 | ||
![]() |
723a9ff095 | ||
![]() |
e472f5f688 | ||
![]() |
8373b720f3 | ||
![]() |
301513311e | ||
![]() |
64cf087ae5 | ||
![]() |
fec9dcbeb0 | ||
![]() |
e0e5c9f195 | ||
![]() |
cfe424e875 | ||
![]() |
3b9c802dee | ||
![]() |
ca07da4563 | ||
![]() |
81c3e809aa | ||
![]() |
be96510ce9 | ||
![]() |
cb05c0102f | ||
![]() |
5f90b64328 | ||
![]() |
71079ce47e | ||
![]() |
ca798804b2 | ||
![]() |
b071495f92 | ||
![]() |
d5f819ebc1 | ||
![]() |
1388c1761f | ||
![]() |
fb8f4b4d72 | ||
![]() |
f42e6ce917 | ||
![]() |
175c79d1d8 | ||
![]() |
945751e2e8 | ||
![]() |
b769771d60 | ||
![]() |
a80f654af9 | ||
![]() |
aa847cb014 | ||
![]() |
8763d8201c | ||
![]() |
9f7a37b4e9 | ||
![]() |
773f7908c0 | ||
![]() |
f4ced74e3a | ||
![]() |
8366effeec | ||
![]() |
5f2e475abf | ||
![]() |
aa3520eb7d | ||
![]() |
823dd5b341 | ||
![]() |
d6d7caa2a8 | ||
![]() |
dcf7baf3d1 | ||
![]() |
4d17418569 | ||
![]() |
a2e069fdda | ||
![]() |
28534d83ee | ||
![]() |
a6292faa97 | ||
![]() |
e2e5f83869 | ||
![]() |
71138f6004 | ||
![]() |
fa0104017a | ||
![]() |
80b67e02b7 | ||
![]() |
18098d38b8 | ||
![]() |
9514fd9080 | ||
![]() |
2e9fdbde9e | ||
![]() |
df76a2048b | ||
![]() |
3d156162af | ||
![]() |
5dc8d287aa | ||
![]() |
6da9e5851a | ||
![]() |
250e299dc3 | ||
![]() |
8f708b561c | ||
![]() |
e34c33cd46 | ||
![]() |
6d8c73a4d6 | ||
![]() |
6ff28ac944 | ||
![]() |
0de93fd402 |
@ -653,9 +653,23 @@ jobs:
|
|||||||
name: Starting Saucelabs tunnel service
|
name: Starting Saucelabs tunnel service
|
||||||
command: ./tools/saucelabs/sauce-service.sh run
|
command: ./tools/saucelabs/sauce-service.sh run
|
||||||
background: true
|
background: true
|
||||||
- run: yarn tsc -p packages
|
# add module umd tsc compile option so the test can work
|
||||||
- run: yarn tsc -p modules
|
# properly in the legacy browsers
|
||||||
|
- run: yarn tsc -p packages --module UMD
|
||||||
|
- run: yarn tsc -p modules --module UMD
|
||||||
- run: yarn bazel build //packages/zone.js:npm_package
|
- run: yarn bazel build //packages/zone.js:npm_package
|
||||||
|
# Build test fixtures for a test that rely on Bazel-generated fixtures. Note that disabling
|
||||||
|
# specific tests which are reliant on such generated fixtures is not an option as SystemJS
|
||||||
|
# in the Saucelabs legacy job always fetches referenced files, even if the imports would be
|
||||||
|
# guarded by an check to skip in the Saucelabs legacy job. We should be good running such
|
||||||
|
# test in all supported browsers on Saucelabs anyway until this job can be removed.
|
||||||
|
- run:
|
||||||
|
name: Preparing Bazel-generated fixtures required in legacy tests
|
||||||
|
command: |
|
||||||
|
yarn bazel build //packages/core/test:downleveled_es5_fixture
|
||||||
|
# Needed for the ES5 downlevel reflector test in `packages/core/test/reflection`.
|
||||||
|
cp dist/bin/packages/core/test/reflection/es5_downleveled_inheritance_fixture.js \
|
||||||
|
dist/all/@angular/core/test/reflection/es5_downleveled_inheritance_fixture.js
|
||||||
- run:
|
- run:
|
||||||
# Waiting on ready ensures that we don't run tests too early without Saucelabs not being ready.
|
# Waiting on ready ensures that we don't run tests too early without Saucelabs not being ready.
|
||||||
name: Waiting for Saucelabs tunnel to connect
|
name: Waiting for Saucelabs tunnel to connect
|
||||||
@ -735,6 +749,8 @@ jobs:
|
|||||||
cp dist/bin/packages/zone.js/npm_package/bundles/zone-patch-electron.umd.js ./packages/zone.js/test/extra/ &&
|
cp dist/bin/packages/zone.js/npm_package/bundles/zone-patch-electron.umd.js ./packages/zone.js/test/extra/ &&
|
||||||
yarn --cwd packages/zone.js electrontest
|
yarn --cwd packages/zone.js electrontest
|
||||||
- run: yarn --cwd packages/zone.js jesttest
|
- run: yarn --cwd packages/zone.js jesttest
|
||||||
|
- run: yarn --cwd packages/zone.js/test/typings install --frozen-lockfile --non-interactive
|
||||||
|
- run: yarn --cwd packages/zone.js/test/typings test
|
||||||
|
|
||||||
# Windows jobs
|
# Windows jobs
|
||||||
# Docs: https://circleci.com/docs/2.0/hello-world-windows/
|
# Docs: https://circleci.com/docs/2.0/hello-world-windows/
|
||||||
|
2
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
2
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
name: "\U0001F41EBug report"
|
name: "\U0001F41E Bug report"
|
||||||
about: Report a bug in the Angular Framework
|
about: Report a bug in the Angular Framework
|
||||||
---
|
---
|
||||||
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
|
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
|
||||||
|
2
.github/ISSUE_TEMPLATE/2-feature-request.md
vendored
2
.github/ISSUE_TEMPLATE/2-feature-request.md
vendored
@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
name: "\U0001F680Feature request"
|
name: "\U0001F680 Feature request"
|
||||||
about: Suggest a feature for Angular Framework
|
about: Suggest a feature for Angular Framework
|
||||||
|
|
||||||
---
|
---
|
||||||
|
2
.github/ISSUE_TEMPLATE/5-support-request.md
vendored
2
.github/ISSUE_TEMPLATE/5-support-request.md
vendored
@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
name: "❓Support request"
|
name: "❓ Support request"
|
||||||
about: Questions and requests for support
|
about: Questions and requests for support
|
||||||
|
|
||||||
---
|
---
|
||||||
|
2
.github/ISSUE_TEMPLATE/6-angular-cli.md
vendored
2
.github/ISSUE_TEMPLATE/6-angular-cli.md
vendored
@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
name: "\U0001F6E0️Angular CLI"
|
name: "\U0001F6E0️ Angular CLI"
|
||||||
about: Issues and feature requests for Angular CLI
|
about: Issues and feature requests for Angular CLI
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
name: "\U0001F48EAngular Components"
|
name: "\U0001F48E Angular Components"
|
||||||
about: Issues and feature requests for Angular Components
|
about: Issues and feature requests for Angular Components
|
||||||
|
|
||||||
---
|
---
|
||||||
|
29
.github/angular-robot.yml
vendored
29
.github/angular-robot.yml
vendored
@ -68,20 +68,20 @@ merge:
|
|||||||
- "packages/**/integrationtest/**"
|
- "packages/**/integrationtest/**"
|
||||||
- "packages/**/test/**"
|
- "packages/**/test/**"
|
||||||
- "packages/zone.js/*"
|
- "packages/zone.js/*"
|
||||||
|
- "packages/zone.js/dist/**"
|
||||||
- "packages/zone.js/doc/**"
|
- "packages/zone.js/doc/**"
|
||||||
- "packages/zone.js/example/**"
|
- "packages/zone.js/example/**"
|
||||||
- "packages/zone.js/scripts/**"
|
- "packages/zone.js/scripts/**"
|
||||||
|
|
||||||
# comment that will be added to a PR when there is a conflict, leave empty or set to false to disable
|
# comment that will be added to a PR when there is a conflict, leave empty or set to false to disable
|
||||||
mergeConflictComment: "Hi @{{PRAuthor}}! This PR has merge conflicts due to recent upstream merges.
|
mergeConflictComment: "Hi @{{PRAuthor}}! This PR has merge conflicts due to recent upstream merges.\nPlease help to unblock it by resolving these conflicts. Thanks!"
|
||||||
\nPlease help to unblock it by resolving these conflicts. Thanks!"
|
|
||||||
|
|
||||||
# label to monitor
|
# label to monitor
|
||||||
mergeLabel: "PR action: merge"
|
mergeLabel: "action: merge"
|
||||||
|
|
||||||
# adding any of these labels will also add the merge label
|
# adding any of these labels will also add the merge label
|
||||||
mergeLinkedLabels:
|
mergeLinkedLabels:
|
||||||
- "PR action: merge-assistance"
|
- "action: merge-assistance"
|
||||||
|
|
||||||
# list of checks that will determine if the merge label can be added
|
# list of checks that will determine if the merge label can be added
|
||||||
checks:
|
checks:
|
||||||
@ -94,17 +94,17 @@ merge:
|
|||||||
|
|
||||||
# whether the PR shouldn't have a conflict with the base branch
|
# whether the PR shouldn't have a conflict with the base branch
|
||||||
noConflict: true
|
noConflict: true
|
||||||
# list of labels that a PR needs to have, checked with a regexp (e.g. "PR target:" will work for the label "PR target: master")
|
# list of labels that a PR needs to have, checked with a regexp (e.g. "target:" will work for the label "target: master")
|
||||||
requiredLabels:
|
requiredLabels:
|
||||||
- "PR target: *"
|
- "target: *"
|
||||||
- "cla: yes"
|
- "cla: yes"
|
||||||
|
|
||||||
# list of labels that a PR shouldn't have, checked after the required labels with a regexp
|
# list of labels that a PR shouldn't have, checked after the required labels with a regexp
|
||||||
forbiddenLabels:
|
forbiddenLabels:
|
||||||
- "PR target: TBD"
|
- "target: TBD"
|
||||||
- "PR action: cleanup"
|
- "action: cleanup"
|
||||||
- "PR action: review"
|
- "action: review"
|
||||||
- "PR state: blocked"
|
- "state: blocked"
|
||||||
- "cla: no"
|
- "cla: no"
|
||||||
|
|
||||||
# list of PR statuses that need to be successful
|
# list of PR statuses that need to be successful
|
||||||
@ -121,12 +121,7 @@ merge:
|
|||||||
# the comment that will be added when the merge label is added despite failing checks, leave empty or set to false to disable
|
# the comment that will be added when the merge label is added despite failing checks, leave empty or set to false to disable
|
||||||
# {{MERGE_LABEL}} will be replaced by the value of the mergeLabel option
|
# {{MERGE_LABEL}} will be replaced by the value of the mergeLabel option
|
||||||
# {{PLACEHOLDER}} will be replaced by the list of failing checks
|
# {{PLACEHOLDER}} will be replaced by the list of failing checks
|
||||||
mergeRemovedComment: "I see that you just added the `{{MERGE_LABEL}}` label, but the following checks are still failing:
|
mergeRemovedComment: "I see that you just added the `{{MERGE_LABEL}}` label, but the following checks are still failing:\n{{PLACEHOLDER}}\n\n**If you want your PR to be merged, it has to pass all the CI checks.**\n\nIf you can't get the PR to a green state due to flakes or broken master, please try rebasing to master and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help."
|
||||||
\n{{PLACEHOLDER}}
|
|
||||||
\n
|
|
||||||
\n**If you want your PR to be merged, it has to pass all the CI checks.**
|
|
||||||
\n
|
|
||||||
\nIf you can't get the PR to a green state due to flakes or broken master, please try rebasing to master and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help."
|
|
||||||
|
|
||||||
# options for the triage plugin
|
# options for the triage plugin
|
||||||
triage:
|
triage:
|
||||||
@ -186,4 +181,4 @@ rerunCircleCI:
|
|||||||
# set to true to disable
|
# set to true to disable
|
||||||
disabled: false
|
disabled: false
|
||||||
# the label which when added triggers a rerun of the default CircleCI workflow
|
# the label which when added triggers a rerun of the default CircleCI workflow
|
||||||
triggerRerunLabel: "PR action: rerun CI at HEAD"
|
triggerRerunLabel: "action: rerun CI at HEAD"
|
||||||
|
2
.github/workflows/lock-closed.yml
vendored
2
.github/workflows/lock-closed.yml
vendored
@ -10,6 +10,6 @@ jobs:
|
|||||||
if: github.repository == 'angular/angular'
|
if: github.repository == 'angular/angular'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: angular/dev-infra/github-actions/lock-closed@66462f6
|
- uses: angular/dev-infra/github-actions/lock-closed@414834b2b24dd2df37c6ed00808387ee6fd91b66
|
||||||
with:
|
with:
|
||||||
lock-bot-key: ${{ secrets.LOCK_BOT_PRIVATE_KEY }}
|
lock-bot-key: ${{ secrets.LOCK_BOT_PRIVATE_KEY }}
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -40,6 +40,9 @@ yarn-error.log
|
|||||||
# User specific bazel settings
|
# User specific bazel settings
|
||||||
.bazelrc.user
|
.bazelrc.user
|
||||||
|
|
||||||
|
# User specific ng-dev settings
|
||||||
|
.ng-dev.user*
|
||||||
|
|
||||||
.notes.md
|
.notes.md
|
||||||
baseline.json
|
baseline.json
|
||||||
|
|
||||||
|
19
.ng-dev/caretaker.ts
Normal file
19
.ng-dev/caretaker.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import {CaretakerConfig} from '../dev-infra/caretaker/config';
|
||||||
|
|
||||||
|
/** The configuration for `ng-dev caretaker` commands. */
|
||||||
|
export const caretaker: CaretakerConfig = {
|
||||||
|
githubQueries: [
|
||||||
|
{
|
||||||
|
name: 'Merge Queue',
|
||||||
|
query: `is:pr is:open status:success label:"action: merge"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Merge Assistance Queue',
|
||||||
|
query: `is:pr is:open status:success label:"action: merge-assistance"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Primary Triage Queue',
|
||||||
|
query: `is:open is:issue no:milestone`,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
@ -7,18 +7,6 @@ export const commitMessage: CommitMessageConfig = {
|
|||||||
maxLineLength: 120,
|
maxLineLength: 120,
|
||||||
minBodyLength: 20,
|
minBodyLength: 20,
|
||||||
minBodyLengthTypeExcludes: ['docs'],
|
minBodyLengthTypeExcludes: ['docs'],
|
||||||
types: [
|
|
||||||
'build',
|
|
||||||
'ci',
|
|
||||||
'docs',
|
|
||||||
'feat',
|
|
||||||
'fix',
|
|
||||||
'perf',
|
|
||||||
'refactor',
|
|
||||||
'release',
|
|
||||||
'style',
|
|
||||||
'test',
|
|
||||||
],
|
|
||||||
scopes: [
|
scopes: [
|
||||||
'animations',
|
'animations',
|
||||||
'bazel',
|
'bazel',
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import {caretaker} from './caretaker';
|
||||||
import {commitMessage} from './commit-message';
|
import {commitMessage} from './commit-message';
|
||||||
import {format} from './format';
|
import {format} from './format';
|
||||||
import {github} from './github';
|
import {github} from './github';
|
||||||
@ -8,4 +9,5 @@ module.exports = {
|
|||||||
format,
|
format,
|
||||||
github,
|
github,
|
||||||
merge,
|
merge,
|
||||||
|
caretaker,
|
||||||
};
|
};
|
||||||
|
@ -1,38 +1,25 @@
|
|||||||
import {MergeConfig} from '../dev-infra/pr/merge/config';
|
import {DevInfraMergeConfig} from '../dev-infra/pr/merge/config';
|
||||||
|
import {getDefaultTargetLabelConfiguration} from '../dev-infra/pr/merge/defaults';
|
||||||
|
import {github} from './github';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration for the merge tool in `ng-dev`. This sets up the labels which
|
* Configuration for the merge tool in `ng-dev`. This sets up the labels which
|
||||||
* are respected by the merge script (e.g. the target labels).
|
* are respected by the merge script (e.g. the target labels).
|
||||||
*/
|
*/
|
||||||
export const merge = (): MergeConfig => {
|
export const merge: DevInfraMergeConfig['merge'] = async api => {
|
||||||
// TODO: resume dynamically determining patch branch
|
|
||||||
const patch = '10.0.x';
|
|
||||||
return {
|
return {
|
||||||
githubApiMerge: false,
|
githubApiMerge: false,
|
||||||
claSignedLabel: 'cla: yes',
|
claSignedLabel: 'cla: yes',
|
||||||
mergeReadyLabel: /^PR action: merge(-assistance)?/,
|
mergeReadyLabel: /^action: merge(-assistance)?/,
|
||||||
caretakerNoteLabel: 'PR action: merge-assistance',
|
caretakerNoteLabel: 'action: merge-assistance',
|
||||||
commitMessageFixupLabel: 'commit message fixup',
|
commitMessageFixupLabel: 'commit message fixup',
|
||||||
labels: [
|
labels: await getDefaultTargetLabelConfiguration(api, github, '@angular/core'),
|
||||||
{
|
|
||||||
pattern: 'PR target: master-only',
|
|
||||||
branches: ['master'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
pattern: 'PR target: patch-only',
|
|
||||||
branches: [patch],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
pattern: 'PR target: master & patch',
|
|
||||||
branches: ['master', patch],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
requiredBaseCommits: {
|
requiredBaseCommits: {
|
||||||
// PRs that target either `master` or the patch branch, need to be rebased
|
// PRs that target either `master` or the patch branch, need to be rebased
|
||||||
// on top of the latest commit message validation fix.
|
// on top of the latest commit message validation fix.
|
||||||
// These SHAs are the commits that update the required license text in the header.
|
// These SHAs are the commits that update the required license text in the header.
|
||||||
'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a',
|
'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a',
|
||||||
[patch]: '27b95ba64a5d99757f4042073fd1860e20e3ed24'
|
'10.0.x': '27b95ba64a5d99757f4042073fd1860e20e3ed24',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -509,8 +509,8 @@ groups:
|
|||||||
- >
|
- >
|
||||||
contains_any_globs(files, [
|
contains_any_globs(files, [
|
||||||
'packages/core/src/i18n/**',
|
'packages/core/src/i18n/**',
|
||||||
'packages/core/src/render3/i18n.ts',
|
'packages/core/src/render3/i18n/**',
|
||||||
'packages/core/src/render3/i18n.md',
|
'packages/core/src/render3/instructions/i18n.ts',
|
||||||
'packages/core/src/render3/interfaces/i18n.ts',
|
'packages/core/src/render3/interfaces/i18n.ts',
|
||||||
'packages/common/locales/**',
|
'packages/common/locales/**',
|
||||||
'packages/common/src/i18n/**',
|
'packages/common/src/i18n/**',
|
||||||
|
@ -44654,7 +44654,7 @@ const FOLDERS_IGNORE = [
|
|||||||
const DEFAULT_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([...FOLDERS_IGNORE,
|
const DEFAULT_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([...FOLDERS_IGNORE,
|
||||||
|
|
||||||
// ignore cruft
|
// ignore cruft
|
||||||
'yarn.lock', '.lock-wscript', '.wafpickle-{0..9}', '*.swp', '._*', 'npm-debug.log', 'yarn-error.log', '.npmrc', '.yarnrc', '.npmignore', '.gitignore', '.DS_Store']);
|
'yarn.lock', '.lock-wscript', '.wafpickle-{0..9}', '*.swp', '._*', 'npm-debug.log', 'yarn-error.log', '.npmrc', '.yarnrc', '.yarnrc.yml', '.npmignore', '.gitignore', '.DS_Store']);
|
||||||
|
|
||||||
const NEVER_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([
|
const NEVER_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([
|
||||||
// never ignore these files
|
// never ignore these files
|
||||||
@ -44663,6 +44663,7 @@ const NEVER_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([
|
|||||||
function packWithIgnoreAndHeaders(cwd, ignoreFunction, { mapHeader } = {}) {
|
function packWithIgnoreAndHeaders(cwd, ignoreFunction, { mapHeader } = {}) {
|
||||||
return tar.pack(cwd, {
|
return tar.pack(cwd, {
|
||||||
ignore: ignoreFunction,
|
ignore: ignoreFunction,
|
||||||
|
sort: true,
|
||||||
map: header => {
|
map: header => {
|
||||||
const suffix = header.name === '.' ? '' : `/${header.name}`;
|
const suffix = header.name === '.' ? '' : `/${header.name}`;
|
||||||
header.name = `package${suffix}`;
|
header.name = `package${suffix}`;
|
||||||
@ -46678,7 +46679,7 @@ function mkdirfix (name, opts, cb) {
|
|||||||
/* 194 */
|
/* 194 */
|
||||||
/***/ (function(module, exports) {
|
/***/ (function(module, exports) {
|
||||||
|
|
||||||
module.exports = {"name":"yarn","installationMethod":"unknown","version":"1.22.4","license":"BSD-2-Clause","preferGlobal":true,"description":"📦🐈 Fast, reliable, and secure dependency management.","dependencies":{"@zkochan/cmd-shim":"^3.1.0","babel-runtime":"^6.26.0","bytes":"^3.0.0","camelcase":"^4.0.0","chalk":"^2.1.0","cli-table3":"^0.4.0","commander":"^2.9.0","death":"^1.0.0","debug":"^3.0.0","deep-equal":"^1.0.1","detect-indent":"^5.0.0","dnscache":"^1.0.1","glob":"^7.1.1","gunzip-maybe":"^1.4.0","hash-for-dep":"^1.2.3","imports-loader":"^0.8.0","ini":"^1.3.4","inquirer":"^6.2.0","invariant":"^2.2.0","is-builtin-module":"^2.0.0","is-ci":"^1.0.10","is-webpack-bundle":"^1.0.0","js-yaml":"^3.13.1","leven":"^2.0.0","loud-rejection":"^1.2.0","micromatch":"^2.3.11","mkdirp":"^0.5.1","node-emoji":"^1.6.1","normalize-url":"^2.0.0","npm-logical-tree":"^1.2.1","object-path":"^0.11.2","proper-lockfile":"^2.0.0","puka":"^1.0.0","read":"^1.0.7","request":"^2.87.0","request-capture-har":"^1.2.2","rimraf":"^2.5.0","semver":"^5.1.0","ssri":"^5.3.0","strip-ansi":"^4.0.0","strip-bom":"^3.0.0","tar-fs":"^1.16.0","tar-stream":"^1.6.1","uuid":"^3.0.1","v8-compile-cache":"^2.0.0","validate-npm-package-license":"^3.0.4","yn":"^2.0.0"},"devDependencies":{"babel-core":"^6.26.0","babel-eslint":"^7.2.3","babel-loader":"^6.2.5","babel-plugin-array-includes":"^2.0.3","babel-plugin-inline-import":"^3.0.0","babel-plugin-transform-builtin-extend":"^1.1.2","babel-plugin-transform-inline-imports-commonjs":"^1.0.0","babel-plugin-transform-runtime":"^6.4.3","babel-preset-env":"^1.6.0","babel-preset-flow":"^6.23.0","babel-preset-stage-0":"^6.0.0","babylon":"^6.5.0","commitizen":"^2.9.6","cz-conventional-changelog":"^2.0.0","eslint":"^4.3.0","eslint-config-fb-strict":"^22.0.0","eslint-plugin-babel":"^5.0.0","eslint-plugin-flowtype":"^2.35.0","eslint-plugin-jasmine":"^2.6.2","eslint-plugin-jest":"^21.0.0","eslint-plugin-jsx-a11y":"^6.0.2","eslint-plugin-prefer-object-spread":"^1.2.1","eslint-plugin-prettier":"^2.1.2","eslint-plugin-react":"^7.1.0","eslint-plugin-relay":"^0.0.28","eslint-plugin-yarn-internal":"file:scripts/eslint-rules","execa":"^0.11.0","fancy-log":"^1.3.2","flow-bin":"^0.66.0","git-release-notes":"^3.0.0","gulp":"^4.0.0","gulp-babel":"^7.0.0","gulp-if":"^2.0.1","gulp-newer":"^1.0.0","gulp-plumber":"^1.0.1","gulp-sourcemaps":"^2.2.0","jest":"^22.4.4","jsinspect":"^0.12.6","minimatch":"^3.0.4","mock-stdin":"^0.3.0","prettier":"^1.5.2","string-replace-loader":"^2.1.1","temp":"^0.8.3","webpack":"^2.1.0-beta.25","yargs":"^6.3.0"},"resolutions":{"sshpk":"^1.14.2"},"engines":{"node":">=4.0.0"},"repository":"yarnpkg/yarn","bin":{"yarn":"./bin/yarn.js","yarnpkg":"./bin/yarn.js"},"scripts":{"build":"gulp build","build-bundle":"node ./scripts/build-webpack.js","build-chocolatey":"powershell ./scripts/build-chocolatey.ps1","build-deb":"./scripts/build-deb.sh","build-dist":"bash ./scripts/build-dist.sh","build-win-installer":"scripts\\build-windows-installer.bat","changelog":"git-release-notes $(git describe --tags --abbrev=0 $(git describe --tags --abbrev=0)^)..$(git describe --tags --abbrev=0) scripts/changelog.md","dupe-check":"yarn jsinspect ./src","lint":"eslint . && flow check","pkg-tests":"yarn --cwd packages/pkg-tests jest yarn.test.js","prettier":"eslint src __tests__ --fix","release-branch":"./scripts/release-branch.sh","test":"yarn lint && yarn test-only","test-only":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --verbose","test-only-debug":"node --inspect-brk --max_old_space_size=4096 node_modules/jest/bin/jest.js --runInBand --verbose","test-coverage":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --coverage --verbose","watch":"gulp watch","commit":"git-cz"},"jest":{"collectCoverageFrom":["src/**/*.js"],"testEnvironment":"node","modulePathIgnorePatterns":["__tests__/fixtures/","packages/pkg-tests/pkg-tests-fixtures","dist/"],"testPathIgnorePatterns":["__tests__/(fixtures|__mocks__)/","updates/","_(temp|mock|install|init|helpers).js$","packages/pkg-tests"]},"config":{"commitizen":{"path":"./node_modules/cz-conventional-changelog"}}}
|
module.exports = {"name":"yarn","installationMethod":"unknown","version":"1.22.5","license":"BSD-2-Clause","preferGlobal":true,"description":"📦🐈 Fast, reliable, and secure dependency management.","dependencies":{"@zkochan/cmd-shim":"^3.1.0","babel-runtime":"^6.26.0","bytes":"^3.0.0","camelcase":"^4.0.0","chalk":"^2.1.0","cli-table3":"^0.4.0","commander":"^2.9.0","death":"^1.0.0","debug":"^3.0.0","deep-equal":"^1.0.1","detect-indent":"^5.0.0","dnscache":"^1.0.1","glob":"^7.1.1","gunzip-maybe":"^1.4.0","hash-for-dep":"^1.2.3","imports-loader":"^0.8.0","ini":"^1.3.4","inquirer":"^6.2.0","invariant":"^2.2.0","is-builtin-module":"^2.0.0","is-ci":"^1.0.10","is-webpack-bundle":"^1.0.0","js-yaml":"^3.13.1","leven":"^2.0.0","loud-rejection":"^1.2.0","micromatch":"^2.3.11","mkdirp":"^0.5.1","node-emoji":"^1.6.1","normalize-url":"^2.0.0","npm-logical-tree":"^1.2.1","object-path":"^0.11.2","proper-lockfile":"^2.0.0","puka":"^1.0.0","read":"^1.0.7","request":"^2.87.0","request-capture-har":"^1.2.2","rimraf":"^2.5.0","semver":"^5.1.0","ssri":"^5.3.0","strip-ansi":"^4.0.0","strip-bom":"^3.0.0","tar-fs":"^1.16.0","tar-stream":"^1.6.1","uuid":"^3.0.1","v8-compile-cache":"^2.0.0","validate-npm-package-license":"^3.0.4","yn":"^2.0.0"},"devDependencies":{"babel-core":"^6.26.0","babel-eslint":"^7.2.3","babel-loader":"^6.2.5","babel-plugin-array-includes":"^2.0.3","babel-plugin-inline-import":"^3.0.0","babel-plugin-transform-builtin-extend":"^1.1.2","babel-plugin-transform-inline-imports-commonjs":"^1.0.0","babel-plugin-transform-runtime":"^6.4.3","babel-preset-env":"^1.6.0","babel-preset-flow":"^6.23.0","babel-preset-stage-0":"^6.0.0","babylon":"^6.5.0","commitizen":"^2.9.6","cz-conventional-changelog":"^2.0.0","eslint":"^4.3.0","eslint-config-fb-strict":"^22.0.0","eslint-plugin-babel":"^5.0.0","eslint-plugin-flowtype":"^2.35.0","eslint-plugin-jasmine":"^2.6.2","eslint-plugin-jest":"^21.0.0","eslint-plugin-jsx-a11y":"^6.0.2","eslint-plugin-prefer-object-spread":"^1.2.1","eslint-plugin-prettier":"^2.1.2","eslint-plugin-react":"^7.1.0","eslint-plugin-relay":"^0.0.28","eslint-plugin-yarn-internal":"file:scripts/eslint-rules","execa":"^0.11.0","fancy-log":"^1.3.2","flow-bin":"^0.66.0","git-release-notes":"^3.0.0","gulp":"^4.0.0","gulp-babel":"^7.0.0","gulp-if":"^2.0.1","gulp-newer":"^1.0.0","gulp-plumber":"^1.0.1","gulp-sourcemaps":"^2.2.0","jest":"^22.4.4","jsinspect":"^0.12.6","minimatch":"^3.0.4","mock-stdin":"^0.3.0","prettier":"^1.5.2","string-replace-loader":"^2.1.1","temp":"^0.8.3","webpack":"^2.1.0-beta.25","yargs":"^6.3.0"},"resolutions":{"sshpk":"^1.14.2"},"engines":{"node":">=4.0.0"},"repository":"yarnpkg/yarn","bin":{"yarn":"./bin/yarn.js","yarnpkg":"./bin/yarn.js"},"scripts":{"build":"gulp build","build-bundle":"node ./scripts/build-webpack.js","build-chocolatey":"powershell ./scripts/build-chocolatey.ps1","build-deb":"./scripts/build-deb.sh","build-dist":"bash ./scripts/build-dist.sh","build-win-installer":"scripts\\build-windows-installer.bat","changelog":"git-release-notes $(git describe --tags --abbrev=0 $(git describe --tags --abbrev=0)^)..$(git describe --tags --abbrev=0) scripts/changelog.md","dupe-check":"yarn jsinspect ./src","lint":"eslint . && flow check","pkg-tests":"yarn --cwd packages/pkg-tests jest yarn.test.js","prettier":"eslint src __tests__ --fix","release-branch":"./scripts/release-branch.sh","test":"yarn lint && yarn test-only","test-only":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --verbose","test-only-debug":"node --inspect-brk --max_old_space_size=4096 node_modules/jest/bin/jest.js --runInBand --verbose","test-coverage":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --coverage --verbose","watch":"gulp watch","commit":"git-cz"},"jest":{"collectCoverageFrom":["src/**/*.js"],"testEnvironment":"node","modulePathIgnorePatterns":["__tests__/fixtures/","packages/pkg-tests/pkg-tests-fixtures","dist/"],"testPathIgnorePatterns":["__tests__/(fixtures|__mocks__)/","updates/","_(temp|mock|install|init|helpers).js$","packages/pkg-tests"]},"config":{"commitizen":{"path":"./node_modules/cz-conventional-changelog"}}}
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
/* 195 */
|
/* 195 */
|
||||||
@ -98338,7 +98339,7 @@ var _buildSubCommands = (0, (_buildSubCommands2 || _load_buildSubCommands()).def
|
|||||||
|
|
||||||
const bundle = yield fetchBundle(config, bundleUrl);
|
const bundle = yield fetchBundle(config, bundleUrl);
|
||||||
|
|
||||||
const yarnPath = path.resolve(config.lockfileFolder, `.yarn/releases/yarn-${bundleVersion}.js`);
|
const yarnPath = path.resolve(config.lockfileFolder, `.yarn/releases/yarn-${bundleVersion}.cjs`);
|
||||||
reporter.log(`Saving it into ${chalk.magenta(yarnPath)}...`);
|
reporter.log(`Saving it into ${chalk.magenta(yarnPath)}...`);
|
||||||
yield (_fs || _load_fs()).mkdirp(path.dirname(yarnPath));
|
yield (_fs || _load_fs()).mkdirp(path.dirname(yarnPath));
|
||||||
yield (_fs || _load_fs()).writeFile(yarnPath, bundle);
|
yield (_fs || _load_fs()).writeFile(yarnPath, bundle);
|
||||||
@ -100190,7 +100191,7 @@ let main = exports.main = (() => {
|
|||||||
|
|
||||||
const config = new (_config || _load_config()).default(reporter);
|
const config = new (_config || _load_config()).default(reporter);
|
||||||
const outputWrapperEnabled = (0, (_conversion || _load_conversion()).boolifyWithDefault)(process.env.YARN_WRAP_OUTPUT, true);
|
const outputWrapperEnabled = (0, (_conversion || _load_conversion()).boolifyWithDefault)(process.env.YARN_WRAP_OUTPUT, true);
|
||||||
const shouldWrapOutput = outputWrapperEnabled && !(_commander || _load_commander()).default.json && command.hasWrapper((_commander || _load_commander()).default, (_commander || _load_commander()).default.args);
|
const shouldWrapOutput = outputWrapperEnabled && !(_commander || _load_commander()).default.json && command.hasWrapper((_commander || _load_commander()).default, (_commander || _load_commander()).default.args) && !(commandName === 'init' && (_commander || _load_commander()).default[`2`]);
|
||||||
|
|
||||||
if (shouldWrapOutput) {
|
if (shouldWrapOutput) {
|
||||||
reporter.header(commandName, { name: 'yarn', version: (_yarnVersion || _load_yarnVersion()).version });
|
reporter.header(commandName, { name: 'yarn', version: (_yarnVersion || _load_yarnVersion()).version });
|
||||||
@ -100604,7 +100605,7 @@ let start = (() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (yarnPath.endsWith(`.js`)) {
|
if (/\.[cm]?js$/.test(yarnPath)) {
|
||||||
exitCode = yield (0, (_child || _load_child()).spawnp)(process.execPath, [yarnPath, ...argv], opts);
|
exitCode = yield (0, (_child || _load_child()).spawnp)(process.execPath, [yarnPath, ...argv], opts);
|
||||||
} else {
|
} else {
|
||||||
exitCode = yield (0, (_child || _load_child()).spawnp)(yarnPath, argv, opts);
|
exitCode = yield (0, (_child || _load_child()).spawnp)(yarnPath, argv, opts);
|
2
.yarnrc
2
.yarnrc
@ -2,4 +2,4 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
yarn-path ".yarn/releases/yarn-1.22.4.js"
|
yarn-path ".yarn/releases/yarn-1.22.5.js"
|
||||||
|
@ -34,7 +34,7 @@ filegroup(
|
|||||||
filegroup(
|
filegroup(
|
||||||
name = "angularjs_scripts",
|
name = "angularjs_scripts",
|
||||||
srcs = [
|
srcs = [
|
||||||
# We also declare the unminfied AngularJS files since these can be used for
|
# We also declare the unminified AngularJS files since these can be used for
|
||||||
# local debugging (e.g. see: packages/upgrade/test/common/test_helpers.ts)
|
# local debugging (e.g. see: packages/upgrade/test/common/test_helpers.ts)
|
||||||
"@npm//:node_modules/angular/angular.js",
|
"@npm//:node_modules/angular/angular.js",
|
||||||
"@npm//:node_modules/angular/angular.min.js",
|
"@npm//:node_modules/angular/angular.min.js",
|
||||||
|
419
CHANGELOG.md
419
CHANGELOG.md
@ -1,19 +1,331 @@
|
|||||||
<a name="10.1.0-next.4"></a>
|
<a name="11.0.0-next.3"></a>
|
||||||
# 10.1.0-next.4 (2020-08-04)
|
# 11.0.0-next.3 (2020-09-23)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **common:** narrow `NgIf` context variables in template type checker ([#36627](https://github.com/angular/angular/issues/36627)) ([9c8bc4a](https://github.com/angular/angular/commit/9c8bc4a))
|
* **common:** add `params` and `reportProgress` options to `HttpClient.put()` overload ([#37873](https://github.com/angular/angular/issues/37873)) ([dd8d8c8](https://github.com/angular/angular/commit/dd8d8c8)), closes [#23600](https://github.com/angular/angular/issues/23600)
|
||||||
* **compiler:** mark `NgModuleFactory` construction as not side effectful ([#38147](https://github.com/angular/angular/issues/38147)) ([7f8c222](https://github.com/angular/angular/commit/7f8c222))
|
* **compiler-cli:** generate `let` statements in ES2015+ mode ([#38775](https://github.com/angular/angular/issues/38775)) ([123bff7](https://github.com/angular/angular/commit/123bff7))
|
||||||
|
* **core:** ensure TestBed is not instantiated before override provider ([#38717](https://github.com/angular/angular/issues/38717)) ([c8f056b](https://github.com/angular/angular/commit/c8f056b))
|
||||||
|
* **forms:** type NG_VALUE_ACCESSOR injection token as array ([#29723](https://github.com/angular/angular/issues/29723)) ([2b1b718](https://github.com/angular/angular/commit/2b1b718)), closes [#29351](https://github.com/angular/angular/issues/29351)
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* **core:** rename async to waitForAsync to avoid confusing ([#37583](https://github.com/angular/angular/issues/37583)) ([8f07429](https://github.com/angular/angular/commit/8f07429))
|
* **common:** Add ISO week-numbering year formats support to formatDate ([#38828](https://github.com/angular/angular/issues/38828)) ([984ed39](https://github.com/angular/angular/commit/984ed39))
|
||||||
* **core:** update reference and doc to change `async` to `waitAsync`. ([#37583](https://github.com/angular/angular/issues/37583)) ([8fbf40b](https://github.com/angular/angular/commit/8fbf40b))
|
* **compiler:** Parse and recover on incomplete opening HTML tags ([#38681](https://github.com/angular/angular/issues/38681)) ([6ae3b68](https://github.com/angular/angular/commit/6ae3b68)), closes [#38596](https://github.com/angular/angular/issues/38596)
|
||||||
|
* **router:** add migration to update calls to navigateByUrl and createUrlTree with invalid parameters ([#38825](https://github.com/angular/angular/issues/38825)) ([7849fdd](https://github.com/angular/angular/commit/7849fdd)), closes [#38227](https://github.com/angular/angular/issues/38227)
|
||||||
|
* **service-worker:** add the option to prefer network for navigation requests ([#38565](https://github.com/angular/angular/issues/38565)) ([a206852](https://github.com/angular/angular/commit/a206852)), closes [#38194](https://github.com/angular/angular/issues/38194)
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* **core:** If you call `TestBed.overrideProvider` after TestBed initialization, provider overrides are not applied. This
|
||||||
|
behavior is consistent with other override methods (such as `TestBed.overrideDirective`, etc) but they
|
||||||
|
throw an error to indicate that, when the check was missing in the `TestBed.overrideProvider` function.
|
||||||
|
Now calling `TestBed.overrideProvider` after TestBed initialization also triggers an
|
||||||
|
error, thus there is a chance that some tests (where `TestBed.overrideProvider` is
|
||||||
|
called after TestBed initialization) will start to fail and require updates to move `TestBed.overrideProvider` calls
|
||||||
|
before TestBed initialization is completed.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="10.1.3"></a>
|
||||||
|
## 10.1.3 (2020-09-23)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **http:** Fix error message when we call jsonp without importing HttpClientJsonpModule ([#38756](https://github.com/angular/angular/issues/38756)) ([3902ec0](https://github.com/angular/angular/commit/3902ec0))
|
||||||
|
* **ngcc:** fix compilation of `ChangeDetectorRef` in pipe constructors ([#38892](https://github.com/angular/angular/issues/38892)) ([093c3a1](https://github.com/angular/angular/commit/093c3a1)), closes [#38666](https://github.com/angular/angular/issues/38666) [#38883](https://github.com/angular/angular/issues/38883)
|
||||||
|
|
||||||
|
|
||||||
|
### Reverts
|
||||||
|
|
||||||
|
* feat(router): better warning message when a router outlet has not been instantiated ([#38920](https://github.com/angular/angular/issues/38920)) ([04d0aa6](https://github.com/angular/angular/commit/04d0aa6))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="11.0.0-next.2"></a>
|
||||||
|
# 11.0.0-next.2 (2020-09-16)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **common:** do not round up fractions of a millisecond in `DatePipe` ([#38009](https://github.com/angular/angular/issues/38009)) ([26f2820](https://github.com/angular/angular/commit/26f2820)), closes [/www.ecma-international.org/ecma-262/5.1/#sec-15](https://github.com//www.ecma-international.org/ecma-262/5.1//issues/sec-15) [#37989](https://github.com/angular/angular/issues/37989)
|
||||||
|
* **common:** mark locale data arrays as readonly ([#30397](https://github.com/angular/angular/issues/30397)) ([6acea54](https://github.com/angular/angular/commit/6acea54)), closes [#27003](https://github.com/angular/angular/issues/27003)
|
||||||
|
* **compiler:** source span for microsyntax text att should be key span ([#38766](https://github.com/angular/angular/issues/38766)) ([8f349b2](https://github.com/angular/angular/commit/8f349b2))
|
||||||
|
* **router:** Fix arguments order for call to shouldReuseRoute ([#26949](https://github.com/angular/angular/issues/26949)) ([3817e5f](https://github.com/angular/angular/commit/3817e5f)), closes [#16192](https://github.com/angular/angular/issues/16192) [#16192](https://github.com/angular/angular/issues/16192)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **compiler-cli:** `TemplateTypeChecker` operation to get `Symbol` from a template node ([#38618](https://github.com/angular/angular/issues/38618)) ([c4556db](https://github.com/angular/angular/commit/c4556db))
|
||||||
|
* **compiler-cli:** Add ability to get `Symbol` of `Template`s and `Element`s in component template ([#38618](https://github.com/angular/angular/issues/38618)) ([cf2e8b9](https://github.com/angular/angular/commit/cf2e8b9))
|
||||||
|
* **compiler-cli:** Add ability to get `Symbol` of AST expression in component template ([#38618](https://github.com/angular/angular/issues/38618)) ([f56ece4](https://github.com/angular/angular/commit/f56ece4))
|
||||||
|
* **compiler-cli:** add ability to get symbol of reference or variable ([#38618](https://github.com/angular/angular/issues/38618)) ([19598b4](https://github.com/angular/angular/commit/19598b4))
|
||||||
|
* **compiler-cli:** define interfaces to be used for TemplateTypeChecker ([#38618](https://github.com/angular/angular/issues/38618)) ([9e77bd3](https://github.com/angular/angular/commit/9e77bd3))
|
||||||
|
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* **compiler-cli:** only emit directive/pipe references that are used ([#38539](https://github.com/angular/angular/issues/38539)) ([077f516](https://github.com/angular/angular/commit/077f516))
|
||||||
|
* **compiler-cli:** optimize computation of type-check scope information ([#38539](https://github.com/angular/angular/issues/38539)) ([297c060](https://github.com/angular/angular/commit/297c060))
|
||||||
|
* **router:** use `ngDevMode` to tree-shake error messages in router ([#38674](https://github.com/angular/angular/issues/38674)) ([db21c4f](https://github.com/angular/angular/commit/db21c4f))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* **router:** This change corrects the argument order when calling
|
||||||
|
RouteReuseStrategy#shouldReuseRoute. Previously, when evaluating child
|
||||||
|
routes, they would be called with the future and current arguments would
|
||||||
|
be swapped. If your RouteReuseStrategy relies specifically on only the future
|
||||||
|
or current snapshot state, you may need to update the shouldReuseRoute
|
||||||
|
implementation's use of "future" and "current" ActivateRouteSnapshots.
|
||||||
|
* **common:** The locale data API has been marked as returning readonly arrays, rather
|
||||||
|
than mutable arrays, since these arrays are shared across calls to the
|
||||||
|
API. If you were mutating them (e.g. calling `sort()`, `push()`, `splice()`, etc)
|
||||||
|
then your code will not longer compile. If you need to mutate the array, you
|
||||||
|
should now take a copy (e.g. by calling `slice()`) and mutate the copy.
|
||||||
|
* **common:** When passing a date-time formatted string to the `DatePipe` in a format that contains
|
||||||
|
fractions of a millisecond, the milliseconds will now always be rounded down rather than
|
||||||
|
to the nearest millisecond.
|
||||||
|
|
||||||
|
Most applications will not be affected by this change. If this is not the desired behaviour
|
||||||
|
then consider pre-processing the string to round the millisecond part before passing
|
||||||
|
it to the `DatePipe`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="10.1.2"></a>
|
||||||
|
## 10.1.2 (2020-09-16)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **compiler:** detect pipes in ICUs in template binder ([#38810](https://github.com/angular/angular/issues/38810)) ([ec2dbe7](https://github.com/angular/angular/commit/ec2dbe7)), closes [#38539](https://github.com/angular/angular/issues/38539) [#38539](https://github.com/angular/angular/issues/38539) [#38539](https://github.com/angular/angular/issues/38539)
|
||||||
|
* **core:** clear the `RefreshTransplantedView` when detached ([#38768](https://github.com/angular/angular/issues/38768)) ([edb7f90](https://github.com/angular/angular/commit/edb7f90)), closes [#38619](https://github.com/angular/angular/issues/38619)
|
||||||
|
* **localize:** ensure that `formatOptions` is optional ([#38787](https://github.com/angular/angular/issues/38787)) ([a47383d](https://github.com/angular/angular/commit/a47383d))
|
||||||
|
* **router:** Ensure routes are processed in priority order and only if needed ([#38780](https://github.com/angular/angular/issues/38780)) ([9c51ba3](https://github.com/angular/angular/commit/9c51ba3)), closes [#38691](https://github.com/angular/angular/issues/38691)
|
||||||
|
* **upgrade:** add try/catch when downgrading injectables ([#38671](https://github.com/angular/angular/issues/38671)) ([5de2ac3](https://github.com/angular/angular/commit/5de2ac3)), closes [#37579](https://github.com/angular/angular/issues/37579)
|
||||||
|
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* **compiler-cli:** only emit directive/pipe references that are used ([#38843](https://github.com/angular/angular/issues/38843)) ([5658405](https://github.com/angular/angular/commit/5658405))
|
||||||
|
* **compiler-cli:** optimize computation of type-check scope information ([#38843](https://github.com/angular/angular/issues/38843)) ([ebede67](https://github.com/angular/angular/commit/ebede67))
|
||||||
|
* **ngcc:** introduce cache for sharing data across entry-points ([#38840](https://github.com/angular/angular/issues/38840)) ([58411e7](https://github.com/angular/angular/commit/58411e7))
|
||||||
|
* **ngcc:** reduce maximum worker count ([#38840](https://github.com/angular/angular/issues/38840)) ([ea36466](https://github.com/angular/angular/commit/ea36466))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="11.0.0-next.1"></a>
|
||||||
|
# 11.0.0-next.1 (2020-09-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **compiler-cli:** compute source-mappings for localized strings ([#38645](https://github.com/angular/angular/issues/38645)) ([7e0b3fd](https://github.com/angular/angular/commit/7e0b3fd)), closes [#38588](https://github.com/angular/angular/issues/38588)
|
||||||
|
* **core:** remove CollectionChangeRecord symbol ([#38668](https://github.com/angular/angular/issues/38668)) ([fdea180](https://github.com/angular/angular/commit/fdea180))
|
||||||
|
* **router:** support lazy loading for empty path named outlets ([#38379](https://github.com/angular/angular/issues/38379)) ([926ffcd](https://github.com/angular/angular/commit/926ffcd)), closes [#12842](https://github.com/angular/angular/issues/12842)
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* **core:** CollectionChangeRecord has been removed, use IterableChangeRecord
|
||||||
|
instead
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="10.1.1"></a>
|
||||||
|
## 10.1.1 (2020-09-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **compiler:** correct confusion between field and property names ([#38685](https://github.com/angular/angular/issues/38685)) ([a1c34c6](https://github.com/angular/angular/commit/a1c34c6))
|
||||||
|
* **compiler-cli:** compute source-mappings for localized strings ([#38747](https://github.com/angular/angular/issues/38747)) ([b4eb016](https://github.com/angular/angular/commit/b4eb016)), closes [#38588](https://github.com/angular/angular/issues/38588)
|
||||||
|
* **compiler-cli:** ensure that a declaration is available in type-to-value conversion ([#38684](https://github.com/angular/angular/issues/38684)) ([56d5ff2](https://github.com/angular/angular/commit/56d5ff2)), closes [#38670](https://github.com/angular/angular/issues/38670)
|
||||||
|
* **core:** reset `tView` between tests in Ivy TestBed ([#38659](https://github.com/angular/angular/issues/38659)) ([efc7606](https://github.com/angular/angular/commit/efc7606)), closes [#38600](https://github.com/angular/angular/issues/38600)
|
||||||
|
* **localize:** do not expose NodeJS typings in $localize runtime code ([#38700](https://github.com/angular/angular/issues/38700)) ([4de8dc3](https://github.com/angular/angular/commit/4de8dc3)), closes [#38692](https://github.com/angular/angular/issues/38692)
|
||||||
|
* **localize:** enable whitespace preservation marker in XLIFF files ([#38737](https://github.com/angular/angular/issues/38737)) ([190dca0](https://github.com/angular/angular/commit/190dca0)), closes [#38679](https://github.com/angular/angular/issues/38679)
|
||||||
|
* **localize:** install `[@angular](https://github.com/angular)/localize` in `devDependencies` by default ([#38680](https://github.com/angular/angular/issues/38680)) ([dbab744](https://github.com/angular/angular/commit/dbab744)), closes [#38329](https://github.com/angular/angular/issues/38329)
|
||||||
|
* **localize:** render context of translation file parse errors ([#38673](https://github.com/angular/angular/issues/38673)) ([32f33f0](https://github.com/angular/angular/commit/32f33f0)), closes [#38377](https://github.com/angular/angular/issues/38377)
|
||||||
|
* **localize:** render location in XLIFF 2 even if there is no metadata ([#38713](https://github.com/angular/angular/issues/38713)) ([ab4f953](https://github.com/angular/angular/commit/ab4f953)), closes [#38705](https://github.com/angular/angular/issues/38705)
|
||||||
|
* **ngcc:** use aliased exported types correctly ([#38666](https://github.com/angular/angular/issues/38666)) ([6a28675](https://github.com/angular/angular/commit/6a28675)), closes [#38238](https://github.com/angular/angular/issues/38238)
|
||||||
|
* **router:** If users are using the Alt key when clicking the router links, prioritize browser’s default behavior ([#38375](https://github.com/angular/angular/issues/38375)) ([309709d](https://github.com/angular/angular/commit/309709d))
|
||||||
|
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* **core:** use `ngDevMode` to tree-shake error messages ([#38612](https://github.com/angular/angular/issues/38612)) ([b084bff](https://github.com/angular/angular/commit/b084bff))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="11.0.0-next.0"></a>
|
||||||
|
# 11.0.0-next.0 (2020-09-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **forms:** ensure to emit `statusChanges` on subsequent value update/validations ([#38354](https://github.com/angular/angular/issues/38354)) ([d9fea85](https://github.com/angular/angular/commit/d9fea85)), closes [#20424](https://github.com/angular/angular/issues/20424) [#14542](https://github.com/angular/angular/issues/14542)
|
||||||
|
* **service-worker:** fix condition to check for a cache-busted request ([#36847](https://github.com/angular/angular/issues/36847)) ([5be4edf](https://github.com/angular/angular/commit/5be4edf))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **service-worker:** add `UnrecoverableStateError` ([#36847](https://github.com/angular/angular/issues/36847)) ([036a2fa](https://github.com/angular/angular/commit/036a2fa)), closes [#36539](https://github.com/angular/angular/issues/36539)
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* **forms:** Previously if FormControl, FormGroup and FormArray class instances had async validators
|
||||||
|
defined at initialization time, the status change event was not emitted once async validator
|
||||||
|
completed. After this change the status event is emitted into the `statusChanges` observable.
|
||||||
|
If your code relies on the old behavior, you can filter/ignore this additional status change
|
||||||
|
event.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="10.1.0"></a>
|
||||||
|
# 10.1.0 (2020-09-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **bazel:** provide LinkablePackageInfo from ng_module ([#37623](https://github.com/angular/angular/issues/37623)) ([6898eab](https://github.com/angular/angular/commit/6898eab))
|
||||||
|
* **common:** add ReadonlyMap in place of Map in keyValuePipe ([#37311](https://github.com/angular/angular/issues/37311)) ([3373453](https://github.com/angular/angular/commit/3373453)), closes [#37308](https://github.com/angular/angular/issues/37308)
|
||||||
|
* **compiler-cli:** add `SourceFile.getOriginalLocation()` to sourcemaps package ([#32912](https://github.com/angular/angular/issues/32912)) ([6abb8d0](https://github.com/angular/angular/commit/6abb8d0))
|
||||||
|
* **compiler-cli:** Add compiler option to report errors when assigning to restricted input fields ([#38249](https://github.com/angular/angular/issues/38249)) ([71138f6](https://github.com/angular/angular/commit/71138f6))
|
||||||
|
* **compiler-cli:** add support for TypeScript 4.0 ([#38076](https://github.com/angular/angular/issues/38076)) ([0fc44e0](https://github.com/angular/angular/commit/0fc44e0))
|
||||||
|
* **compiler-cli:** explain why an expression cannot be used in AOT compilations ([#37587](https://github.com/angular/angular/issues/37587)) ([712f1bd](https://github.com/angular/angular/commit/712f1bd))
|
||||||
|
* **compiler:** support unary operators for more accurate type checking ([#37918](https://github.com/angular/angular/issues/37918)) ([874792d](https://github.com/angular/angular/commit/874792d)), closes [#20845](https://github.com/angular/angular/issues/20845) [#36178](https://github.com/angular/angular/issues/36178)
|
||||||
|
* **core:** rename async to waitForAsync to avoid confusing ([#37583](https://github.com/angular/angular/issues/37583)) ([8f07429](https://github.com/angular/angular/commit/8f07429))
|
||||||
|
* **core:** support injection token as predicate in queries ([#37506](https://github.com/angular/angular/issues/37506)) ([97dc85b](https://github.com/angular/angular/commit/97dc85b)), closes [#21152](https://github.com/angular/angular/issues/21152) [#36144](https://github.com/angular/angular/issues/36144)
|
||||||
|
* **core:** update reference and doc to change `async` to `waitAsync`. ([#37583](https://github.com/angular/angular/issues/37583)) ([8fbf40b](https://github.com/angular/angular/commit/8fbf40b))
|
||||||
|
* **forms:** AbstractControl to store raw validators in addition to combined validators function ([#37881](https://github.com/angular/angular/issues/37881)) ([ad7046b](https://github.com/angular/angular/commit/ad7046b))
|
||||||
|
* **localize:** allow duplicate messages to be handled during extraction ([#38082](https://github.com/angular/angular/issues/38082)) ([cf9a47b](https://github.com/angular/angular/commit/cf9a47b)), closes [#38077](https://github.com/angular/angular/issues/38077)
|
||||||
|
* **localize:** expose `canParse()` diagnostics ([#37909](https://github.com/angular/angular/issues/37909)) ([ec32eba](https://github.com/angular/angular/commit/ec32eba)), closes [#37901](https://github.com/angular/angular/issues/37901)
|
||||||
|
* **localize:** implement message extraction tool ([#32912](https://github.com/angular/angular/issues/32912)) ([190561d](https://github.com/angular/angular/commit/190561d))
|
||||||
|
* **platform-browser:** Allow `sms`-URLs ([#31463](https://github.com/angular/angular/issues/31463)) ([fc5c34d](https://github.com/angular/angular/commit/fc5c34d)), closes [#31462](https://github.com/angular/angular/issues/31462)
|
||||||
|
* **platform-server:** add option for absolute URL HTTP support ([#37539](https://github.com/angular/angular/issues/37539)) ([d37049a](https://github.com/angular/angular/commit/d37049a)), closes [#37071](https://github.com/angular/angular/issues/37071)
|
||||||
|
* **router:** better warning message when a router outlet has not been instantiated ([#30246](https://github.com/angular/angular/issues/30246)) ([1609815](https://github.com/angular/angular/commit/1609815))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** fix integration test for bazel building ([#38629](https://github.com/angular/angular/issues/38629)) ([dd82f2f](https://github.com/angular/angular/commit/dd82f2f))
|
||||||
|
* **common:** date pipe gives wrong week number ([#37632](https://github.com/angular/angular/issues/37632)) ([ef1fb6d](https://github.com/angular/angular/commit/ef1fb6d)), closes [#33961](https://github.com/angular/angular/issues/33961)
|
||||||
|
* **common:** narrow `NgIf` context variables in template type checker ([#36627](https://github.com/angular/angular/issues/36627)) ([9c8bc4a](https://github.com/angular/angular/commit/9c8bc4a))
|
||||||
|
* **compiler-cli:** avoid creating value expressions for symbols from type-only imports ([#37912](https://github.com/angular/angular/issues/37912)) ([18098d3](https://github.com/angular/angular/commit/18098d3)), closes [#37900](https://github.com/angular/angular/issues/37900)
|
||||||
|
* **compiler-cli:** ensure source-maps can handle webpack:// protocol ([#32912](https://github.com/angular/angular/issues/32912)) ([decd95e](https://github.com/angular/angular/commit/decd95e))
|
||||||
|
* **compiler-cli:** only read source-map comment from last line ([#32912](https://github.com/angular/angular/issues/32912)) ([07a07e3](https://github.com/angular/angular/commit/07a07e3))
|
||||||
|
* **compiler-cli:** type-check inputs that include undefined when there's coercion members ([#38273](https://github.com/angular/angular/issues/38273)) ([7525f3a](https://github.com/angular/angular/commit/7525f3a))
|
||||||
|
* **compiler:** incorrectly inferring namespace for HTML nodes inside SVG ([#38477](https://github.com/angular/angular/issues/38477)) ([0dda97e](https://github.com/angular/angular/commit/0dda97e)), closes [#37218](https://github.com/angular/angular/issues/37218)
|
||||||
|
* **compiler:** mark `NgModuleFactory` construction as not side effectful ([#38147](https://github.com/angular/angular/issues/38147)) ([7f8c222](https://github.com/angular/angular/commit/7f8c222))
|
||||||
|
* **core:** Allow modification of lifecycle hooks any time before bootstrap ([#35464](https://github.com/angular/angular/issues/35464)) ([737506e](https://github.com/angular/angular/commit/737506e)), closes [#30497](https://github.com/angular/angular/issues/30497)
|
||||||
|
* **core:** detect DI parameters in JIT mode for downleveled ES2015 classes ([#38463](https://github.com/angular/angular/issues/38463)) ([ca07da4](https://github.com/angular/angular/commit/ca07da4)), closes [#38453](https://github.com/angular/angular/issues/38453)
|
||||||
|
* **core:** determine required DOMParser feature availability ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([c509243](https://github.com/angular/angular/commit/c509243))
|
||||||
|
* **core:** do not trigger CSP alert/report in Firefox and Chrome ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([b950d46](https://github.com/angular/angular/commit/b950d46)), closes [#25214](https://github.com/angular/angular/issues/25214)
|
||||||
|
* **core:** move generated i18n statements to the `consts` field of ComponentDef ([#38404](https://github.com/angular/angular/issues/38404)) ([cb05c01](https://github.com/angular/angular/commit/cb05c01))
|
||||||
|
* **elements:** run strategy methods in correct zone ([#37814](https://github.com/angular/angular/issues/37814)) ([8df888d](https://github.com/angular/angular/commit/8df888d)), closes [#24181](https://github.com/angular/angular/issues/24181)
|
||||||
|
* **forms:** handle form groups/arrays own pending async validation ([#22575](https://github.com/angular/angular/issues/22575)) ([77b62a5](https://github.com/angular/angular/commit/77b62a5)), closes [#10064](https://github.com/angular/angular/issues/10064)
|
||||||
|
* **language-service:** non-existent module format in package output ([#37623](https://github.com/angular/angular/issues/37623)) ([413a0fb](https://github.com/angular/angular/commit/413a0fb))
|
||||||
|
* **localize:** ensure required XLIFF parameters are serialized ([#38575](https://github.com/angular/angular/issues/38575)) ([f0af387](https://github.com/angular/angular/commit/f0af387)), closes [#38570](https://github.com/angular/angular/issues/38570)
|
||||||
|
* **localize:** extract the correct message ids ([#38498](https://github.com/angular/angular/issues/38498)) ([ac461e1](https://github.com/angular/angular/commit/ac461e1))
|
||||||
|
* **localize:** render ICU placeholders in extracted translation files ([#38484](https://github.com/angular/angular/issues/38484)) ([81c3e80](https://github.com/angular/angular/commit/81c3e80))
|
||||||
|
* **localize:** render text of extracted placeholders ([#38536](https://github.com/angular/angular/issues/38536)) ([14e90be](https://github.com/angular/angular/commit/14e90be))
|
||||||
|
* **ngcc:** detect synthesized delegate constructors for downleveled ES2015 classes ([#38463](https://github.com/angular/angular/issues/38463)) ([3b9c802](https://github.com/angular/angular/commit/3b9c802)), closes [#38453](https://github.com/angular/angular/issues/38453) [#38453](https://github.com/angular/angular/issues/38453)
|
||||||
|
* **router:** defer loading of wildcard module until needed ([#38348](https://github.com/angular/angular/issues/38348)) ([8f708b5](https://github.com/angular/angular/commit/8f708b5)), closes [#25494](https://github.com/angular/angular/issues/25494)
|
||||||
|
* **router:** fix navigation ignoring logic to compare to the browser url ([#37716](https://github.com/angular/angular/issues/37716)) ([a5ffca0](https://github.com/angular/angular/commit/a5ffca0)), closes [#16710](https://github.com/angular/angular/issues/16710) [#13586](https://github.com/angular/angular/issues/13586)
|
||||||
|
* **router:** properly compare array queryParams for equality ([#37709](https://github.com/angular/angular/issues/37709)) ([#37860](https://github.com/angular/angular/issues/37860)) ([1801d0c](https://github.com/angular/angular/commit/1801d0c))
|
||||||
|
* **router:** remove parenthesis for primary outlet segment after removing auxiliary outlet segment ([#24656](https://github.com/angular/angular/issues/24656)) ([#37163](https://github.com/angular/angular/issues/37163)) ([71f008f](https://github.com/angular/angular/commit/71f008f))
|
||||||
|
* **router:** restore 'history.state' object for navigations coming from Angular router ([#28108](https://github.com/angular/angular/issues/28108)) ([#28176](https://github.com/angular/angular/issues/28176)) ([df76a20](https://github.com/angular/angular/commit/df76a20))
|
||||||
|
|
||||||
|
### Code Refactoring
|
||||||
|
* **router:** export DefaultRouteReuseStrategy to Router public_api ([#31575](https://github.com/angular/angular/issues/31575)) ([ca79880](https://github.com/angular/angular/commit/ca79880))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
* **compiler-cli:** don't emit template guards when child scope is empty ([#38418](https://github.com/angular/angular/issues/38418)) ([1388c17](https://github.com/angular/angular/commit/1388c17))
|
||||||
|
* **compiler-cli:** fix regressions in incremental program reuse ([#37641](https://github.com/angular/angular/issues/37641)) ([5103d90](https://github.com/angular/angular/commit/5103d90))
|
||||||
|
* **compiler-cli:** only generate directive declarations when used ([#38418](https://github.com/angular/angular/issues/38418)) ([fb8f4b4](https://github.com/angular/angular/commit/fb8f4b4))
|
||||||
|
* **compiler-cli:** only generate type-check code for referenced DOM elements ([#38418](https://github.com/angular/angular/issues/38418)) ([f42e6ce](https://github.com/angular/angular/commit/f42e6ce))
|
||||||
|
* **forms:** use internal `ngDevMode` flag to tree-shake error messages in prod builds ([#37821](https://github.com/angular/angular/issues/37821)) ([201a546](https://github.com/angular/angular/commit/201a546)), closes [#37697](https://github.com/angular/angular/issues/37697)
|
||||||
|
* **ngcc:** shortcircuit tokenizing in ESM dependency host ([#37639](https://github.com/angular/angular/issues/37639)) ([bd7f440](https://github.com/angular/angular/commit/bd7f440))
|
||||||
|
* **ngcc:** use `EntryPointManifest` to speed up noop `ProgramBaseEntryPointFinder` ([#37665](https://github.com/angular/angular/issues/37665)) ([9318e23](https://github.com/angular/angular/commit/9318e23))
|
||||||
|
* **router:** apply prioritizedGuardValue operator to optimize CanLoad guards ([#37523](https://github.com/angular/angular/issues/37523)) ([d7dd295](https://github.com/angular/angular/commit/d7dd295))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="10.0.14"></a>
|
||||||
|
## 10.0.14 (2020-08-26)
|
||||||
|
|
||||||
|
|
||||||
|
<a name="10.0.12"></a>
|
||||||
|
## 10.0.12 (2020-08-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **compiler-cli:** adding references to const enums in runtime code ([#38542](https://github.com/angular/angular/issues/38542)) ([814b436](https://github.com/angular/angular/commit/814b436)), closes [#38513](https://github.com/angular/angular/issues/38513)
|
||||||
|
* **core:** remove closing body tag from inert DOM builder ([#38454](https://github.com/angular/angular/issues/38454)) ([5528536](https://github.com/angular/angular/commit/5528536))
|
||||||
|
* **localize:** include the last placeholder in parsed translation text ([#38452](https://github.com/angular/angular/issues/38452)) ([57d1a48](https://github.com/angular/angular/commit/57d1a48))
|
||||||
|
* **localize:** parse all parts of a translation with nested HTML ([#38452](https://github.com/angular/angular/issues/38452)) ([07b99f5](https://github.com/angular/angular/commit/07b99f5)), closes [#38422](https://github.com/angular/angular/issues/38422)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **language-service:** introduce hybrid visitor to locate AST node ([#38540](https://github.com/angular/angular/issues/38540)) ([66d8c22](https://github.com/angular/angular/commit/66d8c22))
|
||||||
|
|
||||||
|
|
||||||
|
<a name="10.0.11"></a>
|
||||||
|
## 10.0.11 (2020-08-19)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **router:** ensure routerLinkActive updates when associated routerLinks change (resubmit of [#38349](https://github.com/angular/angular/issues/38349)) ([#38511](https://github.com/angular/angular/issues/38511)) ([0af9533](https://github.com/angular/angular/commit/0af9533)), closes [#18469](https://github.com/angular/angular/issues/18469)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="10.0.10"></a>
|
||||||
|
## 10.0.10 (2020-08-17)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **common:** Allow scrolling when browser supports scrollTo ([#38468](https://github.com/angular/angular/issues/38468)) ([b32126c](https://github.com/angular/angular/commit/b32126c)), closes [#30630](https://github.com/angular/angular/issues/30630)
|
||||||
|
* **core:** detect DI parameters in JIT mode for downleveled ES2015 classes ([#38500](https://github.com/angular/angular/issues/38500)) ([863acb6](https://github.com/angular/angular/commit/863acb6)), closes [#38453](https://github.com/angular/angular/issues/38453)
|
||||||
|
* **core:** error if CSS custom property in host binding has number in name ([#38432](https://github.com/angular/angular/issues/38432)) ([cb83b8a](https://github.com/angular/angular/commit/cb83b8a)), closes [#37292](https://github.com/angular/angular/issues/37292)
|
||||||
|
* **core:** fix multiple nested views removal from ViewContainerRef ([#38317](https://github.com/angular/angular/issues/38317)) ([d5e09f4](https://github.com/angular/angular/commit/d5e09f4)), closes [#38201](https://github.com/angular/angular/issues/38201)
|
||||||
|
* **ngcc:** detect synthesized delegate constructors for downleveled ES2015 classes ([#38500](https://github.com/angular/angular/issues/38500)) ([f3dd6c2](https://github.com/angular/angular/commit/f3dd6c2)), closes [#38453](https://github.com/angular/angular/issues/38453) [#38453](https://github.com/angular/angular/issues/38453)
|
||||||
|
* **router:** ensure routerLinkActive updates when associated routerLinks change ([#38349](https://github.com/angular/angular/issues/38349)) ([989e8a1](https://github.com/angular/angular/commit/989e8a1)), closes [#18469](https://github.com/angular/angular/issues/18469)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="10.0.9"></a>
|
||||||
|
## 10.0.9 (2020-08-12)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **common:** ensure scrollRestoration is writable ([#30630](https://github.com/angular/angular/issues/30630)) ([#38357](https://github.com/angular/angular/issues/38357)) ([58f4b3a](https://github.com/angular/angular/commit/58f4b3a)), closes [#30629](https://github.com/angular/angular/issues/30629)
|
||||||
|
* **compiler:** evaluate safe navigation expressions in correct binding order ([#37911](https://github.com/angular/angular/issues/37911)) ([f5b9d87](https://github.com/angular/angular/commit/f5b9d87)), closes [#37194](https://github.com/angular/angular/issues/37194)
|
||||||
|
* **compiler-cli:** avoid creating value expressions for symbols from type-only imports ([#38415](https://github.com/angular/angular/issues/38415)) ([ca2b4bc](https://github.com/angular/angular/commit/ca2b4bc)), closes [#37912](https://github.com/angular/angular/issues/37912)
|
||||||
|
* **compiler-cli:** infer quote expressions as any type in type checker ([#37917](https://github.com/angular/angular/issues/37917)) ([5b87c67](https://github.com/angular/angular/commit/5b87c67)), closes [#36568](https://github.com/angular/angular/issues/36568)
|
||||||
|
* **compiler-cli:** mark eager `NgModuleFactory` construction as not side effectful ([#38320](https://github.com/angular/angular/issues/38320)) ([016a41b](https://github.com/angular/angular/commit/016a41b)), closes [#38147](https://github.com/angular/angular/issues/38147)
|
||||||
|
* **compiler-cli:** match wrapHost parameter types within plugin interface ([#38004](https://github.com/angular/angular/issues/38004)) ([df01a82](https://github.com/angular/angular/commit/df01a82))
|
||||||
|
* **compiler-cli:** preserve quotes in class member names ([#38387](https://github.com/angular/angular/issues/38387)) ([c9acb7b](https://github.com/angular/angular/commit/c9acb7b)), closes [#38311](https://github.com/angular/angular/issues/38311)
|
||||||
|
* **core:** prevent NgModule scope being overwritten in JIT compiler ([#37795](https://github.com/angular/angular/issues/37795)) ([3acebdc](https://github.com/angular/angular/commit/3acebdc)), closes [#37105](https://github.com/angular/angular/issues/37105)
|
||||||
|
* **core:** queries not matching string injection tokens ([#38321](https://github.com/angular/angular/issues/38321)) ([32109dc](https://github.com/angular/angular/commit/32109dc)), closes [#38313](https://github.com/angular/angular/issues/38313) [#38315](https://github.com/angular/angular/issues/38315)
|
||||||
|
* **core:** Store the currently selected ICU in `LView` ([#38345](https://github.com/angular/angular/issues/38345)) ([ee5123f](https://github.com/angular/angular/commit/ee5123f))
|
||||||
|
* **platform-server:** remove styles added by ServerStylesHost on destruction ([#38367](https://github.com/angular/angular/issues/38367)) ([7f11149](https://github.com/angular/angular/commit/7f11149))
|
||||||
|
* **router:** prevent calling unsubscribe on undefined subscription in RouterPreloader ([#38344](https://github.com/angular/angular/issues/38344)) ([4151314](https://github.com/angular/angular/commit/4151314))
|
||||||
|
* **service-worker:** fix the chrome debugger syntax highlighter ([#38332](https://github.com/angular/angular/issues/38332)) ([f5d5bac](https://github.com/angular/angular/commit/f5d5bac))
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.8"></a>
|
<a name="10.0.8"></a>
|
||||||
## 10.0.8 (2020-08-04)
|
## 10.0.8 (2020-08-04)
|
||||||
@ -36,16 +348,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.1.0-next.3"></a>
|
|
||||||
# 10.1.0-next.3 (2020-07-28)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **elements:** run strategy methods in correct zone ([#37814](https://github.com/angular/angular/issues/37814)) ([8df888d](https://github.com/angular/angular/commit/8df888d)), closes [#24181](https://github.com/angular/angular/issues/24181)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.6"></a>
|
<a name="10.0.6"></a>
|
||||||
## 10.0.6 (2020-07-28)
|
## 10.0.6 (2020-07-28)
|
||||||
|
|
||||||
@ -59,23 +361,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.1.0-next.2"></a>
|
|
||||||
# 10.1.0-next.2 (2020-07-22)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **core:** Allow modification of lifecycle hooks any time before bootstrap ([#35464](https://github.com/angular/angular/issues/35464)) ([737506e](https://github.com/angular/angular/commit/737506e)), closes [#30497](https://github.com/angular/angular/issues/30497)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **common:** add ReadonlyMap in place of Map in keyValuePipe ([#37311](https://github.com/angular/angular/issues/37311)) ([3373453](https://github.com/angular/angular/commit/3373453)), closes [#37308](https://github.com/angular/angular/issues/37308)
|
|
||||||
* **forms:** AbstractControl to store raw validators in addition to combined validators function ([#37881](https://github.com/angular/angular/issues/37881)) ([ad7046b](https://github.com/angular/angular/commit/ad7046b))
|
|
||||||
* **localize:** allow duplicate messages to be handled during extraction ([#38082](https://github.com/angular/angular/issues/38082)) ([cf9a47b](https://github.com/angular/angular/commit/cf9a47b)), closes [#38077](https://github.com/angular/angular/issues/38077)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.5"></a>
|
<a name="10.0.5"></a>
|
||||||
## 10.0.5 (2020-07-22)
|
## 10.0.5 (2020-07-22)
|
||||||
|
|
||||||
@ -110,62 +395,6 @@
|
|||||||
* **bazel:** provide LinkablePackageInfo from ng_module ([#37778](https://github.com/angular/angular/issues/37778)) ([6cd10a1](https://github.com/angular/angular/commit/6cd10a1)), closes [/github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl#L144-L146](https://github.com//github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl/issues/L144-L146)
|
* **bazel:** provide LinkablePackageInfo from ng_module ([#37778](https://github.com/angular/angular/issues/37778)) ([6cd10a1](https://github.com/angular/angular/commit/6cd10a1)), closes [/github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl#L144-L146](https://github.com//github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl/issues/L144-L146)
|
||||||
|
|
||||||
|
|
||||||
<a name="10.1.0-next.1"></a>
|
|
||||||
# 10.1.0-next.1 (2020-07-15)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **bazel:** ng_module rule does not expose flat module information in Ivy ([#36971](https://github.com/angular/angular/issues/36971)) ([1550663](https://github.com/angular/angular/commit/1550663))
|
|
||||||
* **compiler:** check more cases for pipe usage inside host bindings ([#37883](https://github.com/angular/angular/issues/37883)) ([9322b9a](https://github.com/angular/angular/commit/9322b9a)), closes [#34655](https://github.com/angular/angular/issues/34655) [#37610](https://github.com/angular/angular/issues/37610)
|
|
||||||
* **compiler-cli:** ensure file_system handles mixed Windows drives ([#37959](https://github.com/angular/angular/issues/37959)) ([6b31155](https://github.com/angular/angular/commit/6b31155)), closes [#36777](https://github.com/angular/angular/issues/36777)
|
|
||||||
* **language-service:** remove completion for string ([#37983](https://github.com/angular/angular/issues/37983)) ([10aba15](https://github.com/angular/angular/commit/10aba15))
|
|
||||||
* **ngcc:** report a warning if ngcc tries to use a solution-style tsconfig ([#38003](https://github.com/angular/angular/issues/38003)) ([b358495](https://github.com/angular/angular/commit/b358495)), closes [#36386](https://github.com/angular/angular/issues/36386)
|
|
||||||
* **router:** ensure duplicate popstate/hashchange events are handled correctly ([#37674](https://github.com/angular/angular/issues/37674)) ([9185c6e](https://github.com/angular/angular/commit/9185c6e)), closes [/github.com/angular/angular/issues/16710#issuecomment-646919529](https://github.com//github.com/angular/angular/issues/16710/issues/issuecomment-646919529) [#16710](https://github.com/angular/angular/issues/16710)
|
|
||||||
* **service-worker:** correctly handle relative base href ([#37922](https://github.com/angular/angular/issues/37922)) ([d19ef65](https://github.com/angular/angular/commit/d19ef65)), closes [#25055](https://github.com/angular/angular/issues/25055) [#25055](https://github.com/angular/angular/issues/25055)
|
|
||||||
* **service-worker:** correctly serve `ngsw/state` with a non-root SW scope ([#37922](https://github.com/angular/angular/issues/37922)) ([2156bee](https://github.com/angular/angular/commit/2156bee)), closes [#30505](https://github.com/angular/angular/issues/30505)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.1.0-next.0"></a>
|
|
||||||
# 10.1.0-next.0 (2020-07-08)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **common:** date pipe gives wrong week number ([#37632](https://github.com/angular/angular/issues/37632)) ([ef1fb6d](https://github.com/angular/angular/commit/ef1fb6d)), closes [#33961](https://github.com/angular/angular/issues/33961)
|
|
||||||
* **compiler-cli:** ensure source-maps can handle webpack:// protocol ([#32912](https://github.com/angular/angular/issues/32912)) ([decd95e](https://github.com/angular/angular/commit/decd95e))
|
|
||||||
* **compiler-cli:** only read source-map comment from last line ([#32912](https://github.com/angular/angular/issues/32912)) ([07a07e3](https://github.com/angular/angular/commit/07a07e3))
|
|
||||||
* **core:** determine required DOMParser feature availability ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([c509243](https://github.com/angular/angular/commit/c509243))
|
|
||||||
* **core:** do not trigger CSP alert/report in Firefox and Chrome ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([b950d46](https://github.com/angular/angular/commit/b950d46)), closes [#25214](https://github.com/angular/angular/issues/25214)
|
|
||||||
* **forms:** handle form groups/arrays own pending async validation ([#22575](https://github.com/angular/angular/issues/22575)) ([77b62a5](https://github.com/angular/angular/commit/77b62a5)), closes [#10064](https://github.com/angular/angular/issues/10064)
|
|
||||||
* **language-service:** non-existent module format in package output ([#37623](https://github.com/angular/angular/issues/37623)) ([413a0fb](https://github.com/angular/angular/commit/413a0fb))
|
|
||||||
* **router:** fix navigation ignoring logic to compare to the browser url ([#37716](https://github.com/angular/angular/issues/37716)) ([a5ffca0](https://github.com/angular/angular/commit/a5ffca0)), closes [#16710](https://github.com/angular/angular/issues/16710) [#13586](https://github.com/angular/angular/issues/13586)
|
|
||||||
* **router:** properly compare array queryParams for equality ([#37709](https://github.com/angular/angular/issues/37709)) ([#37860](https://github.com/angular/angular/issues/37860)) ([1801d0c](https://github.com/angular/angular/commit/1801d0c))
|
|
||||||
* **router:** remove parenthesis for primary outlet segment after removing auxiliary outlet segment ([#24656](https://github.com/angular/angular/issues/24656)) ([#37163](https://github.com/angular/angular/issues/37163)) ([71f008f](https://github.com/angular/angular/commit/71f008f))
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **bazel:** provide LinkablePackageInfo from ng_module ([#37623](https://github.com/angular/angular/issues/37623)) ([6898eab](https://github.com/angular/angular/commit/6898eab))
|
|
||||||
* **compiler-cli:** add `SourceFile.getOriginalLocation()` to sourcemaps package ([#32912](https://github.com/angular/angular/issues/32912)) ([6abb8d0](https://github.com/angular/angular/commit/6abb8d0))
|
|
||||||
* **compiler-cli:** explain why an expression cannot be used in AOT compilations ([#37587](https://github.com/angular/angular/issues/37587)) ([712f1bd](https://github.com/angular/angular/commit/712f1bd))
|
|
||||||
* **core:** support injection token as predicate in queries ([#37506](https://github.com/angular/angular/issues/37506)) ([97dc85b](https://github.com/angular/angular/commit/97dc85b)), closes [#21152](https://github.com/angular/angular/issues/21152) [#36144](https://github.com/angular/angular/issues/36144)
|
|
||||||
* **localize:** expose `canParse()` diagnostics ([#37909](https://github.com/angular/angular/issues/37909)) ([ec32eba](https://github.com/angular/angular/commit/ec32eba)), closes [#37901](https://github.com/angular/angular/issues/37901)
|
|
||||||
* **localize:** implement message extraction tool ([#32912](https://github.com/angular/angular/issues/32912)) ([190561d](https://github.com/angular/angular/commit/190561d))
|
|
||||||
* **platform-browser:** Allow `sms`-URLs ([#31463](https://github.com/angular/angular/issues/31463)) ([fc5c34d](https://github.com/angular/angular/commit/fc5c34d)), closes [#31462](https://github.com/angular/angular/issues/31462)
|
|
||||||
* **platform-server:** add option for absolute URL HTTP support ([#37539](https://github.com/angular/angular/issues/37539)) ([d37049a](https://github.com/angular/angular/commit/d37049a)), closes [#37071](https://github.com/angular/angular/issues/37071)
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
|
|
||||||
* **compiler-cli:** fix regressions in incremental program reuse ([#37641](https://github.com/angular/angular/issues/37641)) ([5103d90](https://github.com/angular/angular/commit/5103d90))
|
|
||||||
* **ngcc:** shortcircuit tokenizing in ESM dependency host ([#37639](https://github.com/angular/angular/issues/37639)) ([bd7f440](https://github.com/angular/angular/commit/bd7f440))
|
|
||||||
* **ngcc:** use `EntryPointManifest` to speed up noop `ProgramBaseEntryPointFinder` ([#37665](https://github.com/angular/angular/issues/37665)) ([9318e23](https://github.com/angular/angular/commit/9318e23))
|
|
||||||
* **router:** apply prioritizedGuardValue operator to optimize CanLoad guards ([#37523](https://github.com/angular/angular/issues/37523)) ([d7dd295](https://github.com/angular/angular/commit/d7dd295))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.3"></a>
|
<a name="10.0.3"></a>
|
||||||
## 10.0.3 (2020-07-08)
|
## 10.0.3 (2020-07-08)
|
||||||
|
|
||||||
@ -447,12 +676,12 @@ https://github.com/microsoft/TypeScript/issues/38374 for more
|
|||||||
information and updates.
|
information and updates.
|
||||||
|
|
||||||
If you used Closure Compiler with Angular in the past, you will likely
|
If you used Closure Compiler with Angular in the past, you will likely
|
||||||
be better off consuming Angular packages built from sources directly
|
be better off consuming Angular packages built from sources directly
|
||||||
rather than consuming the version we publish on npm,
|
rather than consuming the version we publish on npm,
|
||||||
which is primarily optimized for Webpack/Rollup + Terser build pipeline.
|
which is primarily optimized for Webpack/Rollup + Terser build pipeline.
|
||||||
|
|
||||||
As a temporary workaround, you might consider using your current build
|
As a temporary workaround, you might consider using your current build
|
||||||
pipeline with Closure flag `--compilation_level=SIMPLE`. This flag
|
pipeline with Closure flag `--compilation_level=SIMPLE`. This flag
|
||||||
will ensure that your build pipeline produces buildable and
|
will ensure that your build pipeline produces buildable and
|
||||||
runnable artifacts, at the cost of increased payload size due to
|
runnable artifacts, at the cost of increased payload size due to
|
||||||
advanced optimizations being disabled.
|
advanced optimizations being disabled.
|
||||||
@ -460,17 +689,17 @@ advanced optimizations being disabled.
|
|||||||
If you were affected by this change, please help us understand your
|
If you were affected by this change, please help us understand your
|
||||||
needs by leaving a comment on https://github.com/angular/angular/issues/37234.
|
needs by leaving a comment on https://github.com/angular/angular/issues/37234.
|
||||||
|
|
||||||
* **core:** make generic mandatory for ModuleWithProviders
|
* **core:** make generic mandatory for ModuleWithProviders
|
||||||
|
|
||||||
A generic type parameter has always been required for the `ModuleWithProviders` pattern to work with Ivy, but prior to this commit, View Engine allowed the generic type to be omitted (though support was officially deprecated).
|
A generic type parameter has always been required for the `ModuleWithProviders` pattern to work with Ivy, but prior to this commit, View Engine allowed the generic type to be omitted (though support was officially deprecated).
|
||||||
If you're using `ModuleWithProviders` without a generic type in your application code, a v10 migration will update your code for you.
|
If you're using `ModuleWithProviders` without a generic type in your application code, a v10 migration will update your code for you.
|
||||||
|
|
||||||
However, if you are using View Engine and also depending on a library that omits the generic type, you will now get a build time error similar to:
|
However, if you are using View Engine and also depending on a library that omits the generic type, you will now get a build time error similar to:
|
||||||
|
|
||||||
```
|
```
|
||||||
error TS2314: Generic type 'ModuleWithProviders<T>' requires 1 type argument(s).
|
error TS2314: Generic type 'ModuleWithProviders<T>' requires 1 type argument(s).
|
||||||
```
|
```
|
||||||
|
|
||||||
In this case, ngcc won't help you (because it's Ivy-only) and the migration only covers application code.
|
In this case, ngcc won't help you (because it's Ivy-only) and the migration only covers application code.
|
||||||
You should contact the library author to fix their library to provide a type parameter when they use this class.
|
You should contact the library author to fix their library to provide a type parameter when they use this class.
|
||||||
|
|
||||||
@ -1798,7 +2027,7 @@ API surface going forward.
|
|||||||
* **core:** Injector.get now accepts abstract classes to return
|
* **core:** Injector.get now accepts abstract classes to return
|
||||||
type-safe values. Previous implementation returned `any` through the
|
type-safe values. Previous implementation returned `any` through the
|
||||||
deprecated implementation.
|
deprecated implementation.
|
||||||
* Angular now compiles with Ivy by default ([#32219](https://github.com/angular/angular/issues/32219)) ([ec4381d](https://github.com/angular/angular/commit/ec4381d)).
|
* Angular now compiles with Ivy by default ([#32219](https://github.com/angular/angular/issues/32219)) ([ec4381d](https://github.com/angular/angular/commit/ec4381d)).
|
||||||
|
|
||||||
If you aren't familiar with Ivy, read our [blog post about the Ivy preview](https://blog.angular.io/its-time-for-the-compatibility-opt-in-preview-of-ivy-38f3542a282f?gi=8bfeb44b05c) and see the list of changes [here](https://docs.google.com/document/d/1Dije0AsJ0PxL3NaeNPxpYDeapj30b_QC0xfeIvIIzgg/preview).
|
If you aren't familiar with Ivy, read our [blog post about the Ivy preview](https://blog.angular.io/its-time-for-the-compatibility-opt-in-preview-of-ivy-38f3542a282f?gi=8bfeb44b05c) and see the list of changes [here](https://docs.google.com/document/d/1Dije0AsJ0PxL3NaeNPxpYDeapj30b_QC0xfeIvIIzgg/preview).
|
||||||
|
|
||||||
|
@ -230,7 +230,6 @@ Must be one of the following:
|
|||||||
* **fix**: A bug fix
|
* **fix**: A bug fix
|
||||||
* **perf**: A code change that improves performance
|
* **perf**: A code change that improves performance
|
||||||
* **refactor**: A code change that neither fixes a bug nor adds a feature
|
* **refactor**: A code change that neither fixes a bug nor adds a feature
|
||||||
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
|
|
||||||
* **test**: Adding missing tests or correcting existing tests
|
* **test**: Adding missing tests or correcting existing tests
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,13 +16,6 @@ import {BuildNums, PrNums, SHA} from './constants';
|
|||||||
|
|
||||||
const logger = new Logger('mock-external-apis');
|
const logger = new Logger('mock-external-apis');
|
||||||
|
|
||||||
const log = (...args: any[]) => {
|
|
||||||
// Filter out non-matching URL checks
|
|
||||||
if (!/^matching.+: false$/.test(args[0])) {
|
|
||||||
logger.log(...args);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const AIO_CIRCLE_CI_TOKEN = getEnvVar('AIO_CIRCLE_CI_TOKEN');
|
const AIO_CIRCLE_CI_TOKEN = getEnvVar('AIO_CIRCLE_CI_TOKEN');
|
||||||
const AIO_GITHUB_TOKEN = getEnvVar('AIO_GITHUB_TOKEN');
|
const AIO_GITHUB_TOKEN = getEnvVar('AIO_GITHUB_TOKEN');
|
||||||
|
|
||||||
@ -91,8 +84,8 @@ const createArchive = (buildNum: number, prNum: number, sha: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Create request scopes
|
// Create request scopes
|
||||||
const circleCiApi = nock(CIRCLE_CI_API_HOST).log(log).persist();
|
const circleCiApi = nock(CIRCLE_CI_API_HOST).persist();
|
||||||
const githubApi = nock(GITHUB_API_HOST).log(log).persist().matchHeader('Authorization', `token ${AIO_GITHUB_TOKEN}`);
|
const githubApi = nock(GITHUB_API_HOST).persist().matchHeader('Authorization', `token ${AIO_GITHUB_TOKEN}`);
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
|
|
||||||
|
@ -27,28 +27,28 @@
|
|||||||
"body-parser": "^1.19.0",
|
"body-parser": "^1.19.0",
|
||||||
"delete-empty": "^3.0.0",
|
"delete-empty": "^3.0.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"jasmine": "^3.5.0",
|
"jasmine": "^3.6.1",
|
||||||
"nock": "^12.0.3",
|
"nock": "^13.0.4",
|
||||||
"node-fetch": "^2.6.0",
|
"node-fetch": "^2.6.1",
|
||||||
"shelljs": "^0.8.4",
|
"shelljs": "^0.8.4",
|
||||||
"source-map-support": "^0.5.19",
|
"source-map-support": "^0.5.19",
|
||||||
"tar-stream": "^2.1.2",
|
"tar-stream": "^2.1.3",
|
||||||
"tslib": "^1.11.1"
|
"tslib": "^2.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/body-parser": "^1.19.0",
|
"@types/body-parser": "^1.19.0",
|
||||||
"@types/express": "^4.17.6",
|
"@types/express": "^4.17.8",
|
||||||
"@types/jasmine": "^3.5.10",
|
"@types/jasmine": "^3.5.14",
|
||||||
"@types/nock": "^11.1.0",
|
"@types/nock": "^11.1.0",
|
||||||
"@types/node": "^13.13.2",
|
"@types/node": "^14.6.4",
|
||||||
"@types/node-fetch": "^2.5.7",
|
"@types/node-fetch": "^2.5.7",
|
||||||
"@types/shelljs": "^0.8.7",
|
"@types/shelljs": "^0.8.8",
|
||||||
"@types/supertest": "^2.0.8",
|
"@types/supertest": "^2.0.10",
|
||||||
"nodemon": "^2.0.3",
|
"nodemon": "^2.0.4",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"supertest": "^4.0.2",
|
"supertest": "^4.0.2",
|
||||||
"tslint": "^6.1.1",
|
"tslint": "^6.1.3",
|
||||||
"tslint-jasmine-noSkipOrFocus": "^1.0.9",
|
"tslint-jasmine-noSkipOrFocus": "^1.0.9",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^4.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -214,23 +214,24 @@ describe('GithubApi', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should call \'https.request()\' with the correct options', () => {
|
it('should call \'https.request()\' with the correct options', async () => {
|
||||||
const requestHandler = nock('https://api.github.com')
|
const requestHandler = nock('https://api.github.com')
|
||||||
.intercept('/path', 'method')
|
.intercept('/path', 'method')
|
||||||
.reply(200);
|
.reply(200);
|
||||||
|
|
||||||
(api as any).request('method', '/path');
|
await (api as any).request('method', '/path');
|
||||||
requestHandler.done();
|
requestHandler.done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should add the \'Authorization\' header containing the \'githubToken\'', () => {
|
it('should add the \'Authorization\' header containing the \'githubToken\'', async () => {
|
||||||
const requestHandler = nock('https://api.github.com')
|
const requestHandler = nock('https://api.github.com')
|
||||||
.intercept('/path', 'method', undefined, {
|
.intercept('/path', 'method', undefined, {
|
||||||
reqheaders: {Authorization: 'token 12345'},
|
reqheaders: {Authorization: 'token 12345'},
|
||||||
})
|
})
|
||||||
.reply(200);
|
.reply(200);
|
||||||
(api as any).request('method', '/path');
|
|
||||||
|
await (api as any).request('method', '/path');
|
||||||
requestHandler.done();
|
requestHandler.done();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -244,12 +245,13 @@ describe('GithubApi', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should \'JSON.stringify\' and send the data along with the request', () => {
|
it('should \'JSON.stringify\' and send the data along with the request', async () => {
|
||||||
const data = {key: 'value'};
|
const data = {key: 'value'};
|
||||||
const requestHandler = nock('https://api.github.com')
|
const requestHandler = nock('https://api.github.com')
|
||||||
.intercept('/path', 'method', JSON.stringify(data))
|
.intercept('/path', 'method', JSON.stringify(data))
|
||||||
.reply(200);
|
.reply(200);
|
||||||
(api as any).request('method', '/path', data);
|
|
||||||
|
await (api as any).request('method', '/path', data);
|
||||||
requestHandler.done();
|
requestHandler.done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -21,11 +21,13 @@ import { ItemDirective } from './item.directive';
|
|||||||
ItemDirective
|
ItemDirective
|
||||||
],
|
],
|
||||||
// #enddocregion declarations
|
// #enddocregion declarations
|
||||||
|
// #docregion imports
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
HttpClientModule
|
HttpClientModule
|
||||||
],
|
],
|
||||||
|
// #enddocregion imports
|
||||||
providers: [],
|
providers: [],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* This example project is special in that it is not a cli app. To run tests appropriate for this
|
||||||
|
* project, the test command is overwritten in `aio/content/examples/observables/example-config.json`.
|
||||||
|
*
|
||||||
|
* This is an empty placeholder file to ensure that `aio/tools/examples/run-example-e2e.js` runs
|
||||||
|
* tests for this project.
|
||||||
|
*
|
||||||
|
* TODO: Fix our infrastructure/tooling, so that this hack is not necessary.
|
||||||
|
*/
|
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"tests": [
|
||||||
|
{
|
||||||
|
"cmd": "yarn",
|
||||||
|
"args": ["tsc", "--project", "tsconfig.spec.json", "--module", "commonjs"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmd": "yarn",
|
||||||
|
"args": ["jasmine", "out-tsc/**/*.spec.js"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
import { docRegionChain, docRegionObservable, docRegionUnsubscribe } from './observables';
|
||||||
|
|
||||||
|
describe('observables', () => {
|
||||||
|
it('should print 2', (doneFn: DoneFn) => {
|
||||||
|
const consoleLogSpy = spyOn(console, 'log');
|
||||||
|
const observable = docRegionObservable(console);
|
||||||
|
observable.subscribe(() => {
|
||||||
|
expect(consoleLogSpy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(consoleLogSpy).toHaveBeenCalledWith(2);
|
||||||
|
doneFn();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should close the subscription', () => {
|
||||||
|
const subscription = docRegionUnsubscribe();
|
||||||
|
expect(subscription.closed).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should chain an observable', (doneFn: DoneFn) => {
|
||||||
|
const observable = docRegionChain();
|
||||||
|
observable.subscribe(value => {
|
||||||
|
expect(value).toBe(4);
|
||||||
|
doneFn();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -1,40 +1,72 @@
|
|||||||
import { map } from 'rxjs/operators';
|
// #docplaster
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
// #docregion observable
|
export function docRegionObservable(console: Console) {
|
||||||
|
// #docregion observable
|
||||||
|
|
||||||
// declare a publishing operation
|
// declare a publishing operation
|
||||||
const observable = new Observable<number>(observer => {
|
const observable = new Observable<number>(observer => {
|
||||||
// Subscriber fn...
|
// Subscriber fn...
|
||||||
});
|
// #enddocregion observable
|
||||||
|
// The below code is used for unit testing only
|
||||||
|
observer.next(2);
|
||||||
|
// #docregion observable
|
||||||
|
});
|
||||||
|
|
||||||
// initiate execution
|
// initiate execution
|
||||||
observable.subscribe(() => {
|
observable.subscribe(value => {
|
||||||
// observer handles notifications
|
// observer handles notifications
|
||||||
});
|
// #enddocregion observable
|
||||||
|
// The below code is used for unit testing only
|
||||||
|
console.log(value);
|
||||||
|
// #docregion observable
|
||||||
|
});
|
||||||
|
|
||||||
// #enddocregion observable
|
// #enddocregion observable
|
||||||
|
return observable;
|
||||||
|
}
|
||||||
|
|
||||||
// #docregion unsubscribe
|
export function docRegionUnsubscribe() {
|
||||||
|
const observable = new Observable<number>(() => {
|
||||||
|
// Subscriber fn...
|
||||||
|
});
|
||||||
|
// #docregion unsubscribe
|
||||||
|
|
||||||
const subscription = observable.subscribe(() => {
|
const subscription = observable.subscribe(() => {
|
||||||
// observer handles notifications
|
// observer handles notifications
|
||||||
});
|
});
|
||||||
|
|
||||||
subscription.unsubscribe();
|
subscription.unsubscribe();
|
||||||
|
|
||||||
// #enddocregion unsubscribe
|
// #enddocregion unsubscribe
|
||||||
|
return subscription;
|
||||||
|
}
|
||||||
|
|
||||||
// #docregion error
|
export function docRegionError() {
|
||||||
|
const observable = new Observable<number>(() => {
|
||||||
|
// Subscriber fn...
|
||||||
|
});
|
||||||
|
|
||||||
observable.subscribe(() => {
|
// #docregion error
|
||||||
throw Error('my error');
|
observable.subscribe(() => {
|
||||||
});
|
throw new Error('my error');
|
||||||
|
});
|
||||||
|
// #enddocregion error
|
||||||
|
}
|
||||||
|
|
||||||
// #enddocregion error
|
export function docRegionChain() {
|
||||||
|
let observable = new Observable<number>(observer => {
|
||||||
|
// Subscriber fn...
|
||||||
|
observer.next(2);
|
||||||
|
});
|
||||||
|
|
||||||
// #docregion chain
|
observable =
|
||||||
|
// #docregion chain
|
||||||
|
|
||||||
observable.pipe(map(v => 2 * v));
|
observable.pipe(map(v => 2 * v));
|
||||||
|
|
||||||
// #enddocregion chain
|
// #enddocregion chain
|
||||||
|
return observable;
|
||||||
|
}
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
import { docRegionError, docRegionPromise } from './promises';
|
||||||
|
|
||||||
|
describe('promises', () => {
|
||||||
|
it('should print 2', (doneFn: DoneFn) => {
|
||||||
|
const consoleLogSpy = spyOn(console, 'log');
|
||||||
|
const pr = docRegionPromise(console, 2);
|
||||||
|
pr.then((value) => {
|
||||||
|
expect(consoleLogSpy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(consoleLogSpy).toHaveBeenCalledWith(2);
|
||||||
|
expect(value).toBe(4);
|
||||||
|
doneFn();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error', (doneFn: DoneFn) => {
|
||||||
|
const promise = docRegionError();
|
||||||
|
promise
|
||||||
|
.then(() => {
|
||||||
|
throw new Error('Promise should be rejected.');
|
||||||
|
},
|
||||||
|
() => doneFn());
|
||||||
|
});
|
||||||
|
});
|
@ -1,25 +1,44 @@
|
|||||||
// #docregion promise
|
// #docplaster
|
||||||
// initiate execution
|
|
||||||
const promise = new Promise<number>((resolve, reject) => {
|
|
||||||
// Executer fn...
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.then(value => {
|
export function docRegionPromise(console: Console, inputValue: number) {
|
||||||
// handle result here
|
// #docregion promise
|
||||||
});
|
// initiate execution
|
||||||
|
let promise = new Promise<number>((resolve, reject) => {
|
||||||
|
// Executer fn...
|
||||||
|
// #enddocregion promise
|
||||||
|
// The below is used in the unit tests.
|
||||||
|
resolve(inputValue);
|
||||||
|
// #docregion promise
|
||||||
|
});
|
||||||
|
// #enddocregion promise
|
||||||
|
promise =
|
||||||
|
// #docregion promise
|
||||||
|
promise.then(value => {
|
||||||
|
// handle result here
|
||||||
|
// #enddocregion promise
|
||||||
|
// The below is used in the unit tests.
|
||||||
|
console.log(value);
|
||||||
|
return value;
|
||||||
|
// #docregion promise
|
||||||
|
});
|
||||||
|
// #enddocregion promise
|
||||||
|
promise =
|
||||||
|
// #docregion chain
|
||||||
|
promise.then(v => 2 * v);
|
||||||
|
// #enddocregion chain
|
||||||
|
|
||||||
// #enddocregion promise
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
// #docregion chain
|
export function docRegionError() {
|
||||||
|
let promise = Promise.resolve();
|
||||||
|
promise =
|
||||||
|
// #docregion error
|
||||||
|
|
||||||
promise.then(v => 2 * v);
|
promise.then(() => {
|
||||||
|
throw new Error('my error');
|
||||||
|
});
|
||||||
|
|
||||||
// #enddocregion chain
|
// #enddocregion error
|
||||||
|
return promise;
|
||||||
// #docregion error
|
}
|
||||||
|
|
||||||
promise.then(() => {
|
|
||||||
throw Error('my error');
|
|
||||||
});
|
|
||||||
|
|
||||||
// #enddocregion error
|
|
||||||
|
@ -41,7 +41,6 @@
|
|||||||
<!-- #enddocregion translated-plural -->
|
<!-- #enddocregion translated-plural -->
|
||||||
<!-- #docregion translated-select -->
|
<!-- #docregion translated-select -->
|
||||||
<!-- #docregion translate-select-1 -->
|
<!-- #docregion translate-select-1 -->
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">
|
<trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">
|
||||||
<source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>
|
<source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>
|
||||||
<target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>
|
<target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// TODO: Add unit tests for this file.
|
||||||
// tslint:disable: no-output-native
|
// tslint:disable: no-output-native
|
||||||
// #docregion
|
// #docregion
|
||||||
import { Component, Output, OnInit, EventEmitter, NgModule } from '@angular/core';
|
import { Component, Output, OnInit, EventEmitter, NgModule } from '@angular/core';
|
||||||
|
@ -2,7 +2,11 @@
|
|||||||
"tests": [
|
"tests": [
|
||||||
{
|
{
|
||||||
"cmd": "yarn",
|
"cmd": "yarn",
|
||||||
"args": [ "tsc", "--project", "./tsconfig.app.json" ]
|
"args": ["tsc", "--project", "tsconfig.spec.json", "--module", "commonjs"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmd": "yarn",
|
||||||
|
"args": ["jasmine", "out-tsc/**/*.spec.js"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
55
aio/content/examples/observables/src/creating.spec.ts
Normal file
55
aio/content/examples/observables/src/creating.spec.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { docRegionFromEvent, docRegionSubscriber } from './creating';
|
||||||
|
|
||||||
|
describe('observables', () => {
|
||||||
|
it('should create an observable using the constructor', () => {
|
||||||
|
const console = {log: jasmine.createSpy('log')};
|
||||||
|
docRegionSubscriber(console);
|
||||||
|
expect(console.log).toHaveBeenCalledTimes(4);
|
||||||
|
expect(console.log.calls.allArgs()).toEqual([
|
||||||
|
[1],
|
||||||
|
[2],
|
||||||
|
[3],
|
||||||
|
['Finished sequence'],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should listen to input changes', () => {
|
||||||
|
let triggerInputChange;
|
||||||
|
const input = {
|
||||||
|
value: 'Test',
|
||||||
|
addEventListener: jasmine
|
||||||
|
.createSpy('addEvent')
|
||||||
|
.and.callFake((eventName: string, cb: (e) => void) => {
|
||||||
|
if (eventName === 'keydown') {
|
||||||
|
triggerInputChange = cb;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
removeEventListener: jasmine.createSpy('removeEventListener'),
|
||||||
|
};
|
||||||
|
|
||||||
|
const document = { getElementById: () => input };
|
||||||
|
docRegionFromEvent(document);
|
||||||
|
triggerInputChange({keyCode: 65});
|
||||||
|
expect(input.value).toBe('Test');
|
||||||
|
|
||||||
|
triggerInputChange({keyCode: 27});
|
||||||
|
expect(input.value).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call removeEventListener when unsubscribing', (doneFn: DoneFn) => {
|
||||||
|
const input = {
|
||||||
|
addEventListener: jasmine.createSpy('addEvent'),
|
||||||
|
removeEventListener: jasmine
|
||||||
|
.createSpy('removeEvent')
|
||||||
|
.and.callFake((eventName: string, cb: (e) => void) => {
|
||||||
|
if (eventName === 'keydown') {
|
||||||
|
doneFn();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
const document = { getElementById: () => input };
|
||||||
|
const subscription = docRegionFromEvent(document);
|
||||||
|
subscription.unsubscribe();
|
||||||
|
});
|
||||||
|
});
|
@ -1,38 +1,39 @@
|
|||||||
|
// #docplaster
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
// #docregion subscriber
|
export function docRegionSubscriber(console) {
|
||||||
|
// #docregion subscriber
|
||||||
|
// This function runs when subscribe() is called
|
||||||
|
function sequenceSubscriber(observer) {
|
||||||
|
// synchronously deliver 1, 2, and 3, then complete
|
||||||
|
observer.next(1);
|
||||||
|
observer.next(2);
|
||||||
|
observer.next(3);
|
||||||
|
observer.complete();
|
||||||
|
|
||||||
// This function runs when subscribe() is called
|
// unsubscribe function doesn't need to do anything in this
|
||||||
function sequenceSubscriber(observer) {
|
// because values are delivered synchronously
|
||||||
// synchronously deliver 1, 2, and 3, then complete
|
return {unsubscribe() {}};
|
||||||
observer.next(1);
|
}
|
||||||
observer.next(2);
|
|
||||||
observer.next(3);
|
|
||||||
observer.complete();
|
|
||||||
|
|
||||||
// unsubscribe function doesn't need to do anything in this
|
// Create a new Observable that will deliver the above sequence
|
||||||
// because values are delivered synchronously
|
const sequence = new Observable(sequenceSubscriber);
|
||||||
return {unsubscribe() {}};
|
|
||||||
|
// execute the Observable and print the result of each notification
|
||||||
|
sequence.subscribe({
|
||||||
|
next(num) { console.log(num); },
|
||||||
|
complete() { console.log('Finished sequence'); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// Logs:
|
||||||
|
// 1
|
||||||
|
// 2
|
||||||
|
// 3
|
||||||
|
// Finished sequence
|
||||||
|
// #enddocregion subscriber
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new Observable that will deliver the above sequence
|
|
||||||
const sequence = new Observable(sequenceSubscriber);
|
|
||||||
|
|
||||||
// execute the Observable and print the result of each notification
|
|
||||||
sequence.subscribe({
|
|
||||||
next(num) { console.log(num); },
|
|
||||||
complete() { console.log('Finished sequence'); }
|
|
||||||
});
|
|
||||||
|
|
||||||
// Logs:
|
|
||||||
// 1
|
|
||||||
// 2
|
|
||||||
// 3
|
|
||||||
// Finished sequence
|
|
||||||
|
|
||||||
// #enddocregion subscriber
|
|
||||||
|
|
||||||
// #docregion fromevent
|
// #docregion fromevent
|
||||||
|
|
||||||
function fromEvent(target, eventName) {
|
function fromEvent(target, eventName) {
|
||||||
@ -51,16 +52,18 @@ function fromEvent(target, eventName) {
|
|||||||
|
|
||||||
// #enddocregion fromevent
|
// #enddocregion fromevent
|
||||||
|
|
||||||
// #docregion fromevent_use
|
export function docRegionFromEvent(document) {
|
||||||
|
// #docregion fromevent_use
|
||||||
|
|
||||||
const ESC_KEY = 27;
|
const ESC_KEY = 27;
|
||||||
const nameInput = document.getElementById('name') as HTMLInputElement;
|
const nameInput = document.getElementById('name') as HTMLInputElement;
|
||||||
|
|
||||||
const subscription = fromEvent(nameInput, 'keydown')
|
const subscription = fromEvent(nameInput, 'keydown').subscribe((e: KeyboardEvent) => {
|
||||||
.subscribe((e: KeyboardEvent) => {
|
|
||||||
if (e.keyCode === ESC_KEY) {
|
if (e.keyCode === ESC_KEY) {
|
||||||
nameInput.value = '';
|
nameInput.value = '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// #enddocregion fromevent_use
|
||||||
|
return subscription;
|
||||||
|
}
|
||||||
|
|
||||||
// #enddocregion fromevent_use
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
// TODO: Add unit tests for this file.
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
// #docregion
|
// #docregion
|
||||||
|
|
||||||
// Create an Observable that will start listening to geolocation updates
|
// Create an Observable that will start listening to geolocation updates
|
||||||
|
48
aio/content/examples/observables/src/multicasting.spec.ts
Normal file
48
aio/content/examples/observables/src/multicasting.spec.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import { docRegionDelaySequence, docRegionMulticastSequence } from './multicasting';
|
||||||
|
|
||||||
|
describe('multicasting', () => {
|
||||||
|
let console;
|
||||||
|
beforeEach(() => {
|
||||||
|
jasmine.clock().install();
|
||||||
|
console = {log: jasmine.createSpy('log')};
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jasmine.clock().uninstall();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create an observable and emit in sequence', () => {
|
||||||
|
docRegionDelaySequence(console);
|
||||||
|
jasmine.clock().tick(10000);
|
||||||
|
expect(console.log).toHaveBeenCalledTimes(12);
|
||||||
|
expect(console.log.calls.allArgs()).toEqual([
|
||||||
|
[1],
|
||||||
|
['1st subscribe: 1'],
|
||||||
|
['2nd subscribe: 1'],
|
||||||
|
[2],
|
||||||
|
['1st subscribe: 2'],
|
||||||
|
['2nd subscribe: 2'],
|
||||||
|
[3],
|
||||||
|
['Finished sequence'],
|
||||||
|
['1st subscribe: 3'],
|
||||||
|
['1st sequence finished.'],
|
||||||
|
['2nd subscribe: 3'],
|
||||||
|
['2nd sequence finished.']
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create an observable and multicast the emissions', () => {
|
||||||
|
docRegionMulticastSequence(console);
|
||||||
|
jasmine.clock().tick(10000);
|
||||||
|
expect(console.log).toHaveBeenCalledTimes(7);
|
||||||
|
expect(console.log.calls.allArgs()).toEqual([
|
||||||
|
['1st subscribe: 1'],
|
||||||
|
['1st subscribe: 2'],
|
||||||
|
['2nd subscribe: 2'],
|
||||||
|
['1st subscribe: 3'],
|
||||||
|
['2nd subscribe: 3'],
|
||||||
|
['1st sequence finished.'],
|
||||||
|
['2nd sequence finished.']
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
@ -1,155 +1,160 @@
|
|||||||
|
// #docplaster
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
// #docregion delay_sequence
|
export function docRegionDelaySequence(console) {
|
||||||
|
// #docregion delay_sequence
|
||||||
|
function sequenceSubscriber(observer) {
|
||||||
|
const seq = [1, 2, 3];
|
||||||
|
let timeoutId;
|
||||||
|
|
||||||
function sequenceSubscriber(observer) {
|
// Will run through an array of numbers, emitting one value
|
||||||
const seq = [1, 2, 3];
|
// per second until it gets to the end of the array.
|
||||||
let timeoutId;
|
function doInSequence(arr, idx) {
|
||||||
|
timeoutId = setTimeout(() => {
|
||||||
|
observer.next(arr[idx]);
|
||||||
|
if (idx === arr.length - 1) {
|
||||||
|
observer.complete();
|
||||||
|
} else {
|
||||||
|
doInSequence(arr, ++idx);
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
// Will run through an array of numbers, emitting one value
|
doInSequence(seq, 0);
|
||||||
|
|
||||||
|
// Unsubscribe should clear the timeout to stop execution
|
||||||
|
return {
|
||||||
|
unsubscribe() {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new Observable that will deliver the above sequence
|
||||||
|
const sequence = new Observable(sequenceSubscriber);
|
||||||
|
|
||||||
|
sequence.subscribe({
|
||||||
|
next(num) { console.log(num); },
|
||||||
|
complete() { console.log('Finished sequence'); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// Logs:
|
||||||
|
// (at 1 second): 1
|
||||||
|
// (at 2 seconds): 2
|
||||||
|
// (at 3 seconds): 3
|
||||||
|
// (at 3 seconds): Finished sequence
|
||||||
|
|
||||||
|
// #enddocregion delay_sequence
|
||||||
|
|
||||||
|
// #docregion subscribe_twice
|
||||||
|
|
||||||
|
// Subscribe starts the clock, and will emit after 1 second
|
||||||
|
sequence.subscribe({
|
||||||
|
next(num) { console.log('1st subscribe: ' + num); },
|
||||||
|
complete() { console.log('1st sequence finished.'); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// After 1/2 second, subscribe again.
|
||||||
|
setTimeout(() => {
|
||||||
|
sequence.subscribe({
|
||||||
|
next(num) { console.log('2nd subscribe: ' + num); },
|
||||||
|
complete() { console.log('2nd sequence finished.'); }
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
// Logs:
|
||||||
|
// (at 1 second): 1st subscribe: 1
|
||||||
|
// (at 1.5 seconds): 2nd subscribe: 1
|
||||||
|
// (at 2 seconds): 1st subscribe: 2
|
||||||
|
// (at 2.5 seconds): 2nd subscribe: 2
|
||||||
|
// (at 3 seconds): 1st subscribe: 3
|
||||||
|
// (at 3 seconds): 1st sequence finished
|
||||||
|
// (at 3.5 seconds): 2nd subscribe: 3
|
||||||
|
// (at 3.5 seconds): 2nd sequence finished
|
||||||
|
|
||||||
|
// #enddocregion subscribe_twice
|
||||||
|
}
|
||||||
|
|
||||||
|
export function docRegionMulticastSequence(console) {
|
||||||
|
// #docregion multicast_sequence
|
||||||
|
function multicastSequenceSubscriber() {
|
||||||
|
const seq = [1, 2, 3];
|
||||||
|
// Keep track of each observer (one for every active subscription)
|
||||||
|
const observers = [];
|
||||||
|
// Still a single timeoutId because there will only ever be one
|
||||||
|
// set of values being generated, multicasted to each subscriber
|
||||||
|
let timeoutId;
|
||||||
|
|
||||||
|
// Return the subscriber function (runs when subscribe()
|
||||||
|
// function is invoked)
|
||||||
|
return observer => {
|
||||||
|
observers.push(observer);
|
||||||
|
// When this is the first subscription, start the sequence
|
||||||
|
if (observers.length === 1) {
|
||||||
|
timeoutId = doSequence({
|
||||||
|
next(val) {
|
||||||
|
// Iterate through observers and notify all subscriptions
|
||||||
|
observers.forEach(obs => obs.next(val));
|
||||||
|
},
|
||||||
|
complete() {
|
||||||
|
// Notify all complete callbacks
|
||||||
|
observers.slice(0).forEach(obs => obs.complete());
|
||||||
|
}
|
||||||
|
}, seq, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
unsubscribe() {
|
||||||
|
// Remove from the observers array so it's no longer notified
|
||||||
|
observers.splice(observers.indexOf(observer), 1);
|
||||||
|
// If there's no more listeners, do cleanup
|
||||||
|
if (observers.length === 0) {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run through an array of numbers, emitting one value
|
||||||
// per second until it gets to the end of the array.
|
// per second until it gets to the end of the array.
|
||||||
function doInSequence(arr, idx) {
|
function doSequence(observer, arr, idx) {
|
||||||
timeoutId = setTimeout(() => {
|
return setTimeout(() => {
|
||||||
observer.next(arr[idx]);
|
observer.next(arr[idx]);
|
||||||
if (idx === arr.length - 1) {
|
if (idx === arr.length - 1) {
|
||||||
observer.complete();
|
observer.complete();
|
||||||
} else {
|
} else {
|
||||||
doInSequence(arr, ++idx);
|
doSequence(observer, arr, ++idx);
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
doInSequence(seq, 0);
|
// Create a new Observable that will deliver the above sequence
|
||||||
|
const multicastSequence = new Observable(multicastSequenceSubscriber());
|
||||||
|
|
||||||
// Unsubscribe should clear the timeout to stop execution
|
// Subscribe starts the clock, and begins to emit after 1 second
|
||||||
return {unsubscribe() {
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new Observable that will deliver the above sequence
|
|
||||||
const sequence = new Observable(sequenceSubscriber);
|
|
||||||
|
|
||||||
sequence.subscribe({
|
|
||||||
next(num) { console.log(num); },
|
|
||||||
complete() { console.log('Finished sequence'); }
|
|
||||||
});
|
|
||||||
|
|
||||||
// Logs:
|
|
||||||
// (at 1 second): 1
|
|
||||||
// (at 2 seconds): 2
|
|
||||||
// (at 3 seconds): 3
|
|
||||||
// (at 3 seconds): Finished sequence
|
|
||||||
|
|
||||||
// #enddocregion delay_sequence
|
|
||||||
|
|
||||||
// #docregion subscribe_twice
|
|
||||||
|
|
||||||
// Subscribe starts the clock, and will emit after 1 second
|
|
||||||
sequence.subscribe({
|
|
||||||
next(num) { console.log('1st subscribe: ' + num); },
|
|
||||||
complete() { console.log('1st sequence finished.'); }
|
|
||||||
});
|
|
||||||
|
|
||||||
// After 1/2 second, subscribe again.
|
|
||||||
setTimeout(() => {
|
|
||||||
sequence.subscribe({
|
|
||||||
next(num) { console.log('2nd subscribe: ' + num); },
|
|
||||||
complete() { console.log('2nd sequence finished.'); }
|
|
||||||
});
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
// Logs:
|
|
||||||
// (at 1 second): 1st subscribe: 1
|
|
||||||
// (at 1.5 seconds): 2nd subscribe: 1
|
|
||||||
// (at 2 seconds): 1st subscribe: 2
|
|
||||||
// (at 2.5 seconds): 2nd subscribe: 2
|
|
||||||
// (at 3 seconds): 1st subscribe: 3
|
|
||||||
// (at 3 seconds): 1st sequence finished
|
|
||||||
// (at 3.5 seconds): 2nd subscribe: 3
|
|
||||||
// (at 3.5 seconds): 2nd sequence finished
|
|
||||||
|
|
||||||
// #enddocregion subscribe_twice
|
|
||||||
|
|
||||||
// #docregion multicast_sequence
|
|
||||||
|
|
||||||
function multicastSequenceSubscriber() {
|
|
||||||
const seq = [1, 2, 3];
|
|
||||||
// Keep track of each observer (one for every active subscription)
|
|
||||||
const observers = [];
|
|
||||||
// Still a single timeoutId because there will only ever be one
|
|
||||||
// set of values being generated, multicasted to each subscriber
|
|
||||||
let timeoutId;
|
|
||||||
|
|
||||||
// Return the subscriber function (runs when subscribe()
|
|
||||||
// function is invoked)
|
|
||||||
return (observer) => {
|
|
||||||
observers.push(observer);
|
|
||||||
// When this is the first subscription, start the sequence
|
|
||||||
if (observers.length === 1) {
|
|
||||||
timeoutId = doSequence({
|
|
||||||
next(val) {
|
|
||||||
// Iterate through observers and notify all subscriptions
|
|
||||||
observers.forEach(obs => obs.next(val));
|
|
||||||
},
|
|
||||||
complete() {
|
|
||||||
// Notify all complete callbacks
|
|
||||||
observers.slice(0).forEach(obs => obs.complete());
|
|
||||||
}
|
|
||||||
}, seq, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
unsubscribe() {
|
|
||||||
// Remove from the observers array so it's no longer notified
|
|
||||||
observers.splice(observers.indexOf(observer), 1);
|
|
||||||
// If there's no more listeners, do cleanup
|
|
||||||
if (observers.length === 0) {
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run through an array of numbers, emitting one value
|
|
||||||
// per second until it gets to the end of the array.
|
|
||||||
function doSequence(observer, arr, idx) {
|
|
||||||
return setTimeout(() => {
|
|
||||||
observer.next(arr[idx]);
|
|
||||||
if (idx === arr.length - 1) {
|
|
||||||
observer.complete();
|
|
||||||
} else {
|
|
||||||
doSequence(observer, arr, ++idx);
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new Observable that will deliver the above sequence
|
|
||||||
const multicastSequence = new Observable(multicastSequenceSubscriber());
|
|
||||||
|
|
||||||
// Subscribe starts the clock, and begins to emit after 1 second
|
|
||||||
multicastSequence.subscribe({
|
|
||||||
next(num) { console.log('1st subscribe: ' + num); },
|
|
||||||
complete() { console.log('1st sequence finished.'); }
|
|
||||||
});
|
|
||||||
|
|
||||||
// After 1 1/2 seconds, subscribe again (should "miss" the first value).
|
|
||||||
setTimeout(() => {
|
|
||||||
multicastSequence.subscribe({
|
multicastSequence.subscribe({
|
||||||
next(num) { console.log('2nd subscribe: ' + num); },
|
next(num) { console.log('1st subscribe: ' + num); },
|
||||||
complete() { console.log('2nd sequence finished.'); }
|
complete() { console.log('1st sequence finished.'); }
|
||||||
});
|
});
|
||||||
}, 1500);
|
|
||||||
|
|
||||||
// Logs:
|
// After 1 1/2 seconds, subscribe again (should "miss" the first value).
|
||||||
// (at 1 second): 1st subscribe: 1
|
setTimeout(() => {
|
||||||
// (at 2 seconds): 1st subscribe: 2
|
multicastSequence.subscribe({
|
||||||
// (at 2 seconds): 2nd subscribe: 2
|
next(num) { console.log('2nd subscribe: ' + num); },
|
||||||
// (at 3 seconds): 1st subscribe: 3
|
complete() { console.log('2nd sequence finished.'); }
|
||||||
// (at 3 seconds): 1st sequence finished
|
});
|
||||||
// (at 3 seconds): 2nd subscribe: 3
|
}, 1500);
|
||||||
// (at 3 seconds): 2nd sequence finished
|
|
||||||
|
|
||||||
// #enddocregion multicast_sequence
|
// Logs:
|
||||||
|
// (at 1 second): 1st subscribe: 1
|
||||||
|
// (at 2 seconds): 1st subscribe: 2
|
||||||
|
// (at 2 seconds): 2nd subscribe: 2
|
||||||
|
// (at 3 seconds): 1st subscribe: 3
|
||||||
|
// (at 3 seconds): 1st sequence finished
|
||||||
|
// (at 3 seconds): 2nd subscribe: 3
|
||||||
|
// (at 3 seconds): 2nd sequence finished
|
||||||
|
|
||||||
|
// #enddocregion multicast_sequence
|
||||||
|
}
|
||||||
|
19
aio/content/examples/observables/src/subscribing.spec.ts
Normal file
19
aio/content/examples/observables/src/subscribing.spec.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { docRegionObserver } from './subscribing';
|
||||||
|
|
||||||
|
describe('subscribing', () => {
|
||||||
|
it('should subscribe and emit', () => {
|
||||||
|
const console = {log: jasmine.createSpy('log')};
|
||||||
|
docRegionObserver(console);
|
||||||
|
expect(console.log).toHaveBeenCalledTimes(8);
|
||||||
|
expect(console.log.calls.allArgs()).toEqual([
|
||||||
|
['Observer got a next value: 1'],
|
||||||
|
['Observer got a next value: 2'],
|
||||||
|
['Observer got a next value: 3'],
|
||||||
|
['Observer got a complete notification'],
|
||||||
|
['Observer got a next value: 1'],
|
||||||
|
['Observer got a next value: 2'],
|
||||||
|
['Observer got a next value: 3'],
|
||||||
|
['Observer got a complete notification'],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
@ -1,32 +1,35 @@
|
|||||||
|
// #docplaster
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
|
||||||
import { Observable, of } from 'rxjs';
|
export function docRegionObserver(console) {
|
||||||
|
// #docregion observer
|
||||||
|
|
||||||
// #docregion observer
|
// Create simple observable that emits three values
|
||||||
|
const myObservable = of(1, 2, 3);
|
||||||
|
|
||||||
// Create simple observable that emits three values
|
// Create observer object
|
||||||
const myObservable = of(1, 2, 3);
|
const myObserver = {
|
||||||
|
next: x => console.log('Observer got a next value: ' + x),
|
||||||
|
error: err => console.error('Observer got an error: ' + err),
|
||||||
|
complete: () => console.log('Observer got a complete notification'),
|
||||||
|
};
|
||||||
|
|
||||||
// Create observer object
|
// Execute with the observer object
|
||||||
const myObserver = {
|
myObservable.subscribe(myObserver);
|
||||||
next: x => console.log('Observer got a next value: ' + x),
|
|
||||||
error: err => console.error('Observer got an error: ' + err),
|
|
||||||
complete: () => console.log('Observer got a complete notification'),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Execute with the observer object
|
// Logs:
|
||||||
myObservable.subscribe(myObserver);
|
// Observer got a next value: 1
|
||||||
// Logs:
|
// Observer got a next value: 2
|
||||||
// Observer got a next value: 1
|
// Observer got a next value: 3
|
||||||
// Observer got a next value: 2
|
// Observer got a complete notification
|
||||||
// Observer got a next value: 3
|
|
||||||
// Observer got a complete notification
|
|
||||||
|
|
||||||
// #enddocregion observer
|
// #enddocregion observer
|
||||||
|
|
||||||
// #docregion sub_fn
|
// #docregion sub_fn
|
||||||
myObservable.subscribe(
|
myObservable.subscribe(
|
||||||
x => console.log('Observer got a next value: ' + x),
|
x => console.log('Observer got a next value: ' + x),
|
||||||
err => console.error('Observer got an error: ' + err),
|
err => console.error('Observer got an error: ' + err),
|
||||||
() => console.log('Observer got a complete notification')
|
() => console.log('Observer got a complete notification')
|
||||||
);
|
);
|
||||||
// #enddocregion sub_fn
|
// #enddocregion sub_fn
|
||||||
|
}
|
||||||
|
@ -2,7 +2,11 @@
|
|||||||
"tests": [
|
"tests": [
|
||||||
{
|
{
|
||||||
"cmd": "yarn",
|
"cmd": "yarn",
|
||||||
"args": [ "tsc", "--project", "./tsconfig.app.json" ]
|
"args": ["tsc", "--project", "tsconfig.spec.json", "--module", "commonjs"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmd": "yarn",
|
||||||
|
"args": ["jasmine", "out-tsc/**/*.spec.js"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
|
// TODO: Add unit tests for this file.
|
||||||
import { pipe, range, timer, zip } from 'rxjs';
|
import { pipe, range, timer, zip } from 'rxjs';
|
||||||
import { ajax } from 'rxjs/ajax';
|
import { ajax } from 'rxjs/ajax';
|
||||||
import { retryWhen, map, mergeMap } from 'rxjs/operators';
|
import { retryWhen, map, mergeMap } from 'rxjs/operators';
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
import { of } from 'rxjs';
|
||||||
|
import { docRegionTypeahead } from './typeahead';
|
||||||
|
|
||||||
|
describe('typeahead', () => {
|
||||||
|
let document;
|
||||||
|
let ajax;
|
||||||
|
let triggertInputChange;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jasmine.clock().install();
|
||||||
|
const input = {
|
||||||
|
addEventListener: jasmine
|
||||||
|
.createSpy('addEvent')
|
||||||
|
.and.callFake((eventName: string, cb: (e) => void) => {
|
||||||
|
if (eventName === 'input') {
|
||||||
|
triggertInputChange = cb;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
removeEventListener: jasmine.createSpy('removeEvent'),
|
||||||
|
};
|
||||||
|
|
||||||
|
document = { getElementById: (id: string) => input };
|
||||||
|
ajax = jasmine.createSpy('ajax').and.callFake((url: string) => of('foo bar'));
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jasmine.clock().uninstall();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should make an ajax call to the corrent endpoint', () => {
|
||||||
|
docRegionTypeahead(document, ajax);
|
||||||
|
triggertInputChange({ target: { value: 'foo' } });
|
||||||
|
jasmine.clock().tick(11);
|
||||||
|
expect(ajax).toHaveBeenCalledWith('/api/endpoint?search=foo');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not make an ajax call, when the input length < 3', () => {
|
||||||
|
docRegionTypeahead(document, ajax);
|
||||||
|
triggertInputChange({ target: { value: '' } });
|
||||||
|
jasmine.clock().tick(11);
|
||||||
|
expect(ajax).not.toHaveBeenCalled();
|
||||||
|
triggertInputChange({ target: { value: 'fo' } });
|
||||||
|
jasmine.clock().tick(11);
|
||||||
|
expect(ajax).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not make an ajax call for intermediate values when debouncing', () => {
|
||||||
|
docRegionTypeahead(document, ajax);
|
||||||
|
triggertInputChange({ target: { value: 'foo' } });
|
||||||
|
jasmine.clock().tick(9);
|
||||||
|
triggertInputChange({ target: { value: 'bar' } });
|
||||||
|
jasmine.clock().tick(9);
|
||||||
|
triggertInputChange({ target: { value: 'baz' } });
|
||||||
|
jasmine.clock().tick(9);
|
||||||
|
triggertInputChange({ target: { value: 'qux' } });
|
||||||
|
expect(ajax).not.toHaveBeenCalled();
|
||||||
|
jasmine.clock().tick(10);
|
||||||
|
expect(ajax).toHaveBeenCalledTimes(1);
|
||||||
|
expect(ajax).toHaveBeenCalledWith('/api/endpoint?search=qux');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not make an ajax call, when the input value has not changed', () => {
|
||||||
|
docRegionTypeahead(document, ajax);
|
||||||
|
triggertInputChange({ target: { value: 'foo' } });
|
||||||
|
jasmine.clock().tick(11);
|
||||||
|
expect(ajax).toHaveBeenCalled();
|
||||||
|
ajax.calls.reset();
|
||||||
|
triggertInputChange({ target: { value: 'foo' } });
|
||||||
|
jasmine.clock().tick(11);
|
||||||
|
expect(ajax).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
@ -1,18 +1,32 @@
|
|||||||
import { fromEvent } from 'rxjs';
|
/*
|
||||||
import { ajax } from 'rxjs/ajax';
|
Because of how the code is merged together using the doc regions,
|
||||||
import { debounceTime, distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators';
|
we need to indent the imports with the function below.
|
||||||
|
*/
|
||||||
|
// #docplaster
|
||||||
|
// #docregion
|
||||||
|
import { fromEvent } from 'rxjs';
|
||||||
|
import { ajax } from 'rxjs/ajax';
|
||||||
|
import { debounceTime, distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
|
// #enddocregion
|
||||||
|
/* tslint:disable:no-shadowed-variable */
|
||||||
|
/* tslint:disable:align */
|
||||||
|
export function docRegionTypeahead(document, ajax) {
|
||||||
|
// #docregion
|
||||||
|
const searchBox = document.getElementById('search-box');
|
||||||
|
|
||||||
const searchBox = document.getElementById('search-box');
|
const typeahead = fromEvent(searchBox, 'input').pipe(
|
||||||
|
map((e: KeyboardEvent) => (e.target as HTMLInputElement).value),
|
||||||
|
filter(text => text.length > 2),
|
||||||
|
debounceTime(10),
|
||||||
|
distinctUntilChanged(),
|
||||||
|
switchMap(searchTerm => ajax(`/api/endpoint?search=${searchTerm}`))
|
||||||
|
);
|
||||||
|
|
||||||
const typeahead = fromEvent(searchBox, 'input').pipe(
|
typeahead.subscribe(data => {
|
||||||
map((e: KeyboardEvent) => (e.target as HTMLInputElement).value),
|
// Handle the data from the API
|
||||||
filter(text => text.length > 2),
|
});
|
||||||
debounceTime(10),
|
|
||||||
distinctUntilChanged(),
|
|
||||||
switchMap(() => ajax('/api/endpoint'))
|
|
||||||
);
|
|
||||||
|
|
||||||
typeahead.subscribe(data => {
|
// #enddocregion
|
||||||
// Handle the data from the API
|
return typeahead;
|
||||||
});
|
}
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { SwUpdate } from '@angular/service-worker';
|
||||||
|
|
||||||
|
function notifyUser(message: string): void { }
|
||||||
|
|
||||||
|
// #docregion sw-unrecoverable-state
|
||||||
|
@Injectable()
|
||||||
|
export class HandleUnrecoverableStateService {
|
||||||
|
constructor(updates: SwUpdate) {
|
||||||
|
updates.unrecoverable.subscribe(event => {
|
||||||
|
notifyUser(
|
||||||
|
`An error occurred that we cannot recover from:\n${event.reason}\n\n` +
|
||||||
|
'Please reload the page.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion sw-unrecoverable-state
|
@ -10,8 +10,8 @@ import { Hero } from '../shared/hero.model';
|
|||||||
template: `
|
template: `
|
||||||
<section>
|
<section>
|
||||||
Our list of heroes:
|
Our list of heroes:
|
||||||
<hero-profile *ngFor="let hero of heroes" [hero]="hero">
|
<toh-hero *ngFor="let hero of heroes" [hero]="hero">
|
||||||
</hero-profile>
|
</toh-hero>
|
||||||
Total powers: {{totalPowers}}<br>
|
Total powers: {{totalPowers}}<br>
|
||||||
Average power: {{totalPowers / heroes.length}}
|
Average power: {{totalPowers / heroes.length}}
|
||||||
</section>
|
</section>
|
||||||
|
@ -28,7 +28,7 @@ import {
|
|||||||
ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync
|
ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync
|
||||||
} from '@angular/core/testing';
|
} from '@angular/core/testing';
|
||||||
|
|
||||||
import { addMatchers, newEvent, click } from '../../testing';
|
import { addMatchers, click } from '../../testing';
|
||||||
|
|
||||||
export class NotProvided extends ValueService { /* example below */ }
|
export class NotProvided extends ValueService { /* example below */ }
|
||||||
beforeEach(addMatchers);
|
beforeEach(addMatchers);
|
||||||
@ -274,9 +274,11 @@ describe('demo (with TestBed):', () => {
|
|||||||
expect(comp.name).toBe(expectedOrigName,
|
expect(comp.name).toBe(expectedOrigName,
|
||||||
`comp.name should still be ${expectedOrigName} after value change, before binding happens`);
|
`comp.name should still be ${expectedOrigName} after value change, before binding happens`);
|
||||||
|
|
||||||
// dispatch a DOM event so that Angular learns of input value change.
|
// Dispatch a DOM event so that Angular learns of input value change.
|
||||||
// then wait while ngModel pushes input.box value to comp.name
|
// then wait while ngModel pushes input.box value to comp.name
|
||||||
input.dispatchEvent(newEvent('input'));
|
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
||||||
|
input.dispatchEvent(new Event('input'));
|
||||||
return fixture.whenStable();
|
return fixture.whenStable();
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@ -312,9 +314,11 @@ describe('demo (with TestBed):', () => {
|
|||||||
expect(comp.name).toBe(expectedOrigName,
|
expect(comp.name).toBe(expectedOrigName,
|
||||||
`comp.name should still be ${expectedOrigName} after value change, before binding happens`);
|
`comp.name should still be ${expectedOrigName} after value change, before binding happens`);
|
||||||
|
|
||||||
// dispatch a DOM event so that Angular learns of input value change.
|
// Dispatch a DOM event so that Angular learns of input value change.
|
||||||
// then wait a tick while ngModel pushes input.box value to comp.name
|
// then wait a tick while ngModel pushes input.box value to comp.name
|
||||||
input.dispatchEvent(newEvent('input'));
|
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
||||||
|
input.dispatchEvent(new Event('input'));
|
||||||
tick();
|
tick();
|
||||||
expect(comp.name).toBe(expectedNewName,
|
expect(comp.name).toBe(expectedNewName,
|
||||||
`After ngModel updates the model, comp.name should be ${expectedNewName} `);
|
`After ngModel updates the model, comp.name should be ${expectedNewName} `);
|
||||||
@ -335,10 +339,12 @@ describe('demo (with TestBed):', () => {
|
|||||||
// simulate user entering new name in input
|
// simulate user entering new name in input
|
||||||
input.value = inputText;
|
input.value = inputText;
|
||||||
|
|
||||||
// dispatch a DOM event so that Angular learns of input value change.
|
// Dispatch a DOM event so that Angular learns of input value change.
|
||||||
// then wait a tick while ngModel pushes input.box value to comp.text
|
// then wait a tick while ngModel pushes input.box value to comp.text
|
||||||
// and Angular updates the output span
|
// and Angular updates the output span
|
||||||
input.dispatchEvent(newEvent('input'));
|
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
||||||
|
input.dispatchEvent(new Event('input'));
|
||||||
tick();
|
tick();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(span.textContent).toBe(expectedText, 'output span');
|
expect(span.textContent).toBe(expectedText, 'output span');
|
||||||
|
@ -3,7 +3,7 @@ import { ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync } from
|
|||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ActivatedRoute, ActivatedRouteStub, asyncData, click, newEvent
|
ActivatedRoute, ActivatedRouteStub, asyncData, click
|
||||||
} from '../../testing';
|
} from '../../testing';
|
||||||
|
|
||||||
import { Hero } from '../model/hero';
|
import { Hero } from '../model/hero';
|
||||||
@ -99,7 +99,10 @@ function overrideSetup() {
|
|||||||
const newName = 'New Name';
|
const newName = 'New Name';
|
||||||
|
|
||||||
page.nameInput.value = newName;
|
page.nameInput.value = newName;
|
||||||
page.nameInput.dispatchEvent(newEvent('input')); // tell Angular
|
|
||||||
|
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
||||||
|
page.nameInput.dispatchEvent(new Event('input')); // tell Angular
|
||||||
|
|
||||||
expect(component.hero.name).toBe(newName, 'component hero has new name');
|
expect(component.hero.name).toBe(newName, 'component hero has new name');
|
||||||
expect(hdsSpy.testHero.name).toBe(origName, 'service hero unchanged before save');
|
expect(hdsSpy.testHero.name).toBe(origName, 'service hero unchanged before save');
|
||||||
@ -197,9 +200,10 @@ function heroModuleSetup() {
|
|||||||
// simulate user entering a new name into the input box
|
// simulate user entering a new name into the input box
|
||||||
nameInput.value = 'quick BROWN fOx';
|
nameInput.value = 'quick BROWN fOx';
|
||||||
|
|
||||||
// dispatch a DOM event so that Angular learns of input value change.
|
// Dispatch a DOM event so that Angular learns of input value change.
|
||||||
// use newEvent utility function (not provided by Angular) for better browser compatibility
|
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
||||||
nameInput.dispatchEvent(newEvent('input'));
|
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
||||||
|
nameInput.dispatchEvent(new Event('input'));
|
||||||
|
|
||||||
// Tell Angular to update the display binding through the title pipe
|
// Tell Angular to update the display binding through the title pipe
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
@ -6,7 +6,7 @@ import { DebugElement } from '@angular/core';
|
|||||||
|
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
import { addMatchers, newEvent } from '../../testing';
|
import { addMatchers } from '../../testing';
|
||||||
import { HeroService } from '../model/hero.service';
|
import { HeroService } from '../model/hero.service';
|
||||||
import { getTestHeroes, TestHeroService } from '../model/testing/test-hero.service';
|
import { getTestHeroes, TestHeroService } from '../model/testing/test-hero.service';
|
||||||
|
|
||||||
@ -53,7 +53,10 @@ describe('HeroListComponent', () => {
|
|||||||
it('should select hero on click', fakeAsync(() => {
|
it('should select hero on click', fakeAsync(() => {
|
||||||
const expectedHero = HEROES[1];
|
const expectedHero = HEROES[1];
|
||||||
const li = page.heroRows[1];
|
const li = page.heroRows[1];
|
||||||
li.dispatchEvent(newEvent('click'));
|
|
||||||
|
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
||||||
|
li.dispatchEvent(new Event('click'));
|
||||||
tick();
|
tick();
|
||||||
// `.toEqual` because selectedHero is clone of expectedHero; see FakeHeroService
|
// `.toEqual` because selectedHero is clone of expectedHero; see FakeHeroService
|
||||||
expect(comp.selectedHero).toEqual(expectedHero);
|
expect(comp.selectedHero).toEqual(expectedHero);
|
||||||
@ -62,7 +65,10 @@ describe('HeroListComponent', () => {
|
|||||||
it('should navigate to selected hero detail on click', fakeAsync(() => {
|
it('should navigate to selected hero detail on click', fakeAsync(() => {
|
||||||
const expectedHero = HEROES[1];
|
const expectedHero = HEROES[1];
|
||||||
const li = page.heroRows[1];
|
const li = page.heroRows[1];
|
||||||
li.dispatchEvent(newEvent('click'));
|
|
||||||
|
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
||||||
|
li.dispatchEvent(new Event('click'));
|
||||||
tick();
|
tick();
|
||||||
|
|
||||||
// should have navigated
|
// should have navigated
|
||||||
|
@ -3,7 +3,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
|
|
||||||
import { HighlightDirective } from './highlight.directive';
|
import { HighlightDirective } from './highlight.directive';
|
||||||
import { newEvent } from '../../testing';
|
|
||||||
|
|
||||||
// #docregion test-component
|
// #docregion test-component
|
||||||
@Component({
|
@Component({
|
||||||
@ -59,9 +58,12 @@ describe('HighlightDirective', () => {
|
|||||||
const input = des[2].nativeElement as HTMLInputElement;
|
const input = des[2].nativeElement as HTMLInputElement;
|
||||||
expect(input.style.backgroundColor).toBe('cyan', 'initial backgroundColor');
|
expect(input.style.backgroundColor).toBe('cyan', 'initial backgroundColor');
|
||||||
|
|
||||||
// dispatch a DOM event so that Angular responds to the input value change.
|
|
||||||
input.value = 'green';
|
input.value = 'green';
|
||||||
input.dispatchEvent(newEvent('input'));
|
|
||||||
|
// Dispatch a DOM event so that Angular responds to the input value change.
|
||||||
|
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
||||||
|
input.dispatchEvent(new Event('input'));
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
expect(input.style.backgroundColor).toBe('green', 'changed backgroundColor');
|
expect(input.style.backgroundColor).toBe('green', 'changed backgroundColor');
|
||||||
|
@ -14,18 +14,6 @@ export function advance(f: ComponentFixture<any>): void {
|
|||||||
f.detectChanges();
|
f.detectChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create custom DOM event the old fashioned way
|
|
||||||
*
|
|
||||||
* https://developer.mozilla.org/en-US/docs/Web/API/Event/initEvent
|
|
||||||
* Although officially deprecated, some browsers (phantom) don't accept the preferred "new Event(eventName)"
|
|
||||||
*/
|
|
||||||
export function newEvent(eventName: string, bubbles = false, cancelable = false) {
|
|
||||||
const evt = document.createEvent('CustomEvent'); // MUST be 'CustomEvent'
|
|
||||||
evt.initCustomEvent(eventName, bubbles, cancelable, null);
|
|
||||||
return evt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// See https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
|
// See https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
|
||||||
// #docregion click-event
|
// #docregion click-event
|
||||||
/** Button events to pass to `DebugElement.triggerEventHandler` for RouterLink event handler */
|
/** Button events to pass to `DebugElement.triggerEventHandler` for RouterLink event handler */
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, OnInit, Input } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ import { HeroService } from '../hero.service';
|
|||||||
styleUrls: [ './hero-detail.component.css' ]
|
styleUrls: [ './hero-detail.component.css' ]
|
||||||
})
|
})
|
||||||
export class HeroDetailComponent implements OnInit {
|
export class HeroDetailComponent implements OnInit {
|
||||||
@Input() hero: Hero;
|
hero: Hero;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
|
@ -31,7 +31,7 @@ For example:
|
|||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"extends": "../tsconfig.base.json",
|
"extends": "../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
...
|
...
|
||||||
|
@ -62,7 +62,7 @@ In the following example, the `@Component()` metadata object and the class const
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-typical',
|
selector: 'app-typical',
|
||||||
template: '<div>A typical component for {{data.name}}</div>'
|
template: '<div>A typical component for {{data.name}}</div>'
|
||||||
)}
|
})
|
||||||
export class TypicalComponent {
|
export class TypicalComponent {
|
||||||
@Input() data: TypicalData;
|
@Input() data: TypicalData;
|
||||||
constructor(private someService: SomeService) { ... }
|
constructor(private someService: SomeService) { ... }
|
||||||
|
@ -17,7 +17,7 @@ An NgModule is defined by a class decorated with `@NgModule()`. The `@NgModule()
|
|||||||
|
|
||||||
* `imports`: Other modules whose exported classes are needed by component templates declared in *this* NgModule.
|
* `imports`: Other modules whose exported classes are needed by component templates declared in *this* NgModule.
|
||||||
|
|
||||||
* `providers`: Creators of [services](guide/architecture-services) that this NgModule contributes to the global collection of services; they become accessible in all parts of the app. (You can also specify providers at the component level, which is often preferred.)
|
* `providers`: Creators of [services](guide/architecture-services) that this NgModule contributes to the global collection of services; they become accessible in all parts of the app. (You can also specify providers at the component level.)
|
||||||
|
|
||||||
* `bootstrap`: The main application view, called the *root component*, which hosts all other app views. Only the *root NgModule* should set the `bootstrap` property.
|
* `bootstrap`: The main application view, called the *root component*, which hosts all other app views. Only the *root NgModule* should set the `bootstrap` property.
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ Attributes can be changed by `setAttribute()`, which re-initializes correspondin
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
For more information, see the [MDN Interfaces documentation](https://developer.mozilla.org/en-US/docs/Web/API#Interfaces) which has API docs for all the standard DOM elements and their properties.
|
For more information, see the [MDN Interfaces documentation](https://developer.mozilla.org/en-US/docs/Web/API#Interfaces) which has API docs for all the standard DOM elements and their properties.
|
||||||
Comparing the [`<td>` attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td) attributes to the [`<td>` properties](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement) provides a helpful example for differentiation.
|
Comparing the [`<td>` attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td) to the [`<td>` properties](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement) provides a helpful example for differentiation.
|
||||||
In particular, you can navigate from the attributes page to the properties via "DOM interface" link, and navigate the inheritance hierarchy up to `HTMLTableCellElement`.
|
In particular, you can navigate from the attributes page to the properties via "DOM interface" link, and navigate the inheritance hierarchy up to `HTMLTableCellElement`.
|
||||||
|
|
||||||
|
|
||||||
@ -195,7 +195,7 @@ To control the state of the button, set the `disabled` *property*,
|
|||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
Though you could technically set the `[attr.disabled]` attribute binding, the values are different in that the property binding requires to a boolean value, while its corresponding attribute binding relies on whether the value is `null` or not. Consider the following:
|
Though you could technically set the `[attr.disabled]` attribute binding, the values are different in that the property binding requires to be a boolean value, while its corresponding attribute binding relies on whether the value is `null` or not. Consider the following:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<input [disabled]="condition ? true : false">
|
<input [disabled]="condition ? true : false">
|
||||||
|
@ -12,14 +12,12 @@ Every application has at least one Angular module, the _root_ module,
|
|||||||
which must be present for bootstrapping the application on launch.
|
which must be present for bootstrapping the application on launch.
|
||||||
By convention and by default, this NgModule is named `AppModule`.
|
By convention and by default, this NgModule is named `AppModule`.
|
||||||
|
|
||||||
When you use the [Angular CLI](cli) command `ng new` to generate an app, the default `AppModule` is as follows.
|
When you use the [Angular CLI](cli) command `ng new` to generate an app, the default `AppModule` looks like the following:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
/* JavaScript imports */
|
/* JavaScript imports */
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
|
||||||
import { HttpClientModule } from '@angular/common/http';
|
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
@ -29,9 +27,7 @@ import { AppComponent } from './app.component';
|
|||||||
AppComponent
|
AppComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule
|
||||||
FormsModule,
|
|
||||||
HttpClientModule
|
|
||||||
],
|
],
|
||||||
providers: [],
|
providers: [],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
@ -90,8 +86,6 @@ A declarable can only belong to one module, so only declare it in
|
|||||||
one `@NgModule`. When you need it elsewhere,
|
one `@NgModule`. When you need it elsewhere,
|
||||||
import the module that has the declarable you need in it.
|
import the module that has the declarable you need in it.
|
||||||
|
|
||||||
**Only `@NgModule` references** go in the `imports` array.
|
|
||||||
|
|
||||||
|
|
||||||
### Using directives with `@NgModule`
|
### Using directives with `@NgModule`
|
||||||
|
|
||||||
@ -122,9 +116,6 @@ Now you could use your `ItemDirective` in a component. This example uses `AppMod
|
|||||||
|
|
||||||
Remember, components, directives, and pipes belong to one module only. You only need to declare them once in your app because you share them by importing the necessary modules. This saves you time and helps keep your app lean.
|
Remember, components, directives, and pipes belong to one module only. You only need to declare them once in your app because you share them by importing the necessary modules. This saves you time and helps keep your app lean.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{@a imports}
|
{@a imports}
|
||||||
|
|
||||||
## The `imports` array
|
## The `imports` array
|
||||||
@ -132,14 +123,22 @@ Remember, components, directives, and pipes belong to one module only. You only
|
|||||||
The module's `imports` array appears exclusively in the `@NgModule` metadata object.
|
The module's `imports` array appears exclusively in the `@NgModule` metadata object.
|
||||||
It tells Angular about other NgModules that this particular module needs to function properly.
|
It tells Angular about other NgModules that this particular module needs to function properly.
|
||||||
|
|
||||||
|
<code-example
|
||||||
|
path="bootstrapping/src/app/app.module.ts"
|
||||||
|
region="imports"
|
||||||
|
header="src/app/app.module.ts (excerpt)">
|
||||||
|
</code-example>
|
||||||
|
|
||||||
This list of modules are those that export components, directives, or pipes
|
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
|
that component templates in this module reference. In this case, the component is
|
||||||
`AppComponent`, which references components, directives, or pipes in `BrowserModule`,
|
`AppComponent`, which references components, directives, or pipes in `BrowserModule`,
|
||||||
`FormsModule`, or `HttpClientModule`.
|
`FormsModule`, or `HttpClientModule`.
|
||||||
A component template can reference another component, directive,
|
A component template can reference another component, directive,
|
||||||
or pipe when the referenced class is declared in this module or
|
or pipe when the referenced class is declared in this module or
|
||||||
the class was imported from another module.
|
the class was imported from another module.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{@a bootstrap-array}
|
{@a bootstrap-array}
|
||||||
|
|
||||||
## The `providers` array
|
## The `providers` array
|
||||||
|
@ -125,7 +125,7 @@ Emulated is the default and most commonly used view encapsulation. For more info
|
|||||||
|
|
||||||
<div class="alert is-important">
|
<div class="alert is-important">
|
||||||
|
|
||||||
The shadow-piercing descendant combinator is deprecated and [support is being removed from major browsers](https://www.chromestatus.com/features/6750456638341120) and tools.
|
The shadow-piercing descendant combinator is deprecated and [support is being removed from major browsers](https://www.chromestatus.com/feature/6750456638341120) and tools.
|
||||||
As such we plan to drop support in Angular (for all 3 of `/deep/`, `>>>` and `::ng-deep`).
|
As such we plan to drop support in Angular (for all 3 of `/deep/`, `>>>` and `::ng-deep`).
|
||||||
Until then `::ng-deep` should be preferred for a broader compatibility with the tools.
|
Until then `::ng-deep` should be preferred for a broader compatibility with the tools.
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ The `ng generate` command creates the `projects/my-lib` folder in your workspace
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
When you generate a new library, the workspace configuration file, `angular.json`, is updated with a project of type 'library'.
|
When you generate a new library, the workspace configuration file, `angular.json`, is updated with a project of type `library`.
|
||||||
|
|
||||||
<code-example format="json">
|
<code-example format="json">
|
||||||
"projects": {
|
"projects": {
|
||||||
@ -109,7 +109,7 @@ If you want a dropdown that would contain different passed-in values each time,
|
|||||||
|
|
||||||
Suppose you want to read a configuration file and then generate a form based on that configuration.
|
Suppose you want to read a configuration file and then generate a form based on that configuration.
|
||||||
If that form will need additional customization by the developer who is using your library, it might work best as a schematic.
|
If that form will need additional customization by the developer who is using your library, it might work best as a schematic.
|
||||||
However, if the forms will always be the same and not need much customization by developers, then you could create a dynamic component that takes the configuration and generates the form.
|
However, if the form will always be the same and not need much customization by developers, then you could create a dynamic component that takes the configuration and generates the form.
|
||||||
In general, the more complex the customization, the more useful the schematic approach.
|
In general, the more complex the customization, the more useful the schematic approach.
|
||||||
|
|
||||||
To learn more, see [Schematics Overview](guide/schematics) and [Schematics for Libraries](guide/schematics-for-libraries).
|
To learn more, see [Schematics Overview](guide/schematics) and [Schematics for Libraries](guide/schematics-for-libraries).
|
||||||
|
@ -511,9 +511,9 @@ Each script tag has a `type="module"` or `nomodule` attribute. Browsers with nat
|
|||||||
|
|
||||||
To include differential loading in your application builds, you must configure the Browserslist and TypeScript configuration files in your application project.
|
To include differential loading in your application builds, you must configure the Browserslist and TypeScript configuration files in your application project.
|
||||||
|
|
||||||
The following examples show a `browserlistrc` and `tsconfig.json` file for a newly created Angular application. In this configuration, legacy browsers such as IE 9-11 are ignored, and the compilation target is ES2015.
|
The following examples show a `.browserslistrc` and `tsconfig.json` file for a newly created Angular application. In this configuration, legacy browsers such as IE 9-11 are ignored, and the compilation target is ES2015.
|
||||||
|
|
||||||
<code-example language="none" header="browserslistrc">
|
<code-example language="none" header=".browserslistrc">
|
||||||
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
||||||
# For additional information regarding the format and rule options, please see:
|
# For additional information regarding the format and rule options, please see:
|
||||||
# https://github.com/browserslist/browserslist#queries
|
# https://github.com/browserslist/browserslist#queries
|
||||||
@ -527,7 +527,7 @@ The following examples show a `browserlistrc` and `tsconfig.json` file for a new
|
|||||||
last 1 Chrome version
|
last 1 Chrome version
|
||||||
last 1 Firefox version
|
last 1 Firefox version
|
||||||
last 2 Edge major versions
|
last 2 Edge major versions
|
||||||
last 2 Safari major version
|
last 2 Safari major versions
|
||||||
last 2 iOS major versions
|
last 2 iOS major versions
|
||||||
Firefox ESR
|
Firefox ESR
|
||||||
not IE 9-11 # For IE 9-11 support, remove 'not'.
|
not IE 9-11 # For IE 9-11 support, remove 'not'.
|
||||||
|
@ -38,7 +38,6 @@ v9 - v12
|
|||||||
| `@angular/bazel` | [`Bazel builder and schematics`](#bazelbuilder) | v10 |
|
| `@angular/bazel` | [`Bazel builder and schematics`](#bazelbuilder) | v10 |
|
||||||
| `@angular/common` | [`ReflectiveInjector`](#reflectiveinjector) | <!--v8--> v11 |
|
| `@angular/common` | [`ReflectiveInjector`](#reflectiveinjector) | <!--v8--> v11 |
|
||||||
| `@angular/common` | [`CurrencyPipe` - `DEFAULT_CURRENCY_CODE`](api/common/CurrencyPipe#currency-code-deprecation) | <!--v9--> v11 |
|
| `@angular/common` | [`CurrencyPipe` - `DEFAULT_CURRENCY_CODE`](api/common/CurrencyPipe#currency-code-deprecation) | <!--v9--> v11 |
|
||||||
| `@angular/core` | [`CollectionChangeRecord`](#core) | <!--v7--> v11 |
|
|
||||||
| `@angular/core` | [`DefaultIterableDiffer`](#core) | <!--v7--> v11 |
|
| `@angular/core` | [`DefaultIterableDiffer`](#core) | <!--v7--> v11 |
|
||||||
| `@angular/core` | [`ReflectiveKey`](#core) | <!--v8--> v11 |
|
| `@angular/core` | [`ReflectiveKey`](#core) | <!--v8--> v11 |
|
||||||
| `@angular/core` | [`RenderComponentType`](#core) | <!--v7--> v11 |
|
| `@angular/core` | [`RenderComponentType`](#core) | <!--v7--> v11 |
|
||||||
@ -89,7 +88,6 @@ Tip: In the [API reference section](api) of this doc site, deprecated APIs are i
|
|||||||
|
|
||||||
| API | Replacement | Deprecation announced | Notes |
|
| API | Replacement | Deprecation announced | Notes |
|
||||||
| --- | ----------- | --------------------- | ----- |
|
| --- | ----------- | --------------------- | ----- |
|
||||||
| [`CollectionChangeRecord`](api/core/CollectionChangeRecord) | [`IterableChangeRecord`](api/core/IterableChangeRecord) | v4 | none |
|
|
||||||
| [`DefaultIterableDiffer`](api/core/DefaultIterableDiffer) | n/a | v4 | Not part of public API. |
|
| [`DefaultIterableDiffer`](api/core/DefaultIterableDiffer) | n/a | v4 | Not part of public API. |
|
||||||
| [`ReflectiveInjector`](api/core/ReflectiveInjector) | [`Injector.create`](api/core/Injector#create) | v5 | See [`ReflectiveInjector`](#reflectiveinjector) |
|
| [`ReflectiveInjector`](api/core/ReflectiveInjector) | [`Injector.create`](api/core/Injector#create) | v5 | See [`ReflectiveInjector`](#reflectiveinjector) |
|
||||||
| [`ReflectiveKey`](api/core/ReflectiveKey) | none | v5 | none |
|
| [`ReflectiveKey`](api/core/ReflectiveKey) | none | v5 | none |
|
||||||
|
@ -119,7 +119,14 @@ The recently-developed [custom elements](https://developer.mozilla.org/en-US/doc
|
|||||||
|
|
||||||
In browsers that support Custom Elements natively, the specification requires developers use ES2015 classes to define Custom Elements - developers can opt-in to this by setting the `target: "es2015"` property in their project's [TypeScript configuration file](/guide/typescript-configuration). As Custom Element and ES2015 support may not be available in all browsers, developers can instead choose to use a polyfill to support older browsers and ES5 code.
|
In browsers that support Custom Elements natively, the specification requires developers use ES2015 classes to define Custom Elements - developers can opt-in to this by setting the `target: "es2015"` property in their project's [TypeScript configuration file](/guide/typescript-configuration). As Custom Element and ES2015 support may not be available in all browsers, developers can instead choose to use a polyfill to support older browsers and ES5 code.
|
||||||
|
|
||||||
Use the [Angular CLI](cli) to automatically set up your project with the correct polyfill: `ng add @angular/elements --project=*your_project_name*`.
|
Use the [Angular CLI](cli) to automatically set up your project with the correct polyfill:
|
||||||
|
|
||||||
|
<code-example language="sh">
|
||||||
|
|
||||||
|
ng add @angular/elements --project=*your_project_name*
|
||||||
|
|
||||||
|
</code-example>
|
||||||
|
|
||||||
- For more information about polyfills, see [polyfill documentation](https://www.webcomponents.org/polyfills).
|
- For more information about polyfills, see [polyfill documentation](https://www.webcomponents.org/polyfills).
|
||||||
|
|
||||||
- For more information about Angular browser support, see [Browser Support](guide/browser-support).
|
- For more information about Angular browser support, see [Browser Support](guide/browser-support).
|
||||||
|
@ -76,6 +76,12 @@ All router components must be entry components. Because this would require you t
|
|||||||
|
|
||||||
## The `entryComponents` array
|
## The `entryComponents` array
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
Since 9.0.0 with Ivy, the `entryComponents` property is no longer necessary. See [deprecations guide](guide/deprecations#entryComponents).
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
Though the `@NgModule` decorator has an `entryComponents` array, most of the time
|
Though the `@NgModule` decorator has an `entryComponents` array, most of the time
|
||||||
you won't have to explicitly set any entry components because Angular adds components listed in `@NgModule.bootstrap` and those in route definitions to entry components automatically. Though these two mechanisms account for most entry components, if your app happens to bootstrap or dynamically load a component by type imperatively,
|
you won't have to explicitly set any entry components because Angular adds components listed in `@NgModule.bootstrap` and those in route definitions to entry components automatically. Though these two mechanisms account for most entry components, if your app happens to bootstrap or dynamically load a component by type imperatively,
|
||||||
you must add it to `entryComponents` explicitly.
|
you must add it to `entryComponents` explicitly.
|
||||||
|
@ -79,7 +79,7 @@ To incorporate the feature module into your app, you have to let the root module
|
|||||||
<code-example path="feature-modules/src/app/app.module.ts" region="app-module" header="src/app/app.module.ts"></code-example>
|
<code-example path="feature-modules/src/app/app.module.ts" region="app-module" header="src/app/app.module.ts"></code-example>
|
||||||
|
|
||||||
|
|
||||||
Now the `AppModule` knows about the feature module. If you were to add any service providers to the feature module, `AppModule` would know about those too, as would any other feature modules. However, NgModules don’t expose their components.
|
Now the `AppModule` knows about the feature module. If you were to add any service providers to the feature module, `AppModule` would know about those too, as would any other feature modules. However, NgModules don’t expose their components by default.
|
||||||
|
|
||||||
|
|
||||||
## Rendering a feature module’s component template
|
## Rendering a feature module’s component template
|
||||||
|
@ -40,8 +40,7 @@ The top level of the workspace contains workspace-wide configuration files, conf
|
|||||||
| `package-lock.json` | Provides version information for all packages installed into `node_modules` by the npm client. See [npm documentation](https://docs.npmjs.com/files/package-lock.json) for details. If you use the yarn client, this file will be [yarn.lock](https://yarnpkg.com/lang/en/docs/yarn-lock/) instead. |
|
| `package-lock.json` | Provides version information for all packages installed into `node_modules` by the npm client. See [npm documentation](https://docs.npmjs.com/files/package-lock.json) for details. If you use the yarn client, this file will be [yarn.lock](https://yarnpkg.com/lang/en/docs/yarn-lock/) instead. |
|
||||||
| `src/` | Source files for the root-level application project. |
|
| `src/` | Source files for the root-level application project. |
|
||||||
| `node_modules/` | Provides [npm packages](guide/npm-packages) to the entire workspace. Workspace-wide `node_modules` dependencies are visible to all projects. |
|
| `node_modules/` | Provides [npm packages](guide/npm-packages) to the entire workspace. Workspace-wide `node_modules` dependencies are visible to all projects. |
|
||||||
| `tsconfig.json` | The `tsconfig.json` file is a ["Solution Style"](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#support-for-solution-style-tsconfigjson-files) TypeScript configuration file. Code editors and TypeScript’s language server use this file to improve development experience. Compilers do not use this file. |
|
| `tsconfig.json` | The base [TypeScript](https://www.typescriptlang.org/) configuration for projects in the workspace. All other configuration files inherit from this base file. For more information, see the [Configuration inheritance with extends](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#configuration-inheritance-with-extends) section of the TypeScript documentation.|
|
||||||
| `tsconfig.base.json` | The base [TypeScript](https://www.typescriptlang.org/) configuration for projects in the workspace. All other configuration files inherit from this base file. For more information, see the [Configuration inheritance with extends](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#configuration-inheritance-with-extends) section of the TypeScript documentation.|
|
|
||||||
| `tslint.json` | Default [TSLint](https://palantir.github.io/tslint/) configuration for projects in the workspace. |
|
| `tslint.json` | Default [TSLint](https://palantir.github.io/tslint/) configuration for projects in the workspace. |
|
||||||
|
|
||||||
|
|
||||||
@ -103,7 +102,7 @@ Angular components, templates, and styles go here.
|
|||||||
The application-specific configuration files for the root application reside at the workspace root level.
|
The application-specific configuration files for the root application reside at the workspace root level.
|
||||||
For a multi-project workspace, project-specific configuration files are in the project root, under `projects/project-name/`.
|
For a multi-project workspace, project-specific configuration files are in the project root, under `projects/project-name/`.
|
||||||
|
|
||||||
Project-specific [TypeScript](https://www.typescriptlang.org/) configuration files inherit from the workspace-wide `tsconfig.base.json`, and project-specific [TSLint](https://palantir.github.io/tslint/) configuration files inherit from the workspace-wide `tslint.json`.
|
Project-specific [TypeScript](https://www.typescriptlang.org/) configuration files inherit from the workspace-wide `tsconfig.json`, and project-specific [TSLint](https://palantir.github.io/tslint/) configuration files inherit from the workspace-wide `tslint.json`.
|
||||||
|
|
||||||
| APPLICATION-SPECIFIC CONFIG FILES | PURPOSE |
|
| APPLICATION-SPECIFIC CONFIG FILES | PURPOSE |
|
||||||
| :--------------------- | :------------------------------------------|
|
| :--------------------- | :------------------------------------------|
|
||||||
|
@ -627,6 +627,11 @@ The [npm package manager](https://docs.npmjs.com/getting-started/what-is-npm) is
|
|||||||
|
|
||||||
Learn more about how Angular uses [Npm Packages](guide/npm-packages).
|
Learn more about how Angular uses [Npm Packages](guide/npm-packages).
|
||||||
|
|
||||||
|
{@ ngc}
|
||||||
|
## ngc
|
||||||
|
`ngc` is a Typescript-to-Javascript transpiler that processes Angular decorators, metadata, and templates, and emits JavaScript code.
|
||||||
|
The most recent implementation is internally refered to as `ngtsc` because it's a minimalistic wrapper around the TypeScript compiler `tsc` that adds a transform for processing Angular code.
|
||||||
|
|
||||||
{@a O}
|
{@a O}
|
||||||
|
|
||||||
{@a observable}
|
{@a observable}
|
||||||
|
@ -766,8 +766,10 @@ The HTML `base` tag with the `href` attribute specifies the base URI, or URL, fo
|
|||||||
"i18n": {
|
"i18n": {
|
||||||
"sourceLocale": "en-US",
|
"sourceLocale": "en-US",
|
||||||
"locales": {
|
"locales": {
|
||||||
"fr": "src/locale/messages.fr.xlf"
|
"fr": {
|
||||||
"baseHref": ""
|
"translation": "src/locale/messages.fr.xlf",
|
||||||
|
"baseHref": ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"architect": {
|
"architect": {
|
||||||
|
@ -208,7 +208,7 @@ about the event and gives that data to the parent.
|
|||||||
The child's template has two controls. The first is an HTML `<input>` with a
|
The child's template has two controls. The first is an HTML `<input>` with a
|
||||||
[template reference variable](guide/template-reference-variables) , `#newItem`,
|
[template reference variable](guide/template-reference-variables) , `#newItem`,
|
||||||
where the user types in an item name. Whatever the user types
|
where the user types in an item name. Whatever the user types
|
||||||
into the `<input>` gets stored in the `#newItem` variable.
|
into the `<input>` gets stored in the `value` property of the `#newItem` variable.
|
||||||
|
|
||||||
<code-example path="inputs-outputs/src/app/item-output/item-output.component.html" region="child-output" header="src/app/item-output/item-output.component.html"></code-example>
|
<code-example path="inputs-outputs/src/app/item-output/item-output.component.html" region="child-output" header="src/app/item-output/item-output.component.html"></code-example>
|
||||||
|
|
||||||
@ -218,7 +218,7 @@ an event binding because the part to the left of the equal
|
|||||||
sign is in parentheses, `(click)`.
|
sign is in parentheses, `(click)`.
|
||||||
|
|
||||||
The `(click)` event is bound to the `addNewItem()` method in the child component class which
|
The `(click)` event is bound to the `addNewItem()` method in the child component class which
|
||||||
takes as its argument whatever the value of `#newItem` is.
|
takes as its argument whatever the value of `#newItem.value` property is.
|
||||||
|
|
||||||
Now the child component has an `@Output()`
|
Now the child component has an `@Output()`
|
||||||
for sending data to the parent and a method for raising an event.
|
for sending data to the parent and a method for raising an event.
|
||||||
|
@ -11,11 +11,11 @@ That said, some applications will likely need to apply some manual updates.
|
|||||||
In version 10, [a few deprecated APIs have been removed](guide/updating-to-version-10#removals) and there are a [few breaking changes](guide/updating-to-version-10#breaking-changes) unrelated to Ivy.
|
In version 10, [a few deprecated APIs have been removed](guide/updating-to-version-10#removals) and there are a [few breaking changes](guide/updating-to-version-10#breaking-changes) unrelated to Ivy.
|
||||||
If you're seeing errors after updating to version 9, you'll first want to rule those changes out.
|
If you're seeing errors after updating to version 9, you'll first want to rule those changes out.
|
||||||
|
|
||||||
To do so, temporarily [turn off Ivy](guide/ivy#opting-out-of-angular-ivy) in your `tsconfig.base.json` and re-start your app.
|
To do so, temporarily [turn off Ivy](guide/ivy#opting-out-of-angular-ivy) in your `tsconfig.json` and re-start your app.
|
||||||
|
|
||||||
If you're still seeing the errors, they are not specific to Ivy. In this case, you may want to consult the [general version 10 guide](guide/updating-to-version-10). If you've opted into any of the new, stricter type-checking settings, you may also want to check out the [template type-checking guide](guide/template-typecheck).
|
If you're still seeing the errors, they are not specific to Ivy. In this case, you may want to consult the [general version 10 guide](guide/updating-to-version-10). If you've opted into any of the new, stricter type-checking settings, you may also want to check out the [template type-checking guide](guide/template-typecheck).
|
||||||
|
|
||||||
If the errors are gone, switch back to Ivy by removing the changes to the `tsconfig.base.json` and review the list of expected changes below.
|
If the errors are gone, switch back to Ivy by removing the changes to the `tsconfig.json` and review the list of expected changes below.
|
||||||
|
|
||||||
{@a payload-size-debugging}
|
{@a payload-size-debugging}
|
||||||
### Payload size debugging
|
### Payload size debugging
|
||||||
|
@ -87,7 +87,7 @@ To make one, enter the following command in the terminal, where `customers` is t
|
|||||||
ng generate module customers --route customers --module app.module
|
ng generate module customers --route customers --module app.module
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
This creates a `customers` folder with the new lazy-loadable module `CustomersModule` defined in the `customers.module.ts` file. The command automatically declares the `CustomersComponent` inside the new feature module.
|
This creates a `customers` folder having the new lazy-loadable feature module `CustomersModule` defined in the `customers.module.ts` file and the routing module `CustomersRoutingModule` defined in the `customers-routing.module.ts` file. The command automatically declares the `CustomersComponent` and imports `CustomersRoutingModule` inside the new feature module.
|
||||||
|
|
||||||
Because the new module is meant to be lazy-loaded, the command does NOT add a reference to the new feature module in the application's root module file, `app.module.ts`.
|
Because the new module is meant to be lazy-loaded, the command does NOT add a reference to the new feature module in the application's root module file, `app.module.ts`.
|
||||||
Instead, it adds the declared route, `customers` to the `routes` array declared in the module provided as the `--module` option.
|
Instead, it adds the declared route, `customers` to the `routes` array declared in the module provided as the `--module` option.
|
||||||
|
@ -62,6 +62,8 @@ Angular executes hook methods in the following sequence. You can use them to per
|
|||||||
|
|
||||||
Called before `ngOnInit()` and whenever one or more data-bound input properties change.
|
Called before `ngOnInit()` and whenever one or more data-bound input properties change.
|
||||||
|
|
||||||
|
Note that if your component has no inputs or you use it without providing any inputs, the framework will not call `ngOnChanges()`.
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr style='vertical-align:top'>
|
<tr style='vertical-align:top'>
|
||||||
|
@ -141,7 +141,7 @@ Because the token is now an abstract class, and the injectable component impleme
|
|||||||
The implementation of the method (with all of its code overhead) resides in the injectable component that can be tree-shaken.
|
The implementation of the method (with all of its code overhead) resides in the injectable component that can be tree-shaken.
|
||||||
This allows the parent to communicate with the child (if it is present) in a type-safe manner.
|
This allows the parent to communicate with the child (if it is present) in a type-safe manner.
|
||||||
|
|
||||||
For example, the `LibCardComponent` now queries`LibHeaderToken` rather than `LibHeaderComponent`.
|
For example, the `LibCardComponent` now queries `LibHeaderToken` rather than `LibHeaderComponent`.
|
||||||
The following example shows how the pattern allows `LibCardComponent` to communicate with the `LibHeaderComponent` without actually referring to `LibHeaderComponent`.
|
The following example shows how the pattern allows `LibCardComponent` to communicate with the `LibHeaderComponent` without actually referring to `LibHeaderComponent`.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
# Solution-style `tsconfig.json` migration
|
|
||||||
|
|
||||||
## What does this migration do?
|
|
||||||
|
|
||||||
This migration adds support to existing projects for TypeScript's new ["solution-style" tsconfig feature](https://devblogs.microsoft.com/typescript/announcing-typescript-3-9/#solution-style-tsconfig).
|
|
||||||
|
|
||||||
Support is added by making two changes:
|
|
||||||
|
|
||||||
1. Renaming the workspace-level `tsconfig.json` to `tsconfig.base.json`.
|
|
||||||
All project [TypeScript configuration files](guide/typescript-configuration) will extend from this base which contains the common options used throughout the workspace.
|
|
||||||
|
|
||||||
2. Adding the solution `tsconfig.json` file at the root of the workspace.
|
|
||||||
This `tsconfig.json` file will only contain references to project-level TypeScript configuration files and is only used by editors/IDEs.
|
|
||||||
|
|
||||||
As an example, the solution `tsconfig.json` for a new project is as follows:
|
|
||||||
```json
|
|
||||||
// This is a "Solution Style" tsconfig.json file, and is used by editors and TypeScript’s language server to improve development experience.
|
|
||||||
// It is not intended to be used to perform a compilation.
|
|
||||||
{
|
|
||||||
"files": [],
|
|
||||||
"references": [
|
|
||||||
{
|
|
||||||
"path": "./tsconfig.app.json"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "./tsconfig.spec.json"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "./e2e/tsconfig.json"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Why is this migration necessary?
|
|
||||||
|
|
||||||
Solution-style `tsconfig.json` files provide an improved editing experience and fix several long-standing defects when editing files in an IDE.
|
|
||||||
IDEs that leverage the TypeScript language service (for example, [Visual Studio Code](https://code.visualstudio.com)), will only use TypeScript configuration files that are named `tsconfig.json`.
|
|
||||||
In complex projects, there may be more than one compilation unit and each of these units may have different settings and options.
|
|
||||||
|
|
||||||
With the Angular CLI, a project will have application code that will target a browser.
|
|
||||||
It will also have unit tests that should not be included within the built application and that also need additional type information present (`jasmine` in this case).
|
|
||||||
Both parts of the project also share some but not all of the code within the project.
|
|
||||||
As a result, two separate TypeScript configuration files (`tsconfig.app.json` and `tsconfig.spec.json`) are needed to ensure that each part of the application is configured properly and that the right types are used for each part.
|
|
||||||
Also if web workers are used within a project, an additional tsconfig (`tsconfig.worker.json`) is needed.
|
|
||||||
Web workers use similar but incompatible types to the main browser application.
|
|
||||||
This requires the additional configuration file to ensure that the web worker files use the appropriate types and will build successfully.
|
|
||||||
|
|
||||||
While the Angular build system knows about all of these TypeScript configuration files, an IDE using TypeScript's language service does not.
|
|
||||||
Because of this, an IDE will not be able to properly analyze the code from each part of the project and may generate false errors or make suggestions that are incorrect for certain files.
|
|
||||||
By leveraging the new solution-style tsconfig, the IDE can now be aware of the configuration of each part of a project.
|
|
||||||
This allows each file to be treated appropriately based on its tsconfig.
|
|
||||||
IDE features such as error/warning reporting and auto-suggestion will operate more effectively as well.
|
|
||||||
|
|
||||||
The TypeScript 3.9 release [blog post](https://devblogs.microsoft.com/typescript/announcing-typescript-3-9/#solution-style-tsconfig) also contains some additional information regarding this new feature.
|
|
@ -9,7 +9,7 @@ This process helps ensure that intentional changes to the options are kept in pl
|
|||||||
|
|
||||||
TypeScript Configuration File(s) | Changed Property | Existing Value | New Value
|
TypeScript Configuration File(s) | Changed Property | Existing Value | New Value
|
||||||
------------- | ------------- | ------------- | ------------- | -------------
|
------------- | ------------- | ------------- | ------------- | -------------
|
||||||
`<workspace base>/tsconfig.base.json` | `"module"` | `"esnext"` | `"es2020"`
|
`<workspace base>/tsconfig.json` | `"module"` | `"esnext"` | `"es2020"`
|
||||||
Used in `browser` builder options (`ng build` for applications) | `"module"` | `"esnext"` | `"es2020"`
|
Used in `browser` builder options (`ng build` for applications) | `"module"` | `"esnext"` | `"es2020"`
|
||||||
Used in `ng-packgr` builder options (`ng build` for libraries) | `"module"` | `"esnext"` | `"es2020"`
|
Used in `ng-packgr` builder options (`ng build` for libraries) | `"module"` | `"esnext"` | `"es2020"`
|
||||||
Used in `karma` builder options (`ng test` for applications) | `"module"` | `"esnext"` | `"es2020"`
|
Used in `karma` builder options (`ng test` for applications) | `"module"` | `"esnext"` | `"es2020"`
|
||||||
|
@ -101,7 +101,7 @@ should import `BrowserModule` from `@angular/platform-browser`.
|
|||||||
`BrowserModule` provides services that are essential to launch and run a browser app.
|
`BrowserModule` provides services that are essential to launch and run a browser app.
|
||||||
|
|
||||||
`BrowserModule` also re-exports `CommonModule` from `@angular/common`,
|
`BrowserModule` also re-exports `CommonModule` from `@angular/common`,
|
||||||
which means that components in the `AppModule` module also have access to
|
which means that components in the `AppModule` also have access to
|
||||||
the Angular directives every app needs, such as `NgIf` and `NgFor`.
|
the Angular directives every app needs, such as `NgIf` and `NgFor`.
|
||||||
|
|
||||||
Do not import `BrowserModule` in any other module.
|
Do not import `BrowserModule` in any other module.
|
||||||
@ -140,7 +140,7 @@ declared in this NgModule.
|
|||||||
You _can_ export any declarable class—components, directives, and pipes—whether
|
You _can_ export any declarable class—components, directives, and pipes—whether
|
||||||
it's declared in this NgModule or in an imported NgModule.
|
it's declared in this NgModule or in an imported NgModule.
|
||||||
|
|
||||||
You _can_ re-export entire imported NgModules, which effectively re-exports all of their exported classes.
|
You _can_ re-export entire imported NgModules, which effectively re-export all of their exported classes.
|
||||||
An NgModule can even export a module that it doesn't import.
|
An NgModule can even export a module that it doesn't import.
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
@ -192,7 +192,7 @@ Its only purpose is to add http service providers to the application as a whole.
|
|||||||
|
|
||||||
The `forRoot()` static method is a convention that makes it easy for developers to configure services and providers that are intended to be singletons. A good example of `forRoot()` is the `RouterModule.forRoot()` method.
|
The `forRoot()` static method is a convention that makes it easy for developers to configure services and providers that are intended to be singletons. A good example of `forRoot()` is the `RouterModule.forRoot()` method.
|
||||||
|
|
||||||
Apps pass a `Routes` object to `RouterModule.forRoot()` in order to configure the app-wide `Router` service with routes.
|
Apps pass a `Routes` array to `RouterModule.forRoot()` in order to configure the app-wide `Router` service with routes.
|
||||||
`RouterModule.forRoot()` returns a [ModuleWithProviders](api/core/ModuleWithProviders).
|
`RouterModule.forRoot()` returns a [ModuleWithProviders](api/core/ModuleWithProviders).
|
||||||
You add that result to the `imports` list of the root `AppModule`.
|
You add that result to the `imports` list of the root `AppModule`.
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ NgModule metadata does the following:
|
|||||||
* Declares which components, directives, and pipes belong to the module.
|
* Declares which components, directives, and pipes belong to the module.
|
||||||
* Makes some of those components, directives, and pipes public so that other module's component templates can use them.
|
* Makes some of those components, directives, and pipes public so that other module's component templates can use them.
|
||||||
* Imports other modules with the components, directives, and pipes that components in the current module need.
|
* Imports other modules with the components, directives, and pipes that components in the current module need.
|
||||||
* Provides services that the other application components can use.
|
* Provides services that other application components can use.
|
||||||
|
|
||||||
Every Angular app has at least one module, the root module.
|
Every Angular app has at least one module, the root module.
|
||||||
You [bootstrap](guide/bootstrapping) that module to launch the application.
|
You [bootstrap](guide/bootstrapping) that module to launch the application.
|
||||||
|
@ -223,6 +223,6 @@ content harmlessly. The following is the browser output
|
|||||||
of the `evilTitle` examples.
|
of the `evilTitle` examples.
|
||||||
|
|
||||||
<code-example language="bash">
|
<code-example language="bash">
|
||||||
"Template <script>alert("evil never sleeps")</script> Syntax" is the interpolated evil title.
|
"Template <script>alert("evil never sleeps")</script> Syntax" is the interpolated evil title.
|
||||||
"Template alert("evil never sleeps")Syntax" is the property bound evil title.
|
"Template Syntax" is the property bound evil title.
|
||||||
</code-example>
|
</code-example>
|
||||||
|
@ -94,7 +94,7 @@ All of our major releases are supported for 18 months.
|
|||||||
|
|
||||||
* 6 months of *active support*, during which regularly-scheduled updates and patches are released.
|
* 6 months of *active support*, during which regularly-scheduled updates and patches are released.
|
||||||
|
|
||||||
* 12 months of *long-term support (LTS)*, during which only critical fixes and security patches are released.
|
* 12 months of *long-term support (LTS)*, during which only [critical fixes and security patches](#lts-fixes) are released.
|
||||||
|
|
||||||
The following table provides the status for Angular versions under support.
|
The following table provides the status for Angular versions under support.
|
||||||
|
|
||||||
@ -102,11 +102,18 @@ The following table provides the status for Angular versions under support.
|
|||||||
Version | Status | Released | Active Ends | LTS Ends
|
Version | Status | Released | Active Ends | LTS Ends
|
||||||
------- | ------ | ------------ | ------------ | ------------
|
------- | ------ | ------------ | ------------ | ------------
|
||||||
^10.0.0 | Active | Jun 24, 2020 | Dec 24, 2020 | Dec 24, 2021
|
^10.0.0 | Active | Jun 24, 2020 | Dec 24, 2020 | Dec 24, 2021
|
||||||
^9.0.0 | Active | Feb 06, 2020 | Aug 06, 2020 | Aug 06, 2021
|
^9.0.0 | LTS | Feb 06, 2020 | Aug 06, 2020 | Aug 06, 2021
|
||||||
^8.0.0 | LTS | May 28, 2019 | Nov 28, 2019 | Nov 28, 2020
|
^8.0.0 | LTS | May 28, 2019 | Nov 28, 2019 | Nov 28, 2020
|
||||||
|
|
||||||
Angular versions ^4.0.0, ^5.0.0, ^6.0.0 and ^7.0.0 are no longer under support.
|
Angular versions ^4.0.0, ^5.0.0, ^6.0.0 and ^7.0.0 are no longer under support.
|
||||||
|
|
||||||
|
### LTS fixes
|
||||||
|
|
||||||
|
As a general rule, a fix is considered for an LTS version if it resolves one of:
|
||||||
|
|
||||||
|
* a newly identified security vulnerability,
|
||||||
|
* a regression, since the start of LTS, caused by a 3rd party change, such as a new browser version.
|
||||||
|
|
||||||
{@a deprecation}
|
{@a deprecation}
|
||||||
## Deprecation practices
|
## Deprecation practices
|
||||||
|
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
|
|
||||||
In a single-page app, you change what the user sees by showing or hiding portions of the display that correspond to particular components, rather than going out to the server to get a new page.
|
In a single-page app, you change what the user sees by showing or hiding portions of the display that correspond to particular components, rather than going out to the server to get a new page.
|
||||||
As users perform application tasks, they need to move between the different [views](guide/glossary#view "Definition of view") that you have defined.
|
As users perform application tasks, they need to move between the different [views](guide/glossary#view "Definition of view") that you have defined.
|
||||||
To implement this kind of navigation within the single page of your app, you use the Angular **`Router`**.
|
|
||||||
|
|
||||||
To handle the navigation from one [view](guide/glossary#view) to the next, you use the Angular _router_.
|
To handle the navigation from one [view](guide/glossary#view) to the next, you use the Angular **`Router`**.
|
||||||
The router enables navigation by interpreting a browser URL as an instruction to change the view.
|
The **`Router`** enables navigation by interpreting a browser URL as an instruction to change the view.
|
||||||
|
|
||||||
To explore a sample app featuring the router's primary features, see the <live-example></live-example>.
|
To explore a sample app featuring the router's primary features, see the <live-example></live-example>.
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ RxJS provides many operators, but only a handful are used frequently. For a list
|
|||||||
|
|
||||||
| Area | Operators |
|
| Area | Operators |
|
||||||
| :------------| :----------|
|
| :------------| :----------|
|
||||||
| Creation | `from`,`fromEvent`, `of` |
|
| Creation | `from`, `fromEvent`, `of` |
|
||||||
| Combination | `combineLatest`, `concat`, `merge`, `startWith` , `withLatestFrom`, `zip` |
|
| Combination | `combineLatest`, `concat`, `merge`, `startWith` , `withLatestFrom`, `zip` |
|
||||||
| Filtering | `debounceTime`, `distinctUntilChanged`, `filter`, `take`, `takeUntil` |
|
| Filtering | `debounceTime`, `distinctUntilChanged`, `filter`, `take`, `takeUntil` |
|
||||||
| Transformation | `bufferTime`, `concatMap`, `map`, `mergeMap`, `scan`, `switchMap` |
|
| Transformation | `bufferTime`, `concatMap`, `map`, `mergeMap`, `scan`, `switchMap` |
|
||||||
|
@ -67,6 +67,33 @@ Therefore, it is recommended to reload the page once the promise returned by `ac
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
### Handling an unrecoverable state
|
||||||
|
|
||||||
|
In some cases, the version of the app used by the service worker to serve a client might be in a broken state that cannot be recovered from without a full page reload.
|
||||||
|
|
||||||
|
For example, imagine the following scenario:
|
||||||
|
- A user opens the app for the first time and the service worker caches the latest version of the app.
|
||||||
|
Let's assume the app's cached assets include `index.html`, `main.<main-hash-1>.js` and `lazy-chunk.<lazy-hash-1>.js`.
|
||||||
|
- The user closes the app and does not open it for a while.
|
||||||
|
- After some time, a new version of the app is deployed to the server.
|
||||||
|
This newer version includes the files `index.html`, `main.<main-hash-2>.js` and `lazy-chunk.<lazy-hash-2>.js` (note that the hashes are different now, because the content of the files has changed).
|
||||||
|
The old version is no longer available on the server.
|
||||||
|
- In the meantime, the user's browser decides to evict `lazy-chunk.<lazy-hash-1>.js` from its cache.
|
||||||
|
Browsers may decide to evict specific (or all) resources from a cache in order to reclaim disk space.
|
||||||
|
- The user opens the app again.
|
||||||
|
The service worker serves the latest version known to it at this point, namely the old version (`index.html` and `main.<main-hash-1>.js`).
|
||||||
|
- At some later point, the app requests the lazy bundle, `lazy-chunk.<lazy-hash-1>.js`.
|
||||||
|
- The service worker is unable to find the asset in the cache (remember that the browser evicted it).
|
||||||
|
Nor is it able to retrieve it from the server (since the server now only has `lazy-chunk.<lazy-hash-2>.js` from the newer version).
|
||||||
|
|
||||||
|
In the above scenario, the service worker is not able to serve an asset that would normally be cached.
|
||||||
|
That particular app version is broken and there is no way to fix the state of the client without reloading the page.
|
||||||
|
In such cases, the service worker notifies the client by sending an `UnrecoverableStateEvent` event.
|
||||||
|
You can subscribe to `SwUpdate#unrecoverable` to be notified and handle these errors.
|
||||||
|
|
||||||
|
<code-example path="service-worker-getting-started/src/app/handle-unrecoverable-state.service.ts" header="handle-unrecoverable-state.service.ts" region="sw-unrecoverable-state"></code-example>
|
||||||
|
|
||||||
|
|
||||||
## More on Angular service workers
|
## More on Angular service workers
|
||||||
|
|
||||||
You may also be interested in the following:
|
You may also be interested in the following:
|
||||||
|
@ -267,6 +267,12 @@ By default, these criteria are:
|
|||||||
1. The URL must not contain a file extension (i.e. a `.`) in the last path segment.
|
1. The URL must not contain a file extension (i.e. a `.`) in the last path segment.
|
||||||
2. The URL must not contain `__`.
|
2. The URL must not contain `__`.
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
To configure whether navigation requests are sent through to the network or not, see the [navigationRequestStrategy](#navigation-request-strategy) section.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
### Matching navigation request URLs
|
### Matching navigation request URLs
|
||||||
|
|
||||||
While these default criteria are fine in most cases, it is sometimes desirable to configure different rules. For example, you may want to ignore specific routes (that are not part of the Angular app) and pass them through to the server.
|
While these default criteria are fine in most cases, it is sometimes desirable to configure different rules. For example, you may want to ignore specific routes (that are not part of the Angular app) and pass them through to the server.
|
||||||
@ -285,3 +291,32 @@ If the field is omitted, it defaults to:
|
|||||||
'!/**/*__*/**', // Exclude URLs containing `__` in any other segment.
|
'!/**/*__*/**', // Exclude URLs containing `__` in any other segment.
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
{@a navigation-request-strategy}
|
||||||
|
|
||||||
|
## `navigationRequestStrategy`
|
||||||
|
|
||||||
|
This optional property enables you to configure how the service worker handles navigation requests:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"navigationRequestStrategy": "freshness"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Possible values:
|
||||||
|
|
||||||
|
- `'performance'`: The default setting. Serves the specified [index file](#index-file), which is typically cached.
|
||||||
|
- `'freshness'`: Passes the requests through to the network and falls back to the `performance` behavior when offline.
|
||||||
|
This value is useful when the server redirects the navigation requests elsewhere using an HTTP redirect (3xx status code).
|
||||||
|
Reasons for using this value include:
|
||||||
|
- Redirecting to an authentication website when authentication is not handled by the application.
|
||||||
|
- Redirecting specific URLs to avoid breaking existing links/bookmarks after a website redesign.
|
||||||
|
- Redirecting to a different website, such as a server-status page, while a page is temporarily down.
|
||||||
|
|
||||||
|
<div class="alert is-important">
|
||||||
|
|
||||||
|
The `freshness` strategy usually results in more requests sent to the server, which can increase response latency.
|
||||||
|
It is recommended that you use the default performance strategy whenever possible.
|
||||||
|
|
||||||
|
</div>
|
@ -107,7 +107,7 @@ Notice that all of the files the browser needs to render this application are ca
|
|||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
Pay attention to two key points:
|
Pay attention to two key points:
|
||||||
|
|
||||||
1. The generated `ngsw-config.json` includes a limited list of cacheable fonts and images extentions. In some cases, you might want to modify the glob pattern to suit your needs.
|
1. The generated `ngsw-config.json` includes a limited list of cacheable fonts and images extensions. In some cases, you might want to modify the glob pattern to suit your needs.
|
||||||
|
|
||||||
1. If `resourcesOutputPath` or `assets` paths are modified after the generation of configuration file, you need to change the paths manually in `ngsw-config.json`.
|
1. If `resourcesOutputPath` or `assets` paths are modified after the generation of configuration file, you need to change the paths manually in `ngsw-config.json`.
|
||||||
</div>
|
</div>
|
||||||
|
@ -37,9 +37,9 @@ by HTML.
|
|||||||
|
|
||||||
<code-example path="template-reference-variables/src/app/app.component.html" region="ngForm" header="src/app/hero-form.component.html"></code-example>
|
<code-example path="template-reference-variables/src/app/app.component.html" region="ngForm" header="src/app/hero-form.component.html"></code-example>
|
||||||
|
|
||||||
The reference value of itemForm, without the ngForm attribute value, would be
|
The reference value of `itemForm`, without the `ngForm` attribute value, would be
|
||||||
the [HTMLFormElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement).
|
the [HTMLFormElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement).
|
||||||
There is, however, a difference between a Component and a Directive in that a `Component`
|
There is, however, a difference between a `Component` and a `Directive` in that a `Component`
|
||||||
will be referenced without specifying the attribute value, and a `Directive` will not
|
will be referenced without specifying the attribute value, and a `Directive` will not
|
||||||
change the implicit reference (that is, the element).
|
change the implicit reference (that is, the element).
|
||||||
|
|
||||||
|
@ -114,6 +114,7 @@ In case of a false positive like these, there are a few options:
|
|||||||
|Strictness flag|Effect|
|
|Strictness flag|Effect|
|
||||||
|-|-|
|
|-|-|
|
||||||
|`strictInputTypes`|Whether the assignability of a binding expression to the `@Input()` field is checked. Also affects the inference of directive generic types. |
|
|`strictInputTypes`|Whether the assignability of a binding expression to the `@Input()` field is checked. Also affects the inference of directive generic types. |
|
||||||
|
|`strictInputAccessModifiers`|Whether access modifiers such as `private`/`protected`/`readonly` are honored when assigning a binding expression to an `@Input()`. If disabled, the access modifiers of the `@Input` are ignored; only the type is checked.|
|
||||||
|`strictNullInputTypes`|Whether `strictNullChecks` is honored when checking `@Input()` bindings (per `strictInputTypes`). Turning this off can be useful when using a library that was not built with `strictNullChecks` in mind.|
|
|`strictNullInputTypes`|Whether `strictNullChecks` is honored when checking `@Input()` bindings (per `strictInputTypes`). Turning this off can be useful when using a library that was not built with `strictNullChecks` in mind.|
|
||||||
|`strictAttributeTypes`|Whether to check `@Input()` bindings that are made using text attributes (for example, `<mat-tab label="Step 1">` vs `<mat-tab [label]="'Step 1'">`).
|
|`strictAttributeTypes`|Whether to check `@Input()` bindings that are made using text attributes (for example, `<mat-tab label="Step 1">` vs `<mat-tab [label]="'Step 1'">`).
|
||||||
|`strictSafeNavigationTypes`|Whether the return type of safe navigation operations (for example, `user?.name`) will be correctly inferred based on the type of `user`). If disabled, `user?.name` will be of type `any`.
|
|`strictSafeNavigationTypes`|Whether the return type of safe navigation operations (for example, `user?.name`) will be correctly inferred based on the type of `user`). If disabled, `user?.name` will be of type `any`.
|
||||||
|
@ -375,6 +375,5 @@ Some noteworthy observations:
|
|||||||
When you're filtering by CSS selector and only testing properties of a browser's _native element_, the `By.css` approach may be overkill.
|
When you're filtering by CSS selector and only testing properties of a browser's _native element_, the `By.css` approach may be overkill.
|
||||||
|
|
||||||
It's often easier and more clear to filter with a standard `HTMLElement` method
|
It's often easier and more clear to filter with a standard `HTMLElement` method
|
||||||
such as `querySelector()` or `querySelectorAll()`,
|
such as `querySelector()` or `querySelectorAll()`.
|
||||||
as you'll see in the next set of tests.
|
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ It knows who the user is based on a property of the injected `UserService`:
|
|||||||
<code-example path="testing/src/app/welcome/welcome.component.ts" header="app/welcome/welcome.component.ts"></code-example>
|
<code-example path="testing/src/app/welcome/welcome.component.ts" header="app/welcome/welcome.component.ts"></code-example>
|
||||||
|
|
||||||
The `WelcomeComponent` has decision logic that interacts with the service, logic that makes this component worth testing.
|
The `WelcomeComponent` has decision logic that interacts with the service, logic that makes this component worth testing.
|
||||||
Here's the testing module configuration for the spec file, `app/welcome/welcome.component.spec.ts`:
|
Here's the testing module configuration for the spec file:
|
||||||
|
|
||||||
<code-example path="testing/src/app/welcome/welcome.component.spec.ts" region="config-test-module" header="app/welcome/welcome.component.spec.ts"></code-example>
|
<code-example path="testing/src/app/welcome/welcome.component.spec.ts" region="config-test-module" header="app/welcome/welcome.component.spec.ts"></code-example>
|
||||||
|
|
||||||
@ -415,7 +415,7 @@ You do have to call [tick()](api/core/testing/tick) to advance the (virtual) clo
|
|||||||
Calling [tick()](api/core/testing/tick) simulates the passage of time until all pending asynchronous activities finish.
|
Calling [tick()](api/core/testing/tick) simulates the passage of time until all pending asynchronous activities finish.
|
||||||
In this case, it waits for the error handler's `setTimeout()`.
|
In this case, it waits for the error handler's `setTimeout()`.
|
||||||
|
|
||||||
The [tick()](api/core/testing/tick) function accepts milliseconds and tickOptions as parameters, the millisecond (defaults to 0 if not provided) parameter represents how much the virtual clock advances. For example, if you have a `setTimeout(fn, 100)` in a `fakeAsync()` test, you need to use tick(100) to trigger the fn callback. The tickOptions is an optional parameter with a property called `processNewMacroTasksSynchronously` (defaults to true) represents whether to invoke new generated macro tasks when ticking.
|
The [tick()](api/core/testing/tick) function accepts milliseconds and tickOptions as parameters, the millisecond (defaults to 0 if not provided) parameter represents how much the virtual clock advances. For example, if you have a `setTimeout(fn, 100)` in a `fakeAsync()` test, you need to use tick(100) to trigger the fn callback. The tickOptions is an optional parameter with a property called `processNewMacroTasksSynchronously` (defaults to true) that represents whether to invoke new generated macro tasks when ticking.
|
||||||
|
|
||||||
<code-example
|
<code-example
|
||||||
path="testing/src/app/demo/async-helper.spec.ts"
|
path="testing/src/app/demo/async-helper.spec.ts"
|
||||||
@ -594,11 +594,6 @@ Then you can assert that the quote element displays the expected text.
|
|||||||
To use `waitForAsync()` functionality, you must import `zone.js/dist/zone-testing` in your test setup file.
|
To use `waitForAsync()` functionality, you must import `zone.js/dist/zone-testing` in your test setup file.
|
||||||
If you created your project with the Angular CLI, `zone-testing` is already imported in `src/test.ts`.
|
If you created your project with the Angular CLI, `zone-testing` is already imported in `src/test.ts`.
|
||||||
|
|
||||||
The `fakeAsync()` utility function has a few limitations.
|
|
||||||
In particular, it won't work if the test body makes an `XMLHttpRequest` (XHR) call.
|
|
||||||
XHR calls within a test are rare so you can generally stick with [`fakeAsync()`](#fake-async).
|
|
||||||
But if you ever do need to call `XMLHttpRequest`, you'll want to know about `waitForAsync()`.
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
The `TestBed.compileComponents()` method (see [below](#compile-components)) calls `XHR`
|
The `TestBed.compileComponents()` method (see [below](#compile-components)) calls `XHR`
|
||||||
@ -1231,7 +1226,7 @@ and provide for _all_ services injected in _any_ component in the tree.
|
|||||||
That's too much effort just to answer a few simple questions about links.
|
That's too much effort just to answer a few simple questions about links.
|
||||||
|
|
||||||
This section describes two techniques for minimizing the setup.
|
This section describes two techniques for minimizing the setup.
|
||||||
Use them, alone or in combination, to stay focused on the testing the primary component.
|
Use them, alone or in combination, to stay focused on testing the primary component.
|
||||||
|
|
||||||
{@a stub-component}
|
{@a stub-component}
|
||||||
|
|
||||||
@ -1340,7 +1335,7 @@ The `HostListener` wires the click event of the host element
|
|||||||
Clicking the anchor should trigger the `onClick()` method,
|
Clicking the anchor should trigger the `onClick()` method,
|
||||||
which sets the stub's telltale `navigatedTo` property.
|
which sets the stub's telltale `navigatedTo` property.
|
||||||
Tests inspect `navigatedTo` to confirm that clicking the anchor
|
Tests inspect `navigatedTo` to confirm that clicking the anchor
|
||||||
set the expected route definition.
|
sets the expected route definition.
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
@ -1573,7 +1568,7 @@ calls to other `TestBed` static methods such as `compileComponents()`.
|
|||||||
In this example, the `BannerComponent` is the only component to compile.
|
In this example, the `BannerComponent` is the only component to compile.
|
||||||
Other examples configure the testing module with multiple components
|
Other examples configure the testing module with multiple components
|
||||||
and may import application modules that hold yet more components.
|
and may import application modules that hold yet more components.
|
||||||
Any of them could be require external files.
|
Any of them could require external files.
|
||||||
|
|
||||||
The `TestBed.compileComponents` method asynchronously compiles all components configured in the testing module.
|
The `TestBed.compileComponents` method asynchronously compiles all components configured in the testing module.
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ Here's a summary of the stand-alone functions, in order of likely utility:
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td style="vertical-align: top">
|
<td style="vertical-align: top">
|
||||||
<code>async</code>
|
<code>waitForAsync</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
|
@ -75,7 +75,7 @@ The tests run again, the browser refreshes, and the new test results appear.
|
|||||||
|
|
||||||
The CLI takes care of Jasmine and Karma configuration for you.
|
The CLI takes care of Jasmine and Karma configuration for you.
|
||||||
|
|
||||||
You can fine-tune many options by editing the `karma.conf.js` and
|
You can fine-tune many options by editing the `karma.conf.js` in the root folder of the project and
|
||||||
the `test.ts` files in the `src/` folder.
|
the `test.ts` files in the `src/` folder.
|
||||||
|
|
||||||
The `karma.conf.js` file is a partial Karma configuration file.
|
The `karma.conf.js` file is a partial Karma configuration file.
|
||||||
@ -217,7 +217,7 @@ script:
|
|||||||
- npm run e2e -- --protractor-config=e2e/protractor-ci.conf.js
|
- npm run e2e -- --protractor-config=e2e/protractor-ci.conf.js
|
||||||
```
|
```
|
||||||
|
|
||||||
This does the same things as the Circle CI configuration, except that Travis doesn't come with Chrome, so we use Chromium instead.
|
This does the same things as the CircleCI configuration, except that Travis doesn't come with Chrome, so use Chromium instead.
|
||||||
|
|
||||||
Step 2: Commit your changes and push them to your repository.
|
Step 2: Commit your changes and push them to your repository.
|
||||||
|
|
||||||
|
@ -18,32 +18,7 @@ that are important to Angular developers, including details about the following
|
|||||||
## Configuration files
|
## Configuration files
|
||||||
|
|
||||||
A given Angular workspace contains several TypeScript configuration files.
|
A given Angular workspace contains several TypeScript configuration files.
|
||||||
At the root level, there are two main TypeScript configuration files: a `tsconfig.json` file and a `tsconfig.base.json` file.
|
At the root `tsconfig.json` file specifies the base TypeScript and Angular compiler options that all projects in the workspace inherit.
|
||||||
|
|
||||||
The `tsconfig.json` file is a ["Solution Style"](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#support-for-solution-style-tsconfigjson-files) TypeScript configuration file.
|
|
||||||
Code editors and TypeScript’s language server use this file to improve development experience.
|
|
||||||
Compilers do not use this file.
|
|
||||||
|
|
||||||
The `tsconfig.json` file contains a list of paths to the other TypeScript configuration files used in the workspace.
|
|
||||||
|
|
||||||
<code-example lang="json" header="tsconfig.json" linenums="false">
|
|
||||||
{
|
|
||||||
"files": [],
|
|
||||||
"references": [
|
|
||||||
{
|
|
||||||
"path": "./tsconfig.app.json"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "./tsconfig.spec.json"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "./projects/my-lib/tsconfig.lib.json"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
The `tsconfig.base.json` file specifies the base TypeScript and Angular compiler options that all projects in the workspace inherit.
|
|
||||||
|
|
||||||
The TypeScript and Angular have a wide range of options which can be used to configure type-checking features and generated output.
|
The TypeScript and Angular have a wide range of options which can be used to configure type-checking features and generated output.
|
||||||
For more information, see the [Configuration inheritance with extends](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#configuration-inheritance-with-extends) section of the TypeScript documentation.
|
For more information, see the [Configuration inheritance with extends](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#configuration-inheritance-with-extends) section of the TypeScript documentation.
|
||||||
@ -55,9 +30,9 @@ For details about configuration inheritance, see the [Configuration inheritance
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
The initial `tsconfig.base.json` for an Angular workspace typically looks like the following example.
|
The initial `tsconfig.json` for an Angular workspace typically looks like the following example.
|
||||||
|
|
||||||
<code-example lang="json" header="tsconfig.base.json" linenums="false">
|
<code-example lang="json" header="tsconfig.json" linenums="false">
|
||||||
{
|
{
|
||||||
"compileOnSave": false,
|
"compileOnSave": false,
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
@ -48,8 +48,7 @@ src/
|
|||||||
app/ ... <i>application code</i>
|
app/ ... <i>application code</i>
|
||||||
app.server.module.ts <i>* server-side application module</i>
|
app.server.module.ts <i>* server-side application module</i>
|
||||||
server.ts <i>* express web server</i>
|
server.ts <i>* express web server</i>
|
||||||
tsconfig.json <i>TypeScript solution style configuration</i>
|
tsconfig.json <i>TypeScript base configuration</i>
|
||||||
tsconfig.base.json <i>TypeScript base configuration</i>
|
|
||||||
tsconfig.app.json <i>TypeScript browser application configuration</i>
|
tsconfig.app.json <i>TypeScript browser application configuration</i>
|
||||||
tsconfig.server.json <i>TypeScript server application configuration</i>
|
tsconfig.server.json <i>TypeScript server application configuration</i>
|
||||||
tsconfig.spec.json <i>TypeScript tests configuration</i>
|
tsconfig.spec.json <i>TypeScript tests configuration</i>
|
||||||
|
@ -77,6 +77,5 @@ Read about the migrations the CLI handles for you automatically:
|
|||||||
|
|
||||||
* [Migrating missing `@Directive()`/`@Component()` decorators](guide/migration-undecorated-classes)
|
* [Migrating missing `@Directive()`/`@Component()` decorators](guide/migration-undecorated-classes)
|
||||||
* [Migrating `ModuleWithProviders`](guide/migration-module-with-providers)
|
* [Migrating `ModuleWithProviders`](guide/migration-module-with-providers)
|
||||||
* [Solution-style `tsconfig.json` migration](guide/migration-solution-style-tsconfig)
|
|
||||||
* [`tslib` direct dependency migration](guide/migration-update-libraries-tslib)
|
* [`tslib` direct dependency migration](guide/migration-update-libraries-tslib)
|
||||||
* [Update `module` and `target` compiler options migration](guide/migration-update-module-and-target-compiler-options)
|
* [Update `module` and `target` compiler options migration](guide/migration-update-module-and-target-compiler-options)
|
||||||
|
@ -324,5 +324,5 @@ These techniques are useful for small-scale demonstrations, but they
|
|||||||
quickly become verbose and clumsy when handling large amounts of user input.
|
quickly become verbose and clumsy when handling large amounts of user input.
|
||||||
Two-way data binding is a more elegant and compact way to move
|
Two-way data binding is a more elegant and compact way to move
|
||||||
values between data entry fields and model properties.
|
values between data entry fields and model properties.
|
||||||
The next page, `Forms`, explains how to write
|
The [`Forms`](guide/forms-overview) page explains how to write
|
||||||
two-way bindings with `NgModel`.
|
two-way bindings with `NgModel`.
|
||||||
|
@ -32,7 +32,7 @@ To do this:
|
|||||||
|
|
||||||
1. Create a `typings.d.ts` file in your `src/` folder. This file is automatically included as global type definition.
|
1. Create a `typings.d.ts` file in your `src/` folder. This file is automatically included as global type definition.
|
||||||
|
|
||||||
2. Add the following code in `src/typings.d.ts`.
|
2. Add the following code in `src/typings.d.ts`:
|
||||||
|
|
||||||
```
|
```
|
||||||
declare module 'host' {
|
declare module 'host' {
|
||||||
@ -45,7 +45,7 @@ declare module 'host' {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
3. In the component or file that uses the library, add the following code.
|
3. In the component or file that uses the library, add the following code:
|
||||||
|
|
||||||
```
|
```
|
||||||
import * as host from 'host';
|
import * as host from 'host';
|
||||||
@ -129,7 +129,7 @@ interface JQuery {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If don't add the interface for the script-defined extension, your IDE shows an error:
|
If you don't add the interface for the script-defined extension, your IDE shows an error:
|
||||||
|
|
||||||
```
|
```
|
||||||
[TS][Error] Property 'myPlugin' does not exist on type 'JQuery'
|
[TS][Error] Property 'myPlugin' does not exist on type 'JQuery'
|
||||||
|
@ -14,12 +14,16 @@ The CLI does not support running Angular itself in a web worker.
|
|||||||
|
|
||||||
To add a web worker to an existing project, use the Angular CLI `ng generate` command.
|
To add a web worker to an existing project, use the Angular CLI `ng generate` command.
|
||||||
|
|
||||||
`ng generate web-worker` *location*
|
```bash
|
||||||
|
ng generate web-worker <location>
|
||||||
|
```
|
||||||
|
|
||||||
You can add a web worker anywhere in your application.
|
You can add a web worker anywhere in your application.
|
||||||
For example, to add a web worker to the root component, `src/app/app.component.ts`, run the following command.
|
For example, to add a web worker to the root component, `src/app/app.component.ts`, run the following command.
|
||||||
|
|
||||||
`ng generate web-worker app`
|
```bash
|
||||||
|
ng generate web-worker app
|
||||||
|
```
|
||||||
|
|
||||||
The command performs the following actions.
|
The command performs the following actions.
|
||||||
|
|
||||||
|
BIN
aio/content/images/bios/samvloeberghs.jpg
Normal file
BIN
aio/content/images/bios/samvloeberghs.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
BIN
aio/content/images/bios/thekiba.jpg
Normal file
BIN
aio/content/images/bios/thekiba.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.0 KiB |
@ -53,6 +53,9 @@
|
|||||||
},
|
},
|
||||||
"kyliau": {
|
"kyliau": {
|
||||||
"name": "Keen Yee Liau",
|
"name": "Keen Yee Liau",
|
||||||
|
"twitter": "liauky",
|
||||||
|
"website": "https://github.com/kyliau",
|
||||||
|
"bio": "Keen works on language service and CLI. He also maintains Karma and Protractor.",
|
||||||
"groups": ["Angular"],
|
"groups": ["Angular"],
|
||||||
"lead": "igorminar",
|
"lead": "igorminar",
|
||||||
"picture": "kyliau.jpg"
|
"picture": "kyliau.jpg"
|
||||||
@ -86,24 +89,6 @@
|
|||||||
"groups": ["Angular"],
|
"groups": ["Angular"],
|
||||||
"lead": "kara"
|
"lead": "kara"
|
||||||
},
|
},
|
||||||
"matsko": {
|
|
||||||
"name": "Matias Niemela",
|
|
||||||
"picture": "matias.jpg",
|
|
||||||
"twitter": "yearofmoo",
|
|
||||||
"website": "http://yearofmoo.com",
|
|
||||||
"bio": "Matias Niemela is a fullstack web developer who has been programming & building websites for over 10 years, and a core team member of AngularJS for two years. In the spring of 2015 Matias joined Angular full time at Google. In his free time Matias loves to build complex things and is always up for public speaking, travelling and tweaking his current Vim setup.",
|
|
||||||
"groups": ["Angular"],
|
|
||||||
"lead": "kara"
|
|
||||||
},
|
|
||||||
"kara": {
|
|
||||||
"name": "Kara Erickson",
|
|
||||||
"picture": "kara-erickson.jpg",
|
|
||||||
"twitter": "karaforthewin",
|
|
||||||
"website": "https://github.com/kara",
|
|
||||||
"bio": "Kara is a software engineer on the Angular team at Google and a co-organizer of the Angular-SF Meetup. Prior to Google, she helped build UI components in Angular for guest management systems at OpenTable. She enjoys snacking indiscriminately and probably other things too.",
|
|
||||||
"groups": ["Angular"],
|
|
||||||
"lead": "igorminar"
|
|
||||||
},
|
|
||||||
"pkozlowski-opensource": {
|
"pkozlowski-opensource": {
|
||||||
"name": "Pawel Kozlowski",
|
"name": "Pawel Kozlowski",
|
||||||
"picture": "pawel.jpg",
|
"picture": "pawel.jpg",
|
||||||
@ -618,26 +603,6 @@
|
|||||||
"bio": "Justin (aka Schwarty) is a Google Developer Expert in Web Technologies and Angular, the host and maintainer of the weekly AngularAir live video broadcast, educator, writer and content creator. He has Angular courses available on LinkedIn Learning and Pluralsight and loves passing on years of full stack development knowledge to help empower others to find their inner awesomeness!",
|
"bio": "Justin (aka Schwarty) is a Google Developer Expert in Web Technologies and Angular, the host and maintainer of the weekly AngularAir live video broadcast, educator, writer and content creator. He has Angular courses available on LinkedIn Learning and Pluralsight and loves passing on years of full stack development knowledge to help empower others to find their inner awesomeness!",
|
||||||
"groups": ["GDE"]
|
"groups": ["GDE"]
|
||||||
},
|
},
|
||||||
"dennispbrown": {
|
|
||||||
"name": "Denny Brown",
|
|
||||||
"picture": "denny.jpg",
|
|
||||||
"bio": "Denny is founder of Expert Support, a professional services firm specializing in technical communication, and leads the Angular technical writing team. His lifelong passion has been to reduce the time and effort required to understand complex technical information. Early on, he was Associate Chairman of the Computer Science Department at Stanford, where he taught introductory courses in programming. He also plays old-timers baseball in local leagues and national tournaments.",
|
|
||||||
"groups": ["Angular"],
|
|
||||||
"lead": "aikidave"
|
|
||||||
},
|
|
||||||
"jbogarthyde": {
|
|
||||||
"name": "Judy Bogart",
|
|
||||||
"picture": "judy.png",
|
|
||||||
"groups": ["Angular"],
|
|
||||||
"lead": "dennispbrown"
|
|
||||||
},
|
|
||||||
"rockument69": {
|
|
||||||
"name": "Tony Bove",
|
|
||||||
"picture": "rockument69.jpg",
|
|
||||||
"bio": "Tony is a technical writer with Expert Support. His lifelong passions are helping people use technology, writing fiction, and playing music. When he's not working or playing the harmonica with friends in a bluegrass band, he's swimming and snorkeling on a Kauai beach and playing ball with his Irish Wolfhound. He's worked at home for decades before it became a thing.",
|
|
||||||
"groups": ["Angular"],
|
|
||||||
"lead": "aikidave"
|
|
||||||
},
|
|
||||||
"kapunahelewong": {
|
"kapunahelewong": {
|
||||||
"name": "Kapunahele Wong",
|
"name": "Kapunahele Wong",
|
||||||
"picture": "kapunahele.jpg",
|
"picture": "kapunahele.jpg",
|
||||||
@ -751,9 +716,9 @@
|
|||||||
"santosh": {
|
"santosh": {
|
||||||
"name": "Santosh Yadav",
|
"name": "Santosh Yadav",
|
||||||
"picture": "santoshyadav.jpg",
|
"picture": "santoshyadav.jpg",
|
||||||
"twitter": "Santosh19742211",
|
"twitter": "SantoshYadavDev",
|
||||||
"website": "https://www.santoshyadav.dev",
|
"website": "https://www.santoshyadav.dev",
|
||||||
"bio": "Santosh is a GDE for Angular and Web Technologies and loves to contribute to Open Source. He is the creator of ng deploy for netlify and core team member for NestJS Addons. He writes for AngularInDepth, mentors for DotNetTricks, organizes Pune Tech Meetup, and conducts free workshops on Angular.",
|
"bio": "Santosh is a GDE for Angular and loves to contribute to Open Source. He is the creator of ng deploy for netlify and core team member for NestJS Addons. He writes for AngularInDepth, mentors for DotNetTricks, organizes Pune Tech Meetup, and conducts free workshops on Angular.",
|
||||||
"groups": ["GDE"]
|
"groups": ["GDE"]
|
||||||
},
|
},
|
||||||
"josephperrott": {
|
"josephperrott": {
|
||||||
@ -848,5 +813,21 @@
|
|||||||
"website": "kreuzercode.com",
|
"website": "kreuzercode.com",
|
||||||
"bio": "Kevin is a passionate freelance front-end engineer and Google Developer Expert based in Switzerland. He is a JavaScript enthusiast and fascinated by Angular. Kevin always tries to learn new things, expand his knowledge, and share it with others in the form of blog posts, workshops, podcasts, or presentations. He is a writer for various publications and the most active writer on Angular in-depth in 2019. Contributing to multiple projects and maintaining 7 npm packages, Kevin is also a big believer in open source. Furthermore, Kevin is a big football fan. Since his childhood, he has supported Real Madrid, which you might notice in a lot of his blog posts and tutorials.",
|
"bio": "Kevin is a passionate freelance front-end engineer and Google Developer Expert based in Switzerland. He is a JavaScript enthusiast and fascinated by Angular. Kevin always tries to learn new things, expand his knowledge, and share it with others in the form of blog posts, workshops, podcasts, or presentations. He is a writer for various publications and the most active writer on Angular in-depth in 2019. Contributing to multiple projects and maintaining 7 npm packages, Kevin is also a big believer in open source. Furthermore, Kevin is a big football fan. Since his childhood, he has supported Real Madrid, which you might notice in a lot of his blog posts and tutorials.",
|
||||||
"groups": ["GDE"]
|
"groups": ["GDE"]
|
||||||
|
},
|
||||||
|
"samvloeberghs": {
|
||||||
|
"name": "Sam Vloeberghs",
|
||||||
|
"picture": "samvloeberghs.jpg",
|
||||||
|
"groups": ["GDE"],
|
||||||
|
"twitter": "samvloeberghs",
|
||||||
|
"website": "https://samvloeberghs.be",
|
||||||
|
"bio": "Sam is a freelance software architect and Internet entrepreneur, currently focusing on frontend technologies. Co-organiser of the Belgian Angular conference NG-BE and Angular Belgium Meetup group."
|
||||||
|
},
|
||||||
|
"thekiba": {
|
||||||
|
"name": "Andrew Grekov",
|
||||||
|
"picture": "thekiba.jpg",
|
||||||
|
"twitter": "thekiba_io",
|
||||||
|
"website": "https://thekiba.io",
|
||||||
|
"bio": "Andrew is a software engineer using Angular and .NET. He spends most of his spare time staying up-to-date, helping other people, and experimenting with web tech.",
|
||||||
|
"groups": ["GDE"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,162 +3,5 @@
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<article class="events-container">
|
<article class="events-container">
|
||||||
<p>Where we'll be presenting:</p>
|
<aio-events></aio-events>
|
||||||
<table class="is-full-width">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Event</th>
|
|
||||||
<th>Location</th>
|
|
||||||
<th>Date</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p>Where we already presented:</p>
|
|
||||||
<table class="is-full-width">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Event</th>
|
|
||||||
<th>Location</th>
|
|
||||||
<th>Date</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<!-- ng-vikings 2020 -->
|
|
||||||
<tr>
|
|
||||||
<th><a href="https://ngvikings.org/" title="ngVikings">ngVikings</a></th>
|
|
||||||
<td>Oslo, Norway</td>
|
|
||||||
<td>May 25-26 conference, 27 workshops, 2020</td>
|
|
||||||
</tr>
|
|
||||||
<!-- ng-conf 2020 -->
|
|
||||||
<tr>
|
|
||||||
<th><a href="https://ng-conf.org/" title="ng-conf">ng-conf</a></th>
|
|
||||||
<td>Salt Lake City, Utah</td>
|
|
||||||
<td>April 1-3, 2020</td>
|
|
||||||
</tr>
|
|
||||||
<!-- ngIndia 2020 -->
|
|
||||||
<tr>
|
|
||||||
<th><a href="https://www.ng-ind.com/" title="ngIndia">ngIndia</a></th>
|
|
||||||
<td>Delhi, India</td>
|
|
||||||
<td>Feb 29, 2020</td>
|
|
||||||
</tr>
|
|
||||||
<!-- ReactiveConf 2019 -->
|
|
||||||
<tr>
|
|
||||||
<th><a href="https://reactiveconf.com/" title="ReactiveConf">ReactiveConf</a></th>
|
|
||||||
<td>Prague, Czech Republic</td>
|
|
||||||
<td>October 30 - November 1, 2019</td>
|
|
||||||
</tr>
|
|
||||||
<!-- NG Rome 2019-->
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
<a href="https://ngrome.io" title="NG Rome MMXIX - The Italian Angular Conference">NG Rome MMXIX</a>
|
|
||||||
</th>
|
|
||||||
<td>Rome, Italy</td>
|
|
||||||
<td>Oct 6th workshops, 7th conference, 2019</td>
|
|
||||||
</tr>
|
|
||||||
<!-- AngularConnect 2019-->
|
|
||||||
<tr>
|
|
||||||
<th><a href="https://www.angularconnect.com/?utm_source=angular.io&utm_medium=referral"
|
|
||||||
title="AngularConnect">AngularConnect</a></th>
|
|
||||||
<td>London, UK</td>
|
|
||||||
<td>September 19-20, 2019</td>
|
|
||||||
</tr>
|
|
||||||
<!-- NG-DE 2019-->
|
|
||||||
<tr>
|
|
||||||
<th><a href="https://ng-de.org/" title="NG-DE">NG-DE</a></th>
|
|
||||||
<td>Berlin, Germany</td>
|
|
||||||
<td>August 29th workshops, 30-31 conference, 2019</td>
|
|
||||||
</tr>
|
|
||||||
<!-- ngJapan-->
|
|
||||||
<tr>
|
|
||||||
<th><a href="https://ngjapan.org" title="ng-japan">ng-japan</a></th>
|
|
||||||
<td>Tokyo, Japan</td>
|
|
||||||
<td>July 13, 2019</td>
|
|
||||||
</tr>
|
|
||||||
<!-- ngVikings 2019-->
|
|
||||||
<tr>
|
|
||||||
<th><a href="https://ngvikings.org/" title="ngVikings">ngVikings</a></th>
|
|
||||||
<td>Copenhagen, Denmark</td>
|
|
||||||
<td>May 26 (workshops), 27-28 (conference), 2019</td>
|
|
||||||
</tr>
|
|
||||||
<!-- ng-conf 2019-->
|
|
||||||
<tr>
|
|
||||||
<th><a href="https://ng-conf.org/" title="ng-conf">ng-conf</a></th>
|
|
||||||
<td>Salt Lake City, Utah</td>
|
|
||||||
<td>May 1-3, 2019</td>
|
|
||||||
</tr>
|
|
||||||
<!-- ng-India 2019-->
|
|
||||||
<tr>
|
|
||||||
<th><a href="https://www.ng-ind.com/" title="ng-India">ng-India</a></th>
|
|
||||||
<td>Gurgaon, India</td>
|
|
||||||
<td>February 23, 2019</td>
|
|
||||||
</tr>
|
|
||||||
<!-- ngAtlanta 2019 -->
|
|
||||||
<tr>
|
|
||||||
<th><a href="https://ng-atl.org/" title="ngAtlanta">ngAtlanta</a></th>
|
|
||||||
<td>Atlanta, Georgia</td>
|
|
||||||
<td>January 9-12, 2019</td>
|
|
||||||
</tr>
|
|
||||||
<!-- AngularConnect-->
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
<a href="https://past.angularconnect.com/2018" title="AngularConnect">AngularConnect</a>
|
|
||||||
</th>
|
|
||||||
<td>London, United Kingdom</td>
|
|
||||||
<td>November 5-7, 2018</td>
|
|
||||||
</tr>
|
|
||||||
<!-- ReactiveConf -->
|
|
||||||
<tr>
|
|
||||||
<th><a href="https://reactiveconf.com/" title="ReactiveConf">ReactiveConf</a></th>
|
|
||||||
<td>Prague, Czech Republic</td>
|
|
||||||
<td>October 29-31, 2018</td>
|
|
||||||
</tr>
|
|
||||||
<!-- AngularMix -->
|
|
||||||
<tr>
|
|
||||||
<th><a href="https://angularmix.com/" title="AngularMix">AngularMix</a></th>
|
|
||||||
<td>Orlando, Florida</td>
|
|
||||||
<td>October 10-12, 2018</td>
|
|
||||||
</tr>
|
|
||||||
<!-- Angular Conf Australia-->
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
<a href="https://www.angularconf.com.au/" title="Angular Conf Australia">Angular Conf Australia</a>
|
|
||||||
</th>
|
|
||||||
<td>Melbourne, Australia</td>
|
|
||||||
<td>Jun 22, 2018</td>
|
|
||||||
</tr>
|
|
||||||
<!-- ngJapan-->
|
|
||||||
<tr>
|
|
||||||
<th><a href="https://ngjapan.org/en.html" title="ng-japan">ng-japan</a></th>
|
|
||||||
<td>Tokyo, Japan</td>
|
|
||||||
<td>Jun 16, 2018</td>
|
|
||||||
</tr>
|
|
||||||
<!-- WeRDevs-->
|
|
||||||
<tr>
|
|
||||||
<th><a href="https://www.wearedevelopers.com/" title="WeAreDevs">WeAreDevelopers</a></th>
|
|
||||||
<td>Vienna, Austria</td>
|
|
||||||
<td>May 16-18, 2018</td>
|
|
||||||
</tr>
|
|
||||||
<!-- ngconf 2018-->
|
|
||||||
<tr>
|
|
||||||
<th><a href="https://www.ng-conf.org/" title="ng-conf">ng-conf</a></th>
|
|
||||||
<td>Salt Lake City, Utah</td>
|
|
||||||
<td>April 18-20, 2018</td>
|
|
||||||
</tr>
|
|
||||||
<!-- ngVikings-->
|
|
||||||
<tr>
|
|
||||||
<th><a href="https://ngvikings.org/" title="ngVikings">ngVikings</a></th>
|
|
||||||
<td>Helsinki, Finland</td>
|
|
||||||
<td>March 1-2, 2018</td>
|
|
||||||
</tr>
|
|
||||||
<!-- ngAtlanta-->
|
|
||||||
<tr>
|
|
||||||
<th><a href="http://ng-atl.org/" title="ngAtlanta">ngAtlanta</a></th>
|
|
||||||
<td>Atlanta, Georgia</td>
|
|
||||||
<td>January 30, 2018</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</article>
|
</article>
|
||||||
|
236
aio/content/marketing/events.json
Normal file
236
aio/content/marketing/events.json
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "ng-china",
|
||||||
|
"location": "Online",
|
||||||
|
"linkUrl": "https://ng-china.org/",
|
||||||
|
"date": {
|
||||||
|
"start": "2020-11-21",
|
||||||
|
"end": "2020-11-22"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "EnterpriseNG",
|
||||||
|
"location": "Online",
|
||||||
|
"linkUrl": "https://www.ng-conf.org/",
|
||||||
|
"date": {
|
||||||
|
"start": "2020-11-19",
|
||||||
|
"end": "2020-11-20"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ngrome",
|
||||||
|
"location": "Online",
|
||||||
|
"linkUrl": "https://ngrome.io/",
|
||||||
|
"date": {
|
||||||
|
"start": "2020-10-20",
|
||||||
|
"end": "2020-10-20"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ngVikings",
|
||||||
|
"location": "Oslo, Norway",
|
||||||
|
"linkUrl": "https://ngvikings.org/",
|
||||||
|
"date": {
|
||||||
|
"start": "2020-05-25",
|
||||||
|
"end": "2020-05-26"
|
||||||
|
},
|
||||||
|
"workshopsDate": {
|
||||||
|
"start": "2020-05-27",
|
||||||
|
"end": "2020-05-27"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ng-conf",
|
||||||
|
"location": "Salt Lake City, Utah",
|
||||||
|
"linkUrl": "https://ng-conf.org/",
|
||||||
|
"date": {
|
||||||
|
"start": "2020-04-01",
|
||||||
|
"end": "2020-04-03"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ngIndia",
|
||||||
|
"location": "Delhi, India",
|
||||||
|
"linkUrl": "https://www.ng-ind.com/",
|
||||||
|
"date": {
|
||||||
|
"start": "2020-02-29",
|
||||||
|
"end": "2020-02-29"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ReactiveConf",
|
||||||
|
"location": "Prague, Czech Republic",
|
||||||
|
"linkUrl": "https://reactiveconf.com/",
|
||||||
|
"date": {
|
||||||
|
"start": "2019-10-30",
|
||||||
|
"end": "2019-11-01"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "NG Rome MMXIX",
|
||||||
|
"location": "Rome, Italy",
|
||||||
|
"linkUrl": "https://ngrome.io",
|
||||||
|
"tooltip": "NG Rome MMXIX - The Italian Angular Conference",
|
||||||
|
"date": {
|
||||||
|
"start": "2019-10-07",
|
||||||
|
"end": "2019-10-07"
|
||||||
|
},
|
||||||
|
"workshopsDate": {
|
||||||
|
"start": "2019-10-06",
|
||||||
|
"end": "2019-10-06"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AngularConnect",
|
||||||
|
"location": "London, UK",
|
||||||
|
"linkUrl": "https://www.angularconnect.com/?utm_source=angular.io&utm_medium=referral",
|
||||||
|
"date": {
|
||||||
|
"start": "2019-09-19",
|
||||||
|
"end": "2019-09-20"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "NG-DE",
|
||||||
|
"location": "Berlin, Germany",
|
||||||
|
"linkUrl": "https://ng-de.org/",
|
||||||
|
"date": {
|
||||||
|
"start": "2019-08-30",
|
||||||
|
"end": "2019-08-31"
|
||||||
|
},
|
||||||
|
"workshopsDate": {
|
||||||
|
"start": "2019-08-29",
|
||||||
|
"end": "2019-08-29"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ng-japan",
|
||||||
|
"location": "Tokyo, Japan",
|
||||||
|
"linkUrl": "https://ngjapan.org/",
|
||||||
|
"date": {
|
||||||
|
"start": "2019-07-13",
|
||||||
|
"end": "2019-07-13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ngVikings",
|
||||||
|
"location": "Copenhagen, Denmark",
|
||||||
|
"linkUrl": "https://ngvikings.org/",
|
||||||
|
"date": {
|
||||||
|
"start": "2019-05-27",
|
||||||
|
"end": "2019-05-28"
|
||||||
|
},
|
||||||
|
"workshopsDate": {
|
||||||
|
"start": "2019-05-26",
|
||||||
|
"end": "2019-05-26"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ng-conf",
|
||||||
|
"location": "Salt Lake City, Utah",
|
||||||
|
"linkUrl": "https://ng-conf.org/",
|
||||||
|
"date": {
|
||||||
|
"start": "2019-05-01",
|
||||||
|
"end": "2019-05-03"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ng-India",
|
||||||
|
"location": "Gurgaon, India",
|
||||||
|
"linkUrl": "https://www.ng-ind.com/",
|
||||||
|
"date": {
|
||||||
|
"start": "2019-02-23",
|
||||||
|
"end": "2019-02-23"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ngAtlanta",
|
||||||
|
"location": "Atlanta, Georgia",
|
||||||
|
"linkUrl": "https://ng-atl.org/",
|
||||||
|
"date": {
|
||||||
|
"start": "2019-01-09",
|
||||||
|
"end": "2019-01-12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AngularConnect",
|
||||||
|
"location": "London, United Kingdom",
|
||||||
|
"linkUrl": "https://past.angularconnect.com/2018",
|
||||||
|
"date": {
|
||||||
|
"start": "2018-11-05",
|
||||||
|
"end": "2018-11-07"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ReactiveConf",
|
||||||
|
"location": "Prague, Czech Republic",
|
||||||
|
"linkUrl": "https://reactiveconf.com/",
|
||||||
|
"date": {
|
||||||
|
"start": "2018-10-29",
|
||||||
|
"end": "2018-10-31"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AngularMix",
|
||||||
|
"location": "Orlando, Florida",
|
||||||
|
"linkUrl": "https://angularmix.com/",
|
||||||
|
"date": {
|
||||||
|
"start": "2018-10-10",
|
||||||
|
"end": "2018-10-12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Angular Conf Australia",
|
||||||
|
"location": "Melbourne, Australia",
|
||||||
|
"linkUrl": "https://www.angularconf.com.au/",
|
||||||
|
"date": {
|
||||||
|
"start": "2018-06-22",
|
||||||
|
"end": "2018-06-22"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ng-japan",
|
||||||
|
"location": "Tokyo, Japan",
|
||||||
|
"linkUrl": "https://ngjapan.org/en.html",
|
||||||
|
"date": {
|
||||||
|
"start": "2018-06-16",
|
||||||
|
"end": "2018-06-16"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "WeAreDevelopers",
|
||||||
|
"location": "Vienna, Austria",
|
||||||
|
"linkUrl": "https://www.wearedevelopers.com/",
|
||||||
|
"tooltip": "WeAreDevs",
|
||||||
|
"date": {
|
||||||
|
"start": "2018-05-16",
|
||||||
|
"end": "2018-05-18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ng-conf",
|
||||||
|
"location": "Salt Lake City, Utah",
|
||||||
|
"linkUrl": "https://ng-conf.org/",
|
||||||
|
"date": {
|
||||||
|
"start": "2018-04-18",
|
||||||
|
"end": "2018-04-20"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ngVikings",
|
||||||
|
"location": "Helsinki, Finland",
|
||||||
|
"linkUrl": "https://ngvikings.org/",
|
||||||
|
"date": {
|
||||||
|
"start": "2018-03-01",
|
||||||
|
"end": "2018-03-02"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ngAtlanta",
|
||||||
|
"location": "Atlanta, Georgia",
|
||||||
|
"linkUrl": "https://ng-atl.org/",
|
||||||
|
"date": {
|
||||||
|
"start": "2018-01-30",
|
||||||
|
"end": "2018-01-30"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user