Compare commits
334 Commits
6.0.0-beta
...
labs/rxjs-
Author | SHA1 | Date | |
---|---|---|---|
ec6ff1155b | |||
ed78457c38 | |||
8e3b940461 | |||
804d8c89d4 | |||
ea1dd3a2fc | |||
a5e6c64f25 | |||
57760c8d20 | |||
683066fef1 | |||
f5a98f41fe | |||
c09bd67aee | |||
9df13add5d | |||
049757b237 | |||
1f9734315d | |||
6f0dad1710 | |||
37fedd001c | |||
b1365d1fa8 | |||
4ac606b419 | |||
51027d73cc | |||
48636f3e85 | |||
bd9d4df735 | |||
34e355a3b0 | |||
58b94e6f5e | |||
db56836425 | |||
21e44c6ba9 | |||
f5d75d8efd | |||
6e00410e1c | |||
f95730b8e2 | |||
cd58c0a6d9 | |||
38fef1588d | |||
3f70aba272 | |||
eb6fb2d8f9 | |||
c602563589 | |||
8449eb8d62 | |||
a225b48482 | |||
129d1e0fb1 | |||
aa7dba244b | |||
0bf6fa5b32 | |||
40315bef3d | |||
123efba388 | |||
fa451bcd19 | |||
0d8deb0795 | |||
e8326e600d | |||
b5be18f405 | |||
1e6cc42a01 | |||
b26a90567c | |||
b0b9ca3386 | |||
5412e10bcd | |||
489fec1299 | |||
2fee5cc095 | |||
f13f4db9dc | |||
2ca77d80ec | |||
73c203fda9 | |||
c499c8f4db | |||
4c089c1d93 | |||
d485346d3c | |||
8407fcc979 | |||
f64ee15487 | |||
5d4fa7f0c8 | |||
8fb34bcd43 | |||
6d1367d297 | |||
538f1d980f | |||
065bcc5aad | |||
8ad4ae0a07 | |||
ffc6ee0086 | |||
78167915ee | |||
ad8fb8484f | |||
ce649f725f | |||
fcb8c492d6 | |||
4f744cc66f | |||
505ae752b6 | |||
363dfa5437 | |||
b3d1761825 | |||
d0db9ded90 | |||
4c40812b71 | |||
fa974c7d4e | |||
2c75acc5b3 | |||
f86d8ae0fd | |||
94bc277b1b | |||
8ea4c57174 | |||
53b0fe8144 | |||
2a1e3d191f | |||
2c2b62f45f | |||
58932c7f38 | |||
5bb9f64218 | |||
405d97431f | |||
41064fcb36 | |||
b80fd6be58 | |||
3aea8fd5f3 | |||
b64139650c | |||
1d2bdcb4d0 | |||
12be311618 | |||
51ca643c27 | |||
69d359bb51 | |||
4f60968704 | |||
25faf808a5 | |||
d7e5d45f43 | |||
ba8df8a3f1 | |||
0451fd93df | |||
49f074f61d | |||
ec445b5c73 | |||
ab790f3c84 | |||
dd534471ec | |||
8bb2f5c71d | |||
0e311e3918 | |||
997b30a093 | |||
94707fe795 | |||
2f0ab7ee98 | |||
b8fe121a16 | |||
e751a0a2bb | |||
288851c41e | |||
9eaf1bbe67 | |||
aabe16c08c | |||
b6c941053e | |||
c82cef8bc6 | |||
f8749bfb70 | |||
7d65356ae3 | |||
11f30fc351 | |||
b107131f8a | |||
11264e2174 | |||
b924ce3a62 | |||
e75f0cee18 | |||
8c358844dd | |||
e454c5a98e | |||
930ecacd86 | |||
5170ffe844 | |||
e95b61d42a | |||
8a85888773 | |||
83b32a0a0a | |||
8d34364ff5 | |||
142117f6bb | |||
79656e7f96 | |||
d100f1b187 | |||
4bd3e5f92f | |||
3f3be429c9 | |||
7e4c13f2de | |||
82a791223c | |||
ef99126aea | |||
c10c831b8e | |||
40ba009e25 | |||
d3827a0017 | |||
a7e1f236ff | |||
1f599818bd | |||
5a32d7e36f | |||
1ea41d48d3 | |||
25a43041d2 | |||
c593d69ce7 | |||
13ab91e05d | |||
f089bf5333 | |||
8e1e040f72 | |||
28240625e6 | |||
0d248079ba | |||
a4032296cc | |||
4180912538 | |||
094666da17 | |||
3a809cb431 | |||
b43b164a61 | |||
1dcbc12fd3 | |||
ae2e85e8ef | |||
aad431642a | |||
a81d599bfc | |||
7effb0016c | |||
f791862e52 | |||
b2f366b3b7 | |||
9eecb0b27f | |||
45eff4cc65 | |||
b3ffeaa22b | |||
f194d00366 | |||
b7544cccc6 | |||
894b098eb3 | |||
022ad4a420 | |||
a4f9e8180b | |||
e86b64b620 | |||
90e9c59e23 | |||
ca06af40f4 | |||
6091a954cc | |||
d27fca9301 | |||
5c89d6bffa | |||
3e6a86fb0a | |||
a7ebf5aadd | |||
b42921bbd2 | |||
722dec11b0 | |||
9e6268ba59 | |||
435f6eecd2 | |||
1c1cbba04b | |||
3b692a55a7 | |||
69a0578e00 | |||
b5ca275590 | |||
519f022b02 | |||
236a9320df | |||
28ac24444f | |||
99909bbf2c | |||
ee60bb5b36 | |||
f6120c09e7 | |||
e2bdef4cf6 | |||
8115edc82f | |||
a8b5465e24 | |||
9ce495b3d8 | |||
d40263447d | |||
31c5c1060a | |||
c9ebd60435 | |||
5a14e2238f | |||
3ceee99e22 | |||
28b23f954c | |||
ad17e5e791 | |||
c30d329faa | |||
991300b86c | |||
7c45db3a19 | |||
67cf11d071 | |||
49082d7ab2 | |||
6b627f67db | |||
5c320b4c2a | |||
ac2b04a5ab | |||
a63b764b54 | |||
2654357c72 | |||
4ec40c6ab2 | |||
80d424798e | |||
7fa2d4b503 | |||
f4845fae12 | |||
f693be3996 | |||
a73d5308e0 | |||
e1bf067090 | |||
884de18cba | |||
dfa2fb95d5 | |||
2639b4bffb | |||
978f97cc59 | |||
f1a063298e | |||
d241532488 | |||
f755db78dc | |||
5dd2b5135d | |||
7ac34e42a0 | |||
029dbf0e18 | |||
bba65e0f41 | |||
a069e08354 | |||
03d93c96a3 | |||
020338230f | |||
a1d86daa71 | |||
7078fbffb4 | |||
0aa9b46b79 | |||
831592c381 | |||
f628797d91 | |||
47f51c2ead | |||
ba9cd5bbc4 | |||
b54ad053f9 | |||
5b8eb9c5c7 | |||
0b683123d2 | |||
363498b6b4 | |||
a1bb56f739 | |||
5bb9fcad3e | |||
f4697f351e | |||
1d571b299d | |||
3a0b5a928c | |||
265ac8a106 | |||
fa7d8907d0 | |||
0220ce7002 | |||
3bd0b2ab28 | |||
a589ca0adb | |||
72f8abd7b3 | |||
20a900b648 | |||
6435ecd3c6 | |||
16d1700a8e | |||
b75cf3f70b | |||
4f19491fec | |||
8f36fd1374 | |||
2de0d4c1db | |||
5e4af7c550 | |||
8ec21fc325 | |||
eb48750705 | |||
be59c3a98c | |||
b333919722 | |||
235a235fab | |||
2d5e7d1b52 | |||
647b8595d0 | |||
0a1a397cd7 | |||
7f9b1b78f6 | |||
1e9484673d | |||
88bec238ac | |||
62e7b9da1e | |||
61341b2791 | |||
92a5876f51 | |||
a57df4ee20 | |||
92d7060cb0 | |||
7e9b120452 | |||
b081dfe705 | |||
4a4d749710 | |||
c878d55397 | |||
263a2eca88 | |||
44154e71fd | |||
0b2f7d13d0 | |||
420cc7afc6 | |||
5fc77c90cb | |||
c3484450b8 | |||
fbef94a8ee | |||
aa456edafc | |||
7007f51c35 | |||
bc1e22922a | |||
cf8d512e43 | |||
0b1f5d2127 | |||
dcf64a0d01 | |||
a9545aba4d | |||
d9ae70c699 | |||
a751649c8d | |||
3f5a3d6ea1 | |||
10a014d89e | |||
8feb8e5408 | |||
16dada28f5 | |||
67cf7128ae | |||
16e5b866d2 | |||
83d43ac850 | |||
cd25939be9 | |||
b58c3527e9 | |||
efc67ee5ef | |||
7a406a3896 | |||
98001a065d | |||
e442881ead | |||
b37cee36f9 | |||
e56de1025a | |||
64ae6d206e | |||
54a14312d1 | |||
7e95802cc1 | |||
e3e7044d06 | |||
eb3bfc25be | |||
94d769de71 | |||
66191e8a37 | |||
bec188506c | |||
4f869ff755 | |||
8f6047340e | |||
9744a1c966 | |||
0bcfae7cac | |||
140e7c00d1 | |||
941e88ff79 | |||
71ea931df5 | |||
545fdf10e2 | |||
7e928db204 | |||
cd4c0eab94 |
30
.circleci/bazel.rc
Normal file
30
.circleci/bazel.rc
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# These options are enabled when running on CI
|
||||||
|
# We do this by copying this file to /etc/bazel.bazelrc at the start of the build.
|
||||||
|
# See remote cache documentation in /docs/BAZEL.md
|
||||||
|
|
||||||
|
# Don't be spammy in the logs
|
||||||
|
build --noshow_progress
|
||||||
|
|
||||||
|
# Don't run manual tests
|
||||||
|
test --test_tag_filters=-manual
|
||||||
|
|
||||||
|
# Enable experimental CircleCI bazel remote cache proxy
|
||||||
|
# See remote cache documentation in /docs/BAZEL.md
|
||||||
|
build --experimental_remote_spawn_cache --remote_rest_cache=http://localhost:7643
|
||||||
|
|
||||||
|
# Prevent unstable environment variables from tainting cache keys
|
||||||
|
build --experimental_strict_action_env
|
||||||
|
|
||||||
|
# Save downloaded repositories such as the go toolchain
|
||||||
|
# This directory can then be included in the CircleCI cache
|
||||||
|
# It should save time running the first build
|
||||||
|
build --experimental_repository_cache=/home/circleci/bazel_repository_cache
|
||||||
|
|
||||||
|
# Workaround https://github.com/bazelbuild/bazel/issues/3645
|
||||||
|
# Bazel doesn't calculate the memory ceiling correctly when running under Docker.
|
||||||
|
# Limit Bazel to consuming resources that fit in CircleCI "xlarge" class
|
||||||
|
# https://circleci.com/docs/2.0/configuration-reference/#resource_class
|
||||||
|
build --local_resources=14336,8.0,1.0
|
||||||
|
|
||||||
|
# Retry in the event of flakes, eg. https://circleci.com/gh/angular/angular/31309
|
||||||
|
test --flaky_test_attempts=2
|
@ -13,7 +13,14 @@
|
|||||||
# If you change the `docker_image` version, also change the `cache_key` suffix and the version of
|
# If you change the `docker_image` version, also change the `cache_key` suffix and the version of
|
||||||
# `com_github_bazelbuild_buildtools` in the `/WORKSPACE` file.
|
# `com_github_bazelbuild_buildtools` in the `/WORKSPACE` file.
|
||||||
var_1: &docker_image angular/ngcontainer:0.1.0
|
var_1: &docker_image angular/ngcontainer:0.1.0
|
||||||
var_2: &cache_key angular-{{ .Branch }}-{{ checksum "yarn.lock" }}-0.1.0
|
var_2: &cache_key v2-angular-{{ .Branch }}-{{ checksum "yarn.lock" }}-0.1.0
|
||||||
|
|
||||||
|
# See remote cache documentation in /docs/BAZEL.md
|
||||||
|
var_3: &setup-bazel-remote-cache
|
||||||
|
run:
|
||||||
|
name: Start up bazel remote cache proxy
|
||||||
|
command: ~/bazel-remote-proxy -backend circleci://
|
||||||
|
background: true
|
||||||
|
|
||||||
# Settings common to each job
|
# Settings common to each job
|
||||||
anchor_1: &job_defaults
|
anchor_1: &job_defaults
|
||||||
@ -34,6 +41,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout:
|
- checkout:
|
||||||
<<: *post_checkout
|
<<: *post_checkout
|
||||||
|
|
||||||
# Check BUILD.bazel formatting before we have a node_modules directory
|
# Check BUILD.bazel formatting before we have a node_modules directory
|
||||||
# Then we don't need any exclude pattern to avoid checking those files
|
# Then we don't need any exclude pattern to avoid checking those files
|
||||||
- run: 'buildifier -mode=check $(find . -type f \( -name BUILD.bazel -or -name BUILD \)) ||
|
- run: 'buildifier -mode=check $(find . -type f \( -name BUILD.bazel -or -name BUILD \)) ||
|
||||||
@ -42,6 +50,7 @@ jobs:
|
|||||||
- run: 'find . -type f -name "*.bzl" |
|
- run: 'find . -type f -name "*.bzl" |
|
||||||
xargs java -jar /usr/local/bin/Skylint_deploy.jar ||
|
xargs java -jar /usr/local/bin/Skylint_deploy.jar ||
|
||||||
(echo -e "\n.bzl files have lint errors. Please run ''yarn skylint''"; exit 1)'
|
(echo -e "\n.bzl files have lint errors. Please run ''yarn skylint''"; exit 1)'
|
||||||
|
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: *cache_key
|
key: *cache_key
|
||||||
|
|
||||||
@ -50,30 +59,40 @@ jobs:
|
|||||||
|
|
||||||
build:
|
build:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
resource_class: large
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- checkout:
|
||||||
<<: *post_checkout
|
<<: *post_checkout
|
||||||
|
# See remote cache documentation in /docs/BAZEL.md
|
||||||
|
- run: .circleci/setup_cache.sh
|
||||||
|
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||||
|
- *setup-bazel-remote-cache
|
||||||
|
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: *cache_key
|
key: *cache_key
|
||||||
|
|
||||||
|
- run: ls /home/circleci/bazel_repository_cache || true
|
||||||
- run: bazel info release
|
- run: bazel info release
|
||||||
- run: bazel run @yarn//:yarn
|
- run: bazel run @yarn//:yarn
|
||||||
# Use bazel query so that we explicitly ask for all buildable targets to be built as well
|
# Use bazel query so that we explicitly ask for all buildable targets to be built as well
|
||||||
# This avoids waiting for a build command to finish before running the first test
|
# This avoids waiting for a build command to finish before running the first test
|
||||||
# See https://github.com/bazelbuild/bazel/issues/4257
|
# See https://github.com/bazelbuild/bazel/issues/4257
|
||||||
- run: bazel query --output=label '//modules/... union //packages/... union //tools/...' | xargs bazel test --config=ci
|
- run: bazel query --output=label '//modules/... union //packages/... union //tools/...' | xargs bazel test
|
||||||
|
|
||||||
# CircleCI will allow us to go back and view/download these artifacts from past builds.
|
# CircleCI will allow us to go back and view/download these artifacts from past builds.
|
||||||
# Also we can use a service like https://buildsize.org/ to automatically track binary size of these artifacts.
|
# Also we can use a service like https://buildsize.org/ to automatically track binary size of these artifacts.
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: dist/bin/packages/core/test/bundling/hello_world/bundle.min.js
|
path: dist/bin/packages/core/test/bundling/hello_world/bundle.min.js
|
||||||
destination: packages/core/test/bundling/hello_world/bundle.min.js
|
destination: packages/core/test/bundling/hello_world/bundle.min.js
|
||||||
|
- store_artifacts:
|
||||||
|
path: dist/bin/packages/core/test/bundling/hello_world/bundle.min.js.brotli
|
||||||
|
destination: packages/core/test/bundling/hello_world/bundle.min.js.brotli
|
||||||
|
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: *cache_key
|
key: *cache_key
|
||||||
paths:
|
paths:
|
||||||
- "node_modules"
|
- "node_modules"
|
||||||
|
- "~/bazel_repository_cache"
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
version: 2
|
version: 2
|
||||||
|
11
.circleci/setup_cache.sh
Executable file
11
.circleci/setup_cache.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Install bazel remote cache proxy
|
||||||
|
# This is temporary until the feature is no longer experimental on CircleCI.
|
||||||
|
# See remote cache documentation in /docs/BAZEL.md
|
||||||
|
|
||||||
|
set -u -e
|
||||||
|
|
||||||
|
readonly DOWNLOAD_URL="https://5-116431813-gh.circle-artifacts.com/0/pkg/bazel-remote-proxy-$(uname -s)_$(uname -m)"
|
||||||
|
|
||||||
|
curl --fail -o ~/bazel-remote-proxy "$DOWNLOAD_URL"
|
||||||
|
chmod +x ~/bazel-remote-proxy
|
2
.github/ISSUE_TEMPLATE.md
vendored
2
.github/ISSUE_TEMPLATE.md
vendored
@ -25,7 +25,7 @@ ISSUES MISSING IMPORTANT INFORMATION MAY BE CLOSED WITHOUT INVESTIGATION.
|
|||||||
## Minimal reproduction of the problem with instructions
|
## Minimal reproduction of the problem with instructions
|
||||||
<!--
|
<!--
|
||||||
For bug reports please provide the *STEPS TO REPRODUCE* and if possible a *MINIMAL DEMO* of the problem via
|
For bug reports please provide the *STEPS TO REPRODUCE* and if possible a *MINIMAL DEMO* of the problem via
|
||||||
https://plnkr.co or similar (you can use this template as a starting point: http://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5).
|
https://stackblitz.com or similar (you can use this template as a starting point: https://stackblitz.com/fork/angular-gitter).
|
||||||
-->
|
-->
|
||||||
|
|
||||||
## What is the motivation / use case for changing the behavior?
|
## What is the motivation / use case for changing the behavior?
|
||||||
|
29
.github/angular-robot.yml
vendored
29
.github/angular-robot.yml
vendored
@ -26,9 +26,7 @@ merge:
|
|||||||
# list of patterns to check for the files changed by the PR
|
# list of patterns to check for the files changed by the PR
|
||||||
# this list must be manually kept in sync with google3/third_party/javascript/angular2/copy.bara.sky
|
# this list must be manually kept in sync with google3/third_party/javascript/angular2/copy.bara.sky
|
||||||
include:
|
include:
|
||||||
- "BUILD.bazel"
|
|
||||||
- "LICENSE"
|
- "LICENSE"
|
||||||
- "WORKSPACE"
|
|
||||||
- "modules/**"
|
- "modules/**"
|
||||||
- "packages/**"
|
- "packages/**"
|
||||||
# list of patterns to ignore for the files changed by the PR
|
# list of patterns to ignore for the files changed by the PR
|
||||||
@ -36,6 +34,11 @@ merge:
|
|||||||
- "packages/language-service/**"
|
- "packages/language-service/**"
|
||||||
- "**/.gitignore"
|
- "**/.gitignore"
|
||||||
- "**/.gitkeep"
|
- "**/.gitkeep"
|
||||||
|
- "**/tsconfig-build.json"
|
||||||
|
- "**/tsconfig.json"
|
||||||
|
- "**/rollup.config.js"
|
||||||
|
- "**/BUILD.bazel"
|
||||||
|
- "packages/**/test/**"
|
||||||
|
|
||||||
# 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.
|
||||||
@ -50,13 +53,15 @@ merge:
|
|||||||
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. "PR target:" will work for the label "PR target: master")
|
||||||
requiredLabels:
|
requiredLabels:
|
||||||
- "PR target:"
|
- "PR 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"
|
- "PR target: TBD"
|
||||||
- "PR action: cleanup"
|
- "PR action: cleanup"
|
||||||
|
- "PR action: review"
|
||||||
|
- "PR state: blocked"
|
||||||
- "cla: no"
|
- "cla: no"
|
||||||
|
|
||||||
# list of PR statuses that need to be successful
|
# list of PR statuses that need to be successful
|
||||||
@ -78,15 +83,23 @@ merge:
|
|||||||
|
|
||||||
# options for the triage plugin
|
# options for the triage plugin
|
||||||
triage:
|
triage:
|
||||||
|
# number of the milestone to apply when the issue has not been triaged yet
|
||||||
|
needsTriageMilestone: 83,
|
||||||
# number of the milestone to apply when the issue is triaged
|
# number of the milestone to apply when the issue is triaged
|
||||||
defaultMilestone: 82,
|
defaultMilestone: 82,
|
||||||
# arrays of labels that determine if an issue is triaged
|
# arrays of labels that determine if an issue is triaged
|
||||||
triagedLabels:
|
triagedLabels:
|
||||||
-
|
-
|
||||||
- "type: bug"
|
- "type: bug/fix"
|
||||||
- "severity"
|
- "severity*"
|
||||||
- "freq"
|
- "freq*"
|
||||||
- "comp:"
|
- "comp: *"
|
||||||
-
|
-
|
||||||
- "type: feature"
|
- "type: feature"
|
||||||
- "comp:"
|
- "comp: *"
|
||||||
|
-
|
||||||
|
- "type: refactor"
|
||||||
|
- "comp: *"
|
||||||
|
-
|
||||||
|
- "type: RFC / Discussion / question"
|
||||||
|
- "comp: *"
|
||||||
|
@ -68,6 +68,7 @@ groups:
|
|||||||
- "packages/*"
|
- "packages/*"
|
||||||
- "tools/*"
|
- "tools/*"
|
||||||
users:
|
users:
|
||||||
|
- alexeagle
|
||||||
- IgorMinar
|
- IgorMinar
|
||||||
- mhevery
|
- mhevery
|
||||||
|
|
||||||
|
@ -56,7 +56,6 @@ env:
|
|||||||
- CI_MODE=aio
|
- CI_MODE=aio
|
||||||
- CI_MODE=aio_e2e AIO_SHARD=0
|
- CI_MODE=aio_e2e AIO_SHARD=0
|
||||||
- CI_MODE=aio_e2e AIO_SHARD=1
|
- CI_MODE=aio_e2e AIO_SHARD=1
|
||||||
- CI_MODE=bazel
|
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
|
@ -2,8 +2,16 @@ package(default_visibility = ["//visibility:public"])
|
|||||||
|
|
||||||
exports_files([
|
exports_files([
|
||||||
"tsconfig.json",
|
"tsconfig.json",
|
||||||
|
"LICENSE",
|
||||||
])
|
])
|
||||||
|
|
||||||
|
# Developers should always run `bazel run :install`
|
||||||
|
# This ensures that package.json in subdirectories get installed as well.
|
||||||
|
alias(
|
||||||
|
name = "install",
|
||||||
|
actual = "@yarn//:yarn",
|
||||||
|
)
|
||||||
|
|
||||||
# This rule belongs in node_modules/BUILD
|
# This rule belongs in node_modules/BUILD
|
||||||
# It's here as a workaround for
|
# It's here as a workaround for
|
||||||
# https://github.com/bazelbuild/bazel/issues/374#issuecomment-296217940
|
# https://github.com/bazelbuild/bazel/issues/374#issuecomment-296217940
|
||||||
@ -49,6 +57,7 @@ filegroup(
|
|||||||
"//:node_modules/zone.js/dist/async-test.js",
|
"//:node_modules/zone.js/dist/async-test.js",
|
||||||
"//:node_modules/zone.js/dist/sync-test.js",
|
"//:node_modules/zone.js/dist/sync-test.js",
|
||||||
"//:node_modules/zone.js/dist/fake-async-test.js",
|
"//:node_modules/zone.js/dist/fake-async-test.js",
|
||||||
|
"//:node_modules/zone.js/dist/task-tracking.js",
|
||||||
"//:node_modules/zone.js/dist/proxy.js",
|
"//:node_modules/zone.js/dist/proxy.js",
|
||||||
"//:node_modules/zone.js/dist/jasmine-patch.js",
|
"//:node_modules/zone.js/dist/jasmine-patch.js",
|
||||||
],
|
],
|
||||||
|
221
CHANGELOG.md
221
CHANGELOG.md
@ -1,7 +1,226 @@
|
|||||||
|
<a name="6.0.0-beta.7"></a>
|
||||||
|
# [6.0.0-beta.7](https://github.com/angular/angular/compare/6.0.0-beta.6...6.0.0-beta.7) (2018-03-07)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** fixes for ng_package on Windows ([#22597](https://github.com/angular/angular/issues/22597)) ([4c40812](https://github.com/angular/angular/commit/4c40812))
|
||||||
|
* **compiler:** allow tree-shakeable injectables to depend on string tokens ([#22376](https://github.com/angular/angular/issues/22376)) ([dd53447](https://github.com/angular/angular/commit/dd53447))
|
||||||
|
* **router:** fix URL serialization so special characters are only encoded where needed ([#22337](https://github.com/angular/angular/issues/22337)) ([fa974c7](https://github.com/angular/angular/commit/fa974c7)), closes [#10280](https://github.com/angular/angular/issues/10280)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="5.2.8"></a>
|
||||||
|
## [5.2.8](https://github.com/angular/angular/compare/5.2.7...5.2.8) (2018-03-07)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **platform-server:** generate correct stylings for camel case names ([#22263](https://github.com/angular/angular/issues/22263)) ([de02a7a](https://github.com/angular/angular/commit/de02a7a)), closes [#19235](https://github.com/angular/angular/issues/19235)
|
||||||
|
* **router:** don't mutate route configs ([#22358](https://github.com/angular/angular/issues/22358)) ([8f0a064](https://github.com/angular/angular/commit/8f0a064)), closes [#22203](https://github.com/angular/angular/issues/22203)
|
||||||
|
* **router:** fix URL serialization so special characters are only encoded where needed ([#22337](https://github.com/angular/angular/issues/22337)) ([789a47e](https://github.com/angular/angular/commit/789a47e)), closes [#10280](https://github.com/angular/angular/issues/10280)
|
||||||
|
* **upgrade:** correctly destroy nested downgraded component ([#22400](https://github.com/angular/angular/issues/22400)) ([4aef9de](https://github.com/angular/angular/commit/4aef9de)), closes [#22392](https://github.com/angular/angular/issues/22392)
|
||||||
|
* **upgrade:** correctly handle `=` bindings in `[@angular](https://github.com/angular)/upgrade` ([#22167](https://github.com/angular/angular/issues/22167)) ([6638390](https://github.com/angular/angular/commit/6638390))
|
||||||
|
* **upgrade:** fix empty transclusion content with AngularJS@>=1.5.8 ([#22167](https://github.com/angular/angular/issues/22167)) ([a9a0e27](https://github.com/angular/angular/commit/a9a0e27)), closes [#22175](https://github.com/angular/angular/issues/22175)
|
||||||
|
|
||||||
|
|
||||||
|
<a name="6.0.0-beta.6"></a>
|
||||||
|
# [6.0.0-beta.6](https://github.com/angular/angular/compare/6.0.0-beta.5...6.0.0-beta.6) (2018-02-28)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **animations:** only use the WA-polyfill alongside AnimationBuilder ([#22143](https://github.com/angular/angular/issues/22143)) ([b2f366b](https://github.com/angular/angular/commit/b2f366b)), closes [#17496](https://github.com/angular/angular/issues/17496)
|
||||||
|
* **animations:** report correct totalTime value even during noOp animations ([#22225](https://github.com/angular/angular/issues/22225)) ([e1bf067](https://github.com/angular/angular/commit/e1bf067))
|
||||||
|
* **bazel:** ng_package includes transitive .d.ts and flatModuleMetadata ([#22499](https://github.com/angular/angular/issues/22499)) ([aabe16c](https://github.com/angular/angular/commit/aabe16c)), closes [#22419](https://github.com/angular/angular/issues/22419)
|
||||||
|
* **common:** correct mapping of Observable methods ([#20518](https://github.com/angular/angular/issues/20518)) ([2639b4b](https://github.com/angular/angular/commit/2639b4b)), closes [#20516](https://github.com/angular/angular/issues/20516)
|
||||||
|
* **common:** then and else template might be set to null ([#22298](https://github.com/angular/angular/issues/22298)) ([8115edc](https://github.com/angular/angular/commit/8115edc))
|
||||||
|
* **compiler-cli:** add missing entry point to package, update tsickle ([#22295](https://github.com/angular/angular/issues/22295)) ([28ac244](https://github.com/angular/angular/commit/28ac244))
|
||||||
|
* **core:** export inject() from [@angular](https://github.com/angular)/core ([#22389](https://github.com/angular/angular/issues/22389)) ([f8749bf](https://github.com/angular/angular/commit/f8749bf)), closes [#22388](https://github.com/angular/angular/issues/22388)
|
||||||
|
* **core:** properly handle function without prototype in reflector ([#22284](https://github.com/angular/angular/issues/22284)) ([a7ebf5a](https://github.com/angular/angular/commit/a7ebf5a)), closes [#19978](https://github.com/angular/angular/issues/19978)
|
||||||
|
* **core:** require factory to be provided for shakeable InjectionToken ([#22207](https://github.com/angular/angular/issues/22207)) ([f755db7](https://github.com/angular/angular/commit/f755db7)), closes [#22205](https://github.com/angular/angular/issues/22205)
|
||||||
|
* **forms:** set state before emitting a value from ngModelChange ([#21514](https://github.com/angular/angular/issues/21514)) ([3e6a86f](https://github.com/angular/angular/commit/3e6a86f)), closes [#21513](https://github.com/angular/angular/issues/21513)
|
||||||
|
* **platform-server:** generate correct stylings for camel case names ([#22263](https://github.com/angular/angular/issues/22263)) ([40ba009](https://github.com/angular/angular/commit/40ba009)), closes [#19235](https://github.com/angular/angular/issues/19235)
|
||||||
|
* **router:** don't mutate route configs ([#22358](https://github.com/angular/angular/issues/22358)) ([45eff4c](https://github.com/angular/angular/commit/45eff4c)), closes [#22203](https://github.com/angular/angular/issues/22203)
|
||||||
|
* **router:** fix URL serialization so special characters are only encoded where needed ([#22337](https://github.com/angular/angular/issues/22337)) ([094666d](https://github.com/angular/angular/commit/094666d)), closes [#10280](https://github.com/angular/angular/issues/10280)
|
||||||
|
* **upgrade:** correctly destroy nested downgraded component ([#22400](https://github.com/angular/angular/issues/22400)) ([8a85888](https://github.com/angular/angular/commit/8a85888)), closes [#22392](https://github.com/angular/angular/issues/22392)
|
||||||
|
* **upgrade:** correctly handle `=` bindings in `[@angular](https://github.com/angular)/upgrade` ([#22167](https://github.com/angular/angular/issues/22167)) ([f089bf5](https://github.com/angular/angular/commit/f089bf5))
|
||||||
|
* **upgrade:** fix empty transclusion content with AngularJS@>=1.5.8 ([#22167](https://github.com/angular/angular/issues/22167)) ([13ab91e](https://github.com/angular/angular/commit/13ab91e)), closes [#22175](https://github.com/angular/angular/issues/22175)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **bazel:** add an ng_package rule ([#22221](https://github.com/angular/angular/issues/22221)) ([b43b164](https://github.com/angular/angular/commit/b43b164))
|
||||||
|
* **bazel:** introduce a binary stamping feature ([#22176](https://github.com/angular/angular/issues/22176)) ([bba65e0](https://github.com/angular/angular/commit/bba65e0))
|
||||||
|
* **bazel:** ng_module produces bundle index ([#22176](https://github.com/angular/angular/issues/22176)) ([029dbf0](https://github.com/angular/angular/commit/029dbf0))
|
||||||
|
* **bazel:** ng_package adds package.json props ([#22499](https://github.com/angular/angular/issues/22499)) ([b6c9410](https://github.com/angular/angular/commit/b6c9410)), closes [#22416](https://github.com/angular/angular/issues/22416)
|
||||||
|
* **common:** better error message when non-template element used in NgIf ([#22274](https://github.com/angular/angular/issues/22274)) ([67cf11d](https://github.com/angular/angular/commit/67cf11d)), closes [#16410](https://github.com/angular/angular/issues/16410)
|
||||||
|
* **common:** export functions to format numbers, percents, currencies & dates ([#22423](https://github.com/angular/angular/issues/22423)) ([4180912](https://github.com/angular/angular/commit/4180912)), closes [#20536](https://github.com/angular/angular/issues/20536)
|
||||||
|
* **compiler-cli:** Check unvalidated combination of ngc and TypeScript ([#22293](https://github.com/angular/angular/issues/22293)) ([3ceee99](https://github.com/angular/angular/commit/3ceee99)), closes [#20669](https://github.com/angular/angular/issues/20669)
|
||||||
|
* **core:** set preserveWhitespaces to false by default ([#22046](https://github.com/angular/angular/issues/22046)) ([f1a0632](https://github.com/angular/angular/commit/f1a0632)), closes [#22027](https://github.com/angular/angular/issues/22027)
|
||||||
|
* **core:** support metadata reflection for native class types ([#22356](https://github.com/angular/angular/issues/22356)) ([5c89d6b](https://github.com/angular/angular/commit/5c89d6b)), closes [#21731](https://github.com/angular/angular/issues/21731)
|
||||||
|
* **core:** support metadata reflection for native class types ([#22356](https://github.com/angular/angular/issues/22356)) ([b7544cc](https://github.com/angular/angular/commit/b7544cc)), closes [#21731](https://github.com/angular/angular/issues/21731)
|
||||||
|
* **forms:** allow markAsPending to emit events ([#20212](https://github.com/angular/angular/issues/20212)) ([e86b64b](https://github.com/angular/angular/commit/e86b64b)), closes [#17958](https://github.com/angular/angular/issues/17958)
|
||||||
|
* allow direct scoping of @Injectables to the root injector ([#22185](https://github.com/angular/angular/issues/22185)) ([7ac34e4](https://github.com/angular/angular/commit/7ac34e4))
|
||||||
|
* **platform-browser:** do not throw error when Hammer.js not loaded ([#22257](https://github.com/angular/angular/issues/22257)) ([991300b](https://github.com/angular/angular/commit/991300b)), closes [#16992](https://github.com/angular/angular/issues/16992)
|
||||||
|
* **platform-browser:** fix [#19604](https://github.com/angular/angular/issues/19604), can config hammerOptions ([#21979](https://github.com/angular/angular/issues/21979)) ([1d571b2](https://github.com/angular/angular/commit/1d571b2))
|
||||||
|
* **platform-server:** bump Domino to v2.0 ([#22411](https://github.com/angular/angular/issues/22411)) ([d3827a0](https://github.com/angular/angular/commit/d3827a0))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* **platform-server:** * Bump the dependency on Domino to 2.0 to resolve issues with
|
||||||
|
namespacing
|
||||||
|
* **forms:** - `AbstractControl#statusChanges` now emits an event of `'PENDING'` when you call `AbstractControl#markAsPending`
|
||||||
|
- Previously it did not emit an event when you called `markAsPending`
|
||||||
|
- To migrate you would need to ensure that if you are filtering or checking events from `statusChanges` that you account for the new event when calling `markAsPending`
|
||||||
|
* **animations:** When animation is trigged within a disabled zone, the
|
||||||
|
associated event (which an instance of AnimationEvent) will no longer
|
||||||
|
report the totalTime as 0 (it will emit the actual time of the
|
||||||
|
animation). To detect if an animation event is reporting a disabled
|
||||||
|
animation then the `event.disabled` property can be used instead.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="5.2.7"></a>
|
||||||
|
## [5.2.7](https://github.com/angular/angular/compare/5.2.6...5.2.7) (2018-02-28)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **platform-server:** generate correct stylings for camel case names ([#22263](https://github.com/angular/angular/issues/22263)) ([de02a7a](https://github.com/angular/angular/commit/de02a7a)), closes [#19235](https://github.com/angular/angular/issues/19235)
|
||||||
|
* **router:** don't mutate route configs ([#22358](https://github.com/angular/angular/issues/22358)) ([8f0a064](https://github.com/angular/angular/commit/8f0a064)), closes [#22203](https://github.com/angular/angular/issues/22203)
|
||||||
|
* **upgrade:** correctly destroy nested downgraded component ([#22400](https://github.com/angular/angular/issues/22400)) ([4aef9de](https://github.com/angular/angular/commit/4aef9de)), closes [#22392](https://github.com/angular/angular/issues/22392)
|
||||||
|
* **upgrade:** correctly handle `=` bindings in `[@angular](https://github.com/angular)/upgrade` ([#22167](https://github.com/angular/angular/issues/22167)) ([6638390](https://github.com/angular/angular/commit/6638390))
|
||||||
|
* **upgrade:** fix empty transclusion content with AngularJS@>=1.5.8 ([#22167](https://github.com/angular/angular/issues/22167)) ([a9a0e27](https://github.com/angular/angular/commit/a9a0e27)), closes [#22175](https://github.com/angular/angular/issues/22175)
|
||||||
|
|
||||||
|
<a name="6.0.0-beta.5"></a>
|
||||||
|
# [6.0.0-beta.5](https://github.com/angular/angular/compare/6.0.0-beta.4...6.0.0-beta.5) (2018-02-22)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **animations:** report correct totalTime value even during noOp animations ([#22225](https://github.com/angular/angular/issues/22225)) ([e1bf067](https://github.com/angular/angular/commit/e1bf067))
|
||||||
|
* **common:** correct mapping of Observable methods ([#20518](https://github.com/angular/angular/issues/20518)) ([2639b4b](https://github.com/angular/angular/commit/2639b4b)), closes [#20516](https://github.com/angular/angular/issues/20516)
|
||||||
|
* **common:** then and else template might be set to null ([#22298](https://github.com/angular/angular/issues/22298)) ([8115edc](https://github.com/angular/angular/commit/8115edc))
|
||||||
|
* **compiler-cli:** add missing entry point to package, update tsickle ([#22295](https://github.com/angular/angular/issues/22295)) ([28ac244](https://github.com/angular/angular/commit/28ac244))
|
||||||
|
* **core:** properly handle function without prototype in reflector ([#22284](https://github.com/angular/angular/issues/22284)) ([a7ebf5a](https://github.com/angular/angular/commit/a7ebf5a)), closes [#19978](https://github.com/angular/angular/issues/19978)
|
||||||
|
* **core:** require factory to be provided for shakeable InjectionToken ([#22207](https://github.com/angular/angular/issues/22207)) ([f755db7](https://github.com/angular/angular/commit/f755db7)), closes [#22205](https://github.com/angular/angular/issues/22205)
|
||||||
|
* **forms:** set state before emitting a value from ngModelChange ([#21514](https://github.com/angular/angular/issues/21514)) ([3e6a86f](https://github.com/angular/angular/commit/3e6a86f)), closes [#21513](https://github.com/angular/angular/issues/21513)
|
||||||
|
* **core:** set `preserveWhitespaces` to false by default ([#22046](https://github.com/angular/angular/issues/22046)) ([f1a0632](https://github.com/angular/angular/commit/f1a0632)), closes [#22027](https://github.com/angular/angular/issues/22027)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **common:** better error message when non-template element used in NgIf ([#22274](https://github.com/angular/angular/issues/22274)) ([67cf11d](https://github.com/angular/angular/commit/67cf11d)), closes [#16410](https://github.com/angular/angular/issues/16410)
|
||||||
|
* **compiler-cli:** Check unvalidated combination of ngc and TypeScript ([#22293](https://github.com/angular/angular/issues/22293)) ([3ceee99](https://github.com/angular/angular/commit/3ceee99)), closes [#20669](https://github.com/angular/angular/issues/20669)
|
||||||
|
* **core:** support metadata reflection for native class types ([#22356](https://github.com/angular/angular/issues/22356)) ([5c89d6b](https://github.com/angular/angular/commit/5c89d6b)), closes [#21731](https://github.com/angular/angular/issues/21731)
|
||||||
|
* **platform-browser:** do not throw error when Hammer.js not loaded ([#22257](https://github.com/angular/angular/issues/22257)) ([991300b](https://github.com/angular/angular/commit/991300b)), closes [#16992](https://github.com/angular/angular/issues/16992)
|
||||||
|
* **platform-browser:** fix [#19604](https://github.com/angular/angular/issues/19604), can config hammerOptions ([#21979](https://github.com/angular/angular/issues/21979)) ([1d571b2](https://github.com/angular/angular/commit/1d571b2))
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* **animations:** When animation is triggered within a disabled zone, the
|
||||||
|
associated event (which an instance of AnimationEvent) will no longer
|
||||||
|
report the totalTime as 0 (it will emit the actual time of the
|
||||||
|
animation). To detect if an animation event is reporting a disabled
|
||||||
|
animation then the `event.disabled` property can be used instead.
|
||||||
|
|
||||||
|
* **forms:** ngModelChange is now emitted after the value/validity is updated on its control.
|
||||||
|
|
||||||
|
Previously, ngModelChange was emitted before its underlying control was updated.
|
||||||
|
This was fine if you passed through the value directly through the $event keyword, e.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
<input [(ngModel)]="name" (ngModelChange)="onChange($event)">
|
||||||
|
|
||||||
|
onChange(value) {
|
||||||
|
console.log(value); // would log updated value
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
However, if you had a handler for the ngModelChange event that checked the value through the control,
|
||||||
|
you would get the old value rather than the updated value. e.g:
|
||||||
|
|
||||||
|
```
|
||||||
|
<input #modelDir="ngModel" [(ngModel)]="name" (ngModelChange)="onChange(modelDir)">
|
||||||
|
|
||||||
|
onChange(ngModel: NgModel) {
|
||||||
|
console.log(ngModel.value); // would log old value, not updated value
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Now the value and validity will be updated before the ngModelChange event is emitted,
|
||||||
|
so the same setup will log the updated value.
|
||||||
|
|
||||||
|
```
|
||||||
|
onChange(ngModel: NgModel) {
|
||||||
|
console.log(ngModel.value); // will log updated value
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
We think this order will be less confusing when the control is checked directly.
|
||||||
|
You will only need to update your app if it has relied on this bug to keep track of the old control value.
|
||||||
|
If that is the case, you should be able to track the old value directly by saving it on your component.
|
||||||
|
|
||||||
|
<a name="5.2.6"></a>
|
||||||
|
## [5.2.6](https://github.com/angular/angular/compare/5.2.5...5.2.6) (2018-02-22)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **common:** correct mapping of Observable methods ([#20518](https://github.com/angular/angular/issues/20518)) ([ce5e8fa](https://github.com/angular/angular/commit/ce5e8fa)), closes [#20516](https://github.com/angular/angular/issues/20516)
|
||||||
|
* **common:** then and else template might be set to null ([#22298](https://github.com/angular/angular/issues/22298)) ([af6a056](https://github.com/angular/angular/commit/af6a056))
|
||||||
|
* **compiler-cli:** add missing entry point to package, update tsickle ([#22295](https://github.com/angular/angular/issues/22295)) ([c5418c7](https://github.com/angular/angular/commit/c5418c7))
|
||||||
|
* **core:** properly handle function without prototype in reflector ([#22284](https://github.com/angular/angular/issues/22284)) ([5ec38f2](https://github.com/angular/angular/commit/5ec38f2)), closes [#19978](https://github.com/angular/angular/issues/19978)
|
||||||
|
* **core:** support metadata reflection for native class types ([#22356](https://github.com/angular/angular/issues/22356)) ([ee91de9](https://github.com/angular/angular/commit/ee91de9)), closes [#21731](https://github.com/angular/angular/issues/21731)
|
||||||
|
|
||||||
|
<a name="6.0.0-beta.4"></a>
|
||||||
|
# [6.0.0-beta.4](https://github.com/angular/angular/compare/6.0.0-beta.3...6.0.0-beta.4) (2018-02-14)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** allow TS to read ambient typings ([#21876](https://github.com/angular/angular/issues/21876)) ([b081dfe](https://github.com/angular/angular/commit/b081dfe)), closes [#21872](https://github.com/angular/angular/issues/21872)
|
||||||
|
* **bazel:** improve error message for missing assets ([#22096](https://github.com/angular/angular/issues/22096)) ([dcf64a0](https://github.com/angular/angular/commit/dcf64a0)), closes [#22095](https://github.com/angular/angular/issues/22095)
|
||||||
|
* **common:** add locale currency values ([#21783](https://github.com/angular/angular/issues/21783)) ([420cc7a](https://github.com/angular/angular/commit/420cc7a)), closes [#20385](https://github.com/angular/angular/issues/20385)
|
||||||
|
* **common:** round currencies based on decimal digits in `CurrencyPipe` ([#21783](https://github.com/angular/angular/issues/21783)) ([44154e7](https://github.com/angular/angular/commit/44154e7)), closes [#10189](https://github.com/angular/angular/issues/10189)
|
||||||
|
* **common:** weaken AsyncPipe transform signature ([#22169](https://github.com/angular/angular/issues/22169)) ([be59c3a](https://github.com/angular/angular/commit/be59c3a))
|
||||||
|
* **compiler:** make unary plus operator consistent to JavaScript ([#22154](https://github.com/angular/angular/issues/22154)) ([72f8abd](https://github.com/angular/angular/commit/72f8abd)), closes [#22089](https://github.com/angular/angular/issues/22089)
|
||||||
|
* **core:** add stacktrace in log when error during cleanup component in TestBed ([#22162](https://github.com/angular/angular/issues/22162)) ([16d1700](https://github.com/angular/angular/commit/16d1700))
|
||||||
|
* **core:** ensure initial value of QueryList length ([#21980](https://github.com/angular/angular/issues/21980)) ([#21982](https://github.com/angular/angular/issues/21982)) ([e56de10](https://github.com/angular/angular/commit/e56de10)), closes [#21980](https://github.com/angular/angular/issues/21980)
|
||||||
|
* **core:** use appropriate inert document strategy for Firefox & Safari ([#17019](https://github.com/angular/angular/issues/17019)) ([a751649](https://github.com/angular/angular/commit/a751649))
|
||||||
|
* **forms:** make Validators.email support optional controls ([#20869](https://github.com/angular/angular/issues/20869)) ([140e7c0](https://github.com/angular/angular/commit/140e7c0))
|
||||||
|
* **forms:** prevent event emission on enable/disable when emitEvent is false ([#12366](https://github.com/angular/angular/issues/12366)) ([#21018](https://github.com/angular/angular/issues/21018)) ([0bcfae7](https://github.com/angular/angular/commit/0bcfae7))
|
||||||
|
* **forms:** set state before emitting a value from ngModelChange ([#21514](https://github.com/angular/angular/issues/21514)) ([9744a1c](https://github.com/angular/angular/commit/9744a1c)), closes [#21513](https://github.com/angular/angular/issues/21513)
|
||||||
|
* **language-service:** correct instructions to install the language service ([#22000](https://github.com/angular/angular/issues/22000)) ([b37cee3](https://github.com/angular/angular/commit/b37cee3))
|
||||||
|
* **platform-browser:** add @Injectable where it was missing ([#22005](https://github.com/angular/angular/issues/22005)) ([0a1a397](https://github.com/angular/angular/commit/0a1a397))
|
||||||
|
* **platform-browser:** support 0/false/null values in transfer_state ([#22179](https://github.com/angular/angular/issues/22179)) ([6435ecd](https://github.com/angular/angular/commit/6435ecd))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **bazel:** allow explicit specification of factories ([#22003](https://github.com/angular/angular/issues/22003)) ([e442881](https://github.com/angular/angular/commit/e442881))
|
||||||
|
* **compiler:** mark @NgModules in provider lists for identification at runtime ([#22005](https://github.com/angular/angular/issues/22005)) ([2d5e7d1](https://github.com/angular/angular/commit/2d5e7d1))
|
||||||
|
* **forms:** multiple validators for array method ([#20766](https://github.com/angular/angular/issues/20766)) ([941e88f](https://github.com/angular/angular/commit/941e88f)), closes [#20665](https://github.com/angular/angular/issues/20665)
|
||||||
|
* change @Injectable() to support tree-shakeable tokens ([#22005](https://github.com/angular/angular/issues/22005)) ([235a235](https://github.com/angular/angular/commit/235a235))
|
||||||
|
|
||||||
|
<a name="5.2.5"></a>
|
||||||
|
## [5.2.5](https://github.com/angular/angular/compare/5.2.4...5.2.5) (2018-02-14)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **aio:** update Firebase redirects and SW routes ([#21763](https://github.com/angular/angular/pull/21763)) ([#22104](https://github.com/angular/angular/pull/22104)) ([15ff7ba](https://github.com/angular/angular/commit/15ff7ba)), closes [#21377](https://github.com/angular/angular/issues/21377)
|
||||||
|
* **bazel:** allow TS to read ambient typings ([#21876](https://github.com/angular/angular/issues/21876)) ([d57fd0b](https://github.com/angular/angular/commit/d57fd0b)), closes [#21872](https://github.com/angular/angular/issues/21872)
|
||||||
|
* **bazel:** improve error message for missing assets ([#22096](https://github.com/angular/angular/issues/22096)) ([c5ec8d9](https://github.com/angular/angular/commit/c5ec8d9)), closes [#22095](https://github.com/angular/angular/issues/22095)
|
||||||
|
* **common:** weaken AsyncPipe transform signature ([#22169](https://github.com/angular/angular/issues/22169)) ([c6bdc83](https://github.com/angular/angular/commit/c6bdc83))
|
||||||
|
* **compiler:** make unary plus operator consistent to JavaScript ([#22154](https://github.com/angular/angular/issues/22154)) ([1b8ea10](https://github.com/angular/angular/commit/1b8ea10)), closes [#22089](https://github.com/angular/angular/issues/22089)
|
||||||
|
* **core:** add stacktrace in log when error during cleanup component in TestBed ([#22162](https://github.com/angular/angular/issues/22162)) ([c4f841f](https://github.com/angular/angular/commit/c4f841f))
|
||||||
|
* **core:** ensure initial value of QueryList length ([#21980](https://github.com/angular/angular/issues/21980)) ([#21982](https://github.com/angular/angular/issues/21982)) ([47b73fd](https://github.com/angular/angular/commit/47b73fd)), closes [#21980](https://github.com/angular/angular/issues/21980)
|
||||||
|
* **core:** use appropriate inert document strategy for Firefox & Safari ([#17019](https://github.com/angular/angular/issues/17019)) ([47b71d9](https://github.com/angular/angular/commit/47b71d9))
|
||||||
|
* **forms:** prevent event emission on enable/disable when emitEvent is false ([#12366](https://github.com/angular/angular/issues/12366)) ([#21018](https://github.com/angular/angular/issues/21018)) ([56b9591](https://github.com/angular/angular/commit/56b9591))
|
||||||
|
* **language-service:** correct instructions to install the language service ([#22000](https://github.com/angular/angular/issues/22000)) ([0b23573](https://github.com/angular/angular/commit/0b23573))
|
||||||
|
* **platform-browser:** support 0/false/null values in transfer_state ([#22179](https://github.com/angular/angular/issues/22179)) ([da6ab91](https://github.com/angular/angular/commit/da6ab91))
|
||||||
|
|
||||||
<a name="6.0.0-beta.3"></a>
|
<a name="6.0.0-beta.3"></a>
|
||||||
# [6.0.0-beta.3](https://github.com/angular/angular/compare/6.0.0-beta.2...6.0.0-beta.3) (2018-02-07)
|
# [6.0.0-beta.3](https://github.com/angular/angular/compare/6.0.0-beta.2...6.0.0-beta.3) (2018-02-07)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **common:** don't convert null to a string when flushing a mock request ([#21417](https://github.com/angular/angular/issues/21417)) ([8b14488](https://github.com/angular/angular/commit/8b14488)), closes [#20744](https://github.com/angular/angular/issues/20744)
|
* **common:** don't convert null to a string when flushing a mock request ([#21417](https://github.com/angular/angular/issues/21417)) ([8b14488](https://github.com/angular/angular/commit/8b14488)), closes [#20744](https://github.com/angular/angular/issues/20744)
|
||||||
|
12
CODE_OF_CONDUCT.md
Normal file
12
CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Contributor Code of Conduct
|
||||||
|
## Version 0.3b-angular
|
||||||
|
|
||||||
|
As contributors and maintainers of the Angular project, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities.
|
||||||
|
|
||||||
|
Communication through any of Angular's channels (GitHub, Gitter, IRC, mailing lists, Google+, Twitter, etc.) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
||||||
|
|
||||||
|
We promise to extend courtesy and respect to everyone involved in this project regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to the Angular project to do the same.
|
||||||
|
|
||||||
|
If any member of the community violates this code of conduct, the maintainers of the Angular project may take action, removing issues, comments, and PRs or blocking accounts as deemed appropriate.
|
||||||
|
|
||||||
|
If you are subject to or witness unacceptable behavior, or have any other concerns, please email us at [conduct@angular.io](mailto:conduct@angular.io).
|
@ -51,7 +51,7 @@ and help you to craft the change so that it is successfully accepted into the pr
|
|||||||
|
|
||||||
Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available.
|
Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available.
|
||||||
|
|
||||||
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs we will systematically ask you to provide a minimal reproduction scenario using http://plnkr.co. Having a live, reproducible scenario gives us wealth of important information without going back & forth to you with additional questions like:
|
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs, we will systematically ask you to provide a minimal reproduction scenario using http://plnkr.co. Having a live, reproducible scenario gives us a wealth of important information without going back & forth to you with additional questions like:
|
||||||
|
|
||||||
- version of Angular used
|
- version of Angular used
|
||||||
- 3rd-party libraries and their versions
|
- 3rd-party libraries and their versions
|
||||||
@ -61,7 +61,7 @@ A minimal reproduce scenario using http://plnkr.co/ allows us to quickly confirm
|
|||||||
|
|
||||||
We will be insisting on a minimal reproduce scenario in order to save maintainers time and ultimately be able to fix more bugs. Interestingly, from our experience users often find coding problems themselves while preparing a minimal plunk. We understand that sometimes it might be hard to extract essentials bits of code from a larger code-base but we really need to isolate the problem before we can fix it.
|
We will be insisting on a minimal reproduce scenario in order to save maintainers time and ultimately be able to fix more bugs. Interestingly, from our experience users often find coding problems themselves while preparing a minimal plunk. We understand that sometimes it might be hard to extract essentials bits of code from a larger code-base but we really need to isolate the problem before we can fix it.
|
||||||
|
|
||||||
Unfortunately we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you we are going to close an issue that don't have enough info to be reproduced.
|
Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you we are going to close an issue that doesn't have enough info to be reproduced.
|
||||||
|
|
||||||
You can file new issues by filling out our [new issue form](https://github.com/angular/angular/issues/new).
|
You can file new issues by filling out our [new issue form](https://github.com/angular/angular/issues/new).
|
||||||
|
|
||||||
@ -173,12 +173,12 @@ The **header** is mandatory and the **scope** of the header is optional.
|
|||||||
Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
|
Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
|
||||||
to read on GitHub as well as in various git tools.
|
to read on GitHub as well as in various git tools.
|
||||||
|
|
||||||
Footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.
|
The footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.
|
||||||
|
|
||||||
Samples: (even more [samples](https://github.com/angular/angular/commits/master))
|
Samples: (even more [samples](https://github.com/angular/angular/commits/master))
|
||||||
|
|
||||||
```
|
```
|
||||||
docs(changelog): update change log to beta.5
|
docs(changelog): update changelog to beta.5
|
||||||
```
|
```
|
||||||
```
|
```
|
||||||
fix(release): need to depend on latest rxjs and zone.js
|
fix(release): need to depend on latest rxjs and zone.js
|
||||||
@ -203,7 +203,7 @@ Must be one of the following:
|
|||||||
* **test**: Adding missing tests or correcting existing tests
|
* **test**: Adding missing tests or correcting existing tests
|
||||||
|
|
||||||
### Scope
|
### Scope
|
||||||
The scope should be the name of the npm package affected (as perceived by person reading changelog generated from commit messages.
|
The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages.
|
||||||
|
|
||||||
The following is the list of supported scopes:
|
The following is the list of supported scopes:
|
||||||
|
|
||||||
@ -232,10 +232,10 @@ There are currently a few exceptions to the "use package name" rule:
|
|||||||
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all packages (e.g. `style: add missing semicolons`)
|
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all packages (e.g. `style: add missing semicolons`)
|
||||||
|
|
||||||
### Subject
|
### Subject
|
||||||
The subject contains succinct description of the change:
|
The subject contains a succinct description of the change:
|
||||||
|
|
||||||
* use the imperative, present tense: "change" not "changed" nor "changes"
|
* use the imperative, present tense: "change" not "changed" nor "changes"
|
||||||
* don't capitalize first letter
|
* don't capitalize the first letter
|
||||||
* no dot (.) at the end
|
* no dot (.) at the end
|
||||||
|
|
||||||
### Body
|
### Body
|
||||||
@ -266,7 +266,7 @@ changes to be accepted, the CLA must be signed. It's a quick process, we promise
|
|||||||
* https://help.github.com/articles/setting-your-commit-email-address-in-git/
|
* https://help.github.com/articles/setting-your-commit-email-address-in-git/
|
||||||
* https://stackoverflow.com/questions/37245303/what-does-usera-committed-with-userb-13-days-ago-on-github-mean
|
* https://stackoverflow.com/questions/37245303/what-does-usera-committed-with-userb-13-days-ago-on-github-mean
|
||||||
* https://help.github.com/articles/about-commit-email-addresses/
|
* https://help.github.com/articles/about-commit-email-addresses/
|
||||||
* https://help.github.com/articles/blocking-command-line-pushes-that-expose-your-personal-email-address/
|
* https://help.github.com/articles/blocking-command-line-pushes-that-expose-your-personal-email-address/
|
||||||
|
|
||||||
Note that if you have more than one Git identity, it is important to verify that you are logged in with the same ID with which you signed the CLA, before you commit changes. If not, your PR will fail the CLA check.
|
Note that if you have more than one Git identity, it is important to verify that you are logged in with the same ID with which you signed the CLA, before you commit changes. If not, your PR will fail the CLA check.
|
||||||
|
|
||||||
|
50
WORKSPACE
50
WORKSPACE
@ -1,22 +1,25 @@
|
|||||||
workspace(name = "angular")
|
workspace(name = "angular")
|
||||||
|
|
||||||
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
|
http_archive(
|
||||||
|
|
||||||
git_repository(
|
|
||||||
name = "build_bazel_rules_nodejs",
|
name = "build_bazel_rules_nodejs",
|
||||||
remote = "https://github.com/bazelbuild/rules_nodejs.git",
|
url = "https://github.com/bazelbuild/rules_nodejs/archive/f03c8b5df155da2a640b6775afdd4fe4aa6fec72.zip",
|
||||||
commit = "5307b572d86a0764bd86a5681fc72cca016e9390",
|
strip_prefix = "rules_nodejs-f03c8b5df155da2a640b6775afdd4fe4aa6fec72",
|
||||||
|
sha256 = "9d541f49af8cf60c73efb102186bfa5670ee190a088ce52638dcdf90cd9e2de6",
|
||||||
)
|
)
|
||||||
|
|
||||||
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories")
|
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories")
|
||||||
|
|
||||||
check_bazel_version("0.9.0")
|
check_bazel_version("0.9.0")
|
||||||
node_repositories(package_json = ["//:package.json"])
|
node_repositories(package_json = [
|
||||||
|
"//:package.json",
|
||||||
|
"//tools/ts-api-guardian:package.json",
|
||||||
|
])
|
||||||
|
|
||||||
git_repository(
|
http_archive(
|
||||||
name = "build_bazel_rules_typescript",
|
name = "build_bazel_rules_typescript",
|
||||||
remote = "https://github.com/bazelbuild/rules_typescript.git",
|
url = "https://github.com/bazelbuild/rules_typescript/archive/0.11.1.zip",
|
||||||
commit = "eb3244363e1cb265c84e723b347926f28c29aa35"
|
strip_prefix = "rules_typescript-0.11.1",
|
||||||
|
sha256 = "7406bea7954e1c906f075115dfa176551a881119f6820b126ea1eacb09f34a1a",
|
||||||
)
|
)
|
||||||
|
|
||||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")
|
load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")
|
||||||
@ -28,13 +31,16 @@ local_repository(
|
|||||||
path = "node_modules/rxjs/src",
|
path = "node_modules/rxjs/src",
|
||||||
)
|
)
|
||||||
|
|
||||||
git_repository(
|
# This commit matches the version of buildifier in angular/ngcontainer
|
||||||
|
# If you change this, also check if it matches the version in the angular/ngcontainer
|
||||||
|
# version in /.circleci/config.yml
|
||||||
|
BAZEL_BUILDTOOLS_VERSION = "b3b620e8bcff18ed3378cd3f35ebeb7016d71f71"
|
||||||
|
|
||||||
|
http_archive(
|
||||||
name = "com_github_bazelbuild_buildtools",
|
name = "com_github_bazelbuild_buildtools",
|
||||||
remote = "https://github.com/bazelbuild/buildtools.git",
|
url = "https://github.com/bazelbuild/buildtools/archive/%s.zip" % BAZEL_BUILDTOOLS_VERSION,
|
||||||
# Note, this commit matches the version of buildifier in angular/ngcontainer
|
strip_prefix = "buildtools-%s" % BAZEL_BUILDTOOLS_VERSION,
|
||||||
# If you change this, also check if it matches the version in the angular/ngcontainer
|
sha256 = "dad19224258ed67cbdbae9b7befb785c3b966e5a33b04b3ce58ddb7824b97d73",
|
||||||
# version in /.circleci/config.yml
|
|
||||||
commit = "b3b620e8bcff18ed3378cd3f35ebeb7016d71f71",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
http_archive(
|
http_archive(
|
||||||
@ -63,8 +69,16 @@ http_archive(
|
|||||||
# re-packaging or "npm link"ing.
|
# re-packaging or "npm link"ing.
|
||||||
# Even better, things like aspects will visit the entire graph including
|
# Even better, things like aspects will visit the entire graph including
|
||||||
# ts_library rules in the devkit repository.
|
# ts_library rules in the devkit repository.
|
||||||
git_repository(
|
http_archive(
|
||||||
name = "angular_devkit",
|
name = "angular_devkit",
|
||||||
remote = "https://github.com/angular/devkit.git",
|
url = "https://github.com/angular/devkit/archive/v0.3.1.zip",
|
||||||
commit = "69fcdee61c5ff3f08aa609dec69155dfd29c809a",
|
strip_prefix = "devkit-0.3.1",
|
||||||
|
sha256 = "31d4b597fe9336650acf13df053c1c84dcbe9c29c6a833bcac3819cd3fd8cad3",
|
||||||
|
)
|
||||||
|
|
||||||
|
http_archive(
|
||||||
|
name = "org_brotli",
|
||||||
|
url = "https://github.com/google/brotli/archive/v1.0.2.zip",
|
||||||
|
strip_prefix = "brotli-1.0.2",
|
||||||
|
sha256 = "b43d5d6bc40f2fa6c785b738d86c6bbe022732fe25196ebbe43b9653a025920d",
|
||||||
)
|
)
|
||||||
|
@ -1,20 +1,19 @@
|
|||||||
<!--The content below is only a placeholder and can be replaced.-->
|
<!--The content below is only a placeholder and can be replaced.-->
|
||||||
<div style="text-align:center">
|
<div style="text-align:center">
|
||||||
<h1>
|
<h1>
|
||||||
Welcome to {{title}}!!
|
Welcome to {{ title }}!
|
||||||
</h1>
|
</h1>
|
||||||
<img width="300" alt="Angular logo" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxOS4xLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCAyNTAgMjUwIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyNTAgMjUwOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCS5zdDB7ZmlsbDojREQwMDMxO30NCgkuc3Qxe2ZpbGw6I0MzMDAyRjt9DQoJLnN0MntmaWxsOiNGRkZGRkY7fQ0KPC9zdHlsZT4NCjxnPg0KCTxwb2x5Z29uIGNsYXNzPSJzdDAiIHBvaW50cz0iMTI1LDMwIDEyNSwzMCAxMjUsMzAgMzEuOSw2My4yIDQ2LjEsMTg2LjMgMTI1LDIzMCAxMjUsMjMwIDEyNSwyMzAgMjAzLjksMTg2LjMgMjE4LjEsNjMuMiAJIi8+DQoJPHBvbHlnb24gY2xhc3M9InN0MSIgcG9pbnRzPSIxMjUsMzAgMTI1LDUyLjIgMTI1LDUyLjEgMTI1LDE1My40IDEyNSwxNTMuNCAxMjUsMjMwIDEyNSwyMzAgMjAzLjksMTg2LjMgMjE4LjEsNjMuMiAxMjUsMzAgCSIvPg0KCTxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0xMjUsNTIuMUw2Ni44LDE4Mi42aDBoMjEuN2gwbDExLjctMjkuMmg0OS40bDExLjcsMjkuMmgwaDIxLjdoMEwxMjUsNTIuMUwxMjUsNTIuMUwxMjUsNTIuMUwxMjUsNTIuMQ0KCQlMMTI1LDUyLjF6IE0xNDIsMTM1LjRIMTA4bDE3LTQwLjlMMTQyLDEzNS40eiIvPg0KPC9nPg0KPC9zdmc+DQo=">
|
<img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
|
||||||
</div>
|
</div>
|
||||||
<h2>Here are some links to help you start: </h2>
|
<h2>Here are some links to help you start: </h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<h2><a target="_blank" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
|
<h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<h2><a target="_blank" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
|
<h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<h2><a target="_blank" href="http://angularjs.blogspot.ca/">Angular blog</a></h2>
|
<h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import { TestBed, async } from '@angular/core/testing';
|
import { TestBed, async } from '@angular/core/testing';
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
describe('AppComponent', () => {
|
describe('AppComponent', () => {
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
@ -20,13 +18,13 @@ describe('AppComponent', () => {
|
|||||||
it(`should have as title 'app'`, async(() => {
|
it(`should have as title 'app'`, async(() => {
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
const app = fixture.debugElement.componentInstance;
|
const app = fixture.debugElement.componentInstance;
|
||||||
expect(app.title).toEqual('app');
|
expect(app.title).toMatch(/app/i);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should render title in a h1 tag', async(() => {
|
it('should render title in a h1 tag', async(() => {
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const compiled = fixture.debugElement.nativeElement;
|
const compiled = fixture.debugElement.nativeElement;
|
||||||
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!!');
|
expect(compiled.querySelector('h1').textContent).toMatch(/app/i);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@ -11,6 +11,6 @@ import { Component } from '@angular/core';
|
|||||||
// #enddocregion metadata
|
// #enddocregion metadata
|
||||||
// #docregion title, class
|
// #docregion title, class
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
title = 'My First Angular App';
|
title = 'My First Angular App!';
|
||||||
}
|
}
|
||||||
// #enddocregion title, class
|
// #enddocregion title, class
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { Component, Input, OnDestroy } from '@angular/core';
|
import { Component, Input, OnDestroy } from '@angular/core';
|
||||||
|
|
||||||
import { MissionService } from './mission.service';
|
import { MissionService } from './mission.service';
|
||||||
import { Subscription } from 'rxjs/Subscription';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-astronaut',
|
selector: 'app-astronaut',
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Subject } from 'rxjs/Subject';
|
import { Subject } from 'rxjs';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MissionService {
|
export class MissionService {
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Component, Input, AfterViewInit, ViewChild, ComponentFactoryResolver, OnDestroy } from '@angular/core';
|
import { Component, Input, OnInit, ViewChild, ComponentFactoryResolver, OnDestroy } from '@angular/core';
|
||||||
|
|
||||||
import { AdDirective } from './ad.directive';
|
import { AdDirective } from './ad.directive';
|
||||||
import { AdItem } from './ad-item';
|
import { AdItem } from './ad-item';
|
||||||
import { AdComponent } from './ad.component';
|
import { AdComponent } from './ad.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-add-banner',
|
selector: 'app-ad-banner',
|
||||||
// #docregion ad-host
|
// #docregion ad-host
|
||||||
template: `
|
template: `
|
||||||
<div class="ad-banner">
|
<div class="ad-banner">
|
||||||
@ -17,16 +17,15 @@ import { AdComponent } from './ad.component';
|
|||||||
// #enddocregion ad-host
|
// #enddocregion ad-host
|
||||||
})
|
})
|
||||||
// #docregion class
|
// #docregion class
|
||||||
export class AdBannerComponent implements AfterViewInit, OnDestroy {
|
export class AdBannerComponent implements OnInit, OnDestroy {
|
||||||
@Input() ads: AdItem[];
|
@Input() ads: AdItem[];
|
||||||
currentAddIndex: number = -1;
|
currentAdIndex: number = -1;
|
||||||
@ViewChild(AdDirective) adHost: AdDirective;
|
@ViewChild(AdDirective) adHost: AdDirective;
|
||||||
subscription: any;
|
|
||||||
interval: any;
|
interval: any;
|
||||||
|
|
||||||
constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
|
constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngOnInit() {
|
||||||
this.loadComponent();
|
this.loadComponent();
|
||||||
this.getAds();
|
this.getAds();
|
||||||
}
|
}
|
||||||
@ -36,8 +35,8 @@ export class AdBannerComponent implements AfterViewInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadComponent() {
|
loadComponent() {
|
||||||
this.currentAddIndex = (this.currentAddIndex + 1) % this.ads.length;
|
this.currentAdIndex = (this.currentAdIndex + 1) % this.ads.length;
|
||||||
let adItem = this.ads[this.currentAddIndex];
|
let adItem = this.ads[this.currentAdIndex];
|
||||||
|
|
||||||
let componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component);
|
let componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component);
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import { AdItem } from './ad-item';
|
|||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
template: `
|
template: `
|
||||||
<div>
|
<div>
|
||||||
<app-add-banner [ads]="ads"></app-add-banner>
|
<app-ad-banner [ads]="ads"></app-ad-banner>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
|
@ -15,6 +15,7 @@ describe('Form Validation Tests', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
tests('Template-Driven Form');
|
tests('Template-Driven Form');
|
||||||
|
bobTests();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Reactive form', () => {
|
describe('Reactive form', () => {
|
||||||
|
@ -20,7 +20,7 @@ export function forbiddenNameValidator(nameRe: RegExp): ValidatorFn {
|
|||||||
// #enddocregion directive-providers
|
// #enddocregion directive-providers
|
||||||
})
|
})
|
||||||
export class ForbiddenValidatorDirective implements Validator {
|
export class ForbiddenValidatorDirective implements Validator {
|
||||||
@Input() forbiddenName: string;
|
@Input('appForbiddenName') forbiddenName: string;
|
||||||
|
|
||||||
validate(control: AbstractControl): {[key: string]: any} {
|
validate(control: AbstractControl): {[key: string]: any} {
|
||||||
return this.forbiddenName ? forbiddenNameValidator(new RegExp(this.forbiddenName, 'i'))(control)
|
return this.forbiddenName ? forbiddenNameValidator(new RegExp(this.forbiddenName, 'i'))(control)
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<!-- #docregion name-with-error-msg -->
|
<!-- #docregion name-with-error-msg -->
|
||||||
<!-- #docregion name-input -->
|
<!-- #docregion name-input -->
|
||||||
<input id="name" name="name" class="form-control"
|
<input id="name" name="name" class="form-control"
|
||||||
required minlength="4" forbiddenName="bob"
|
required minlength="4" appForbiddenName="bob"
|
||||||
[(ngModel)]="hero.name" #name="ngModel" >
|
[(ngModel)]="hero.name" #name="ngModel" >
|
||||||
<!-- #enddocregion name-input -->
|
<!-- #enddocregion name-input -->
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
import { Hero, HeroTaxReturn } from './hero';
|
import { Hero, HeroTaxReturn } from './hero';
|
||||||
import { HeroesService } from './heroes.service';
|
import { HeroesService } from './heroes.service';
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable, Observer } from 'rxjs';
|
||||||
import { Observer } from 'rxjs/Observer';
|
|
||||||
|
|
||||||
import { Hero, HeroTaxReturn } from './hero';
|
import { Hero, HeroTaxReturn } from './hero';
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
import { Villain, VillainsService } from './villains.service';
|
import { Villain, VillainsService } from './villains.service';
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { of } from 'rxjs/observable/of';
|
import { of } from 'rxjs';
|
||||||
|
|
||||||
export interface Villain { id: number; name: string; }
|
export interface Villain { id: number; name: string; }
|
||||||
|
|
||||||
|
@ -28,7 +28,10 @@ let checkLogForMessage = (message: string) => {
|
|||||||
expect(page.logList.getText()).toContain(message);
|
expect(page.logList.getText()).toContain(message);
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Http Tests', function() {
|
// TODO(i): temorarily disable these tests because angular-in-memory-web-api is not compatible with rxjs v6 yet
|
||||||
|
// and we don't have the backwards compatibility package yet.
|
||||||
|
// Reenable after rxjs v6 compatibility package is out or angular-in-memory-web-api is compatible with rxjs v6
|
||||||
|
xdescribe('Http Tests', function() {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
@ -30,7 +30,7 @@ export class ConfigComponent {
|
|||||||
this.configService.getConfig()
|
this.configService.getConfig()
|
||||||
// #enddocregion v1, v2
|
// #enddocregion v1, v2
|
||||||
.subscribe(
|
.subscribe(
|
||||||
data => this.config = { ...data }, // success path
|
(data: Config) => this.config = { ...data }, // success path
|
||||||
error => this.error = error // error path
|
error => this.error = error // error path
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -39,7 +39,7 @@ export class ConfigComponent {
|
|||||||
showConfig_v1() {
|
showConfig_v1() {
|
||||||
this.configService.getConfig_1()
|
this.configService.getConfig_1()
|
||||||
// #docregion v1, v1_callback
|
// #docregion v1, v1_callback
|
||||||
.subscribe(data => this.config = {
|
.subscribe((data: Config) => this.config = {
|
||||||
heroesUrl: data['heroesUrl'],
|
heroesUrl: data['heroesUrl'],
|
||||||
textfile: data['textfile']
|
textfile: data['textfile']
|
||||||
});
|
});
|
||||||
@ -51,7 +51,7 @@ export class ConfigComponent {
|
|||||||
this.configService.getConfig()
|
this.configService.getConfig()
|
||||||
// #docregion v2, v2_callback
|
// #docregion v2, v2_callback
|
||||||
// clone the data object, using its known Config shape
|
// clone the data object, using its known Config shape
|
||||||
.subscribe(data => this.config = { ...data });
|
.subscribe((data: Config) => this.config = { ...data });
|
||||||
// #enddocregion v2_callback
|
// #enddocregion v2_callback
|
||||||
}
|
}
|
||||||
// #enddocregion v2
|
// #enddocregion v2
|
||||||
|
@ -6,8 +6,7 @@ import { HttpClient } from '@angular/common/http';
|
|||||||
import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
|
import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
|
||||||
|
|
||||||
// #docregion rxjs-imports
|
// #docregion rxjs-imports
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable, throwError } from 'rxjs';
|
||||||
import { ErrorObservable } from 'rxjs/observable/ErrorObservable';
|
|
||||||
import { catchError, retry } from 'rxjs/operators';
|
import { catchError, retry } from 'rxjs/operators';
|
||||||
// #enddocregion rxjs-imports
|
// #enddocregion rxjs-imports
|
||||||
|
|
||||||
@ -82,8 +81,8 @@ export class ConfigService {
|
|||||||
`Backend returned code ${error.status}, ` +
|
`Backend returned code ${error.status}, ` +
|
||||||
`body was: ${error.error}`);
|
`body was: ${error.error}`);
|
||||||
}
|
}
|
||||||
// return an ErrorObservable with a user-facing error message
|
// return an observable with a user-facing error message
|
||||||
return new ErrorObservable(
|
return throwError(
|
||||||
'Something bad happened; please try again later.');
|
'Something bad happened; please try again later.');
|
||||||
};
|
};
|
||||||
// #enddocregion handleError
|
// #enddocregion handleError
|
||||||
|
@ -6,8 +6,7 @@ import { HttpHeaders } from '@angular/common/http';
|
|||||||
|
|
||||||
// #enddocregion http-options
|
// #enddocregion http-options
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
import { of } from 'rxjs/observable/of';
|
|
||||||
import { catchError } from 'rxjs/operators';
|
import { catchError } from 'rxjs/operators';
|
||||||
|
|
||||||
import { Hero } from './hero';
|
import { Hero } from './hero';
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { HttpErrorResponse } from '@angular/common/http';
|
import { HttpErrorResponse } from '@angular/common/http';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable, of } from 'rxjs';
|
||||||
import { of } from 'rxjs/observable/of';
|
|
||||||
|
|
||||||
import { MessageService } from './message.service';
|
import { MessageService } from './message.service';
|
||||||
|
|
||||||
|
@ -4,8 +4,6 @@ import {
|
|||||||
HttpEvent, HttpInterceptor, HttpHandler, HttpRequest
|
HttpEvent, HttpInterceptor, HttpHandler, HttpRequest
|
||||||
} from '@angular/common/http';
|
} from '@angular/common/http';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import { AuthService } from '../auth.service';
|
import { AuthService } from '../auth.service';
|
||||||
|
|
||||||
|
@ -5,8 +5,7 @@ import {
|
|||||||
HttpInterceptor, HttpHandler
|
HttpInterceptor, HttpHandler
|
||||||
} from '@angular/common/http';
|
} from '@angular/common/http';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable, of } from 'rxjs';
|
||||||
import { of } from 'rxjs/observable/of';
|
|
||||||
import { startWith, tap } from 'rxjs/operators';
|
import { startWith, tap } from 'rxjs/operators';
|
||||||
|
|
||||||
import { RequestCache } from '../request-cache.service';
|
import { RequestCache } from '../request-cache.service';
|
||||||
|
@ -3,7 +3,7 @@ import {
|
|||||||
HttpEvent, HttpInterceptor, HttpHandler, HttpRequest
|
HttpEvent, HttpInterceptor, HttpHandler, HttpRequest
|
||||||
} from '@angular/common/http';
|
} from '@angular/common/http';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class EnsureHttpsInterceptor implements HttpInterceptor {
|
export class EnsureHttpsInterceptor implements HttpInterceptor {
|
||||||
|
@ -4,7 +4,6 @@ import {
|
|||||||
HttpRequest, HttpResponse
|
HttpRequest, HttpResponse
|
||||||
} from '@angular/common/http';
|
} from '@angular/common/http';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
// #docregion excerpt
|
// #docregion excerpt
|
||||||
import { finalize, tap } from 'rxjs/operators';
|
import { finalize, tap } from 'rxjs/operators';
|
||||||
import { MessageService } from '../message.service';
|
import { MessageService } from '../message.service';
|
||||||
|
@ -3,7 +3,7 @@ import {
|
|||||||
HttpEvent, HttpInterceptor, HttpHandler, HttpRequest
|
HttpEvent, HttpInterceptor, HttpHandler, HttpRequest
|
||||||
} from '@angular/common/http';
|
} from '@angular/common/http';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
/** Pass untouched request through to the next request handler. */
|
/** Pass untouched request through to the next request handler. */
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -3,7 +3,7 @@ import {
|
|||||||
HttpEvent, HttpInterceptor, HttpHandler, HttpRequest
|
HttpEvent, HttpInterceptor, HttpHandler, HttpRequest
|
||||||
} from '@angular/common/http';
|
} from '@angular/common/http';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TrimNameInterceptor implements HttpInterceptor {
|
export class TrimNameInterceptor implements HttpInterceptor {
|
||||||
|
@ -5,8 +5,7 @@ import {
|
|||||||
HttpEventType, HttpProgressEvent
|
HttpEventType, HttpProgressEvent
|
||||||
} from '@angular/common/http';
|
} from '@angular/common/http';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
import { of } from 'rxjs/observable/of';
|
|
||||||
|
|
||||||
/** Simulate server replying to file upload request */
|
/** Simulate server replying to file upload request */
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable, Subject } from 'rxjs';
|
||||||
import { Subject } from 'rxjs/Subject';
|
|
||||||
import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';
|
import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
import { NpmPackageInfo, PackageSearchService } from './package-search.service';
|
import { NpmPackageInfo, PackageSearchService } from './package-search.service';
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
|
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable, of } from 'rxjs';
|
||||||
import { of } from 'rxjs/observable/of';
|
|
||||||
import { catchError, map } from 'rxjs/operators';
|
import { catchError, map } from 'rxjs/operators';
|
||||||
|
|
||||||
import { HttpErrorHandler, HandleError } from '../http-error-handler.service';
|
import { HttpErrorHandler, HandleError } from '../http-error-handler.service';
|
||||||
|
@ -4,7 +4,7 @@ import {
|
|||||||
HttpRequest, HttpResponse, HttpErrorResponse
|
HttpRequest, HttpResponse, HttpErrorResponse
|
||||||
} from '@angular/common/http';
|
} from '@angular/common/http';
|
||||||
|
|
||||||
import { of } from 'rxjs/observable/of';
|
import { of } from 'rxjs';
|
||||||
import { catchError, last, map, tap } from 'rxjs/operators';
|
import { catchError, last, map, tap } from 'rxjs/operators';
|
||||||
|
|
||||||
import { MessageService } from '../message.service';
|
import { MessageService } from '../message.service';
|
||||||
|
@ -2,8 +2,7 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Injectable, OnDestroy } from '@angular/core';
|
import { Injectable, OnDestroy } from '@angular/core';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable, of } from 'rxjs';
|
||||||
import { of } from 'rxjs/observable/of';
|
|
||||||
import { delay } from 'rxjs/operators';
|
import { delay } from 'rxjs/operators';
|
||||||
|
|
||||||
export class Contact {
|
export class Contact {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
import { Crisis,
|
import { Crisis,
|
||||||
CrisisService } from './crisis.service';
|
CrisisService } from './crisis.service';
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Injectable, OnDestroy } from '@angular/core';
|
import { Injectable, OnDestroy } from '@angular/core';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable, of } from 'rxjs';
|
||||||
import { of } from 'rxjs/observable/of';
|
|
||||||
import { delay } from 'rxjs/operators';
|
import { delay } from 'rxjs/operators';
|
||||||
|
|
||||||
export class Crisis {
|
export class Crisis {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
import { Hero,
|
import { Hero,
|
||||||
HeroService } from './hero.service';
|
HeroService } from './hero.service';
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Injectable, OnDestroy } from '@angular/core';
|
import { Injectable, OnDestroy } from '@angular/core';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable, of } from 'rxjs';
|
||||||
import { of } from 'rxjs/observable/of';
|
|
||||||
import { delay } from 'rxjs/operators';
|
import { delay } from 'rxjs/operators';
|
||||||
|
|
||||||
export class Hero {
|
export class Hero {
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { Injectable, OnDestroy } from '@angular/core';
|
import { Injectable, OnDestroy } from '@angular/core';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable, of } from 'rxjs';
|
||||||
import { of } from 'rxjs/observable/of';
|
import { delay } from 'rxjs/operators';
|
||||||
import { delay } from 'rxjs/operator/delay';
|
|
||||||
|
|
||||||
export class Contact {
|
export class Contact {
|
||||||
constructor(public id: number, public name: string) { }
|
constructor(public id: number, public name: string) { }
|
||||||
@ -24,12 +23,12 @@ export class ContactService implements OnDestroy {
|
|||||||
ngOnDestroy() { console.log('ContactService instance destroyed.'); }
|
ngOnDestroy() { console.log('ContactService instance destroyed.'); }
|
||||||
|
|
||||||
getContacts(): Observable<Contact[]> {
|
getContacts(): Observable<Contact[]> {
|
||||||
return delay.call(of(CONTACTS), FETCH_LATENCY);
|
return of(CONTACTS).pipe(delay(FETCH_LATENCY));
|
||||||
}
|
}
|
||||||
|
|
||||||
getContact(id: number | string): Observable<Contact> {
|
getContact(id: number | string): Observable<Contact> {
|
||||||
const contact$ = of(CONTACTS.find(contact => contact.id === +id));
|
const contact$ = of(CONTACTS.find(contact => contact.id === +id));
|
||||||
return delay.call(contact$, FETCH_LATENCY);
|
return contact$.pipe(delay(FETCH_LATENCY));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
import { Customer,
|
import { Customer,
|
||||||
CustomersService } from './customers.service';
|
CustomersService } from './customers.service';
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { Injectable, OnDestroy } from '@angular/core';
|
import { Injectable, OnDestroy } from '@angular/core';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable, of } from 'rxjs';
|
||||||
import { of } from 'rxjs/observable/of';
|
import { delay } from 'rxjs/operators';
|
||||||
import { delay } from 'rxjs/operator/delay';
|
|
||||||
|
|
||||||
export class Customer {
|
export class Customer {
|
||||||
constructor(public id: number, public name: string) { }
|
constructor(public id: number, public name: string) { }
|
||||||
@ -27,11 +26,11 @@ export class CustomersService implements OnDestroy {
|
|||||||
ngOnDestroy() { console.log('CustomersService instance destroyed.'); }
|
ngOnDestroy() { console.log('CustomersService instance destroyed.'); }
|
||||||
|
|
||||||
getCustomers(): Observable<Customer[]> {
|
getCustomers(): Observable<Customer[]> {
|
||||||
return delay.call(of(CUSTOMERS), FETCH_LATENCY);
|
return of(CUSTOMERS).pipe(delay(FETCH_LATENCY));
|
||||||
}
|
}
|
||||||
|
|
||||||
getCustomer(id: number | string): Observable<Customer> {
|
getCustomer(id: number | string): Observable<Customer> {
|
||||||
const customer$ = of(CUSTOMERS.find(customer => customer.id === +id));
|
const customer$ = of(CUSTOMERS.find(customer => customer.id === +id));
|
||||||
return delay.call(customer$, FETCH_LATENCY);
|
return customer$.pipe(delay(FETCH_LATENCY));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { Observable }from 'rxjs/Observable';
|
import { Observable }from 'rxjs';
|
||||||
|
|
||||||
import { Item,
|
import { Item,
|
||||||
ItemService } from './items.service';
|
ItemService } from './items.service';
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
import { ItemsComponent } from './items.component';
|
||||||
import { ItemsListComponent } from './items-list.component';
|
import { ItemsListComponent } from './items-list.component';
|
||||||
import { ItemsDetailComponent } from './items-detail.component';
|
import { ItemsDetailComponent } from './items-detail.component';
|
||||||
import { ItemService } from './items.service';
|
import { ItemService } from './items.service';
|
||||||
@ -8,7 +9,7 @@ import { ItemsRoutingModule } from './items-routing.module';
|
|||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [ CommonModule, ItemsRoutingModule ],
|
imports: [ CommonModule, ItemsRoutingModule ],
|
||||||
declarations: [ ItemsDetailComponent, ItemsListComponent ],
|
declarations: [ ItemsComponent, ItemsDetailComponent, ItemsListComponent ],
|
||||||
providers: [ ItemService ]
|
providers: [ ItemService ]
|
||||||
})
|
})
|
||||||
export class ItemsModule {}
|
export class ItemsModule {}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { Injectable, OnDestroy } from '@angular/core';
|
import { Injectable, OnDestroy } from '@angular/core';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable, of } from 'rxjs';
|
||||||
import { of } from 'rxjs/observable/of';
|
import { delay } from 'rxjs/operators';
|
||||||
import { delay } from 'rxjs/operator/delay';
|
|
||||||
|
|
||||||
export class Item {
|
export class Item {
|
||||||
constructor(public id: number, public name: string) { }
|
constructor(public id: number, public name: string) { }
|
||||||
@ -25,12 +24,12 @@ export class ItemService implements OnDestroy {
|
|||||||
ngOnDestroy() { console.log('ItemService instance destroyed.'); }
|
ngOnDestroy() { console.log('ItemService instance destroyed.'); }
|
||||||
|
|
||||||
getItems(): Observable<Item[]> {
|
getItems(): Observable<Item[]> {
|
||||||
return delay.call(of(ITEMS), FETCH_LATENCY);
|
return of(ITEMS).pipe(delay(FETCH_LATENCY));
|
||||||
}
|
}
|
||||||
|
|
||||||
getItem(id: number | string): Observable<Item> {
|
getItem(id: number | string): Observable<Item> {
|
||||||
const item$ = of(ITEMS.find(item => item.id === +id));
|
const item$ = of(ITEMS.find(item => item.id === +id));
|
||||||
return delay.call(item$, FETCH_LATENCY);
|
return item$.pipe(delay(FETCH_LATENCY));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
131
aio/content/examples/observables-in-angular/src/main.ts
Normal file
131
aio/content/examples/observables-in-angular/src/main.ts
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
|
||||||
|
import { Component, Output, OnInit, EventEmitter, NgModule } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
// #docregion eventemitter
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'zippy',
|
||||||
|
template: `
|
||||||
|
<div class="zippy">
|
||||||
|
<div (click)="toggle()">Toggle</div>
|
||||||
|
<div [hidden]="!visible">
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</div>
|
||||||
|
</div>`})
|
||||||
|
|
||||||
|
export class ZippyComponent {
|
||||||
|
visible = true;
|
||||||
|
@Output() open = new EventEmitter<any>();
|
||||||
|
@Output() close = new EventEmitter<any>();
|
||||||
|
|
||||||
|
toggle() {
|
||||||
|
this.visible = !this.visible;
|
||||||
|
if (this.visible) {
|
||||||
|
this.open.emit(null);
|
||||||
|
} else {
|
||||||
|
this.close.emit(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #enddocregion eventemitter
|
||||||
|
|
||||||
|
// #docregion pipe
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'async-observable-pipe',
|
||||||
|
template: `<div><code>observable|async</code>:
|
||||||
|
Time: {{ time | async }}</div>`
|
||||||
|
})
|
||||||
|
export class AsyncObservablePipeComponent {
|
||||||
|
time = new Observable(observer =>
|
||||||
|
setInterval(() => observer.next(new Date().toString()), 1000)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #enddocregion pipe
|
||||||
|
|
||||||
|
// #docregion router
|
||||||
|
|
||||||
|
import { Router, NavigationStart } from '@angular/router';
|
||||||
|
import { filter } from 'rxjs/operators';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-routable',
|
||||||
|
templateUrl: './routable.component.html',
|
||||||
|
styleUrls: ['./routable.component.css']
|
||||||
|
})
|
||||||
|
export class Routable1Component implements OnInit {
|
||||||
|
|
||||||
|
navStart: Observable<NavigationStart>;
|
||||||
|
|
||||||
|
constructor(private router: Router) {
|
||||||
|
// Create a new Observable the publishes only the NavigationStart event
|
||||||
|
this.navStart = router.events.pipe(
|
||||||
|
filter(evt => evt instanceof NavigationStart)
|
||||||
|
) as Observable<NavigationStart>;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.navStart.subscribe(evt => console.log('Navigation Started!'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #enddocregion router
|
||||||
|
|
||||||
|
|
||||||
|
// #docregion activated_route
|
||||||
|
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-routable',
|
||||||
|
templateUrl: './routable.component.html',
|
||||||
|
styleUrls: ['./routable.component.css']
|
||||||
|
})
|
||||||
|
export class Routable2Component implements OnInit {
|
||||||
|
constructor(private activatedRoute: ActivatedRoute) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.activatedRoute.url
|
||||||
|
.subscribe(url => console.log('The URL changed to: ' + url));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #enddocregion activated_route
|
||||||
|
|
||||||
|
|
||||||
|
// #docregion forms
|
||||||
|
|
||||||
|
import { FormGroup } from '@angular/forms';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-component',
|
||||||
|
template: 'MyComponent Template'
|
||||||
|
})
|
||||||
|
export class MyComponent implements OnInit {
|
||||||
|
nameChangeLog: string[] = [];
|
||||||
|
heroForm: FormGroup;
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.logNameChange();
|
||||||
|
}
|
||||||
|
logNameChange() {
|
||||||
|
const nameControl = this.heroForm.get('name');
|
||||||
|
nameControl.valueChanges.forEach(
|
||||||
|
(value: string) => this.nameChangeLog.push(value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #enddocregion forms
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations:
|
||||||
|
[ZippyComponent, AsyncObservablePipeComponent, Routable1Component, Routable2Component, MyComponent]
|
||||||
|
})
|
||||||
|
export class AppModule {
|
||||||
|
}
|
66
aio/content/examples/observables/src/creating.ts
Normal file
66
aio/content/examples/observables/src/creating.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
// #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();
|
||||||
|
|
||||||
|
// unsubscribe function doesn't need to do anything in this
|
||||||
|
// because values are delivered synchronously
|
||||||
|
return {unsubscribe() {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
function fromEvent(target, eventName) {
|
||||||
|
return new Observable((observer) => {
|
||||||
|
const handler = (e) => observer.next(e);
|
||||||
|
|
||||||
|
// Add the event handler to the target
|
||||||
|
target.addEventListener(eventName, handler);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
// Detach the event handler from the target
|
||||||
|
target.removeEventListener(eventName, handler);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// #enddocregion fromevent
|
||||||
|
|
||||||
|
// #docregion fromevent_use
|
||||||
|
|
||||||
|
const ESC_KEY = 27;
|
||||||
|
const nameInput = document.getElementById('name') as HTMLInputElement;
|
||||||
|
|
||||||
|
const subscription = fromEvent(nameInput, 'keydown')
|
||||||
|
.subscribe((e: KeyboardEvent) => {
|
||||||
|
if (e.keyCode === ESC_KEY) {
|
||||||
|
nameInput.value = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// #enddocregion fromevent_use
|
32
aio/content/examples/observables/src/geolocation.ts
Normal file
32
aio/content/examples/observables/src/geolocation.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
|
||||||
|
// Create an Observable that will start listening to geolocation updates
|
||||||
|
// when a consumer subscribes.
|
||||||
|
const locations = new Observable((observer) => {
|
||||||
|
// Get the next and error callbacks. These will be passed in when
|
||||||
|
// the consumer subscribes.
|
||||||
|
const {next, error} = observer;
|
||||||
|
let watchId;
|
||||||
|
|
||||||
|
// Simple geolocation API check provides values to publish
|
||||||
|
if ('geolocation' in navigator) {
|
||||||
|
watchId = navigator.geolocation.watchPosition(next, error);
|
||||||
|
} else {
|
||||||
|
error('Geolocation not available');
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the consumer unsubscribes, clean up data ready for next subscription.
|
||||||
|
return {unsubscribe() { navigator.geolocation.clearWatch(watchId); }};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call subscribe() to start listening for updates.
|
||||||
|
const locationsSubscription = locations.subscribe({
|
||||||
|
next(position) { console.log('Current Position: ', position); },
|
||||||
|
error(msg) { console.log('Error Getting Location: ', msg); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// Stop listening for location after 10 seconds
|
||||||
|
setTimeout(() => { locationsSubscription.unsubscribe(); }, 10000);
|
||||||
|
// #enddocregion
|
5
aio/content/examples/observables/src/main.ts
Normal file
5
aio/content/examples/observables/src/main.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
import './geolocation';
|
||||||
|
import './subscribing';
|
||||||
|
import './creating';
|
||||||
|
import './multicasting';
|
155
aio/content/examples/observables/src/multicasting.ts
Normal file
155
aio/content/examples/observables/src/multicasting.ts
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
// #docregion delay_sequence
|
||||||
|
|
||||||
|
function sequenceSubscriber(observer) {
|
||||||
|
const seq = [1, 2, 3];
|
||||||
|
let timeoutId;
|
||||||
|
|
||||||
|
// Will run through an array of numbers, emitting one value
|
||||||
|
// per second until it gets to the end of the array.
|
||||||
|
function doSequence(arr, idx) {
|
||||||
|
timeoutId = setTimeout(() => {
|
||||||
|
observer.next(arr[idx]);
|
||||||
|
if (idx === arr.length - 1) {
|
||||||
|
observer.complete();
|
||||||
|
} else {
|
||||||
|
doSequence(arr, idx++);
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
doSequence(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
|
||||||
|
|
||||||
|
// #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.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({
|
||||||
|
next(num) { console.log('2nd subscribe: ' + num); },
|
||||||
|
complete() { console.log('2nd sequence finished.'); }
|
||||||
|
});
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
|
// 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
|
32
aio/content/examples/observables/src/subscribing.ts
Normal file
32
aio/content/examples/observables/src/subscribing.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
import { Observable, of } from 'rxjs';
|
||||||
|
|
||||||
|
// #docregion observer
|
||||||
|
|
||||||
|
// Create simple observable that emits three values
|
||||||
|
const myObservable = Observable.of(1, 2, 3);
|
||||||
|
|
||||||
|
// Create observer object
|
||||||
|
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'),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Execute with the observer object
|
||||||
|
myObservable.subscribe(myObserver);
|
||||||
|
// Logs:
|
||||||
|
// Observer got a next value: 1
|
||||||
|
// Observer got a next value: 2
|
||||||
|
// Observer got a next value: 3
|
||||||
|
// Observer got a complete notification
|
||||||
|
|
||||||
|
// #enddocregion observer
|
||||||
|
|
||||||
|
// #docregion sub_fn
|
||||||
|
myObservable.subscribe(
|
||||||
|
x => console.log('Observer got a next value: ' + x),
|
||||||
|
err => console.error('Observer got an error: ' + err),
|
||||||
|
() => console.log('Observer got a complete notification')
|
||||||
|
);
|
||||||
|
// #enddocregion sub_fn
|
@ -2,7 +2,7 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { HttpModule } from '@angular/http';
|
import { HttpClientModule } from '@angular//common/http';
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import {
|
import {
|
||||||
@ -26,7 +26,7 @@ import { ExponentialStrengthPipe } from './exponential-strength.pipe';
|
|||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
HttpModule
|
HttpClientModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Pipe, PipeTransform } from '@angular/core';
|
import { Pipe, PipeTransform } from '@angular/core';
|
||||||
import { Http } from '@angular/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
|
||||||
import 'rxjs/add/operator/map';
|
|
||||||
|
|
||||||
// #docregion pipe-metadata
|
// #docregion pipe-metadata
|
||||||
@Pipe({
|
@Pipe({
|
||||||
name: 'fetch',
|
name: 'fetch',
|
||||||
@ -14,15 +11,13 @@ export class FetchJsonPipe implements PipeTransform {
|
|||||||
private cachedData: any = null;
|
private cachedData: any = null;
|
||||||
private cachedUrl = '';
|
private cachedUrl = '';
|
||||||
|
|
||||||
constructor(private http: Http) { }
|
constructor(private http: HttpClient) { }
|
||||||
|
|
||||||
transform(url: string): any {
|
transform(url: string): any {
|
||||||
if (url !== this.cachedUrl) {
|
if (url !== this.cachedUrl) {
|
||||||
this.cachedData = null;
|
this.cachedData = null;
|
||||||
this.cachedUrl = url;
|
this.cachedUrl = url;
|
||||||
this.http.get(url)
|
this.http.get(url).subscribe( result => this.cachedData = result );
|
||||||
.map( result => result.json() )
|
|
||||||
.subscribe( result => this.cachedData = result );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.cachedData;
|
return this.cachedData;
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable, interval } from 'rxjs';
|
||||||
import 'rxjs/add/observable/interval';
|
import { map, take } from 'rxjs/operators';
|
||||||
import 'rxjs/add/operator/map';
|
|
||||||
import 'rxjs/add/operator/take';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-hero-message',
|
selector: 'app-hero-message',
|
||||||
@ -25,14 +23,17 @@ export class HeroAsyncMessageComponent {
|
|||||||
constructor() { this.resend(); }
|
constructor() { this.resend(); }
|
||||||
|
|
||||||
resend() {
|
resend() {
|
||||||
this.message$ = Observable.interval(500)
|
this.message$ = interval(500).pipe(
|
||||||
.map(i => this.messages[i])
|
map(i => this.messages[i]),
|
||||||
.take(this.messages.length);
|
take(this.messages.length)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
// Alternative message$ formula:
|
// Alternative message$ formula:
|
||||||
// this.message$ = Observable.fromArray(this.messages)
|
// this.message$ = fromArray(this.messages).pipe(
|
||||||
// .map(message => Observable.timer(500).map(() => message))
|
// map(message => timer(500),
|
||||||
// .concatAll();
|
// map(() => message)),
|
||||||
|
// concatAll()
|
||||||
|
// );
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
import { pipe, range, timer, zip } from 'rxjs';
|
||||||
|
import { ajax } from 'rxjs/ajax';
|
||||||
|
import { retryWhen, map, mergeMap } from 'rxjs/operators';
|
||||||
|
|
||||||
|
function backoff(maxTries, ms) {
|
||||||
|
return pipe(
|
||||||
|
retryWhen(attempts => range(1, maxTries)
|
||||||
|
.pipe(
|
||||||
|
zip(attempts, (i) => i),
|
||||||
|
map(i => i * i),
|
||||||
|
mergeMap(i => timer(i * ms))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ajax('/api/endpoint')
|
||||||
|
.pipe(backoff(3, 250))
|
||||||
|
.subscribe(data => handleData(data));
|
||||||
|
|
||||||
|
function handleData(data) {
|
||||||
|
// ...
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
import { fromEvent } from 'rxjs';
|
||||||
|
import { ajax } from 'rxjs/ajax';
|
||||||
|
import { map, filter, debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
|
const searchBox = document.getElementById('search-box');
|
||||||
|
|
||||||
|
const typeahead = fromEvent(searchBox, 'input').pipe(
|
||||||
|
map((e: KeyboardEvent) => e.target.value),
|
||||||
|
filter(text => text.length > 2),
|
||||||
|
debounceTime(10),
|
||||||
|
distinctUntilChanged(),
|
||||||
|
switchMap(() => ajax('/api/endpoint'))
|
||||||
|
);
|
||||||
|
|
||||||
|
typeahead.subscribe(data => {
|
||||||
|
// Handle the data from the API
|
||||||
|
});
|
@ -6,32 +6,38 @@ import { BrowserModule } from '@angular/platform-browser';
|
|||||||
import { ReactiveFormsModule } from '@angular/forms'; // <-- #1 import module
|
import { ReactiveFormsModule } from '@angular/forms'; // <-- #1 import module
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { HeroDetailComponent } from './hero-detail/hero-detail.component'; // <-- #1 import component
|
import { HeroDetailComponent } from './hero-detail/hero-detail.component';
|
||||||
// #enddocregion v1
|
// #enddocregion v1
|
||||||
|
// #docregion hero-service-list
|
||||||
|
// add JavaScript imports
|
||||||
import { HeroListComponent } from './hero-list/hero-list.component';
|
import { HeroListComponent } from './hero-list/hero-list.component';
|
||||||
|
import { HeroService } from './hero.service';
|
||||||
import { HeroService } from './hero.service'; // <-- #1 import service
|
|
||||||
// #docregion v1
|
// #docregion v1
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
|
||||||
BrowserModule,
|
|
||||||
ReactiveFormsModule // <-- #2 add to @NgModule imports
|
|
||||||
],
|
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
HeroDetailComponent,
|
HeroDetailComponent,
|
||||||
// #enddocregion v1
|
// #enddocregion v1
|
||||||
HeroListComponent
|
HeroListComponent // <--declare HeroListComponent
|
||||||
// #docregion v1
|
// #docregion v1
|
||||||
],
|
],
|
||||||
// #enddocregion v1
|
// #enddocregion hero-service-list
|
||||||
exports: [ // export for the DemoModule
|
imports: [
|
||||||
|
BrowserModule,
|
||||||
|
ReactiveFormsModule // <-- #2 add to @NgModule imports
|
||||||
|
],
|
||||||
|
// #enddocregion v1
|
||||||
|
// export for the DemoModule
|
||||||
|
// #docregion hero-service-list
|
||||||
|
// ...
|
||||||
|
exports: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
HeroDetailComponent,
|
HeroDetailComponent,
|
||||||
HeroListComponent
|
HeroListComponent // <-- export HeroListComponent
|
||||||
],
|
],
|
||||||
providers: [ HeroService ], // <-- #4 provide HeroService
|
providers: [ HeroService ], // <-- provide HeroService
|
||||||
|
// #enddocregion hero-service-list
|
||||||
// #docregion v1
|
// #docregion v1
|
||||||
bootstrap: [ AppComponent ]
|
bootstrap: [ AppComponent ]
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/* tslint:disable:member-ordering */
|
/* tslint:disable:member-ordering */
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
|
import { finalize } from 'rxjs/operators';
|
||||||
|
|
||||||
import { Hero } from './data-model';
|
import { Hero } from './data-model';
|
||||||
import { HeroService } from './hero.service';
|
import { HeroService } from './hero.service';
|
||||||
@ -33,8 +34,9 @@ export class DemoComponent {
|
|||||||
|
|
||||||
getHeroes() {
|
getHeroes() {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
this.heroes = this.heroService.getHeroes()
|
this.heroes = this.heroService.getHeroes().pipe(
|
||||||
.finally(() => this.isLoading = false);
|
finalize(() => this.isLoading = false)
|
||||||
|
);
|
||||||
this.selectedHero = undefined;
|
this.selectedHero = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!-- #docregion basic-form-->
|
<!-- #docregion basic-form-->
|
||||||
<h2>Hero Detail</h2>
|
<h2>Hero Detail</h2>
|
||||||
<h3><i>FormControl in a FormGroup</i></h3>
|
<h3><i>FormControl in a FormGroup</i></h3>
|
||||||
<form [formGroup]="heroForm" novalidate>
|
<form [formGroup]="heroForm">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="center-block">Name:
|
<label class="center-block">Name:
|
||||||
<input class="form-control" formControlName="name">
|
<input class="form-control" formControlName="name">
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!-- #docregion basic-form-->
|
<!-- #docregion basic-form-->
|
||||||
<h2>Hero Detail</h2>
|
<h2>Hero Detail</h2>
|
||||||
<h3><i>A FormGroup with a single FormControl using FormBuilder</i></h3>
|
<h3><i>A FormGroup with a single FormControl using FormBuilder</i></h3>
|
||||||
<form [formGroup]="heroForm" novalidate>
|
<form [formGroup]="heroForm">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="center-block">Name:
|
<label class="center-block">Name:
|
||||||
<input class="form-control" formControlName="name">
|
<input class="form-control" formControlName="name">
|
||||||
@ -13,4 +13,4 @@
|
|||||||
<!-- #docregion form-value-json -->
|
<!-- #docregion form-value-json -->
|
||||||
<p>Form value: {{ heroForm.value | json }}</p>
|
<p>Form value: {{ heroForm.value | json }}</p>
|
||||||
<p>Form status: {{ heroForm.status | json }}</p>
|
<p>Form status: {{ heroForm.status | json }}</p>
|
||||||
<!-- #enddocregion form-value-json -->
|
<!-- #enddocregion form-value-json -->
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!-- #docregion -->
|
<!-- #docregion -->
|
||||||
<h2>Hero Detail</h2>
|
<h2>Hero Detail</h2>
|
||||||
<h3><i>A FormGroup with multiple FormControls</i></h3>
|
<h3><i>A FormGroup with multiple FormControls</i></h3>
|
||||||
<form [formGroup]="heroForm" novalidate>
|
<form [formGroup]="heroForm">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="center-block">Name:
|
<label class="center-block">Name:
|
||||||
<input class="form-control" formControlName="name">
|
<input class="form-control" formControlName="name">
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
<form [formGroup]="heroForm" novalidate>
|
<form [formGroup]="heroForm">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="center-block">Name:
|
<label class="center-block">Name:
|
||||||
<input class="form-control" formControlName="name">
|
<input class="form-control" formControlName="name">
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!-- #docregion -->
|
<!-- #docregion -->
|
||||||
<h2>Hero Detail</h2>
|
<h2>Hero Detail</h2>
|
||||||
<h3><i>PatchValue to initialize a value</i></h3>
|
<h3><i>PatchValue to initialize a value</i></h3>
|
||||||
<form [formGroup]="heroForm" novalidate>
|
<form [formGroup]="heroForm">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="center-block">Name:
|
<label class="center-block">Name:
|
||||||
<input class="form-control" formControlName="name">
|
<input class="form-control" formControlName="name">
|
||||||
|
@ -44,7 +44,13 @@ export class HeroDetailComponent6 implements OnChanges {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// #docregion patch-value-on-changes
|
// #docregion patch-value-on-changes
|
||||||
ngOnChanges() { // <-- wrap patchValue in ngOnChanges
|
ngOnChanges() { // <-- call rebuildForm in ngOnChanges
|
||||||
|
this.rebuildForm();
|
||||||
|
}
|
||||||
|
// #enddocregion patch-value-on-changes
|
||||||
|
|
||||||
|
// #docregion patch-value-rebuildform
|
||||||
|
rebuildForm() { // <-- wrap patchValue in rebuildForm
|
||||||
this.heroForm.reset();
|
this.heroForm.reset();
|
||||||
// #docregion patch-value
|
// #docregion patch-value
|
||||||
this.heroForm.patchValue({
|
this.heroForm.patchValue({
|
||||||
@ -52,7 +58,9 @@ export class HeroDetailComponent6 implements OnChanges {
|
|||||||
});
|
});
|
||||||
// #enddocregion patch-value
|
// #enddocregion patch-value
|
||||||
}
|
}
|
||||||
// #enddocregion patch-value-on-changes
|
// #enddocregion patch-value-rebuildform
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// #enddocregion v6
|
// #enddocregion v6
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!-- #docregion -->
|
<!-- #docregion -->
|
||||||
<h2>Hero Detail</h2>
|
<h2>Hero Detail</h2>
|
||||||
<h3><i>A FormGroup with multiple FormControls</i></h3>
|
<h3><i>A FormGroup with multiple FormControls</i></h3>
|
||||||
<form [formGroup]="heroForm" novalidate>
|
<form [formGroup]="heroForm">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="center-block">Name:
|
<label class="center-block">Name:
|
||||||
<input class="form-control" formControlName="name">
|
<input class="form-control" formControlName="name">
|
||||||
|
@ -38,32 +38,31 @@ export class HeroDetailComponent7 implements OnChanges {
|
|||||||
|
|
||||||
// #docregion ngOnChanges
|
// #docregion ngOnChanges
|
||||||
ngOnChanges() {
|
ngOnChanges() {
|
||||||
|
this.rebuildForm();
|
||||||
|
}
|
||||||
|
// #enddocregion ngOnChanges
|
||||||
|
|
||||||
|
// #docregion rebuildForm
|
||||||
|
rebuildForm() {
|
||||||
this.heroForm.reset({
|
this.heroForm.reset({
|
||||||
name: this.hero.name,
|
name: this.hero.name,
|
||||||
address: this.hero.addresses[0] || new Address()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// #enddocregion ngOnChanges
|
|
||||||
|
|
||||||
/* First version of ngOnChanges
|
|
||||||
// #docregion ngOnChanges-1
|
|
||||||
ngOnChanges()
|
|
||||||
// #enddocregion ngOnChanges-1
|
|
||||||
*/
|
|
||||||
ngOnChanges1() {
|
|
||||||
// #docregion reset
|
|
||||||
this.heroForm.reset();
|
|
||||||
// #enddocregion reset
|
|
||||||
// #docregion ngOnChanges-1
|
|
||||||
// #docregion set-value
|
|
||||||
this.heroForm.setValue({
|
|
||||||
name: this.hero.name,
|
|
||||||
// #docregion set-value-address
|
// #docregion set-value-address
|
||||||
address: this.hero.addresses[0] || new Address()
|
address: this.hero.addresses[0] || new Address()
|
||||||
// #enddocregion set-value-address
|
// #enddocregion set-value-address
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
// #enddocregion rebuildForm
|
||||||
|
|
||||||
|
/* First version of rebuildForm */
|
||||||
|
rebuildForm1() {
|
||||||
|
// #docregion reset
|
||||||
|
this.heroForm.reset();
|
||||||
|
// #enddocregion reset
|
||||||
|
// #docregion set-value
|
||||||
|
this.heroForm.setValue({
|
||||||
|
name: this.hero.name,
|
||||||
|
address: this.hero.addresses[0] || new Address()
|
||||||
|
});
|
||||||
// #enddocregion set-value
|
// #enddocregion set-value
|
||||||
}
|
}
|
||||||
// #enddocregion ngOnChanges-1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!-- #docplaster-->
|
<!-- #docplaster-->
|
||||||
<h3><i>Using FormArray to add groups</i></h3>
|
<h3><i>Using FormArray to add groups</i></h3>
|
||||||
|
|
||||||
<form [formGroup]="heroForm" novalidate>
|
<form [formGroup]="heroForm">
|
||||||
<p>Form Changed: {{ heroForm.dirty }}</p>
|
<p>Form Changed: {{ heroForm.dirty }}</p>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@ -11,7 +11,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- #docregion form-array-->
|
<!-- #docregion form-array-->
|
||||||
<!-- #docregion form-array-skeleton -->
|
<!-- #docregion form-array-skeleton -->
|
||||||
|
<!-- #docregion form-array-name -->
|
||||||
<div formArrayName="secretLairs" class="well well-lg">
|
<div formArrayName="secretLairs" class="well well-lg">
|
||||||
|
<!-- #enddocregion form-array-name -->
|
||||||
<div *ngFor="let address of secretLairs.controls; let i=index" [formGroupName]="i" >
|
<div *ngFor="let address of secretLairs.controls; let i=index" [formGroupName]="i" >
|
||||||
<!-- The repeated address template -->
|
<!-- The repeated address template -->
|
||||||
<!-- #enddocregion form-array-skeleton -->
|
<!-- #enddocregion form-array-skeleton -->
|
||||||
|
@ -39,12 +39,18 @@ export class HeroDetailComponent8 implements OnChanges {
|
|||||||
|
|
||||||
// #docregion onchanges
|
// #docregion onchanges
|
||||||
ngOnChanges() {
|
ngOnChanges() {
|
||||||
|
this.rebuildForm();
|
||||||
|
}
|
||||||
|
// #enddocregion onchanges
|
||||||
|
|
||||||
|
// #docregion rebuildform
|
||||||
|
rebuildForm() {
|
||||||
this.heroForm.reset({
|
this.heroForm.reset({
|
||||||
name: this.hero.name
|
name: this.hero.name
|
||||||
});
|
});
|
||||||
this.setAddresses(this.hero.addresses);
|
this.setAddresses(this.hero.addresses);
|
||||||
}
|
}
|
||||||
// #enddocregion onchanges
|
// #enddocregion rebuildform
|
||||||
|
|
||||||
// #docregion get-secret-lairs
|
// #docregion get-secret-lairs
|
||||||
get secretLairs(): FormArray {
|
get secretLairs(): FormArray {
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<!-- #docplaster -->
|
<!-- #docplaster -->
|
||||||
<!-- #docregion -->
|
<!-- #docregion -->
|
||||||
<!-- #docregion buttons -->
|
<!-- #docregion buttons -->
|
||||||
<form [formGroup]="heroForm" (ngSubmit)="onSubmit()" novalidate>
|
<form [formGroup]="heroForm" (ngSubmit)="onSubmit()">
|
||||||
<div style="margin-bottom: 1em">
|
<div style="margin-bottom: 1em">
|
||||||
<button type="submit"
|
<button type="submit"
|
||||||
[disabled]="heroForm.pristine" class="btn btn-success">Save</button>
|
[disabled]="heroForm.pristine" class="btn btn-success">Save</button>
|
||||||
<button type="reset" (click)="revert()"
|
<button type="button" (click)="revert()"
|
||||||
[disabled]="heroForm.pristine" class="btn btn-danger">Revert</button>
|
[disabled]="heroForm.pristine" class="btn btn-danger">Revert</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -13,7 +13,10 @@ import { HeroService } from '../hero.service';
|
|||||||
templateUrl: './hero-detail.component.html',
|
templateUrl: './hero-detail.component.html',
|
||||||
styleUrls: ['./hero-detail.component.css']
|
styleUrls: ['./hero-detail.component.css']
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #docregion onchanges-implementation
|
||||||
export class HeroDetailComponent implements OnChanges {
|
export class HeroDetailComponent implements OnChanges {
|
||||||
|
// #enddocregion onchanges-implementation
|
||||||
@Input() hero: Hero;
|
@Input() hero: Hero;
|
||||||
|
|
||||||
heroForm: FormGroup;
|
heroForm: FormGroup;
|
||||||
@ -42,6 +45,10 @@ export class HeroDetailComponent implements OnChanges {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges() {
|
ngOnChanges() {
|
||||||
|
this.rebuildForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
rebuildForm() {
|
||||||
this.heroForm.reset({
|
this.heroForm.reset({
|
||||||
name: this.hero.name
|
name: this.hero.name
|
||||||
});
|
});
|
||||||
@ -66,7 +73,7 @@ export class HeroDetailComponent implements OnChanges {
|
|||||||
onSubmit() {
|
onSubmit() {
|
||||||
this.hero = this.prepareSaveHero();
|
this.hero = this.prepareSaveHero();
|
||||||
this.heroService.updateHero(this.hero).subscribe(/* error handling */);
|
this.heroService.updateHero(this.hero).subscribe(/* error handling */);
|
||||||
this.ngOnChanges();
|
this.rebuildForm();
|
||||||
}
|
}
|
||||||
// #enddocregion on-submit
|
// #enddocregion on-submit
|
||||||
|
|
||||||
@ -92,7 +99,7 @@ export class HeroDetailComponent implements OnChanges {
|
|||||||
// #enddocregion prepare-save-hero
|
// #enddocregion prepare-save-hero
|
||||||
|
|
||||||
// #docregion revert
|
// #docregion revert
|
||||||
revert() { this.ngOnChanges(); }
|
revert() { this.rebuildForm(); }
|
||||||
// #enddocregion revert
|
// #enddocregion revert
|
||||||
|
|
||||||
// #docregion log-name-change
|
// #docregion log-name-change
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
import 'rxjs/add/operator/finally';
|
import { finalize } from 'rxjs/operators';
|
||||||
|
|
||||||
import { Hero } from '../data-model';
|
import { Hero } from '../data-model';
|
||||||
import { HeroService } from '../hero.service';
|
import { HeroService } from '../hero.service';
|
||||||
@ -24,7 +24,7 @@ export class HeroListComponent implements OnInit {
|
|||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
this.heroes = this.heroService.getHeroes()
|
this.heroes = this.heroService.getHeroes()
|
||||||
// Todo: error handling
|
// Todo: error handling
|
||||||
.finally(() => this.isLoading = false);
|
.pipe(finalize(() => this.isLoading = false));
|
||||||
this.selectedHero = undefined;
|
this.selectedHero = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable, of } from 'rxjs';
|
||||||
import { of } from 'rxjs/observable/of';
|
import { delay } from 'rxjs/operators';
|
||||||
import 'rxjs/add/operator/delay';
|
|
||||||
|
|
||||||
import { Hero, heroes } from './data-model';
|
import { Hero, heroes } from './data-model';
|
||||||
|
|
||||||
@ -14,13 +13,13 @@ export class HeroService {
|
|||||||
|
|
||||||
// Fake server get; assume nothing can go wrong
|
// Fake server get; assume nothing can go wrong
|
||||||
getHeroes(): Observable<Hero[]> {
|
getHeroes(): Observable<Hero[]> {
|
||||||
return of(heroes).delay(this.delayMs); // simulate latency with delay
|
return of(heroes).pipe(delay(this.delayMs)); // simulate latency with delay
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fake server update; assume nothing can go wrong
|
// Fake server update; assume nothing can go wrong
|
||||||
updateHero(hero: Hero): Observable<Hero> {
|
updateHero(hero: Hero): Observable<Hero> {
|
||||||
const oldHero = heroes.find(h => h.id === hero.id);
|
const oldHero = heroes.find(h => h.id === hero.id);
|
||||||
const newHero = Object.assign(oldHero, hero); // Demo: mutate cached hero
|
const newHero = Object.assign(oldHero, hero); // Demo: mutate cached hero
|
||||||
return of(newHero).delay(this.delayMs); // simulate latency with delay
|
return of(newHero).pipe(delay(this.delayMs)); // simulate latency with delay
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
import 'rxjs/add/operator/map';
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
@ -23,11 +23,11 @@ export class AdminDashboardComponent implements OnInit {
|
|||||||
// Capture the session ID if available
|
// Capture the session ID if available
|
||||||
this.sessionId = this.route
|
this.sessionId = this.route
|
||||||
.queryParamMap
|
.queryParamMap
|
||||||
.map(params => params.get('session_id') || 'None');
|
.pipe(map(params => params.get('session_id') || 'None'));
|
||||||
|
|
||||||
// Capture the fragment if available
|
// Capture the fragment if available
|
||||||
this.token = this.route
|
this.token = this.route
|
||||||
.fragment
|
.fragment
|
||||||
.map(fragment => fragment || 'None');
|
.pipe(map(fragment => fragment || 'None'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
import { SelectivePreloadingStrategy } from '../selective-preloading-strategy';
|
import { SelectivePreloadingStrategy } from '../selective-preloading-strategy';
|
||||||
|
|
||||||
import 'rxjs/add/operator/map';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
@ -37,11 +37,11 @@ export class AdminDashboardComponent implements OnInit {
|
|||||||
// Capture the session ID if available
|
// Capture the session ID if available
|
||||||
this.sessionId = this.route
|
this.sessionId = this.route
|
||||||
.queryParamMap
|
.queryParamMap
|
||||||
.map(params => params.get('session_id') || 'None');
|
.pipe(map(params => params.get('session_id') || 'None'));
|
||||||
|
|
||||||
// Capture the fragment if available
|
// Capture the fragment if available
|
||||||
this.token = this.route
|
this.token = this.route
|
||||||
.fragment
|
.fragment
|
||||||
.map(fragment => fragment || 'None');
|
.pipe(map(fragment => fragment || 'None'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { animate, AnimationEntryMetadata, state, style, transition, trigger } from '@angular/core';
|
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||||
|
|
||||||
// Component transition animations
|
// Component transition animations
|
||||||
export const slideInDownAnimation: AnimationEntryMetadata =
|
export const slideInDownAnimation =
|
||||||
trigger('routeAnimation', [
|
trigger('routeAnimation', [
|
||||||
state('*',
|
state('*',
|
||||||
style({
|
style({
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable, of } from 'rxjs';
|
||||||
import 'rxjs/add/observable/of';
|
import { tap, delay } from 'rxjs/operators';
|
||||||
import 'rxjs/add/operator/do';
|
|
||||||
import 'rxjs/add/operator/delay';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthService {
|
export class AuthService {
|
||||||
@ -14,7 +12,10 @@ export class AuthService {
|
|||||||
redirectUrl: string;
|
redirectUrl: string;
|
||||||
|
|
||||||
login(): Observable<boolean> {
|
login(): Observable<boolean> {
|
||||||
return Observable.of(true).delay(1000).do(val => this.isLoggedIn = true);
|
return of(true).pipe(
|
||||||
|
delay(1000),
|
||||||
|
tap(val => this.isLoggedIn = true)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
logout(): void {
|
logout(): void {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
import { CanDeactivate,
|
import { CanDeactivate,
|
||||||
ActivatedRouteSnapshot,
|
ActivatedRouteSnapshot,
|
||||||
RouterStateSnapshot } from '@angular/router';
|
RouterStateSnapshot } from '@angular/router';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { CanDeactivate } from '@angular/router';
|
import { CanDeactivate } from '@angular/router';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
export interface CanComponentDeactivate {
|
export interface CanComponentDeactivate {
|
||||||
canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
|
canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import 'rxjs/add/operator/map';
|
|
||||||
import 'rxjs/add/operator/take';
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
import { Router, Resolve, RouterStateSnapshot,
|
import { Router, Resolve, RouterStateSnapshot,
|
||||||
ActivatedRouteSnapshot } from '@angular/router';
|
ActivatedRouteSnapshot } from '@angular/router';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { map, take } from 'rxjs/operators';
|
||||||
|
|
||||||
import { Crisis, CrisisService } from './crisis.service';
|
import { Crisis, CrisisService } from './crisis.service';
|
||||||
|
|
||||||
@ -15,13 +14,16 @@ export class CrisisDetailResolver implements Resolve<Crisis> {
|
|||||||
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Crisis> {
|
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Crisis> {
|
||||||
let id = route.paramMap.get('id');
|
let id = route.paramMap.get('id');
|
||||||
|
|
||||||
return this.cs.getCrisis(id).take(1).map(crisis => {
|
return this.cs.getCrisis(id).pipe(
|
||||||
if (crisis) {
|
take(1),
|
||||||
return crisis;
|
map(crisis => {
|
||||||
} else { // id not found
|
if (crisis) {
|
||||||
this.router.navigate(['/crisis-center']);
|
return crisis;
|
||||||
return null;
|
} else { // id not found
|
||||||
}
|
this.router.navigate(['/crisis-center']);
|
||||||
});
|
return null;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion
|
// #docregion
|
||||||
import 'rxjs/add/operator/switchMap';
|
|
||||||
import { Component, OnInit, HostBinding } from '@angular/core';
|
import { Component, OnInit, HostBinding } from '@angular/core';
|
||||||
import { ActivatedRoute, Router, ParamMap } from '@angular/router';
|
import { ActivatedRoute, Router, ParamMap } from '@angular/router';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
|
import { switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
import { slideInDownAnimation } from '../animations';
|
import { slideInDownAnimation } from '../animations';
|
||||||
import { Crisis, CrisisService } from './crisis.service';
|
import { Crisis, CrisisService } from './crisis.service';
|
||||||
@ -46,8 +46,9 @@ export class CrisisDetailComponent implements OnInit {
|
|||||||
// #docregion ngOnInit
|
// #docregion ngOnInit
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.route.paramMap
|
this.route.paramMap
|
||||||
.switchMap((params: ParamMap) =>
|
.pipe(
|
||||||
this.service.getCrisis(params.get('id')))
|
switchMap((params: ParamMap) =>
|
||||||
|
this.service.getCrisis(params.get('id'))))
|
||||||
.subscribe((crisis: Crisis) => {
|
.subscribe((crisis: Crisis) => {
|
||||||
if (crisis) {
|
if (crisis) {
|
||||||
this.editName = crisis.name;
|
this.editName = crisis.name;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Component, OnInit, HostBinding } from '@angular/core';
|
import { Component, OnInit, HostBinding } from '@angular/core';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
import { slideInDownAnimation } from '../animations';
|
import { slideInDownAnimation } from '../animations';
|
||||||
import { Crisis } from './crisis.service';
|
import { Crisis } from './crisis.service';
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
|
|
||||||
import 'rxjs/add/operator/switchMap';
|
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute, ParamMap } from '@angular/router';
|
import { ActivatedRoute, ParamMap } from '@angular/router';
|
||||||
|
|
||||||
import { Crisis, CrisisService } from './crisis.service';
|
import { Crisis, CrisisService } from './crisis.service';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
|
import { switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
// #docregion relative-navigation-router-link
|
// #docregion relative-navigation-router-link
|
||||||
@ -34,10 +34,11 @@ export class CrisisListComponent implements OnInit {
|
|||||||
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.crises$ = this.route.paramMap
|
this.crises$ = this.route.paramMap.pipe(
|
||||||
.switchMap((params: ParamMap) => {
|
switchMap((params: ParamMap) => {
|
||||||
this.selectedId = +params.get('id');
|
this.selectedId = +params.get('id');
|
||||||
return this.service.getCrises();
|
return this.service.getCrises();
|
||||||
});
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import 'rxjs/add/operator/switchMap';
|
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute, ParamMap } from '@angular/router';
|
import { ActivatedRoute, ParamMap } from '@angular/router';
|
||||||
|
|
||||||
import { Crisis, CrisisService } from './crisis.service';
|
import { Crisis, CrisisService } from './crisis.service';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
|
import { switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
@ -32,10 +32,11 @@ export class CrisisListComponent implements OnInit {
|
|||||||
// #enddocregion ctor
|
// #enddocregion ctor
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.crises$ = this.route.paramMap
|
this.crises$ = this.route.paramMap.pipe(
|
||||||
.switchMap((params: ParamMap) => {
|
switchMap((params: ParamMap) => {
|
||||||
this.selectedId = +params.get('id');
|
this.selectedId = +params.get('id');
|
||||||
return this.service.getCrises();
|
return this.service.getCrises();
|
||||||
});
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion , mock-crises
|
// #docregion , mock-crises
|
||||||
import 'rxjs/add/observable/of';
|
import { BehaviorSubject } from 'rxjs';
|
||||||
import 'rxjs/add/operator/map';
|
import { map } from 'rxjs/operators';
|
||||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
|
||||||
|
|
||||||
export class Crisis {
|
export class Crisis {
|
||||||
constructor(public id: number, public name: string) { }
|
constructor(public id: number, public name: string) { }
|
||||||
@ -26,8 +25,9 @@ export class CrisisService {
|
|||||||
getCrises() { return this.crises$; }
|
getCrises() { return this.crises$; }
|
||||||
|
|
||||||
getCrisis(id: number | string) {
|
getCrisis(id: number | string) {
|
||||||
return this.getCrises()
|
return this.getCrises().pipe(
|
||||||
.map(crises => crises.find(crisis => crisis.id === +id));
|
map(crises => crises.find(crisis => crisis.id === +id))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import 'rxjs/add/observable/of';
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable, of } from 'rxjs';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Async modal dialog service
|
* Async modal dialog service
|
||||||
@ -17,6 +16,6 @@ export class DialogService {
|
|||||||
confirm(message?: string): Observable<boolean> {
|
confirm(message?: string): Observable<boolean> {
|
||||||
const confirmation = window.confirm(message || 'Is it OK?');
|
const confirmation = window.confirm(message || 'Is it OK?');
|
||||||
|
|
||||||
return Observable.of(confirmation);
|
return of(confirmation);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion
|
// #docregion
|
||||||
// #docregion rxjs-operator-import
|
// #docregion rxjs-operator-import
|
||||||
import 'rxjs/add/operator/switchMap';
|
import { switchMap } from 'rxjs/operators';
|
||||||
// #enddocregion rxjs-operator-import
|
// #enddocregion rxjs-operator-import
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
// #docregion imports
|
// #docregion imports
|
||||||
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
|
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
|
||||||
// #enddocregion imports
|
// #enddocregion imports
|
||||||
@ -41,9 +41,10 @@ export class HeroDetailComponent implements OnInit {
|
|||||||
|
|
||||||
// #docregion ngOnInit
|
// #docregion ngOnInit
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.hero$ = this.route.paramMap
|
this.hero$ = this.route.paramMap.pipe(
|
||||||
.switchMap((params: ParamMap) =>
|
switchMap((params: ParamMap) =>
|
||||||
this.service.getHero(params.get('id')));
|
this.service.getHero(params.get('id')))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// #enddocregion ngOnInit
|
// #enddocregion ngOnInit
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
import { Hero, HeroService } from './hero.service';
|
import { Hero, HeroService } from './hero.service';
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion
|
// #docregion
|
||||||
// #docregion rxjs-operator-import
|
// #docregion rxjs-operator-import
|
||||||
import 'rxjs/add/operator/switchMap';
|
import { switchMap } from 'rxjs/operators';
|
||||||
// #enddocregion rxjs-operator-import
|
// #enddocregion rxjs-operator-import
|
||||||
import { Component, OnInit, HostBinding } from '@angular/core';
|
import { Component, OnInit, HostBinding } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
|
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
import { slideInDownAnimation } from '../animations';
|
import { slideInDownAnimation } from '../animations';
|
||||||
|
|
||||||
@ -48,9 +48,10 @@ export class HeroDetailComponent implements OnInit {
|
|||||||
|
|
||||||
// #docregion ngOnInit
|
// #docregion ngOnInit
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.hero$ = this.route.paramMap
|
this.hero$ = this.route.paramMap.pipe(
|
||||||
.switchMap((params: ParamMap) =>
|
switchMap((params: ParamMap) =>
|
||||||
this.service.getHero(params.get('id')));
|
this.service.getHero(params.get('id')))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// #enddocregion ngOnInit
|
// #enddocregion ngOnInit
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
// TODO SOMEDAY: Feature Componetized like HeroCenter
|
// TODO SOMEDAY: Feature Componetized like HeroCenter
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
import { Hero, HeroService } from './hero.service';
|
import { Hero, HeroService } from './hero.service';
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user