Compare commits
507 Commits
Author | SHA1 | Date | |
---|---|---|---|
1f0c1f3ff2 | |||
a86a41210f | |||
20c44a6240 | |||
0feb560136 | |||
f4d06445a3 | |||
6c1ab479ee | |||
f7997256fc | |||
dc9da17f37 | |||
99c41d6db0 | |||
1aae94a421 | |||
f0f319b1d6 | |||
454e073918 | |||
76d64331bd | |||
6855396449 | |||
0b96908225 | |||
65f52f3761 | |||
9ce55d08f8 | |||
765c1c5b17 | |||
ccfa3426f7 | |||
83379fa0bb | |||
2ffd44ad96 | |||
4a84842bbb | |||
daa715a1ca | |||
31bce80771 | |||
711e4d4cc2 | |||
fdc5941fe7 | |||
ae10a541bf | |||
b797913d10 | |||
1465372a0e | |||
a33cb2d39b | |||
1202d17b4c | |||
d837828317 | |||
dc210bc75b | |||
75ead94ed5 | |||
6ac0042aef | |||
3eee53603c | |||
5c94fa97c1 | |||
468f4a3f9e | |||
a2393bef02 | |||
5bd1c7bbf7 | |||
19313f7dad | |||
4e2500278c | |||
2c4cfa6f2c | |||
c8f0c3b637 | |||
cf4883240b | |||
6f3157fe6d | |||
12d8af50dd | |||
94fc8463cc | |||
87b9f08d3b | |||
1c8f1799d4 | |||
d98d0dbf17 | |||
7e56222afb | |||
2ed66acdd9 | |||
fa073bafbd | |||
363f14c893 | |||
a9edbc3a4e | |||
e62fa67440 | |||
57236f1e11 | |||
14ffecdf09 | |||
9ae3e1199d | |||
947f542185 | |||
353195c9c5 | |||
72505dfd6f | |||
a63f634592 | |||
18d08a3857 | |||
c4234577db | |||
4830d664da | |||
e26879ad1d | |||
c5c3113f00 | |||
178a78f9ed | |||
7de7871dd9 | |||
784cf46a93 | |||
ba9e63a278 | |||
83231f2174 | |||
62e3196849 | |||
127a06c031 | |||
d4e00ee5a1 | |||
6db8e7eb8f | |||
ee1ef8512f | |||
efef04487c | |||
74d8b2308b | |||
7543e5925e | |||
5ca8ba3be9 | |||
3f70e3df3b | |||
0b68189051 | |||
b811212013 | |||
4d0b831d09 | |||
2cf6b809ae | |||
639fab2c14 | |||
0912be47ff | |||
9548c7cb94 | |||
de5449380f | |||
5ffa4f12e5 | |||
9022091dc6 | |||
74878984b2 | |||
6a6fbc3890 | |||
cb888afd0c | |||
48cf61cf45 | |||
d808333047 | |||
f872b69d3b | |||
9cca82ed70 | |||
e3d33958d2 | |||
4de546eef5 | |||
719ca5283b | |||
3813f54bec | |||
92590693e6 | |||
ef9da2f619 | |||
23f380d6b9 | |||
92b97f7d60 | |||
d12ef0c0a7 | |||
4827dbe308 | |||
04cd4187ce | |||
bb5e455ab2 | |||
96787f2e40 | |||
4f1b7a4a6a | |||
d113bfa14f | |||
a8aa2caeb6 | |||
f20c725406 | |||
caafd7e0a3 | |||
f59f5a2ab3 | |||
b91b3d7462 | |||
a235daee71 | |||
77218d6974 | |||
928dc8f263 | |||
468aeb454a | |||
b9dd2b45af | |||
2ab32c870f | |||
53897d4a84 | |||
efe1713371 | |||
24b9e12383 | |||
ad3fbe1ea0 | |||
f0ce3c2ce5 | |||
ae989b8cb7 | |||
edcc8b8acf | |||
790af88288 | |||
6eef7dbdbe | |||
ba1dfd0cf3 | |||
b37071c22f | |||
b6cba54821 | |||
451e7e2364 | |||
99b63b677e | |||
00b9de56f5 | |||
4423ab5109 | |||
0fc0d9bb3d | |||
00cc02fb0c | |||
0783d482a7 | |||
6cce05e2c5 | |||
bf446cb2d5 | |||
04fd90e32a | |||
be06a44861 | |||
d4a14697ec | |||
35e0d8311b | |||
964d8679b3 | |||
6cbde69e8f | |||
6da2a28dc0 | |||
fbdd282e7c | |||
d1b3af697c | |||
dcf1dcb757 | |||
c6e5225ec3 | |||
3361f59a4f | |||
7e9d5f5e82 | |||
654868f584 | |||
b6c042d0a3 | |||
4becc1bc95 | |||
5bddeea559 | |||
65337fb8b8 | |||
4abd60361a | |||
9d13ee0052 | |||
be1a83337e | |||
0be3792b5c | |||
4edd5fc694 | |||
c88ba02d83 | |||
8719ccdcfb | |||
36083c7c3c | |||
44c350236c | |||
8a85c31667 | |||
293557c80b | |||
e61f094a19 | |||
244f736e47 | |||
9307bc063f | |||
64453e42ff | |||
9e755f30f0 | |||
d0e024ec2d | |||
a576852ad9 | |||
4573a9997b | |||
4af10c6bb0 | |||
eabeb574cf | |||
a297fa9ecd | |||
ea51b62786 | |||
701016d6c4 | |||
e5317d5eaf | |||
389ff894ee | |||
d6417f02af | |||
a239decc91 | |||
a11542ab6f | |||
723fb492ce | |||
971c6f8d3b | |||
e8efd67e71 | |||
75370107c2 | |||
48ae3a0639 | |||
b6d0e215f9 | |||
5ea51b21fd | |||
ebb473368c | |||
7ff9050c25 | |||
ec0c6b3dcc | |||
e92d53f157 | |||
2dbed5e8f5 | |||
a0342763b8 | |||
0d747337a3 | |||
decacd5f74 | |||
c8c2272a9f | |||
e5f459d32b | |||
901b980b8e | |||
186373300a | |||
f30307a2de | |||
166a4553dc | |||
465215b11c | |||
a0eed742b4 | |||
4775f63847 | |||
304816e573 | |||
d70cf76962 | |||
3800455c6f | |||
c635123fc8 | |||
15e1bfc026 | |||
9b961a410a | |||
420c73c722 | |||
62930aac7b | |||
d7433316b0 | |||
c440165384 | |||
0ce96f1d78 | |||
d3deaf9a99 | |||
5c88a9fcfe | |||
0bd7517c73 | |||
d669429bd2 | |||
6a9b2c9a67 | |||
0f389fa5ae | |||
2a27f69522 | |||
180a32894e | |||
00724dcdbb | |||
cc71116ba6 | |||
ddfcf082ca | |||
c7e4f5eb4d | |||
b3fe9017f7 | |||
d3a77ea91a | |||
1b5a931d63 | |||
d840503d35 | |||
b49a734f0d | |||
695f83529d | |||
f898c9ab57 | |||
5337e138e3 | |||
e33047454f | |||
858fa45556 | |||
b97211ee2b | |||
25d4238371 | |||
7743c43529 | |||
54883cb477 | |||
91cef8cfc7 | |||
d40bcce84e | |||
7a18fb2448 | |||
ec39bdcc15 | |||
b7070b0ad6 | |||
aa94cd505c | |||
cc6ccf28a6 | |||
e1071615c6 | |||
8bd5374cfd | |||
b9b9cc2ba8 | |||
a6e10ef869 | |||
9724169bf4 | |||
c0ed57db76 | |||
0bd50e2e50 | |||
0ceb27041f | |||
ec2affe104 | |||
c590e8ca7a | |||
254b9ea44c | |||
2a53f47159 | |||
722d9397b0 | |||
03de31a78e | |||
b22c5a953d | |||
24222e0c1f | |||
95f45e8070 | |||
18be33a9d1 | |||
a22d4f6c98 | |||
5ae8473c6b | |||
fd7c39e3cf | |||
d85d91df66 | |||
15930d21c7 | |||
61a7f98b98 | |||
c3c7bf6509 | |||
b2e7ce47ec | |||
94e518e3c7 | |||
0fa5ac8d0d | |||
f2fca3e243 | |||
5bab49828d | |||
db4e93d0ca | |||
479a59be43 | |||
52aab63dd9 | |||
506beeddc1 | |||
0075078179 | |||
bb7edc52aa | |||
ed2b0e945e | |||
da159bde83 | |||
06a9809e32 | |||
1e4fb74ec8 | |||
797c306306 | |||
972fc06135 | |||
a9117061d0 | |||
fe1d9bacc3 | |||
08b8b51486 | |||
1d4af3f734 | |||
609d81c65e | |||
af30efddc5 | |||
15115f6179 | |||
eec9b6bbb5 | |||
45fd77ead1 | |||
f16587e9b7 | |||
4f9991534e | |||
51a0ed2222 | |||
a5ea100e7c | |||
0429c7f5e9 | |||
1756cced4a | |||
793a001d7c | |||
5c3774cfe6 | |||
12266b2042 | |||
e385abc83c | |||
933cbfb828 | |||
c5e725111d | |||
93993864b1 | |||
26f49151e7 | |||
4b3f9ac739 | |||
80604d3a76 | |||
e615a10371 | |||
c8f2ca2349 | |||
a67afcc932 | |||
fd7698253e | |||
32de025dce | |||
a4e1768a74 | |||
b336871303 | |||
92fa6399f7 | |||
3992341d34 | |||
8c559ef104 | |||
0bac2b062c | |||
58d028178f | |||
e06512b22f | |||
603b0944d5 | |||
918e628f9b | |||
468cf69c55 | |||
c8f3fa9f3e | |||
78136cc3a7 | |||
66724fd159 | |||
8e7f9033a3 | |||
c8f9092364 | |||
bc995835b9 | |||
1bfa908ab3 | |||
2479f7d7ef | |||
333b8679ad | |||
5da621d3dd | |||
cbed582a1a | |||
d5aa6b5bd6 | |||
33eee43263 | |||
72053b0f27 | |||
d20ef47b16 | |||
bdc05aef64 | |||
798d959bee | |||
3570aaa363 | |||
421b6a97d6 | |||
b28a5f6eef | |||
52ab9397a0 | |||
b99e539b0e | |||
fd2ef74a31 | |||
cbc25bbf31 | |||
7385b2cf25 | |||
0daa48800e | |||
ffa4e11db1 | |||
41a41e741d | |||
c5384aee58 | |||
b02c950aac | |||
2eaa304aba | |||
9faf2e4a96 | |||
0e7a89a391 | |||
af4269471d | |||
915a6c17b9 | |||
93b32d3023 | |||
bd82b34f79 | |||
c626e90ab0 | |||
c6bbb0d8e5 | |||
f48a065db0 | |||
aeb6d0d0f7 | |||
655c9e386b | |||
2ad20b953f | |||
7059eaf2d2 | |||
939fda410f | |||
35ab6acab3 | |||
f4ee067cb8 | |||
068e28381d | |||
dff52ecb11 | |||
56af303dc3 | |||
136596ddb4 | |||
e515c913d9 | |||
31eaf78035 | |||
b0d680daa0 | |||
93cbef26c7 | |||
e2b221b8fa | |||
7a33c456d3 | |||
61db817eed | |||
4894220acf | |||
74b7a8eaf5 | |||
bfa55162de | |||
776f991c1a | |||
d9d1a1e682 | |||
867ff14a4a | |||
879457ca05 | |||
efbe4ad28a | |||
64f72c0600 | |||
81c05bfa01 | |||
56abcf088d | |||
6818432cd0 | |||
79bfb037df | |||
0fce20d79d | |||
9f486c31d2 | |||
d36066dd6c | |||
a631b99c69 | |||
78211c42ea | |||
5ff5a11509 | |||
e80047e897 | |||
eee5eeae76 | |||
c3ce1903b6 | |||
21da0346c7 | |||
af2d74fde9 | |||
8de62a9811 | |||
26e28453d6 | |||
8ea30b662f | |||
cb0a2a055d | |||
14ae3c0a21 | |||
90cae34c05 | |||
7bb35889fa | |||
03a3c753bb | |||
74b1464dff | |||
ff523c9ec9 | |||
392ef93c2b | |||
29dcb5bf68 | |||
de594ca221 | |||
3545a49a79 | |||
f4681b6e40 | |||
fb16557381 | |||
61c9da5542 | |||
dbb1eb0ffe | |||
002b81c0b0 | |||
beb3f19dc0 | |||
e8f3c47b03 | |||
c58e6ba13a | |||
61e5ab4703 | |||
10385c27da | |||
0ab244f39e | |||
eafa5260db | |||
15cffa210c | |||
df8e45a193 | |||
bb8744db94 | |||
43bad87ae1 | |||
c3b297a318 | |||
6ea232eb3c | |||
0baab0f3db | |||
e53b686375 | |||
5c28af0e74 | |||
60adc35d30 | |||
024cc3b84a | |||
ac17142001 | |||
8d7066223f | |||
0cb3c04128 | |||
2649794e65 | |||
bf426c5f0d | |||
aa6b9f0382 | |||
822b420a11 | |||
294c6297d7 | |||
58fc65d198 | |||
b6bd8d7572 | |||
b08168bb90 | |||
407fa42679 | |||
aef432384a | |||
fb70083339 | |||
c9c2408176 | |||
e066bddfe9 | |||
447a600477 | |||
70f9bfff43 | |||
57c02b044c | |||
6defe962c8 | |||
267bcb3e9c | |||
b0b66881b4 | |||
9ff8d78bcd | |||
563b707497 | |||
5357e643b3 | |||
f71d132f7c | |||
ba3edda230 | |||
0767d37c07 | |||
8ba24578bc | |||
133a97ad67 | |||
4e67a3ab3f | |||
377f0010fc | |||
6e09129e4c | |||
d80e51a6b1 | |||
feb66b00da | |||
cb19eac105 | |||
6e0564ade6 | |||
05eeb7d279 | |||
2ce5fa3cce | |||
e140cdcb34 | |||
14b2db1d43 | |||
2afc7e982e |
@ -1,3 +1,3 @@
|
||||
3.2.0
|
||||
2.1.1
|
||||
# [NB: this comment has to be after the first line, see https://github.com/bazelbuild/bazelisk/issues/117]
|
||||
# When updating the Bazel version you also need to update the RBE toolchains version in package.bzl
|
||||
|
@ -19,12 +19,4 @@ build --local_ram_resources=14336
|
||||
|
||||
# All build executed remotely should be done using our RBE configuration.
|
||||
build:remote --google_default_credentials
|
||||
|
||||
# Upload to GCP's Build Status viewer to allow for us to have better viewing of execution/build
|
||||
# logs. This is only done on CI as the BES (GCP's Build Status viewer) API requires credentials
|
||||
# from service accounts, rather than end user accounts.
|
||||
build:remote --bes_backend=buildeventservice.googleapis.com
|
||||
build:remote --bes_timeout=30s
|
||||
build:remote --bes_results_url="https://source.cloud.google.com/results/invocations/"
|
||||
|
||||
build --config=remote
|
||||
|
@ -22,17 +22,17 @@ version: 2.1
|
||||
# **NOTE 1 **: If you change the cache key prefix, also sync the cache_key_fallback to match.
|
||||
# **NOTE 2 **: Keep the static part of the cache key as prefix to enable correct fallbacks.
|
||||
# See https://circleci.com/docs/2.0/caching/#restoring-cache for how prefixes work in CircleCI.
|
||||
var_3: &cache_key v7-angular-node-12-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
||||
var_3: &cache_key v6-angular-node-12-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
||||
# We invalidate the cache if the Bazel version changes because otherwise the `bazelisk` cache
|
||||
# folder will contain all previously used versions and ultimately cause the cache restoring to
|
||||
# be slower due to its growing size.
|
||||
var_4: &cache_key_fallback v7-angular-node-12-{{ checksum ".bazelversion" }}
|
||||
var_3_win: &cache_key_win v7-angular-win-node-12-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
||||
var_4_win: &cache_key_win_fallback v7-angular-win-node-12-{{ checksum ".bazelversion" }}
|
||||
var_4: &cache_key_fallback v6-angular-node-12-{{ checksum ".bazelversion" }}
|
||||
var_3_win: &cache_key_win v6-angular-win-node-12-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
||||
var_4_win: &cache_key_win_fallback v6-angular-win-node-12-{{ checksum ".bazelversion" }}
|
||||
|
||||
# Cache key for the `components-repo-unit-tests` job. **Note** when updating the SHA in the
|
||||
# cache keys also update the SHA for the "COMPONENTS_REPO_COMMIT" environment variable.
|
||||
var_5: &components_repo_unit_tests_cache_key v7-angular-components-f428c00465dfcf8a020237f22532480eedbd2cb6
|
||||
var_5: &components_repo_unit_tests_cache_key v7-angular-components-caad0b54ed41949f0ee529c152508749875bc9af
|
||||
var_6: &components_repo_unit_tests_cache_key_fallback v7-angular-components-
|
||||
|
||||
# Workspace initially persisted by the `setup` job, and then enhanced by `build-npm-packages` and
|
||||
@ -67,6 +67,9 @@ var_10: &only_on_master
|
||||
# **NOTE 1**: Pin to exact images using an ID (SHA). See https://circleci.com/docs/2.0/circleci-images/#using-a-docker-image-id-to-pin-an-image-to-a-fixed-version.
|
||||
# (Using the tag in not necessary when pinning by ID, but include it anyway for documentation purposes.)
|
||||
# **NOTE 2**: If you change the version of the docker images, also change the `cache_key` suffix.
|
||||
# **NOTE 3**: If you change the version of the `*-browsers` docker image, make sure the
|
||||
# `--versions.chrome` arg in `integration/bazel-schematics/test.sh` specifies a
|
||||
# ChromeDriver version that is compatible with the Chrome version in the image.
|
||||
executors:
|
||||
default-executor:
|
||||
parameters:
|
||||
@ -117,7 +120,7 @@ commands:
|
||||
sudo apt-get update
|
||||
# Install GTK+ graphical user interface (libgtk-3-0), advanced linux sound architecture (libasound2)
|
||||
# and network security service libraries (libnss3) & X11 Screen Saver extension library (libssx1)
|
||||
# which are dependencies of chrome & needed for karma & protractor headless chrome tests.
|
||||
# which are dependendies of chrome & needed for karma & protractor headless chrome tests.
|
||||
# This is a very small install which takes around 7s in comparing to using the full
|
||||
# circleci/node:x.x.x-browsers image.
|
||||
sudo apt-get -y install libgtk-3-0 libasound2 libnss3 libxss1
|
||||
@ -160,7 +163,7 @@ commands:
|
||||
description: Sets up a domain that resolves to the local host.
|
||||
steps:
|
||||
- run:
|
||||
name: Preparing environment for running tests on Sauce Labs.
|
||||
name: Preparing environment for running tests on Saucelabs.
|
||||
command: |
|
||||
# For SauceLabs jobs, we set up a domain which resolves to the machine which launched
|
||||
# the tunnel. We do this because devices are sometimes not able to properly resolve
|
||||
@ -172,13 +175,13 @@ commands:
|
||||
setSecretVar SAUCE_ACCESS_KEY $(echo $SAUCE_ACCESS_KEY | rev)
|
||||
- run:
|
||||
# Sets up a local domain in the machine's host file that resolves to the local
|
||||
# host. This domain is helpful in Sauce Labs tests where devices are not able to
|
||||
# host. This domain is helpful in Saucelabs tests where devices are not able to
|
||||
# properly resolve `localhost` or `127.0.0.1` through the sauce-connect tunnel.
|
||||
name: Setting up alias domain for local host.
|
||||
command: echo "127.0.0.1 $SAUCE_LOCALHOST_ALIAS_DOMAIN" | sudo tee -a /etc/hosts
|
||||
|
||||
# Normally this would be an individual job instead of a command.
|
||||
# But startup and setup time for each individual windows job are high enough to discourage
|
||||
# But startup and setup time for each invidual windows job are high enough to discourage
|
||||
# many small jobs, so instead we use a command for setup unless the gain becomes significant.
|
||||
setup_win:
|
||||
description: Setup windows node environment
|
||||
@ -596,8 +599,8 @@ jobs:
|
||||
- run:
|
||||
name: Decrypt github credentials
|
||||
# We need ensure that the same default digest is used for encoding and decoding with
|
||||
# OpenSSL. OpenSSL versions might have different default digests which can cause
|
||||
# decryption failures based on the installed OpenSSL version. https://stackoverflow.com/a/39641378/4317734
|
||||
# openssl. Openssl versions might have different default digests which can cause
|
||||
# decryption failures based on the installed openssl version. https://stackoverflow.com/a/39641378/4317734
|
||||
command: 'openssl aes-256-cbc -d -in .circleci/github_token -md md5 -k "${KEY}" -out ~/.git_credentials'
|
||||
- run: ./scripts/ci/publish-build-artifacts.sh
|
||||
|
||||
|
@ -74,7 +74,7 @@ setPublicVar COMPONENTS_REPO_TMP_DIR "/tmp/angular-components-repo"
|
||||
setPublicVar COMPONENTS_REPO_URL "https://github.com/angular/components.git"
|
||||
setPublicVar COMPONENTS_REPO_BRANCH "master"
|
||||
# **NOTE**: When updating the commit SHA, also update the cache key in the CircleCI `config.yml`.
|
||||
setPublicVar COMPONENTS_REPO_COMMIT "f428c00465dfcf8a020237f22532480eedbd2cb6"
|
||||
setPublicVar COMPONENTS_REPO_COMMIT "caad0b54ed41949f0ee529c152508749875bc9af"
|
||||
|
||||
|
||||
####################################################################################################
|
||||
|
@ -60,12 +60,11 @@ if (require.resolve === module) {
|
||||
|
||||
// Helpers
|
||||
function _main(args) {
|
||||
triggerWebhook(...args)
|
||||
.then(
|
||||
({statusCode, responseText}) => (200 <= statusCode && statusCode < 400) ?
|
||||
triggerWebhook(...args).
|
||||
then(({statusCode, responseText}) => (200 <= statusCode && statusCode < 400) ?
|
||||
console.log(`Status: ${statusCode}\n${responseText}`) :
|
||||
Promise.reject(new Error(`Request failed (status: ${statusCode}): ${responseText}`)))
|
||||
.catch(err => {
|
||||
Promise.reject(new Error(`Request failed (status: ${statusCode}): ${responseText}`))).
|
||||
catch(err => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
@ -78,12 +77,15 @@ function postJson(url, data) {
|
||||
const statusCode = res.statusCode || -1;
|
||||
let responseText = '';
|
||||
|
||||
res.on('error', reject)
|
||||
.on('data', d => responseText += d)
|
||||
.on('end', () => resolve({statusCode, responseText}));
|
||||
res.
|
||||
on('error', reject).
|
||||
on('data', d => responseText += d).
|
||||
on('end', () => resolve({statusCode, responseText}));
|
||||
};
|
||||
|
||||
request(url, opts, onResponse).on('error', reject).end(JSON.stringify(data));
|
||||
request(url, opts, onResponse).
|
||||
on('error', reject).
|
||||
end(JSON.stringify(data));
|
||||
});
|
||||
}
|
||||
|
||||
|
2
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
2
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
@ -32,7 +32,7 @@ Existing issues often contain information about workarounds, resolution, or prog
|
||||
|
||||
## 🔬 Minimal Reproduction
|
||||
<!--
|
||||
Please create and share minimal reproduction of the issue starting with this template: https://stackblitz.com/fork/angular-ivy
|
||||
Please create and share minimal reproduction of the issue starting with this template: https://stackblitz.com/fork/angular-issue-repro2
|
||||
-->
|
||||
<!-- ✍️--> https://stackblitz.com/...
|
||||
|
||||
|
6
.github/angular-robot.yml
vendored
6
.github/angular-robot.yml
vendored
@ -154,12 +154,6 @@ triage:
|
||||
-
|
||||
- "type: RFC / Discussion / question"
|
||||
- "comp: *"
|
||||
-
|
||||
- "type: confusing"
|
||||
- "comp: *"
|
||||
-
|
||||
- "type: use-case"
|
||||
- "comp: *"
|
||||
|
||||
# options for the triage PR plugin
|
||||
triagePR:
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -42,6 +42,3 @@ yarn-error.log
|
||||
|
||||
.notes.md
|
||||
baseline.json
|
||||
|
||||
# Ignore .history for the xyz.local-history VSCode extension
|
||||
.history
|
||||
|
145
.gitmessage
145
.gitmessage
@ -1,145 +0,0 @@
|
||||
<type>(<scope>): <summary>
|
||||
|
||||
<Describe the motivation behind this change - explain WHY you are making this change. Wrap all lines
|
||||
at 100 characters.>
|
||||
|
||||
Fixes #<issue number>
|
||||
|
||||
# ────────────────────────────────────────── 100 chars ────────────────────────────────────────────┤
|
||||
|
||||
|
||||
# Example Commit Messages
|
||||
# =======================
|
||||
|
||||
|
||||
# ─── Example: Simple refactor ────────────────────────────────────────────────────────────────────┤
|
||||
# refactor(core): rename refreshDynamicEmbeddedViews to refreshEmbeddedViews
|
||||
#
|
||||
# Improve code readability. The original name no longer matches how the function is used.
|
||||
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
|
||||
|
||||
# ─── Example: Simple docs change ─────────────────────────────────────────────────────────────────┤
|
||||
# docs: clarify the service limitation in providers.md guide
|
||||
#
|
||||
# Fixes #36332
|
||||
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
|
||||
|
||||
# ─── Example: A bug fix ──────────────────────────────────────────────────────────────────────────┤
|
||||
# fix(ngcc): ensure lockfile is removed when `analyzeFn` fails
|
||||
#
|
||||
# Previously an error thrown in the `analyzeFn` would cause the ngcc process to exit immediately
|
||||
# without removing the lockfile, and potentially before the unlocker process had been successfully
|
||||
# spawned resulting in the lockfile being orphaned and left behind.
|
||||
#
|
||||
# Now we catch these errors and remove the lockfile as needed.
|
||||
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
|
||||
|
||||
# ─── Example: Breaking change ────────────────────────────────────────────────────────────────────┤
|
||||
# feat(bazel): simplify ng_package by dropping esm5 and fesm5
|
||||
#
|
||||
# esm5 and fesm5 distributions are no longer needed and have been deprecated in the past.
|
||||
#
|
||||
# https://v9.angular.io/guide/deprecations#esm5-and-fesm5-code-formats-in-angular-npm-packages
|
||||
#
|
||||
# This commit modifies ng_package to no longer distribute these two formats in npm packages built by
|
||||
# ng_package (e.g. @angular/core).
|
||||
#
|
||||
# This commit intentionally doesn't fully clean up the ng_package rule to remove all traces of esm5
|
||||
# and fems5 build artifacts as that is a bigger cleanup and currently we are narrowing down the
|
||||
# scope of this change to the MVP needed for v10, which in this case is 'do not put esm5 and fesm5'
|
||||
# into the npm packages.
|
||||
#
|
||||
# More cleanup to follow: https://angular-team.atlassian.net/browse/FW-2143
|
||||
#
|
||||
# BREAKING CHANGE: esm5 and fesm5 format is no longer distributed in Angular's npm packages e.g.
|
||||
# @angular/core
|
||||
#
|
||||
# Angular CLI will automatically downlevel the code to es5 if differential loading is enabled in the
|
||||
# Angular project, so no action is required from Angular CLI users.
|
||||
#
|
||||
# If you are not using Angular CLI to build your application or library, and you need to be able to
|
||||
# build es5 artifacts, then you will need to downlevel the distributed Angular code to es5 on your
|
||||
# own.
|
||||
#
|
||||
#
|
||||
# Fixes #1234
|
||||
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
|
||||
|
||||
|
||||
# Angular Commit Message Format
|
||||
# =============================
|
||||
#
|
||||
# The full specification of the Angular Commit Message Format can be found at
|
||||
# https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
|
||||
#
|
||||
# The following is an excerpt of the specification with the most commonly needed info.
|
||||
#
|
||||
# Each commit message consists of a *header*, a *body*, and a *footer*.
|
||||
#
|
||||
# <header>
|
||||
# <BLANK LINE>
|
||||
# <body>
|
||||
# <BLANK LINE>
|
||||
# <footer>
|
||||
#
|
||||
# The header is mandatory.
|
||||
#
|
||||
# The body is mandatory for all commits except for those of scope "docs". When the body is required
|
||||
# it must be at least 20 characters long.
|
||||
#
|
||||
# The footer is optional.
|
||||
#
|
||||
# Any line of the commit message cannot be longer than 100 characters.
|
||||
#
|
||||
#
|
||||
# Commit Message Header
|
||||
# ---------------------
|
||||
#
|
||||
# <type>(<scope>): <short summary>
|
||||
# │ │ │
|
||||
# │ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
|
||||
# │ │
|
||||
# │ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
|
||||
# │ elements|forms|http|language-service|localize|platform-browser|
|
||||
# │ platform-browser-dynamic|platform-server|platform-webworker|
|
||||
# │ platform-webworker-dynamic|router|service-worker|upgrade|zone.js|
|
||||
# │ packaging|changelog|dev-infra|docs-infra|migrations|ngcc|ve
|
||||
# │ https://github.com/angular/angular/blob/master/CONTRIBUTING.md#scope
|
||||
# │
|
||||
# └─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
|
||||
# https://github.com/angular/angular/blob/master/CONTRIBUTING.md#type
|
||||
#
|
||||
#
|
||||
# Commit Message Body
|
||||
# ---------------------
|
||||
#
|
||||
# Just as in the summary, use the imperative, present tense: "fix" not "fixed" nor "fixes".
|
||||
#
|
||||
# Explain the motivation for the change in the commit message body. This commit message should
|
||||
# explain WHY you are making the change. You can include a comparison of the previous behavior with
|
||||
# the new behavior in order to illustrate the impact of the change.
|
||||
#
|
||||
#
|
||||
# Commit Message Footer
|
||||
# ---------------------
|
||||
#
|
||||
# The footer can contain information about breaking changes and is also the place to reference
|
||||
# GitHub issues, Jira tickets, and other PRs that this commit closes or is related to.
|
||||
#
|
||||
# ```
|
||||
# BREAKING CHANGE: <breaking change summary>
|
||||
# <BLANK LINE>
|
||||
# <breaking change description + migration instructions>
|
||||
# <BLANK LINE>
|
||||
# <BLANK LINE>
|
||||
# Fixes #<issue number>
|
||||
# ```
|
||||
#
|
||||
# Breaking Change section should start with the phrase "BREAKING CHANGE: " followed by a summary of
|
||||
# the breaking change, a blank line, and a detailed description of the breaking change that also
|
||||
# includes migration instructions.
|
||||
#
|
123
.ng-dev-config.ts
Normal file
123
.ng-dev-config.ts
Normal file
@ -0,0 +1,123 @@
|
||||
import {MergeConfig} from './dev-infra/pr/merge/config';
|
||||
|
||||
// The configuration for `ng-dev commit-message` commands.
|
||||
const commitMessage = {
|
||||
'maxLength': 120,
|
||||
'minBodyLength': 100,
|
||||
'types': [
|
||||
'build',
|
||||
'ci',
|
||||
'docs',
|
||||
'feat',
|
||||
'fix',
|
||||
'perf',
|
||||
'refactor',
|
||||
'release',
|
||||
'style',
|
||||
'test',
|
||||
],
|
||||
'scopes': [
|
||||
'animations',
|
||||
'bazel',
|
||||
'benchpress',
|
||||
'changelog',
|
||||
'common',
|
||||
'compiler',
|
||||
'compiler-cli',
|
||||
'core',
|
||||
'dev-infra',
|
||||
'docs-infra',
|
||||
'elements',
|
||||
'forms',
|
||||
'http',
|
||||
'language-service',
|
||||
'localize',
|
||||
'ngcc',
|
||||
'packaging',
|
||||
'platform-browser',
|
||||
'platform-browser-dynamic',
|
||||
'platform-server',
|
||||
'platform-webworker',
|
||||
'platform-webworker-dynamic',
|
||||
'router',
|
||||
'service-worker',
|
||||
'upgrade',
|
||||
've',
|
||||
'zone.js',
|
||||
]
|
||||
};
|
||||
|
||||
// The configuration for `ng-dev format` commands.
|
||||
const format = {
|
||||
'clang-format': {
|
||||
'matchers': [
|
||||
'dev-infra/**/*.{js,ts}',
|
||||
'packages/**/*.{js,ts}',
|
||||
'!packages/zone.js',
|
||||
'!packages/common/locales/**/*.{js,ts}',
|
||||
'!packages/common/src/i18n/available_locales.ts',
|
||||
'!packages/common/src/i18n/currencies.ts',
|
||||
'!packages/common/src/i18n/locale_en.ts',
|
||||
'modules/benchmarks/**/*.{js,ts}',
|
||||
'modules/playground/**/*.{js,ts}',
|
||||
'tools/**/*.{js,ts}',
|
||||
'!tools/gulp-tasks/cldr/extract.js',
|
||||
'!tools/public_api_guard/**/*.d.ts',
|
||||
'!tools/ts-api-guardian/test/fixtures/**',
|
||||
'*.{js,ts}',
|
||||
'!**/node_modules/**',
|
||||
'!**/dist/**',
|
||||
'!**/built/**',
|
||||
'!shims_for_IE.js',
|
||||
]
|
||||
},
|
||||
'buildifier': true
|
||||
};
|
||||
|
||||
/** Github metadata information for `ng-dev` commands. */
|
||||
const github = {
|
||||
owner: 'angular',
|
||||
name: 'angular',
|
||||
};
|
||||
|
||||
// Configuration for the `ng-dev pr merge` command. The command can be used
|
||||
// for merging upstream pull requests into branches based on a PR target label.
|
||||
const merge = () => {
|
||||
// TODO: resume dynamically determining patch branch
|
||||
const patch = '10.0.x';
|
||||
const config: MergeConfig = {
|
||||
githubApiMerge: false,
|
||||
claSignedLabel: 'cla: yes',
|
||||
mergeReadyLabel: /^PR action: merge(-assistance)?/,
|
||||
commitMessageFixupLabel: 'commit message fixup',
|
||||
labels: [
|
||||
{
|
||||
pattern: 'PR target: master-only',
|
||||
branches: ['master'],
|
||||
},
|
||||
{
|
||||
pattern: 'PR target: patch-only',
|
||||
branches: [patch],
|
||||
},
|
||||
{
|
||||
pattern: 'PR target: master & patch',
|
||||
branches: ['master', patch],
|
||||
},
|
||||
],
|
||||
requiredBaseCommits: {
|
||||
// PRs that target either `master` or the patch branch, need to be rebased
|
||||
// on top of the latest commit message validation fix.
|
||||
'master': '4341743b4a6d7e23c6f944aa9e34166b701369a1',
|
||||
[patch]: '2a53f471592f424538802907aca1f60f1177a86d'
|
||||
},
|
||||
};
|
||||
return config;
|
||||
};
|
||||
|
||||
// Export function to build ng-dev configuration object.
|
||||
module.exports = {
|
||||
commitMessage,
|
||||
format,
|
||||
github,
|
||||
merge,
|
||||
};
|
@ -1,52 +0,0 @@
|
||||
import {CommitMessageConfig} from '../dev-infra/commit-message/config';
|
||||
|
||||
/**
|
||||
* The configuration for `ng-dev commit-message` commands.
|
||||
*/
|
||||
export const commitMessage: CommitMessageConfig = {
|
||||
maxLineLength: 120,
|
||||
minBodyLength: 20,
|
||||
minBodyLengthTypeExcludes: ['docs'],
|
||||
types: [
|
||||
'build',
|
||||
'ci',
|
||||
'docs',
|
||||
'feat',
|
||||
'fix',
|
||||
'perf',
|
||||
'refactor',
|
||||
'release',
|
||||
'style',
|
||||
'test',
|
||||
],
|
||||
scopes: [
|
||||
'animations',
|
||||
'bazel',
|
||||
'benchpress',
|
||||
'changelog',
|
||||
'common',
|
||||
'compiler',
|
||||
'compiler-cli',
|
||||
'core',
|
||||
'dev-infra',
|
||||
'docs-infra',
|
||||
'elements',
|
||||
'forms',
|
||||
'http',
|
||||
'language-service',
|
||||
'localize',
|
||||
'migrations',
|
||||
'ngcc',
|
||||
'packaging',
|
||||
'platform-browser',
|
||||
'platform-browser-dynamic',
|
||||
'platform-server',
|
||||
'platform-webworker',
|
||||
'platform-webworker-dynamic',
|
||||
'router',
|
||||
'service-worker',
|
||||
'upgrade',
|
||||
've',
|
||||
'zone.js',
|
||||
]
|
||||
};
|
@ -1,11 +0,0 @@
|
||||
import {commitMessage} from './commit-message';
|
||||
import {format} from './format';
|
||||
import {github} from './github';
|
||||
import {merge} from './merge';
|
||||
|
||||
module.exports = {
|
||||
commitMessage,
|
||||
format,
|
||||
github,
|
||||
merge,
|
||||
};
|
@ -1,22 +0,0 @@
|
||||
import {FormatConfig} from '../dev-infra/format/config';
|
||||
|
||||
/**
|
||||
* Configuration for the `ng-dev format` command.
|
||||
*/
|
||||
export const format: FormatConfig = {
|
||||
'clang-format': {
|
||||
'matchers': [
|
||||
'**/*.{js,ts}',
|
||||
// TODO: burn down format failures and remove aio and integration exceptions.
|
||||
'!aio/**',
|
||||
'!integration/**',
|
||||
// Both third_party and .yarn are directories containing copied code which should
|
||||
// not be modified.
|
||||
'!third_party/**',
|
||||
'!.yarn/**',
|
||||
// Do not format d.ts files as they are generated
|
||||
'!**/*.d.ts',
|
||||
]
|
||||
},
|
||||
'buildifier': true
|
||||
};
|
@ -1,15 +0,0 @@
|
||||
# The file is inert unless it's explicitly included into the local git config via:
|
||||
#
|
||||
# ```
|
||||
# git config --add include.path '../.ng-dev/gitconfig'
|
||||
# ```
|
||||
#
|
||||
# Calling that command will append the following into `.git/config` of the current git workspace
|
||||
# (i.e. $GIT_DIR, typically `angular/.git/config`):
|
||||
#
|
||||
# ```
|
||||
# [include]
|
||||
# path = ../.ng-dev/gitconfig
|
||||
# ```
|
||||
[commit]
|
||||
template = .gitmessage
|
@ -1,11 +0,0 @@
|
||||
import {GithubConfig} from '../dev-infra/utils/config';
|
||||
|
||||
/**
|
||||
* Github configuration for the `ng-dev` command. This repository is used as
|
||||
* remote for the merge script and other utilities like `ng-dev pr rebase`.
|
||||
*/
|
||||
|
||||
export const github: GithubConfig = {
|
||||
owner: 'angular',
|
||||
name: 'angular'
|
||||
};
|
@ -1,38 +0,0 @@
|
||||
import {MergeConfig} from '../dev-infra/pr/merge/config';
|
||||
|
||||
/**
|
||||
* Configuration for the merge tool in `ng-dev`. This sets up the labels which
|
||||
* are respected by the merge script (e.g. the target labels).
|
||||
*/
|
||||
export const merge = (): MergeConfig => {
|
||||
// TODO: resume dynamically determining patch branch
|
||||
const patch = '10.0.x';
|
||||
return {
|
||||
githubApiMerge: false,
|
||||
claSignedLabel: 'cla: yes',
|
||||
mergeReadyLabel: /^PR action: merge(-assistance)?/,
|
||||
caretakerNoteLabel: 'PR action: merge-assistance',
|
||||
commitMessageFixupLabel: 'commit message fixup',
|
||||
labels: [
|
||||
{
|
||||
pattern: 'PR target: master-only',
|
||||
branches: ['master'],
|
||||
},
|
||||
{
|
||||
pattern: 'PR target: patch-only',
|
||||
branches: [patch],
|
||||
},
|
||||
{
|
||||
pattern: 'PR target: master & patch',
|
||||
branches: ['master', patch],
|
||||
},
|
||||
],
|
||||
requiredBaseCommits: {
|
||||
// PRs that target either `master` or the patch branch, need to be rebased
|
||||
// on top of the latest commit message validation fix.
|
||||
// These SHAs are the commits that update the required license text in the header.
|
||||
'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a',
|
||||
[patch]: '27b95ba64a5d99757f4042073fd1860e20e3ed24'
|
||||
},
|
||||
};
|
||||
};
|
320
.pullapprove.yml
320
.pullapprove.yml
@ -34,8 +34,41 @@
|
||||
####################################################################################
|
||||
# GitHub usernames
|
||||
####################################################################################
|
||||
# See reviewer list under `required-minimum-review` group. Team member names and
|
||||
# usernames are managed there.
|
||||
# aikidave - Dave Shevitz
|
||||
# alan-agius4 - Alan Agius
|
||||
# alxhub - Alex Rickabaugh
|
||||
# AndrewKushnir - Andrew Kushnir
|
||||
# andrewseguin - Andrew Seguin
|
||||
# atscott - Andrew Scott
|
||||
# ayazhafiz - Ayaz Hafiz
|
||||
# clydin - Charles Lyding
|
||||
# crisbeto - Kristiyan Kostadinov
|
||||
# dennispbrown - Denny Brown
|
||||
# devversion - Paul Gschwendtner
|
||||
# dgp1130 - Doug Parker
|
||||
# filipesilva - Filipe Silva
|
||||
# gkalpak - Georgios Kalpakas
|
||||
# gregmagolan - Greg Magolan
|
||||
# IgorMinar - Igor Minar
|
||||
# jbogarthyde - Judy Bogart
|
||||
# jelbourn - Jeremy Elbourn
|
||||
# JiaLiPassion - Jia Li
|
||||
# JoostK - Joost Koehoorn
|
||||
# josephperrott - Joey Perrott
|
||||
# juleskremer - Jules Kremer
|
||||
# kapunahelewong - Kapunahele Wong
|
||||
# kara - Kara Erickson
|
||||
# kyliau - Keen Yee Liau
|
||||
# manughub - Manu Murthy
|
||||
# matsko - Matias Niemela
|
||||
# mgechev - Minko Gechev
|
||||
# mhevery - Miško Hevery
|
||||
# michaelprentice - Michael Prentice
|
||||
# mmalerba - Miles Malerba
|
||||
# petebacondarwin - Pete Bacon Darwin
|
||||
# pkozlowski-opensource - Pawel Kozlowski
|
||||
# robwormald - Rob Wormald
|
||||
# StephenFluin - Stephen Fluin
|
||||
|
||||
|
||||
####################################################################################
|
||||
@ -47,8 +80,8 @@
|
||||
# Used for approving minor changes, large-scale refactorings, and in emergency situations.
|
||||
#
|
||||
# IgorMinar
|
||||
# jelbourn
|
||||
# josephperrott
|
||||
# kara
|
||||
# mhevery
|
||||
#
|
||||
# =========================================================
|
||||
@ -67,35 +100,8 @@ version: 3
|
||||
# Meta field that goes unused by PullApprove to allow for defining aliases to be
|
||||
# used throughout the config.
|
||||
meta:
|
||||
# The following groups have no file based conditions and will be initially `active` on all PRs
|
||||
# - `global-approvers`
|
||||
# - `global-docs-approvers`
|
||||
# - `required-minimum-review`
|
||||
#
|
||||
# By checking the number of active/pending/rejected groups when these are excluded, we can determine
|
||||
# if any other groups are matched.
|
||||
#
|
||||
# Note: Because all inactive groups start as pending, we are only checking pending and rejected active groups.
|
||||
#
|
||||
# Also note that the ordering of groups matters in this file. The only groups visible to the current
|
||||
# one are those that appear above it.
|
||||
no-groups-above-this-pending: &no-groups-above-this-pending
|
||||
len(groups.active.pending.exclude("required-minimum-review").exclude("global-approvers").exclude("global-docs-approvers")) == 0
|
||||
no-groups-above-this-rejected: &no-groups-above-this-rejected
|
||||
len(groups.active.rejected.exclude("required-minimum-review").exclude("global-approvers").exclude("global-docs-approvers")) == 0
|
||||
no-groups-above-this-active: &no-groups-above-this-active
|
||||
len(groups.active.exclude("required-minimum-review").exclude("global-approvers").exclude("global-docs-approvers")) == 0
|
||||
|
||||
can-be-global-approved: &can-be-global-approved "\"global-approvers\" not in groups.approved"
|
||||
can-be-global-docs-approved: &can-be-global-docs-approved "\"global-docs-approvers\" not in groups.approved"
|
||||
defaults: &defaults
|
||||
reviews:
|
||||
# Authors provide their approval implicitly, this approval allows for a reviewer
|
||||
# from a group not to need a review specifically for an area of the repository
|
||||
# they own. This is coupled with the `required-minimum-review` group which requires
|
||||
# that all PRs are reviewed by at least one team member who is not the author of
|
||||
# the PR.
|
||||
author_value: 1
|
||||
1: &can-be-global-approved "\"global-approvers\" not in groups.approved"
|
||||
2: &can-be-global-docs-approved "\"global-docs-approvers\" not in groups.approved"
|
||||
|
||||
# turn on 'draft' support
|
||||
# https://docs.pullapprove.com/config/github-api-version/
|
||||
@ -115,54 +121,6 @@ pullapprove_conditions:
|
||||
|
||||
|
||||
groups:
|
||||
# =========================================================
|
||||
# Require review on all PRs
|
||||
#
|
||||
# All PRs require at least one review. This rule will not
|
||||
# request any reviewers, however will require that at least
|
||||
# one review is provided before the group is satisfied.
|
||||
# =========================================================
|
||||
required-minimum-review:
|
||||
reviews:
|
||||
request: 0 # Do not request any reviews from the reviewer group
|
||||
required: 1 # Require that all PRs have approval from at least one of the users in the group
|
||||
author_value: 0 # The author of the PR cannot provide an approval for themself
|
||||
reviewers:
|
||||
users:
|
||||
- aikidave # Dave Shevitz
|
||||
- alan-agius4 # Alan Agius
|
||||
- alxhub # Alex Rickabaugh
|
||||
- AndrewKushnir # Andrew Kushnir
|
||||
- andrewseguin # Andrew Seguin
|
||||
- atscott # Andrew Scott
|
||||
- ayazhafiz # Ayaz Hafiz
|
||||
- clydin # Charles Lyding
|
||||
- crisbeto # Kristiyan Kostadinov
|
||||
- dennispbrown # Denny Brown
|
||||
- devversion # Paul Gschwendtner
|
||||
- dgp1130 # Doug Parker
|
||||
- filipesilva # Filipe Silva
|
||||
- gkalpak # Georgios Kalpakas
|
||||
- gregmagolan # Greg Magolan
|
||||
- IgorMinar # Igor Minar
|
||||
- jbogarthyde # Judy Bogart
|
||||
- jelbourn # Jeremy Elbourn
|
||||
- JiaLiPassion # Jia Li
|
||||
- JoostK # Joost Koehoorn
|
||||
- josephperrott # Joey Perrott
|
||||
- juleskremer # Jules Kremer
|
||||
- kapunahelewong # Kapunahele Wong
|
||||
- kara # Kara Erickson
|
||||
- kyliau # Keen Yee Liau
|
||||
- manughub # Manu Murthy
|
||||
- mgechev # Minko Gechev
|
||||
- mhevery # Miško Hevery
|
||||
- michaelprentice # Michael Prentice
|
||||
- mmalerba # Miles Malerba
|
||||
- petebacondarwin # Pete Bacon Darwin
|
||||
- pkozlowski-opensource # Pawel Kozlowski
|
||||
- StephenFluin # Stephen Fluin
|
||||
|
||||
# =========================================================
|
||||
# Global Approvers
|
||||
#
|
||||
@ -203,7 +161,6 @@ groups:
|
||||
# Framework: Animations
|
||||
# =========================================================
|
||||
fw-animations:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -221,16 +178,13 @@ groups:
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
- crisbeto
|
||||
- IgorMinar
|
||||
- jelbourn
|
||||
- matsko
|
||||
|
||||
|
||||
# =========================================================
|
||||
# Framework: Compiler
|
||||
# =========================================================
|
||||
fw-compiler:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -249,13 +203,13 @@ groups:
|
||||
- alxhub
|
||||
- AndrewKushnir
|
||||
- JoostK
|
||||
- kara
|
||||
|
||||
|
||||
# =========================================================
|
||||
# Framework: Compiler / ngcc
|
||||
# =========================================================
|
||||
fw-ngcc:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -272,7 +226,6 @@ groups:
|
||||
# Framework: Migrations
|
||||
# =========================================================
|
||||
fw-migrations:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -282,13 +235,13 @@ groups:
|
||||
- alxhub
|
||||
- crisbeto
|
||||
- devversion
|
||||
- kara
|
||||
|
||||
|
||||
# =========================================================
|
||||
# Framework: Core
|
||||
# =========================================================
|
||||
fw-core:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -362,38 +315,26 @@ groups:
|
||||
'aio/content/guide/ngmodule-vs-jsmodule.md',
|
||||
'aio/content/guide/module-types.md',
|
||||
'aio/content/guide/template-syntax.md',
|
||||
'aio/content/guide/built-in-template-functions.md',
|
||||
'aio/content/examples/built-in-template-functions/**',
|
||||
'aio/content/guide/event-binding.md',
|
||||
'aio/content/examples/event-binding/**',
|
||||
'aio/content/guide/interpolation.md',
|
||||
'aio/content/examples/interpolation/**',
|
||||
'aio/content/examples/template-syntax/**',
|
||||
'aio/content/images/guide/template-syntax/**',
|
||||
'aio/content/guide/binding-syntax.md',
|
||||
'aio/content/examples/binding-syntax/**',
|
||||
'aio/content/guide/property-binding.md',
|
||||
'aio/content/examples/property-binding/**',
|
||||
'aio/content/guide/attribute-binding.md',
|
||||
'aio/content/examples/attribute-binding/**',
|
||||
'aio/content/guide/two-way-binding.md',
|
||||
'aio/content/examples/two-way-binding/**',
|
||||
'aio/content/guide/built-in-directives.md',
|
||||
'aio/content/examples/built-in-directives/**',
|
||||
'aio/content/images/guide/built-in-directives/**',
|
||||
'aio/content/guide/template-reference-variables.md',
|
||||
'aio/content/examples/template-reference-variables/**',
|
||||
'aio/content/guide/inputs-outputs.md',
|
||||
'aio/content/examples/inputs-outputs/**',
|
||||
'aio/content/images/guide/inputs-outputs/**',
|
||||
'aio/content/guide/template-expression-operators.md',
|
||||
'aio/content/examples/template-expression-operators/**',
|
||||
'aio/content/guide/pipes.md',
|
||||
'aio/content/examples/pipes/**',
|
||||
'aio/content/images/guide/pipes/**',
|
||||
'aio/content/guide/providers.md',
|
||||
'aio/content/examples/providers/**',
|
||||
'aio/content/images/guide/providers/**',
|
||||
'aio/content/guide/singleton-services.md',
|
||||
'aio/content/guide/set-document-title.md',
|
||||
'aio/content/examples/set-document-title/**',
|
||||
@ -401,9 +342,7 @@ groups:
|
||||
'aio/content/guide/sharing-ngmodules.md',
|
||||
'aio/content/guide/structural-directives.md',
|
||||
'aio/content/examples/structural-directives/**',
|
||||
'aio/content/guide/svg-in-templates.md',
|
||||
'aio/content/images/guide/structural-directives/**',
|
||||
'aio/content/guide/template-statements.md',
|
||||
'aio/content/guide/user-input.md',
|
||||
'aio/content/examples/user-input/**',
|
||||
'aio/content/images/guide/user-input/**'
|
||||
@ -413,7 +352,7 @@ groups:
|
||||
- alxhub
|
||||
- AndrewKushnir
|
||||
- atscott
|
||||
- ~kara # do not request reviews from Kara, but allow her to approve PRs
|
||||
- kara
|
||||
- mhevery
|
||||
- pkozlowski-opensource
|
||||
|
||||
@ -422,13 +361,13 @@ groups:
|
||||
# Framework: Http
|
||||
# =========================================================
|
||||
fw-http:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
- >
|
||||
contains_any_globs(files, [
|
||||
'packages/common/http/**',
|
||||
'packages/http/**',
|
||||
'packages/examples/http/**',
|
||||
'aio/content/guide/http.md',
|
||||
'aio/content/examples/http/**',
|
||||
@ -444,7 +383,6 @@ groups:
|
||||
# Framework: Elements
|
||||
# =========================================================
|
||||
fw-elements:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -465,7 +403,6 @@ groups:
|
||||
# Framework: Forms
|
||||
# =========================================================
|
||||
fw-forms:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -498,7 +435,6 @@ groups:
|
||||
# Framework: i18n
|
||||
# =========================================================
|
||||
fw-i18n:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -532,7 +468,6 @@ groups:
|
||||
# Framework: Platform Server
|
||||
# =========================================================
|
||||
fw-platform-server:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -552,7 +487,6 @@ groups:
|
||||
# Framework: Router
|
||||
# =========================================================
|
||||
fw-router:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -561,9 +495,6 @@ groups:
|
||||
'packages/router/**',
|
||||
'packages/examples/router/**',
|
||||
'aio/content/guide/router.md',
|
||||
'aio/content/guide/router-tutorial.md',
|
||||
'aio/content/guide/router-tutorial-toh.md',
|
||||
'aio/content/examples/router-tutorial/**',
|
||||
'aio/content/examples/router/**',
|
||||
'aio/content/images/guide/router/**'
|
||||
])
|
||||
@ -576,7 +507,6 @@ groups:
|
||||
# Framework: Service Worker
|
||||
# =========================================================
|
||||
fw-service-worker:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -604,7 +534,6 @@ groups:
|
||||
# Framework: Upgrade
|
||||
# =========================================================
|
||||
fw-upgrade:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -635,7 +564,6 @@ groups:
|
||||
# Framework: Testing
|
||||
# =========================================================
|
||||
fw-testing:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -643,14 +571,6 @@ groups:
|
||||
contains_any_globs(files.exclude('packages/compiler-cli/**'), [
|
||||
'**/testing/**',
|
||||
'aio/content/guide/testing.md',
|
||||
'aio/content/guide/test-debugging.md',
|
||||
'aio/content/guide/testing-attribute-directives.md',
|
||||
'aio/content/guide/testing-code-coverage.md',
|
||||
'aio/content/guide/testing-components-basics.md',
|
||||
'aio/content/guide/testing-components-scenarios.md',
|
||||
'aio/content/guide/testing-pipes.md',
|
||||
'aio/content/guide/testing-services.md',
|
||||
'aio/content/guide/testing-utility-apis.md',
|
||||
'aio/content/examples/testing/**',
|
||||
'aio/content/images/guide/testing/**'
|
||||
])
|
||||
@ -658,6 +578,7 @@ groups:
|
||||
users:
|
||||
- AndrewKushnir
|
||||
- IgorMinar
|
||||
- kara
|
||||
- pkozlowski-opensource
|
||||
|
||||
|
||||
@ -665,7 +586,6 @@ groups:
|
||||
# Framework: Benchmarks
|
||||
# =========================================================
|
||||
fw-benchmarks:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- >
|
||||
@ -675,6 +595,7 @@ groups:
|
||||
reviewers:
|
||||
users:
|
||||
- IgorMinar
|
||||
- kara
|
||||
- pkozlowski-opensource
|
||||
|
||||
|
||||
@ -682,7 +603,6 @@ groups:
|
||||
# Framework: Playground
|
||||
# =========================================================
|
||||
fw-playground:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- >
|
||||
@ -692,15 +612,13 @@ groups:
|
||||
reviewers:
|
||||
users:
|
||||
- IgorMinar
|
||||
- jelbourn
|
||||
- pkozlowski-opensource
|
||||
- kara
|
||||
|
||||
|
||||
# =========================================================
|
||||
# Framework: Security
|
||||
# =========================================================
|
||||
fw-security:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -718,25 +636,18 @@ groups:
|
||||
users:
|
||||
- IgorMinar
|
||||
- mhevery
|
||||
- jelbourn
|
||||
- pkozlowski-opensource
|
||||
reviews:
|
||||
request: -1 # request reviews from everyone
|
||||
required: 2 # require at least 2 approvals
|
||||
reviewed_for: required
|
||||
|
||||
|
||||
# =========================================================
|
||||
# Bazel
|
||||
# =========================================================
|
||||
bazel:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
- >
|
||||
contains_any_globs(files, [
|
||||
'packages/bazel/**',
|
||||
'aio/content/guide/bazel.md'
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
@ -749,7 +660,6 @@ groups:
|
||||
# Language Service
|
||||
# =========================================================
|
||||
language-service:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -769,7 +679,6 @@ groups:
|
||||
# zone.js
|
||||
# =========================================================
|
||||
zone-js:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -788,7 +697,6 @@ groups:
|
||||
# Benchpress
|
||||
# =========================================================
|
||||
benchpress:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -799,14 +707,12 @@ groups:
|
||||
reviewers:
|
||||
users:
|
||||
- alxhub
|
||||
- josephperrott
|
||||
|
||||
|
||||
# =========================================================
|
||||
# Integration Tests
|
||||
# =========================================================
|
||||
integration-tests:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- >
|
||||
@ -817,6 +723,7 @@ groups:
|
||||
users:
|
||||
- IgorMinar
|
||||
- josephperrott
|
||||
- kara
|
||||
- mhevery
|
||||
|
||||
|
||||
@ -824,7 +731,6 @@ groups:
|
||||
# Docs: Gettings Started & Tutorial
|
||||
# =========================================================
|
||||
docs-getting-started-and-tutorial:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -857,7 +763,6 @@ groups:
|
||||
# Docs: Marketing
|
||||
# =========================================================
|
||||
docs-marketing:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -880,7 +785,6 @@ groups:
|
||||
# Docs: Observables
|
||||
# =========================================================
|
||||
docs-observables:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -906,7 +810,6 @@ groups:
|
||||
# Docs: Packaging, Tooling, Releasing
|
||||
# =========================================================
|
||||
docs-packaging-and-releasing:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -926,47 +829,20 @@ groups:
|
||||
'aio/content/guide/migration-localize.md',
|
||||
'aio/content/guide/migration-module-with-providers.md',
|
||||
'aio/content/guide/static-query-migration.md',
|
||||
'aio/content/guide/updating-to-version-10.md',
|
||||
'aio/content/guide/updating-to-version-9.md',
|
||||
'aio/content/guide/ivy-compatibility.md',
|
||||
'aio/content/guide/ivy-compatibility-examples.md'
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
- IgorMinar
|
||||
- jelbourn
|
||||
|
||||
|
||||
# =========================================================
|
||||
# Tooling: Compiler API shared with Angular CLI
|
||||
#
|
||||
# Changing this API might break Angular CLI, so we require
|
||||
# the CLI team to approve changes here.
|
||||
# =========================================================
|
||||
tooling-cli-shared-api:
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
- >
|
||||
contains_any_globs(files, [
|
||||
'packages/compiler-cli/src/tooling.ts'
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
- alan-agius4
|
||||
- clydin
|
||||
- kyliau
|
||||
- IgorMinar
|
||||
reviews:
|
||||
request: -1 # request reviews from everyone
|
||||
required: 2 # require at least 2 approvals
|
||||
reviewed_for: required
|
||||
- kara
|
||||
|
||||
|
||||
# =========================================================
|
||||
# Docs: CLI
|
||||
# =========================================================
|
||||
docs-cli:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -983,12 +859,8 @@ groups:
|
||||
'aio/content/images/guide/deployment/**',
|
||||
'aio/content/guide/file-structure.md',
|
||||
'aio/content/guide/ivy.md',
|
||||
'aio/content/guide/strict-mode.md',
|
||||
'aio/content/guide/web-worker.md',
|
||||
'aio/content/guide/workspace-config.md',
|
||||
'aio/content/guide/migration-solution-style-tsconfig.md',
|
||||
'aio/content/guide/migration-update-module-and-target-compiler-options.md',
|
||||
'aio/content/guide/migration-update-libraries-tslib.md',
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
@ -1001,7 +873,6 @@ groups:
|
||||
# Docs: CLI Libraries
|
||||
# =========================================================
|
||||
docs-libraries:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -1022,7 +893,6 @@ groups:
|
||||
# Docs: Schematics
|
||||
# =========================================================
|
||||
docs-schematics:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -1045,7 +915,6 @@ groups:
|
||||
# Docs-infra
|
||||
# =========================================================
|
||||
docs-infra:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
@ -1075,16 +944,14 @@ groups:
|
||||
# Dev-infra
|
||||
# =========================================================
|
||||
dev-infra:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- >
|
||||
contains_any_globs(files.exclude("CHANGELOG.md").exclude("packages/compiler-cli/**/BUILD.bazel"), [
|
||||
contains_any_globs(files.exclude("CHANGELOG.md"), [
|
||||
'*',
|
||||
'.circleci/**',
|
||||
'.devcontainer/**',
|
||||
'.github/**',
|
||||
'.ng-dev/**',
|
||||
'.vscode/**',
|
||||
'.yarn/**',
|
||||
'dev-infra/**',
|
||||
@ -1100,6 +967,8 @@ groups:
|
||||
'docs/TOOLS.md',
|
||||
'docs/TRIAGE_AND_LABELS.md',
|
||||
'goldens/*',
|
||||
'modules/e2e_util/e2e_util.ts',
|
||||
'modules/e2e_util/perf_util.ts',
|
||||
'modules/*',
|
||||
'packages/*',
|
||||
'packages/examples/test-utils/**',
|
||||
@ -1107,10 +976,15 @@ groups:
|
||||
'packages/examples/*',
|
||||
'scripts/**',
|
||||
'third_party/**',
|
||||
'tools/brotli-cli/**',
|
||||
'tools/browsers/**',
|
||||
'tools/build/**',
|
||||
'tools/circular_dependency_test/**',
|
||||
'tools/contributing-stats/**',
|
||||
'tools/components/**',
|
||||
'tools/gulp-tasks/**',
|
||||
'tools/ng_rollup_bundle/**',
|
||||
'tools/ngcontainer/**',
|
||||
'tools/npm/**',
|
||||
'tools/npm_integration_test/**',
|
||||
'tools/rxjs/**',
|
||||
@ -1140,10 +1014,7 @@ groups:
|
||||
# Public API
|
||||
# =========================================================
|
||||
public-api:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *no-groups-above-this-pending
|
||||
- *no-groups-above-this-rejected
|
||||
- *can-be-global-approved
|
||||
- >
|
||||
contains_any_globs(files, [
|
||||
@ -1157,27 +1028,15 @@ groups:
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
- AndrewKushnir
|
||||
- IgorMinar
|
||||
- alxhub
|
||||
- atscott
|
||||
- jelbourn
|
||||
- petebacondarwin
|
||||
- pkozlowski-opensource
|
||||
reviews:
|
||||
request: 4 # Request reviews from four people
|
||||
required: 3 # Require that three people approve
|
||||
reviewed_for: required
|
||||
- kara
|
||||
|
||||
|
||||
# ================================================
|
||||
# Size tracking
|
||||
# ================================================
|
||||
size-tracking:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *no-groups-above-this-pending
|
||||
- *no-groups-above-this-rejected
|
||||
- *can-be-global-approved
|
||||
- >
|
||||
contains_any_globs(files, [
|
||||
@ -1185,27 +1044,15 @@ groups:
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
- AndrewKushnir
|
||||
- IgorMinar
|
||||
- alxhub
|
||||
- atscott
|
||||
- jelbourn
|
||||
- petebacondarwin
|
||||
- pkozlowski-opensource
|
||||
reviews:
|
||||
request: 4 # Request reviews from four people
|
||||
required: 2 # Require that two people approve
|
||||
reviewed_for: required
|
||||
- kara
|
||||
|
||||
|
||||
# ================================================
|
||||
# Circular dependencies
|
||||
# ================================================
|
||||
circular-dependencies:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *no-groups-above-this-pending
|
||||
- *no-groups-above-this-rejected
|
||||
- *can-be-global-approved
|
||||
- >
|
||||
contains_any_globs(files, [
|
||||
@ -1213,13 +1060,9 @@ groups:
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
- AndrewKushnir
|
||||
- IgorMinar
|
||||
- alxhub
|
||||
- atscott
|
||||
- jelbourn
|
||||
- petebacondarwin
|
||||
- pkozlowski-opensource
|
||||
- josephperrott
|
||||
- kara
|
||||
|
||||
|
||||
####################################################################################
|
||||
@ -1230,7 +1073,6 @@ groups:
|
||||
# Code Ownership
|
||||
# =========================================================
|
||||
code-ownership:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- *can-be-global-approved
|
||||
- >
|
||||
@ -1239,43 +1081,19 @@ groups:
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
- AndrewKushnir
|
||||
- IgorMinar
|
||||
- alxhub
|
||||
- atscott
|
||||
- jelbourn
|
||||
- josephperrott
|
||||
- mhevery
|
||||
|
||||
|
||||
# ====================================================
|
||||
# Catch all for if no groups match the code change
|
||||
# ====================================================
|
||||
fallback:
|
||||
<<: *defaults
|
||||
# A group is considered to be `active` for a PR if at least one of group's
|
||||
# conditions matches the PR.
|
||||
#
|
||||
# The PullApprove CI check should fail if a PR has no `active` groups, as
|
||||
# this indicates the PR is modifying a file that has no owner.
|
||||
#
|
||||
# This is enforced through the pullapprove verification check done
|
||||
# as part of the CircleCI lint job. Failures in this lint job should be
|
||||
# fixed as part of the PR. This can be done by updating the
|
||||
# `.pullapprove.yml` file cover the unmatched path.
|
||||
# The pullapprove verification script is part of the ng-dev tool and can be
|
||||
# run locally with the command: `yarn -s ng-dev pullapprove verify`
|
||||
#
|
||||
# For cases in which the verification check fails to ensure coverage, this
|
||||
# group will be active. The expectation is that this should be remedied
|
||||
# before merging the PR as described above. In an emergency situation
|
||||
# `global-approvers` can still approve PRs that match this `fallback` rule,
|
||||
# but that should be an exception and not an expectation.
|
||||
conditions:
|
||||
- *no-groups-above-this-active
|
||||
# When any of the `global-*` groups is approved, they cause other groups to deactivate.
|
||||
# In those cases, the condition above would evaluate to `true` while in reality, only a global
|
||||
# approval has been provided. To ensure we don't activate the fallback group in such cases,
|
||||
# ensure that no explicit global approval has been provided.
|
||||
- *can-be-global-approved
|
||||
- *can-be-global-docs-approved
|
||||
# Groups which are found to have matching conditions are `active`
|
||||
# according to PullApprove. If no groups are matched and considered
|
||||
# active, we still want to have a review occur.
|
||||
- len(groups.active) == 0
|
||||
reviewers:
|
||||
users:
|
||||
- IgorMinar
|
||||
|
1
.vscode/recommended-settings.json
vendored
1
.vscode/recommended-settings.json
vendored
@ -26,7 +26,6 @@
|
||||
"**/bazel-out": true,
|
||||
"**/dist": true,
|
||||
"**/aio/src/generated": true,
|
||||
".history": true,
|
||||
},
|
||||
"git.ignoreLimitWarning": true,
|
||||
}
|
@ -2,6 +2,7 @@ package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files([
|
||||
"LICENSE",
|
||||
"protractor-perf.conf.js",
|
||||
"karma-js.conf.js",
|
||||
"browser-providers.conf.js",
|
||||
"scripts/ci/track-payload-size.sh",
|
||||
@ -24,7 +25,7 @@ filegroup(
|
||||
"//packages/zone.js/dist:zone-testing.js",
|
||||
"//packages/zone.js/dist:task-tracking.js",
|
||||
"//:test-events.js",
|
||||
"//:third_party/shims_for_IE.js",
|
||||
"//:shims_for_IE.js",
|
||||
# Including systemjs because it defines `__eval`, which produces correct stack traces.
|
||||
"@npm//:node_modules/systemjs/dist/system.src.js",
|
||||
"@npm//:node_modules/reflect-metadata/Reflect.js",
|
||||
|
524
CHANGELOG.md
524
CHANGELOG.md
@ -1,436 +1,33 @@
|
||||
<a name="10.0.7"></a>
|
||||
## 10.0.7 (2020-07-30)
|
||||
<a name="9.1.12"></a>
|
||||
## [9.1.12](https://github.com/angular/angular/compare/9.1.11...9.1.12) (2020-07-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler:** Metadata should not include methods on Object.prototype ([#38292](https://github.com/angular/angular/issues/38292)) ([879ff08](https://github.com/angular/angular/commit/879ff08))
|
||||
* **core:** infinite loop if injectable using inheritance has a custom decorator ([6c1ab47](https://github.com/angular/angular/commit/6c1ab47)), closes [#35733](https://github.com/angular/angular/issues/35733)
|
||||
|
||||
|
||||
|
||||
<a name="10.0.6"></a>
|
||||
## 10.0.6 (2020-07-28)
|
||||
<a name="9.1.11"></a>
|
||||
## [9.1.11](https://github.com/angular/angular/compare/9.1.10...9.1.11) (2020-06-10)
|
||||
|
||||
### Reverts
|
||||
|
||||
* **elements:** fire custom element output events during component initialization ([dc9da17](https://github.com/angular/angular/commit/dc9da17))
|
||||
|
||||
|
||||
<a name="9.1.10"></a>
|
||||
## [9.1.10](https://github.com/angular/angular/compare/9.1.9...9.1.10) (2020-06-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler:** share identical stylesheets between components in the same file ([#38213](https://github.com/angular/angular/issues/38213)) ([264950b](https://github.com/angular/angular/commit/264950b)), closes [#38204](https://github.com/angular/angular/issues/38204)
|
||||
* **compiler-cli:** Add support for string literal class members ([#38226](https://github.com/angular/angular/issues/38226)) ([b1e7775](https://github.com/angular/angular/commit/b1e7775))
|
||||
* **core:** `Attribute` decorator `attributeName` is mandatory ([#38131](https://github.com/angular/angular/issues/38131)) ([1c4fcce](https://github.com/angular/angular/commit/1c4fcce)), closes [#32658](https://github.com/angular/angular/issues/32658)
|
||||
* **core:** unify the signature between ngZone and noopZone ([#37581](https://github.com/angular/angular/issues/37581)) ([d5264f5](https://github.com/angular/angular/commit/d5264f5))
|
||||
|
||||
|
||||
|
||||
<a name="10.0.5"></a>
|
||||
## 10.0.5 (2020-07-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler:** properly associate source spans for implicitly closed elements ([#38126](https://github.com/angular/angular/issues/38126)) ([e80278c](https://github.com/angular/angular/commit/e80278c)), closes [#36118](https://github.com/angular/angular/issues/36118)
|
||||
* **compiler-cli:** ensure file_system handles mixed Windows drives ([#38030](https://github.com/angular/angular/issues/38030)) ([dba4023](https://github.com/angular/angular/commit/dba4023)), closes [#36777](https://github.com/angular/angular/issues/36777)
|
||||
* **core:** Allow modification of lifecycle hooks any time before bootstrap ([#38119](https://github.com/angular/angular/issues/38119)) ([14b4718](https://github.com/angular/angular/commit/14b4718)), closes [#30497](https://github.com/angular/angular/issues/30497)
|
||||
* **core:** error due to integer overflow when there are too many host bindings ([#38014](https://github.com/angular/angular/issues/38014)) ([7b6e73c](https://github.com/angular/angular/commit/7b6e73c)), closes [#37876](https://github.com/angular/angular/issues/37876) [#37876](https://github.com/angular/angular/issues/37876)
|
||||
* **core:** incorrectly validating properties on ng-content and ng-container ([#37773](https://github.com/angular/angular/issues/37773)) ([17ddab9](https://github.com/angular/angular/commit/17ddab9))
|
||||
|
||||
|
||||
|
||||
<a name="10.0.4"></a>
|
||||
## 10.0.4 (2020-07-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** ng_module rule does not expose flat module information in Ivy ([#36971](https://github.com/angular/angular/issues/36971)) ([b76a2dc](https://github.com/angular/angular/commit/b76a2dc))
|
||||
* **compiler:** check more cases for pipe usage inside host bindings ([#37883](https://github.com/angular/angular/issues/37883)) ([a94383f](https://github.com/angular/angular/commit/a94383f)), closes [#34655](https://github.com/angular/angular/issues/34655) [#37610](https://github.com/angular/angular/issues/37610)
|
||||
* **language-service:** non-existent module format in package output ([#37778](https://github.com/angular/angular/issues/37778)) ([12f1773](https://github.com/angular/angular/commit/12f1773))
|
||||
* **language-service:** remove completion for string ([#37983](https://github.com/angular/angular/issues/37983)) ([387e838](https://github.com/angular/angular/commit/387e838))
|
||||
* **ngcc:** report a warning if ngcc tries to use a solution-style tsconfig ([#38003](https://github.com/angular/angular/issues/38003)) ([e3b8010](https://github.com/angular/angular/commit/e3b8010)), closes [#36386](https://github.com/angular/angular/issues/36386)
|
||||
* **service-worker:** correctly handle relative base href ([#37922](https://github.com/angular/angular/issues/37922)) ([b186db7](https://github.com/angular/angular/commit/b186db7)), closes [#25055](https://github.com/angular/angular/issues/25055) [#25055](https://github.com/angular/angular/issues/25055)
|
||||
* **service-worker:** correctly serve `ngsw/state` with a non-root SW scope ([#37922](https://github.com/angular/angular/issues/37922)) ([dc42c97](https://github.com/angular/angular/commit/dc42c97)), closes [#30505](https://github.com/angular/angular/issues/30505)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **bazel:** provide LinkablePackageInfo from ng_module ([#37778](https://github.com/angular/angular/issues/37778)) ([6cd10a1](https://github.com/angular/angular/commit/6cd10a1)), closes [/github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl#L144-L146](https://github.com//github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl/issues/L144-L146)
|
||||
|
||||
|
||||
|
||||
<a name="10.0.3"></a>
|
||||
## 10.0.3 (2020-07-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** handle spaces after `select` and `plural` ICU keywords ([#37866](https://github.com/angular/angular/issues/37866)) ([790bb94](https://github.com/angular/angular/commit/790bb94))
|
||||
|
||||
|
||||
|
||||
<a name="10.0.2"></a>
|
||||
## [10.0.2](https://github.com/angular/angular/compare/10.0.1...10.0.2) (2020-06-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** determine required DOMParser feature availability ([#36578](https://github.com/angular/angular/issues/36578)) ([#37783](https://github.com/angular/angular/issues/37783)) ([12a71bc](https://github.com/angular/angular/commit/12a71bc))
|
||||
* **core:** do not trigger CSP alert/report in Firefox and Chrome ([#36578](https://github.com/angular/angular/issues/36578)) ([#37783](https://github.com/angular/angular/issues/37783)) ([b0b7248](https://github.com/angular/angular/commit/b0b7248)), closes [#25214](https://github.com/angular/angular/issues/25214)
|
||||
* **core:** don't consider inherited NG_ELEMENT_ID during DI ([#37574](https://github.com/angular/angular/issues/37574)) ([64b0ae9](https://github.com/angular/angular/commit/64b0ae9)), closes [#36235](https://github.com/angular/angular/issues/36235)
|
||||
* **core:** error when invoking callbacks registered via ViewRef.onDestroy ([#37543](https://github.com/angular/angular/issues/37543)) ([75b119e](https://github.com/angular/angular/commit/75b119e)), closes [#36213](https://github.com/angular/angular/issues/36213)
|
||||
* **core:** error when invoking callbacks registered via ViewRef.onDestroy ([#37543](https://github.com/angular/angular/issues/37543)) ([#37783](https://github.com/angular/angular/issues/37783)) ([df2cd37](https://github.com/angular/angular/commit/df2cd37)), closes [#36213](https://github.com/angular/angular/issues/36213)
|
||||
* **core:** fake_async_fallback should have the same logic with fake-async ([#37680](https://github.com/angular/angular/issues/37680)) ([7a91b23](https://github.com/angular/angular/commit/7a91b23))
|
||||
* **elements:** fire custom element output events during component initialization ([#37570](https://github.com/angular/angular/issues/37570)) ([89e16ed](https://github.com/angular/angular/commit/89e16ed)), closes [/github.com/angular/angular/blob/c0143cb2abdd172de1b95fd1d2c4cfc738640e28/packages/elements/src/create-custom-element.ts#L167-L170](https://github.com//github.com/angular/angular/blob/c0143cb2abdd172de1b95fd1d2c4cfc738640e28/packages/elements/src/create-custom-element.ts/issues/L167-L170) [/github.com/angular/angular/blob/c0143cb2abdd172de1b95fd1d2c4cfc738640e28/packages/elements/src/create-custom-element.ts#L164](https://github.com//github.com/angular/angular/blob/c0143cb2abdd172de1b95fd1d2c4cfc738640e28/packages/elements/src/create-custom-element.ts/issues/L164) [/github.com/angular/angular/blob/c0143cb2abdd172de1b95fd1d2c4cfc738640e28/packages/elements/src/component-factory-strategy.ts#L158](https://github.com//github.com/angular/angular/blob/c0143cb2abdd172de1b95fd1d2c4cfc738640e28/packages/elements/src/component-factory-strategy.ts/issues/L158) [#36141](https://github.com/angular/angular/issues/36141)
|
||||
* **language-service:** incorrect autocomplete results on unknown symbol ([#37518](https://github.com/angular/angular/issues/37518)) ([7c0b25f](https://github.com/angular/angular/commit/7c0b25f))
|
||||
* **ngcc:** ensure lockfile is removed when analyzeFn fails ([#37739](https://github.com/angular/angular/issues/37739)) ([1a1f99a](https://github.com/angular/angular/commit/1a1f99a))
|
||||
* **ngcc:** prevent including JavaScript sources outside of the package ([#37596](https://github.com/angular/angular/issues/37596)) ([4b90b6a](https://github.com/angular/angular/commit/4b90b6a)), closes [#37508](https://github.com/angular/angular/issues/37508)
|
||||
* **elements:** fire custom element output events during component initialization ([454e073](https://github.com/angular/angular/commit/454e073)), closes [/github.com/angular/angular/blob/c0143cb2abdd172de1b95fd1d2c4cfc738640e28/packages/elements/src/create-custom-element.ts#L167-L170](https://github.com//github.com/angular/angular/blob/c0143cb2abdd172de1b95fd1d2c4cfc738640e28/packages/elements/src/create-custom-element.ts/issues/L167-L170) [/github.com/angular/angular/blob/c0143cb2abdd172de1b95fd1d2c4cfc738640e28/packages/elements/src/create-custom-element.ts#L164](https://github.com//github.com/angular/angular/blob/c0143cb2abdd172de1b95fd1d2c4cfc738640e28/packages/elements/src/create-custom-element.ts/issues/L164) [/github.com/angular/angular/blob/c0143cb2abdd172de1b95fd1d2c4cfc738640e28/packages/elements/src/component-factory-strategy.ts#L158](https://github.com//github.com/angular/angular/blob/c0143cb2abdd172de1b95fd1d2c4cfc738640e28/packages/elements/src/component-factory-strategy.ts/issues/L158) [#36141](https://github.com/angular/angular/issues/36141)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **compiler-cli:** fix memory leak in retained incremental state ([#37835](https://github.com/angular/angular/issues/37835)) ([57a518a](https://github.com/angular/angular/commit/57a518a))
|
||||
|
||||
|
||||
|
||||
<a name="10.0.1"></a>
|
||||
## [10.0.1](https://github.com/angular/angular/compare/10.0.0...10.0.1) (2020-06-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** cleanup DOM elements when root view is removed ([#37600](https://github.com/angular/angular/issues/37600)) ([64f2ffa](https://github.com/angular/angular/commit/64f2ffa)), closes [#36449](https://github.com/angular/angular/issues/36449)
|
||||
* **forms:** change error message ([#37643](https://github.com/angular/angular/issues/37643)) ([c5bc2e7](https://github.com/angular/angular/commit/c5bc2e7))
|
||||
* **forms:** correct usage of `selectedOptions` ([#37620](https://github.com/angular/angular/issues/37620)) ([dfb58c4](https://github.com/angular/angular/commit/dfb58c4)), closes [#37433](https://github.com/angular/angular/issues/37433)
|
||||
* **http:** avoid abort a request when fetch operation is completed ([#37367](https://github.com/angular/angular/issues/37367)) ([a5d5f67](https://github.com/angular/angular/commit/a5d5f67))
|
||||
* **language-service:** reinstate getExternalFiles() ([#37750](https://github.com/angular/angular/issues/37750)) ([ad6680f](https://github.com/angular/angular/commit/ad6680f))
|
||||
* **migrations:** do not incorrectly add todo for @Injectable or @Pipe ([#37732](https://github.com/angular/angular/issues/37732)) ([13020b9](https://github.com/angular/angular/commit/13020b9)), closes [#37726](https://github.com/angular/angular/issues/37726)
|
||||
* **router:** `RouterLinkActive` should run CD when setting `isActive` ([#21411](https://github.com/angular/angular/issues/21411)) ([a8ea817](https://github.com/angular/angular/commit/a8ea817)), closes [#15943](https://github.com/angular/angular/issues/15943) [#19934](https://github.com/angular/angular/issues/19934)
|
||||
* **router:** add null support for RouterLink directive ([#32616](https://github.com/angular/angular/issues/32616)) ([69948ce](https://github.com/angular/angular/commit/69948ce))
|
||||
* **router:** fix error when calling ParamMap.get function ([#31599](https://github.com/angular/angular/issues/31599)) ([3190ccf](https://github.com/angular/angular/commit/3190ccf))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **compiler-cli:** fix regressions in incremental program reuse ([#37690](https://github.com/angular/angular/issues/37690)) ([96b96fb](https://github.com/angular/angular/commit/96b96fb))
|
||||
|
||||
|
||||
|
||||
<a name="10.0.0"></a>
|
||||
# [10.0.0](https://github.com/angular/angular/compare/10.0.0-rc.6...10.0.0) (2020-06-24)
|
||||
|
||||
### Release Highlights & Update instructions
|
||||
To learn about the release highlights and our CLI-powered automated update workflow for your projects please check out the [v10 release announcement](https://blog.angular.io/version-10-of-angular-now-available-78960babd41).
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **bazel:** expose explicit mapping from closure to devmode files ([#36262](https://github.com/angular/angular/issues/36262)) ([ba796bb](https://github.com/angular/angular/commit/ba796bb))
|
||||
* **bazel:** simplify ng_package by dropping esm5 and fesm5 ([#36944](https://github.com/angular/angular/issues/36944)) ([9dbb30f](https://github.com/angular/angular/commit/9dbb30f))
|
||||
* **compiler-cli:** report error if undecorated class with Angular features is discovered ([#36921](https://github.com/angular/angular/issues/36921)) ([4c92cf4](https://github.com/angular/angular/commit/4c92cf4))
|
||||
* **compiler:** Propagate value span of ExpressionBinding to ParsedProperty ([#36133](https://github.com/angular/angular/issues/36133)) ([d714b95](https://github.com/angular/angular/commit/d714b95))
|
||||
* **compiler:** add dependency info and ng-content selectors to metadata ([#35695](https://github.com/angular/angular/issues/35695)) ([32ce8b1](https://github.com/angular/angular/commit/32ce8b1))
|
||||
* **compiler:** add name spans for property reads and method calls ([#36826](https://github.com/angular/angular/issues/36826)) ([eb34aa5](https://github.com/angular/angular/commit/eb34aa5))
|
||||
* **core** make generic mandatory for ModuleWithProviders ([#36892](https://github.com/angular/angular/issues/36892)) ([20cc3ab](https://github.com/angular/angular/commit/20cc3ab))
|
||||
* **core** update to tslib 2.0 and move to direct dependencies ([#37198](https://github.com/angular/angular/pull/37198)), closes [#37188](https://github.com/angular/angular/issues/37188)
|
||||
* **core:** undecorated-classes migration should handle derived abstract classes ([#35339](https://github.com/angular/angular/issues/35339)) ([c24ad56](https://github.com/angular/angular/commit/c24ad56))
|
||||
* **core:** undecorated-classes-with-decorated-fields migration should handle classes with lifecycle hooks ([#36921](https://github.com/angular/angular/issues/36921)) ([c6ecdc9](https://github.com/angular/angular/commit/c6ecdc9))
|
||||
* **language-service:** Remove HTML entities autocompletion ([#37515](https://github.com/angular/angular/issues/37515)) ([67bd88b](https://github.com/angular/angular/commit/67bd88b))
|
||||
* **language-service:** TS references from template items ([#37437](https://github.com/angular/angular/issues/37437)) ([bf2cb6f](https://github.com/angular/angular/commit/bf2cb6f))
|
||||
* **language-service:** [ivy] Parse Angular compiler options ([#36922](https://github.com/angular/angular/issues/36922)) ([dbd0f8e](https://github.com/angular/angular/commit/dbd0f8e))
|
||||
* **language-service:** [ivy] wrap ngtsc to handle typecheck files ([#36930](https://github.com/angular/angular/issues/36930)) ([1142c37](https://github.com/angular/angular/commit/1142c37))
|
||||
* **localize:** support merging multiple translation files ([#36792](https://github.com/angular/angular/issues/36792)) ([72f534f](https://github.com/angular/angular/commit/72f534f))
|
||||
* **ngcc:** allow async locking timeouts to be configured ([#36838](https://github.com/angular/angular/issues/36838)) ([38f805c](https://github.com/angular/angular/commit/38f805c))
|
||||
* **ngcc:** implement a program-based entry-point finder ([#37075](https://github.com/angular/angular/issues/37075)) ([f3ccd29](https://github.com/angular/angular/commit/f3ccd29))
|
||||
* **ngcc:** support for new APF where `module` points to esm2015 output ([#36944](https://github.com/angular/angular/issues/36944)) ([c98a4d6](https://github.com/angular/angular/commit/c98a4d6))
|
||||
* **ngcc:** support marking an in-progress task as unprocessed ([#36626](https://github.com/angular/angular/issues/36626)) ([4665c35](https://github.com/angular/angular/commit/4665c35))
|
||||
* **ngcc:** support reverting a file written by `FileWriter` ([#36626](https://github.com/angular/angular/issues/36626)) ([772ccf0](https://github.com/angular/angular/commit/772ccf0))
|
||||
* **platform-server:** use absolute URLs from Location for HTTP ([#37071](https://github.com/angular/angular/issues/37071)) ([9edea0b](https://github.com/angular/angular/commit/9edea0b))
|
||||
* **router:** allow CanLoad guard to return UrlTree ([#36610](https://github.com/angular/angular/issues/36610)) ([00e6cb1](https://github.com/angular/angular/commit/00e6cb1)), closes [#26521](https://github.com/angular/angular/issues/26521) [#28306](https://github.com/angular/angular/issues/28306)
|
||||
* **service-worker:** include `CacheQueryOptions` options in ngsw-config ([#34663](https://github.com/angular/angular/issues/34663)) ([dc9f4b9](https://github.com/angular/angular/commit/dc9f4b9)), closes [#28443](https://github.com/angular/angular/issues/28443)
|
||||
* **service-worker:** support timeout in `registerWhenStable` SW registration strategy ([#35870](https://github.com/angular/angular/issues/35870)) ([00efacf](https://github.com/angular/angular/commit/00efacf)), closes [#34464](https://github.com/angular/angular/issues/34464)
|
||||
* **service-worker:** use `ignoreVary: true` when retrieving responses from cache ([#34663](https://github.com/angular/angular/issues/34663)) ([ee35e22](https://github.com/angular/angular/commit/ee35e22)), closes [#36638](https://github.com/angular/angular/issues/36638)
|
||||
* remove TypeScript 3.6 and 3.7 support ([#36329](https://github.com/angular/angular/issues/36329)) ([fbd281c](https://github.com/angular/angular/commit/fbd281c))
|
||||
* remove support for TypeScript 3.8 ([#37129](https://github.com/angular/angular/issues/37129)) ([6466fb2](https://github.com/angular/angular/commit/6466fb2))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** ng_package rule should update "package.json" of ts_library targets ([#36944](https://github.com/angular/angular/issues/36944)) ([d5293d2](https://github.com/angular/angular/commit/d5293d2))
|
||||
* **common:** `locales/global/*.js` are not ES5 compliant ([#36342](https://github.com/angular/angular/issues/36342)) ([078b0be](https://github.com/angular/angular/commit/078b0be)), closes [angular/angular-cli#16394](https://github.com/angular/angular-cli/issues/16394)
|
||||
* **common:** format day-periods that cross midnight ([#36611](https://github.com/angular/angular/issues/36611)) ([c6e5fc4](https://github.com/angular/angular/commit/c6e5fc4)), closes [#36566](https://github.com/angular/angular/issues/36566)
|
||||
* **common:** let `KeyValuePipe` accept type unions with `null` ([#36093](https://github.com/angular/angular/issues/36093)) ([d783519](https://github.com/angular/angular/commit/d783519)), closes [#35743](https://github.com/angular/angular/issues/35743)
|
||||
* **common:** prevent duplicate URL change notifications ([#37404](https://github.com/angular/angular/issues/37404)) ([fff424a](https://github.com/angular/angular/commit/fff424a))
|
||||
* **common:** prevent duplicate URL change notifications ([#37459](https://github.com/angular/angular/issues/37459)) ([0864726](https://github.com/angular/angular/commit/0864726))
|
||||
* **compiler-cli:** `isCaseSensitive()` returns correct value ([#36859](https://github.com/angular/angular/issues/36859)) ([fc4741f](https://github.com/angular/angular/commit/fc4741f))
|
||||
* **compiler-cli:** compute the correct target output for `$localize` messages ([#36989](https://github.com/angular/angular/issues/36989)) ([4e1b5e4](https://github.com/angular/angular/commit/4e1b5e4))
|
||||
* **compiler-cli:** don't try to tag non-ts files as shims ([#36987](https://github.com/angular/angular/issues/36987)) ([42d1091](https://github.com/angular/angular/commit/42d1091))
|
||||
* **compiler-cli:** downlevel angular decorators to static properties ([#37382](https://github.com/angular/angular/issues/37382)) ([323651b](https://github.com/angular/angular/commit/323651b)), closes [#30586](https://github.com/angular/angular/issues/30586) [#30106](https://github.com/angular/angular/issues/30106) [#30586](https://github.com/angular/angular/issues/30586) [#30141](https://github.com/angular/angular/issues/30141)
|
||||
* **compiler-cli:** ensure LogicalFileSystem handles case-sensitivity ([#36859](https://github.com/angular/angular/issues/36859)) ([53a8459](https://github.com/angular/angular/commit/53a8459))
|
||||
* **compiler-cli:** ensure LogicalFileSystem maintains case in paths ([#37008](https://github.com/angular/angular/issues/37008)) ([3dfc770](https://github.com/angular/angular/commit/3dfc770)), closes [#36992](https://github.com/angular/angular/issues/36992) [#36993](https://github.com/angular/angular/issues/36993) [#37000](https://github.com/angular/angular/issues/37000)
|
||||
* **compiler-cli:** ensure `MockFileSystem` handles case-sensitivity ([#36859](https://github.com/angular/angular/issues/36859)) ([26eacd4](https://github.com/angular/angular/commit/26eacd4))
|
||||
* **compiler-cli:** ensure `getRootDirs()` handles case-sensitivity ([#36859](https://github.com/angular/angular/issues/36859)) ([3f3e9b7](https://github.com/angular/angular/commit/3f3e9b7))
|
||||
* **compiler-cli:** fix bug tracking indirect NgModule dependencies ([#36211](https://github.com/angular/angular/issues/36211)) ([bab90a7](https://github.com/angular/angular/commit/bab90a7))
|
||||
* **compiler-cli:** fix case-sensitivity issues in NgtscCompilerHost ([#36859](https://github.com/angular/angular/issues/36859)) ([0ec0ff3](https://github.com/angular/angular/commit/0ec0ff3))
|
||||
* **compiler-cli:** normalize mock Windows file paths correctly ([#36859](https://github.com/angular/angular/issues/36859)) ([b682bd1](https://github.com/angular/angular/commit/b682bd1))
|
||||
* **compiler-cli:** pass real source spans where they are empty ([#31805](https://github.com/angular/angular/issues/31805)) ([e893c5a](https://github.com/angular/angular/commit/e893c5a))
|
||||
* **compiler-cli:** use CompilerHost to ensure canonical file paths ([#36859](https://github.com/angular/angular/issues/36859)) ([a10c126](https://github.com/angular/angular/commit/a10c126))
|
||||
* **compiler-cli:** use ModuleWithProviders type if static eval fails ([#37126](https://github.com/angular/angular/issues/37126)) ([305b5a3](https://github.com/angular/angular/commit/305b5a3))
|
||||
* **compiler:** avoid generating i18n attributes in plain form ([#36422](https://github.com/angular/angular/issues/36422)) ([88b0985](https://github.com/angular/angular/commit/88b0985))
|
||||
* **compiler:** avoid undefined expressions in holey array ([#36343](https://github.com/angular/angular/issues/36343)) ([5516802](https://github.com/angular/angular/commit/5516802))
|
||||
* **compiler:** handle type references to namespaced symbols correctly ([#36106](https://github.com/angular/angular/issues/36106)) ([4aa4e6f](https://github.com/angular/angular/commit/4aa4e6f)), closes [#36006](https://github.com/angular/angular/issues/36006)
|
||||
* **compiler:** normalize line endings in ICU expansions ([#36741](https://github.com/angular/angular/issues/36741)) ([70dd27f](https://github.com/angular/angular/commit/70dd27f)), closes [#36725](https://github.com/angular/angular/issues/36725)
|
||||
* **compiler:** record correct end of expression ([#34690](https://github.com/angular/angular/issues/34690)) ([df890d7](https://github.com/angular/angular/commit/df890d7)), closes [#33477](https://github.com/angular/angular/issues/33477)
|
||||
* **compiler:** remove outdated and invalid warning for unresolved DI parameters ([#36985](https://github.com/angular/angular/issues/36985)) ([d0280a0](https://github.com/angular/angular/commit/d0280a0))
|
||||
* **compiler:** resolve enum values in binary operations ([#36461](https://github.com/angular/angular/issues/36461)) ([64022f5](https://github.com/angular/angular/commit/64022f5)), closes [#35584](https://github.com/angular/angular/issues/35584)
|
||||
* **compiler:** switch to 'referencedFiles' for shim generation ([#36211](https://github.com/angular/angular/issues/36211)) ([4213e8d](https://github.com/angular/angular/commit/4213e8d))
|
||||
* **compiler:** unable to resolve destructuring variable declarations ([#37497](https://github.com/angular/angular/issues/37497)) ([df10597](https://github.com/angular/angular/commit/df10597)), closes [#36917](https://github.com/angular/angular/issues/36917)
|
||||
* **core:** Host classes should not be fed back into `@Input` ([#35889](https://github.com/angular/angular/issues/35889)) ([cda2530](https://github.com/angular/angular/commit/cda2530)), closes [#35383](https://github.com/angular/angular/issues/35383)
|
||||
* **core:** Refresh transplanted views at insertion point only ([#35968](https://github.com/angular/angular/issues/35968)) ([1786586](https://github.com/angular/angular/commit/1786586)), closes [#35400](https://github.com/angular/angular/issues/35400) [#21324](https://github.com/angular/angular/issues/21324)
|
||||
* **core:** attempt to recover from user errors during creation ([#36381](https://github.com/angular/angular/issues/36381)) ([3d82aa7](https://github.com/angular/angular/commit/3d82aa7)), closes [#31221](https://github.com/angular/angular/issues/31221)
|
||||
* **core:** avoid migration error when non-existent symbol is imported ([#36367](https://github.com/angular/angular/issues/36367)) ([d43c306](https://github.com/angular/angular/commit/d43c306)), closes [#36346](https://github.com/angular/angular/issues/36346)
|
||||
* **core:** correct "development mode" console message ([#36571](https://github.com/angular/angular/issues/36571)) ([8d8e419](https://github.com/angular/angular/commit/8d8e419)), closes [#36570](https://github.com/angular/angular/issues/36570)
|
||||
* **core:** disable tsickle pass when producing APF packages ([#37221](https://github.com/angular/angular/issues/37221)) ([a1001f2](https://github.com/angular/angular/commit/a1001f2))
|
||||
* **core:** do not use unbound attributes as inputs to structural directives ([#36441](https://github.com/angular/angular/issues/36441)) ([acf6075](https://github.com/angular/angular/commit/acf6075))
|
||||
* **core:** handle empty translations correctly ([#36499](https://github.com/angular/angular/issues/36499)) ([b1f1d3f](https://github.com/angular/angular/commit/b1f1d3f)), closes [#36476](https://github.com/angular/angular/issues/36476)
|
||||
* **core:** handle pluralize functions that expect a number ([#36901](https://github.com/angular/angular/issues/36901)) ([2ff4b35](https://github.com/angular/angular/commit/2ff4b35)), closes [#36888](https://github.com/angular/angular/issues/36888)
|
||||
* **core:** handle synthetic props in Directive host bindings correctly ([#35568](https://github.com/angular/angular/issues/35568)) ([f27deea](https://github.com/angular/angular/commit/f27deea)), closes [#35501](https://github.com/angular/angular/issues/35501)
|
||||
* **core:** infinite loop if injectable using inheritance has a custom decorator ([#37022](https://github.com/angular/angular/issues/37022)) ([bc54936](https://github.com/angular/angular/commit/bc54936)), closes [#35733](https://github.com/angular/angular/issues/35733)
|
||||
* **core:** inheritance delegate ctor regex updated to work on minified code ([#36962](https://github.com/angular/angular/issues/36962)) ([ea971f7](https://github.com/angular/angular/commit/ea971f7))
|
||||
* **core:** log error instead of warning for unknown properties and elements ([#36399](https://github.com/angular/angular/issues/36399)) ([9d9d46f](https://github.com/angular/angular/commit/9d9d46f)), closes [#35699](https://github.com/angular/angular/issues/35699)
|
||||
* **core:** missing-injectable migration should not migrate `@NgModule` classes ([#36369](https://github.com/angular/angular/issues/36369)) ([28995db](https://github.com/angular/angular/commit/28995db)), closes [#35700](https://github.com/angular/angular/issues/35700)
|
||||
* **core:** ngOnDestroy on multi providers called with incorrect context ([#35840](https://github.com/angular/angular/issues/35840)) ([95fc3d4](https://github.com/angular/angular/commit/95fc3d4)), closes [#35231](https://github.com/angular/angular/issues/35231)
|
||||
* **core:** pipes injecting viewProviders when used on a component host node ([#36512](https://github.com/angular/angular/issues/36512)) ([81d23b3](https://github.com/angular/angular/commit/81d23b3)), closes [#36146](https://github.com/angular/angular/issues/36146)
|
||||
* **core:** prevent unknown property check for AOT-compiled components ([#36072](https://github.com/angular/angular/issues/36072)) ([4a9f0be](https://github.com/angular/angular/commit/4a9f0be)), closes [#35945](https://github.com/angular/angular/issues/35945)
|
||||
* **core:** properly get root nodes from embedded views with <ng-content> ([#36051](https://github.com/angular/angular/issues/36051)) ([e30e132](https://github.com/angular/angular/commit/e30e132)), closes [#35967](https://github.com/angular/angular/issues/35967)
|
||||
* **core:** properly identify modules affected by overrides in TestBed ([#36649](https://github.com/angular/angular/issues/36649)) ([942b986](https://github.com/angular/angular/commit/942b986)), closes [#36619](https://github.com/angular/angular/issues/36619)
|
||||
* **core:** reenable decorator downleveling for Angular npm packages ([#37317](https://github.com/angular/angular/issues/37317)) ([d16a7f3](https://github.com/angular/angular/commit/d16a7f3)), closes [#37221](https://github.com/angular/angular/issues/37221) [#37221](https://github.com/angular/angular/issues/37221)
|
||||
* **core:** run `APP_INITIALIZER`s before accessing `LOCALE_ID` token in Ivy TestBed ([#36237](https://github.com/angular/angular/issues/36237)) ([1649743](https://github.com/angular/angular/commit/1649743)), closes [#36230](https://github.com/angular/angular/issues/36230)
|
||||
* **core:** should fake a top event task when coalescing events to prevent draining microTaskQueue too early. ([#36841](https://github.com/angular/angular/issues/36841)) ([9b8eb42](https://github.com/angular/angular/commit/9b8eb42)), closes [#36839](https://github.com/angular/angular/issues/36839)
|
||||
* **core:** undecorated-classes-with-decorated-fields migration does not decorate derived classes ([#35339](https://github.com/angular/angular/issues/35339)) ([32eafef](https://github.com/angular/angular/commit/32eafef)), closes [#34376](https://github.com/angular/angular/issues/34376)
|
||||
* **core:** undecorated-classes-with-decorated-fields migration should avoid error if base class has no value declaration ([#36543](https://github.com/angular/angular/issues/36543)) ([ca67748](https://github.com/angular/angular/commit/ca67748)), closes [#36522](https://github.com/angular/angular/issues/36522)
|
||||
* **core:** workaround Terser inlining bug ([#36200](https://github.com/angular/angular/issues/36200)) ([0ce8ad3](https://github.com/angular/angular/commit/0ce8ad3))
|
||||
* **elements:** capture input properties set before upgrading the element ([#36114](https://github.com/angular/angular/issues/36114)) ([2fc5ae5](https://github.com/angular/angular/commit/2fc5ae5)), closes [#30848](https://github.com/angular/angular/issues/30848) [#31416](https://github.com/angular/angular/issues/31416)
|
||||
* **elements:** correctly handle getting/setting properties before connecting the element ([#36114](https://github.com/angular/angular/issues/36114)) ([327980b](https://github.com/angular/angular/commit/327980b)), closes [#30848](https://github.com/angular/angular/issues/30848)
|
||||
* **elements:** correctly handle setting inputs to `undefined` ([#36140](https://github.com/angular/angular/issues/36140)) ([9ba46d9](https://github.com/angular/angular/commit/9ba46d9))
|
||||
* **elements:** correctly set `SimpleChange#firstChange` for pre-existing inputs ([#36140](https://github.com/angular/angular/issues/36140)) ([b14ac96](https://github.com/angular/angular/commit/b14ac96)), closes [#36130](https://github.com/angular/angular/issues/36130)
|
||||
* **elements:** do not break when the constructor of an Angular Element is not called ([#36114](https://github.com/angular/angular/issues/36114)) ([89b44d1](https://github.com/angular/angular/commit/89b44d1))
|
||||
* **elements:** fire custom element output events during component initialization ([#36161](https://github.com/angular/angular/issues/36161)) ([e9bff5f](https://github.com/angular/angular/commit/e9bff5f)), closes [#36141](https://github.com/angular/angular/issues/36141)
|
||||
* **forms:** handle numeric values properly in the validator ([#36157](https://github.com/angular/angular/issues/36157)) ([88a235d](https://github.com/angular/angular/commit/88a235d)), closes [#35591](https://github.com/angular/angular/issues/35591)
|
||||
* **forms:** number input fires valueChanges twice ([#36087](https://github.com/angular/angular/issues/36087)) ([97d6d90](https://github.com/angular/angular/commit/97d6d90)), closes [#12540](https://github.com/angular/angular/issues/12540)
|
||||
* **language-service:** Improve signature selection by finding exact match ([#37494](https://github.com/angular/angular/issues/37494)) ([e97a2d4](https://github.com/angular/angular/commit/e97a2d4))
|
||||
* **language-service:** Recover from error in analyzing Ng Modules ([#37108](https://github.com/angular/angular/issues/37108)) ([2c1f35e](https://github.com/angular/angular/commit/2c1f35e))
|
||||
* **language-service:** disable update the `[@angular](https://github.com/angular)/core` module ([#36783](https://github.com/angular/angular/issues/36783)) ([dd049ca](https://github.com/angular/angular/commit/dd049ca))
|
||||
* **language-service:** infer type of elements of array-like objects ([#36312](https://github.com/angular/angular/issues/36312)) ([fe2b692](https://github.com/angular/angular/commit/fe2b692)), closes [#36191](https://github.com/angular/angular/issues/36191)
|
||||
* **language-service:** properly evaluate types in comparable expressions ([#36529](https://github.com/angular/angular/issues/36529)) ([8be0972](https://github.com/angular/angular/commit/8be0972))
|
||||
* **language-service:** use empty statement as parent of type node ([#36989](https://github.com/angular/angular/issues/36989)) ([a32cbed](https://github.com/angular/angular/commit/a32cbed))
|
||||
* **language-service:** use the `HtmlAst` to get the span of HTML tag ([#36371](https://github.com/angular/angular/issues/36371)) ([81195a2](https://github.com/angular/angular/commit/81195a2))
|
||||
* **language-service:** wrong completions in conditional operator ([#37505](https://github.com/angular/angular/issues/37505)) ([32020f9](https://github.com/angular/angular/commit/32020f9))
|
||||
* **localize:** allow ICU expansion case to start with any character except `}` ([#36123](https://github.com/angular/angular/issues/36123)) ([fced8ee](https://github.com/angular/angular/commit/fced8ee)), closes [#31586](https://github.com/angular/angular/issues/31586)
|
||||
* **localize:** ensure `getLocation()` works ([#36853](https://github.com/angular/angular/issues/36853)) ([70b25a3](https://github.com/angular/angular/commit/70b25a3))
|
||||
* **localize:** include legacy ids when describing messages ([#36761](https://github.com/angular/angular/issues/36761)) ([47f9867](https://github.com/angular/angular/commit/47f9867))
|
||||
* **ngcc:** `viaModule` should be `null` for local imports ([#36989](https://github.com/angular/angular/issues/36989)) ([d268d2a](https://github.com/angular/angular/commit/d268d2a))
|
||||
* **ngcc:** add process title ([#36448](https://github.com/angular/angular/issues/36448)) ([76a8cd5](https://github.com/angular/angular/commit/76a8cd5)), closes [36414#issuecomment-609644282](https://github.com/angular/angular/issues/36414#issuecomment-609644282)
|
||||
* **ngcc:** allow ngcc configuration to match pre-release versions of packages ([#36370](https://github.com/angular/angular/issues/36370)) ([326240e](https://github.com/angular/angular/commit/326240e))
|
||||
* **ngcc:** capture dynamic import expressions as well as declarations ([#37075](https://github.com/angular/angular/issues/37075)) ([5c0bdae](https://github.com/angular/angular/commit/5c0bdae))
|
||||
* **ngcc:** correctly detect external files from nested `node_modules/` ([#36559](https://github.com/angular/angular/issues/36559)) ([6ab43d7](https://github.com/angular/angular/commit/6ab43d7)), closes [#36526](https://github.com/angular/angular/issues/36526)
|
||||
* **ngcc:** correctly detect imported TypeScript helpers ([#36284](https://github.com/angular/angular/issues/36284)) ([ca25c95](https://github.com/angular/angular/commit/ca25c95)), closes [#36089](https://github.com/angular/angular/issues/36089)
|
||||
* **ngcc:** correctly get config for packages in nested `node_modules/` ([#37040](https://github.com/angular/angular/issues/37040)) ([9ade1c3](https://github.com/angular/angular/commit/9ade1c3))
|
||||
* **ngcc:** correctly get config for sub-entry-points when primary entry-point is ignored ([#37040](https://github.com/angular/angular/issues/37040)) ([bf57776](https://github.com/angular/angular/commit/bf57776))
|
||||
* **ngcc:** correctly identify relative Windows-style import paths ([#36372](https://github.com/angular/angular/issues/36372)) ([aecf9de](https://github.com/angular/angular/commit/aecf9de))
|
||||
* **ngcc:** correctly identify the package path of secondary entry-points ([#36249](https://github.com/angular/angular/issues/36249)) ([995cd15](https://github.com/angular/angular/commit/995cd15)), closes [#35747](https://github.com/angular/angular/issues/35747)
|
||||
* **ngcc:** correctly retrieve a package's version from its `package.json` ([#37040](https://github.com/angular/angular/issues/37040)) ([11c0402](https://github.com/angular/angular/commit/11c0402))
|
||||
* **ngcc:** detect non-emitted, non-imported TypeScript helpers ([#36418](https://github.com/angular/angular/issues/36418)) ([5fa7b8b](https://github.com/angular/angular/commit/5fa7b8b))
|
||||
* **ngcc:** display output from the unlocker process on Windows ([#36569](https://github.com/angular/angular/issues/36569)) ([e041ac6](https://github.com/angular/angular/commit/e041ac6))
|
||||
* **ngcc:** display unlocker process output in sync mode ([#36637](https://github.com/angular/angular/issues/36637)) ([cabf997](https://github.com/angular/angular/commit/cabf997)), closes [/github.com/nodejs/node/issues/3596#issuecomment-250890218](https://github.com/nodejs/node/issues/3596#issuecomment-250890218)
|
||||
* **ngcc:** do not inline source-maps for non-inline typings source-maps ([#37363](https://github.com/angular/angular/issues/37363)) ([b4e26b5](https://github.com/angular/angular/commit/b4e26b5)), closes [#37324](https://github.com/angular/angular/issues/37324)
|
||||
* **ngcc:** do not run in parallel mode if there are less than 3 CPU cores ([#36626](https://github.com/angular/angular/issues/36626)) ([4c63241](https://github.com/angular/angular/commit/4c63241))
|
||||
* **ngcc:** do not scan import expressions in d.ts files ([#37503](https://github.com/angular/angular/issues/37503)) ([8248307](https://github.com/angular/angular/commit/8248307))
|
||||
* **ngcc:** do not spawn more processes than intended in parallel mode ([#36280](https://github.com/angular/angular/issues/36280)) ([5cee709](https://github.com/angular/angular/commit/5cee709)), closes [#35719](https://github.com/angular/angular/issues/35719) [#36278](https://github.com/angular/angular/issues/36278)
|
||||
* **ngcc:** do not spawn unlocker processes on cluster workers ([#36569](https://github.com/angular/angular/issues/36569)) ([66effde](https://github.com/angular/angular/commit/66effde)), closes [#35861](https://github.com/angular/angular/issues/35861)
|
||||
* **ngcc:** do not use cached file-system ([#36687](https://github.com/angular/angular/issues/36687)) ([0c2ed4c](https://github.com/angular/angular/commit/0c2ed4c)), closes [/github.com/angular/angular-cli/issues/16860#issuecomment-614694269](https://github.com/angular/angular-cli/issues/16860#issuecomment-614694269)
|
||||
* **ngcc:** do not warn if `paths` mapping does not exist ([#36525](https://github.com/angular/angular/issues/36525)) ([717df13](https://github.com/angular/angular/commit/717df13)), closes [#36518](https://github.com/angular/angular/issues/36518)
|
||||
* **ngcc:** do not write entry-point manifest outside node_modules ([#36299](https://github.com/angular/angular/issues/36299)) ([c6dd900](https://github.com/angular/angular/commit/c6dd900)), closes [#36296](https://github.com/angular/angular/issues/36296)
|
||||
* **ngcc:** don't crash on cyclic source-map references ([#36452](https://github.com/angular/angular/issues/36452)) ([ee70a18](https://github.com/angular/angular/commit/ee70a18)), closes [#35727](https://github.com/angular/angular/issues/35727) [#35757](https://github.com/angular/angular/issues/35757)
|
||||
* **ngcc:** ensure reflection hosts can handle TS 3.9 IIFE wrapped classes ([#36989](https://github.com/angular/angular/issues/36989)) ([d7440c4](https://github.com/angular/angular/commit/d7440c4))
|
||||
* **ngcc:** ensure rendering formatters work with IIFE wrapped classes ([#36989](https://github.com/angular/angular/issues/36989)) ([c8ee390](https://github.com/angular/angular/commit/c8ee390))
|
||||
* **ngcc:** ensure that more dependencies are found by `EsmDependencyHost` ([#37075](https://github.com/angular/angular/issues/37075)) ([c6872c0](https://github.com/angular/angular/commit/c6872c0))
|
||||
* **ngcc:** find decorated constructor params on IIFE wrapped classes ([#37436](https://github.com/angular/angular/issues/37436)) ([2cb3b66](https://github.com/angular/angular/commit/2cb3b66)), closes [#37330](https://github.com/angular/angular/issues/37330)
|
||||
* **ngcc:** force ngcc to exit on error ([#36622](https://github.com/angular/angular/issues/36622)) ([663b768](https://github.com/angular/angular/commit/663b768)), closes [#36616](https://github.com/angular/angular/issues/36616)
|
||||
* **ngcc:** give up re-spawning crashed worker process after 3 attempts ([#36626](https://github.com/angular/angular/issues/36626)) ([793cb32](https://github.com/angular/angular/commit/793cb32))
|
||||
* **ngcc:** handle `ENOMEM` errors in worker processes ([#36626](https://github.com/angular/angular/issues/36626)) ([4779c4b](https://github.com/angular/angular/commit/4779c4b))
|
||||
* **ngcc:** handle bad path mappings when finding entry-points ([#36331](https://github.com/angular/angular/issues/36331)) ([cc4b813](https://github.com/angular/angular/commit/cc4b813)), closes [#36313](https://github.com/angular/angular/issues/36313) [#36283](https://github.com/angular/angular/issues/36283)
|
||||
* **ngcc:** handle entry-points within container folders ([#36305](https://github.com/angular/angular/issues/36305)) ([38ad1d9](https://github.com/angular/angular/commit/38ad1d9)), closes [#35756](https://github.com/angular/angular/issues/35756) [#36216](https://github.com/angular/angular/issues/36216)
|
||||
* **ngcc:** identifier ModuleWithProviders functions in IIFE wrapped classes ([#37206](https://github.com/angular/angular/issues/37206)) ([97e1399](https://github.com/angular/angular/commit/97e1399)), closes [#37189](https://github.com/angular/angular/issues/37189)
|
||||
* **ngcc:** provide a unique exit code for timeouts ([#36838](https://github.com/angular/angular/issues/36838)) ([d805526](https://github.com/angular/angular/commit/d805526))
|
||||
* **ngcc:** recognize enum declarations emitted in JavaScript ([#36550](https://github.com/angular/angular/issues/36550)) ([89c5890](https://github.com/angular/angular/commit/89c5890)), closes [#35584](https://github.com/angular/angular/issues/35584)
|
||||
* **ngcc:** sniff `main` property for ESM5 format ([#36396](https://github.com/angular/angular/issues/36396)) ([2463548](https://github.com/angular/angular/commit/2463548)), closes [#35788](https://github.com/angular/angular/issues/35788)
|
||||
* **ngcc:** support ModuleWithProviders functions that delegate ([#36948](https://github.com/angular/angular/issues/36948)) ([fafa50d](https://github.com/angular/angular/commit/fafa50d)), closes [#36892](https://github.com/angular/angular/issues/36892)
|
||||
* **ngcc:** support TS 3.9 wrapped ES2015 classes ([#36884](https://github.com/angular/angular/issues/36884)) ([db4c59d](https://github.com/angular/angular/commit/db4c59d))
|
||||
* **ngcc:** support `defineProperty()` re-exports in CommonJS and UMD ([#36989](https://github.com/angular/angular/issues/36989)) ([91092f6](https://github.com/angular/angular/commit/91092f6))
|
||||
* **ngcc:** support ignoring deep-imports via package config ([#36423](https://github.com/angular/angular/issues/36423)) ([f9fb833](https://github.com/angular/angular/commit/f9fb833)), closes [#35750](https://github.com/angular/angular/issues/35750)
|
||||
* **ngcc:** support recovering when a worker process crashes ([#36626](https://github.com/angular/angular/issues/36626)) ([966598c](https://github.com/angular/angular/commit/966598c)), closes [#36278](https://github.com/angular/angular/issues/36278)
|
||||
* **ngcc:** support simple `browser` property in entry-points ([#36396](https://github.com/angular/angular/issues/36396)) ([6b3aa60](https://github.com/angular/angular/commit/6b3aa60)), closes [#36062](https://github.com/angular/angular/issues/36062)
|
||||
* **ngcc:** use annotateForClosureCompiler option ([#36652](https://github.com/angular/angular/issues/36652)) ([eca8d11](https://github.com/angular/angular/commit/eca8d11)), closes [#36618](https://github.com/angular/angular/issues/36618)
|
||||
* **ngcc:** use path-mappings from tsconfig in dependency resolution ([#36180](https://github.com/angular/angular/issues/36180)) ([380de1e](https://github.com/angular/angular/commit/380de1e)), closes [#36119](https://github.com/angular/angular/issues/36119)
|
||||
* **ngcc:** use preserve whitespaces from tsconfig if provided ([#36189](https://github.com/angular/angular/issues/36189)) ([b8e9a30](https://github.com/angular/angular/commit/b8e9a30)), closes [#35871](https://github.com/angular/angular/issues/35871)
|
||||
* **platform-server:** correctly handle absolute relative URLs ([#37341](https://github.com/angular/angular/issues/37341)) ([420d1c3](https://github.com/angular/angular/commit/420d1c3)), closes [#37314](https://github.com/angular/angular/issues/37314)
|
||||
* **platform-server:** update `xhr2` dependency ([#36366](https://github.com/angular/angular/issues/36366)) ([b59bc0e](https://github.com/angular/angular/commit/b59bc0e)), closes [#36358](https://github.com/angular/angular/issues/36358)
|
||||
* **router:** Fix relative link generation from empty path components ([#37446](https://github.com/angular/angular/issues/37446)) ([585e3f6](https://github.com/angular/angular/commit/585e3f6)), closes [#26243](https://github.com/angular/angular/issues/26243) [#13011](https://github.com/angular/angular/issues/13011) [#35687](https://github.com/angular/angular/issues/35687)
|
||||
* **router:** allow UrlMatcher to return null ([#36402](https://github.com/angular/angular/issues/36402)) ([568e9df](https://github.com/angular/angular/commit/568e9df)), closes [#29824](https://github.com/angular/angular/issues/29824)
|
||||
* **router:** cancel navigation when at least one resolver completes with no "next" emission ([#24621](https://github.com/angular/angular/issues/24621)) ([d9c4840](https://github.com/angular/angular/commit/d9c4840)), closes [#24195](https://github.com/angular/angular/issues/24195)
|
||||
* **router:** fix navigation ignoring logic to compare to the browser url ([#37408](https://github.com/angular/angular/issues/37408)) ([5db2e79](https://github.com/angular/angular/commit/5db2e79)), closes [#16710](https://github.com/angular/angular/issues/16710) [#13586](https://github.com/angular/angular/issues/13586)
|
||||
* **router:** pass correct component to canDeactivate checks when using two or more sibling router-outlets ([#36302](https://github.com/angular/angular/issues/36302)) ([80e6c07](https://github.com/angular/angular/commit/80e6c07)), closes [#34614](https://github.com/angular/angular/issues/34614)
|
||||
* **router:** state data missing in routerLink ([#36462](https://github.com/angular/angular/issues/36462)) ([e0415db](https://github.com/angular/angular/commit/e0415db)), closes [#33173](https://github.com/angular/angular/issues/33173)
|
||||
* **router:** update type for routerLink to include null and undefined ([#37018](https://github.com/angular/angular/issues/37018)) ([ef9f8df](https://github.com/angular/angular/commit/ef9f8df)), closes [#13380](https://github.com/angular/angular/issues/13380) [#36544](https://github.com/angular/angular/issues/36544)
|
||||
* **service-worker:** Don't stay locked in EXISTING_CLIENTS_ONLY if corrupted data ([#37453](https://github.com/angular/angular/issues/37453)) ([6f93847](https://github.com/angular/angular/commit/6f93847)), closes [#31109](https://github.com/angular/angular/issues/31109) [#31865](https://github.com/angular/angular/issues/31865)
|
||||
* **service-worker:** by default register the SW after 30s even the app never stabilizes ([#35870](https://github.com/angular/angular/issues/35870)) ([29e8a64](https://github.com/angular/angular/commit/29e8a64)), closes [#34464](https://github.com/angular/angular/issues/34464)
|
||||
* **service-worker:** prevent SW registration strategies from affecting app stabilization ([#35870](https://github.com/angular/angular/issues/35870)) ([2d7c95f](https://github.com/angular/angular/commit/2d7c95f))
|
||||
* **upgrade:** update $locationShim to handle Location changes before initialization ([#36498](https://github.com/angular/angular/issues/36498)) ([0cc53fb](https://github.com/angular/angular/commit/0cc53fb)), closes [#36492](https://github.com/angular/angular/issues/36492)
|
||||
* add aikidave as reviewer for DOCS: Marketing ([#37014](https://github.com/angular/angular/issues/37014)) ([286fbf4](https://github.com/angular/angular/commit/286fbf4))
|
||||
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* **common:** remove WrappedValue from AsyncPipe ([#36633](https://github.com/angular/angular/issues/36633)) ([49be32c](https://github.com/angular/angular/commit/49be32c)), closes [#29927](https://github.com/angular/angular/issues/29927)
|
||||
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **compiler-cli:** perform template type-checking incrementally ([#36211](https://github.com/angular/angular/issues/36211)) ([ecffc35](https://github.com/angular/angular/commit/ecffc35))
|
||||
* **compiler-cli:** split Ivy template type-checking into multiple files ([#36211](https://github.com/angular/angular/issues/36211)) ([b861e9c](https://github.com/angular/angular/commit/b861e9c))
|
||||
* **core:** avoid pulling in jit-specific code in aot bundles ([#37372](https://github.com/angular/angular/issues/37372)) ([#37514](https://github.com/angular/angular/issues/37514)) ([6114cd2](https://github.com/angular/angular/commit/6114cd2)), closes [#29083](https://github.com/angular/angular/issues/29083)
|
||||
* **forms:** optimize internal method _anyControls in FormGroup ([#32534](https://github.com/angular/angular/issues/32534)) ([6c7467a](https://github.com/angular/angular/commit/6c7467a))
|
||||
* **ngcc:** allow immediately reporting a stale lock file ([#37250](https://github.com/angular/angular/issues/37250)) ([930d204](https://github.com/angular/angular/commit/930d204))
|
||||
* **ngcc:** cache parsed tsconfig between runs ([#37417](https://github.com/angular/angular/issues/37417)) ([f9daa13](https://github.com/angular/angular/commit/f9daa13)), closes [#36882](https://github.com/angular/angular/issues/36882)
|
||||
* **ngcc:** only compute basePaths in TargetedEntryPointFinder when needed ([#36881](https://github.com/angular/angular/issues/36881)) ([ec6b9cc](https://github.com/angular/angular/commit/ec6b9cc)), closes [#36874](https://github.com/angular/angular/issues/36874)
|
||||
* **ngcc:** only load if it is needed ([#36486](https://github.com/angular/angular/issues/36486)) ([3bedfda](https://github.com/angular/angular/commit/3bedfda))
|
||||
* **ngcc:** read dependencies from entry-point manifest ([#36486](https://github.com/angular/angular/issues/36486)) ([a185efb](https://github.com/angular/angular/commit/a185efb)), closes [#issuecomment-608401834](https://github.com/angular/angular#issuecomment-608401834)
|
||||
* **ngcc:** reduce the size of the entry-point manifest file ([#36486](https://github.com/angular/angular/issues/36486)) ([ec0ce60](https://github.com/angular/angular/commit/ec0ce60))
|
||||
* **ngcc:** speed up the `getBasePaths()` computation ([#36881](https://github.com/angular/angular/issues/36881)) ([e037840](https://github.com/angular/angular/commit/e037840))
|
||||
|
||||
|
||||
|
||||
#### Dependency updates
|
||||
@angular/compiler-cli now requires:
|
||||
- TypeScript 3.9
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* TypeScript 3.6, 3.7 and 3.8 are no longer supported, please update to TypeScript 3.9.
|
||||
* **core:** Angular npm packages no longer contain jsdoc comments
|
||||
to support Closure Compiler's advanced optimizations
|
||||
|
||||
The support for Closure Compiler in Angular packages has been
|
||||
experimental and broken for quite some time.
|
||||
|
||||
As of TS3.9, Closure is unusable with the JavaScript emit. Please follow
|
||||
https://github.com/microsoft/TypeScript/issues/38374 for more
|
||||
information and updates.
|
||||
|
||||
If you used Closure Compiler with Angular in the past, you will likely
|
||||
be better off consuming Angular packages built from sources directly
|
||||
rather than consuming the version we publish on npm,
|
||||
which is primarily optimized for Webpack/Rollup + Terser build pipeline.
|
||||
|
||||
As a temporary workaround, you might consider using your current build
|
||||
pipeline with Closure flag `--compilation_level=SIMPLE`. This flag
|
||||
will ensure that your build pipeline produces buildable and
|
||||
runnable artifacts, at the cost of increased payload size due to
|
||||
advanced optimizations being disabled.
|
||||
|
||||
If you were affected by this change, please help us understand your
|
||||
needs by leaving a comment on https://github.com/angular/angular/issues/37234.
|
||||
|
||||
* **core:** make generic mandatory for ModuleWithProviders
|
||||
|
||||
A generic type parameter has always been required for the `ModuleWithProviders` pattern to work with Ivy, but prior to this commit, View Engine allowed the generic type to be omitted (though support was officially deprecated).
|
||||
If you're using `ModuleWithProviders` without a generic type in your application code, a v10 migration will update your code for you.
|
||||
|
||||
However, if you are using View Engine and also depending on a library that omits the generic type, you will now get a build time error similar to:
|
||||
|
||||
```
|
||||
error TS2314: Generic type 'ModuleWithProviders<T>' requires 1 type argument(s).
|
||||
```
|
||||
|
||||
In this case, ngcc won't help you (because it's Ivy-only) and the migration only covers application code.
|
||||
You should contact the library author to fix their library to provide a type parameter when they use this class.
|
||||
|
||||
As a workaround, we suggest setting `skipLibChecks` to false in your tsconfig or updating your app to use Ivy.
|
||||
|
||||
* **forms:** Number inputs no longer listen to the `change` event.
|
||||
|
||||
Tests which trigger `change` events need to be updated to trigger `input` events instead.
|
||||
|
||||
The `change` event was in place to support IE9, as we found that `input` events were not fired with backspace or cut actions. If you need to maintain IE9 support, you will need to add a change event listener to number inputs and call the `onChange` method of `NumberValueAccessor` manually.
|
||||
|
||||
Lastly, old versions of WebDriver would synthetically trigger the `change` event on `WebElement.clear` and `WebElement.sendKeys`. If you are using an old version of WebDriver, you may need to update tests to ensure `input` events are triggered. For example, you could use `element.sendKeys(Keys.chord(Keys.CONTROL, "a"), Keys.BACK_SPACE);` in place of `element.clear()`.
|
||||
* **forms:** The `minLength` and `maxLength` validators now verify that the form control's value has a
|
||||
numeric `length` property, and only validate for length if that's the case.
|
||||
|
||||
Previously, falsey values without the length property (such as `0` or
|
||||
`false` values) were triggering validation errors. If your code relies on
|
||||
the old behavior, you can include other validators such as [min][1] or
|
||||
[requiredTrue][2] to the list of validators for a particular field.
|
||||
|
||||
[1]: https://angular.io/api/forms/Validators#min
|
||||
[2]: https://angular.io/api/forms/Validators#requiredTrue
|
||||
* **bazel:** esm5 and fesm5 format is no longer distributed in
|
||||
Angular's npm packages e.g. @angular/core
|
||||
|
||||
If you are not using Angular CLI to build your application or library,
|
||||
and you need to be able to build es5 artifacts, then you will need to
|
||||
downlevel the distributed Angular code to es5 on your own.
|
||||
|
||||
Angular CLI will automatically downlevel the code to es5 if differential
|
||||
loading is enabled in the Angular project, so no action is required from
|
||||
Angular CLI users.
|
||||
|
||||
* **core:** Warnings about unknown elements are now logged as errors. This won't break your app, but it may trip up tools that expect nothing to be logged via `console.error`.
|
||||
* **router:** Any resolver which return EMPTY will cancel navigation.
|
||||
If you want to allow the navigation to continue, you will need to update the resolvers to emit
|
||||
some value, (i.e. defaultIfEmpty(...), of(...), etc).
|
||||
* **service-worker:** Previously, [Vary](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary)
|
||||
headers would be taken into account when retrieving resources from the
|
||||
cache, completely preventing the retrieval of cached assets (due to
|
||||
ServiceWorker implementation details) and leading to unpredictable
|
||||
behavior due to inconsistent/buggy implementations in different
|
||||
browsers.
|
||||
|
||||
Now, `Vary` headers are ignored when retrieving resources from the
|
||||
ServiceWorker caches, which can result in resources being retrieved even
|
||||
when their headers are different. If your application needs to
|
||||
differentiate its responses based on request headers, please make sure
|
||||
the Angular ServiceWorker is [configured](https://angular.io/guide/service-worker-config)
|
||||
to avoid caching the affected resources.
|
||||
* **common:** This change could result in ExpressionChangedAfterItHasBeenChecked errors that
|
||||
were not detected before. The error could previously have gone undetected
|
||||
because two WrappedValues are considered "equal" in all cases for the purposes
|
||||
of the check, even if their respective unwrapped values are not.
|
||||
|
||||
Additionally, `[val]=(observable | async).someProperty` will no longer
|
||||
trigger change detection if the value of `someProperty` is identical to
|
||||
the value in the previous emit. If you need to force change detection,
|
||||
either update the binding to use an object whose reference changes or
|
||||
subscribe to the observable and call markForCheck as needed.
|
||||
|
||||
* **common:** format day-periods that cross midnight
|
||||
|
||||
When formatting a time with the `b` or `B` format codes, the rendered
|
||||
string was not correctly handling day periods that spanned midnight.
|
||||
Instead the logic was falling back to the default case of `AM`.
|
||||
|
||||
Now the logic has been updated so that it matches times that are within
|
||||
a day period that spans midnight, so it will now render the correct
|
||||
output, such as `at night` in the case of English.
|
||||
|
||||
Applications that are using either `formatDate()` or `DatePipe` and any
|
||||
of the `b` or `B` format codes will be affected by this change.
|
||||
|
||||
* **router:** UrlMatcher's type now reflects that it could always return
|
||||
null.
|
||||
|
||||
If you implemented your own Router or Recognizer class, please update it to
|
||||
handle matcher returning null.
|
||||
* **ngcc:** cache parsed tsconfig between runs ([1aae94a](https://github.com/angular/angular/commit/1aae94a)), closes [#37417](https://github.com/angular/angular/issues/37417) [#36882](https://github.com/angular/angular/issues/36882)
|
||||
|
||||
|
||||
|
||||
@ -442,7 +39,7 @@ This release contains a re-submit of the following 3 commits with fixes for TS 3
|
||||
### Bug Fixes
|
||||
|
||||
* **elements:** capture input properties set before upgrading the element ([#36114](https://github.com/angular/angular/issues/36114)) ([#37226](https://github.com/angular/angular/issues/37226)) ([a33cb2d](https://github.com/angular/angular/commit/a33cb2d)), closes [#30848](https://github.com/angular/angular/issues/30848) [#31416](https://github.com/angular/angular/issues/31416)
|
||||
* **elements:** correctly handle getting/setting properties before connecting the element ([#36114](https://github.com/angular/angular/issues/36114)) ([#37226](https://github.com/angular/angular/issues/37226)) ([6ac0042](https://github.com/angular/angular/commit/6ac0042)), closes [/github.com/angular/angular/pull/31416/files#r300326698](https://github.com/angular/angular/pull/31416/files/issues/r300326698)
|
||||
* **elements:** correctly handle getting/setting properties before connecting the element ([#36114](https://github.com/angular/angular/issues/36114)) ([#37226](https://github.com/angular/angular/issues/37226)) ([6ac0042](https://github.com/angular/angular/commit/6ac0042)), closes [/github.com/angular/angular/pull/31416/files#r300326698](https://github.com//github.com/angular/angular/pull/31416/files/issues/r300326698)
|
||||
* **elements:** do not break when the constructor of an Angular Element is not called ([#36114](https://github.com/angular/angular/issues/36114)) ([#37226](https://github.com/angular/angular/issues/37226)) ([1465372](https://github.com/angular/angular/commit/1465372))
|
||||
|
||||
|
||||
@ -456,7 +53,7 @@ This release contains a re-submit of the following 3 commits with fixes for TS 3
|
||||
* **core:** Host classes should not be fed back into `@Input` ([#35889](https://github.com/angular/angular/issues/35889)) ([f872b69](https://github.com/angular/angular/commit/f872b69)), closes [#35383](https://github.com/angular/angular/issues/35383)
|
||||
* **core:** inheritance delegate ctor regex updated to work on minified code ([#36962](https://github.com/angular/angular/issues/36962)) ([e3d3395](https://github.com/angular/angular/commit/e3d3395))
|
||||
* **elements:** capture input properties set before upgrading the element ([#36114](https://github.com/angular/angular/issues/36114)) ([1c8f179](https://github.com/angular/angular/commit/1c8f179)), closes [#30848](https://github.com/angular/angular/issues/30848) [#31416](https://github.com/angular/angular/issues/31416)
|
||||
* **elements:** correctly handle getting/setting properties before connecting the element ([#36114](https://github.com/angular/angular/issues/36114)) ([363f14c](https://github.com/angular/angular/commit/363f14c)), closes [/github.com/angular/angular/pull/31416/files#r300326698](https://github.com/angular/angular/pull/31416/files/issues/r300326698)
|
||||
* **elements:** correctly handle getting/setting properties before connecting the element ([#36114](https://github.com/angular/angular/issues/36114)) ([363f14c](https://github.com/angular/angular/commit/363f14c)), closes [/github.com/angular/angular/pull/31416/files#r300326698](https://github.com//github.com/angular/angular/pull/31416/files/issues/r300326698)
|
||||
* **elements:** do not break when the constructor of an Angular Element is not called ([#36114](https://github.com/angular/angular/issues/36114)) ([87b9f08](https://github.com/angular/angular/commit/87b9f08))
|
||||
* **router:** update type for routerLink to include null and undefined ([#37018](https://github.com/angular/angular/issues/37018)) ([7de7871](https://github.com/angular/angular/commit/7de7871)), closes [#13380](https://github.com/angular/angular/issues/13380) [#36544](https://github.com/angular/angular/issues/36544)
|
||||
|
||||
@ -475,6 +72,7 @@ This release contains various API docs improvements.
|
||||
* **compiler-cli**: Revert "fix(compiler-cli): fix case-sensitivity issues in NgtscCompilerHost (#36968)" (#37003)
|
||||
|
||||
|
||||
|
||||
<a name="9.1.5"></a>
|
||||
## [9.1.5](https://github.com/angular/angular/compare/9.1.4...9.1.5) (2020-05-07)
|
||||
|
||||
@ -520,6 +118,7 @@ This release contains various API docs improvements.
|
||||
* **ngcc:** recognize enum declarations emitted in JavaScript ([#36550](https://github.com/angular/angular/issues/36550)) ([c440165](https://github.com/angular/angular/commit/c440165)), closes [#35584](https://github.com/angular/angular/issues/35584)
|
||||
|
||||
|
||||
|
||||
<a name="9.1.3"></a>
|
||||
## [9.1.3](https://github.com/angular/angular/compare/9.1.2...9.1.3) (2020-04-22)
|
||||
|
||||
@ -534,8 +133,8 @@ This release contains various API docs improvements.
|
||||
* **core:** prevent unknown property check for AOT-compiled components ([#36072](https://github.com/angular/angular/issues/36072)) ([fe1d9ba](https://github.com/angular/angular/commit/fe1d9ba)), closes [#35945](https://github.com/angular/angular/issues/35945)
|
||||
* **core:** properly identify modules affected by overrides in TestBed ([#36649](https://github.com/angular/angular/issues/36649)) ([9724169](https://github.com/angular/angular/commit/9724169)), closes [#36619](https://github.com/angular/angular/issues/36619)
|
||||
* **language-service:** properly evaluate types in comparable expressions ([#36529](https://github.com/angular/angular/issues/36529)) ([5bab498](https://github.com/angular/angular/commit/5bab498))
|
||||
* **ngcc:** display unlocker process output in sync mode ([#36637](https://github.com/angular/angular/issues/36637)) ([da159bd](https://github.com/angular/angular/commit/da159bd)), closes [/github.com/nodejs/node/issues/3596#issuecomment-250890218](https://github.com/nodejs/node/issues/3596#issuecomment-250890218)
|
||||
* **ngcc:** do not use cached file-system ([#36687](https://github.com/angular/angular/issues/36687)) ([18be33a](https://github.com/angular/angular/commit/18be33a)), closes [/github.com/angular/angular-cli/issues/16860#issuecomment-614694269](https://github.com/angular/angular-cli/issues/16860#issuecomment-614694269)
|
||||
* **ngcc:** display unlocker process output in sync mode ([#36637](https://github.com/angular/angular/issues/36637)) ([da159bd](https://github.com/angular/angular/commit/da159bd)), closes [/github.com/nodejs/node/issues/3596#issuecomment-250890218](https://github.com//github.com/nodejs/node/issues/3596/issues/issuecomment-250890218)
|
||||
* **ngcc:** do not use cached file-system ([#36687](https://github.com/angular/angular/issues/36687)) ([18be33a](https://github.com/angular/angular/commit/18be33a)), closes [/github.com/angular/angular-cli/issues/16860#issuecomment-614694269](https://github.com//github.com/angular/angular-cli/issues/16860/issues/issuecomment-614694269)
|
||||
|
||||
|
||||
|
||||
@ -555,11 +154,15 @@ This release contains various API docs improvements.
|
||||
* **router:** pass correct component to canDeactivate checks when using two or more sibling router-outlets ([#36302](https://github.com/angular/angular/issues/36302)) ([8e7f903](https://github.com/angular/angular/commit/8e7f903)), closes [#34614](https://github.com/angular/angular/issues/34614)
|
||||
* **upgrade:** update $locationShim to handle Location changes before initialization ([#36498](https://github.com/angular/angular/issues/36498)) ([a67afcc](https://github.com/angular/angular/commit/a67afcc)), closes [#36492](https://github.com/angular/angular/issues/36492)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
* **ngcc:** only load if it is needed ([#36486](https://github.com/angular/angular/issues/36486)) ([e06512b](https://github.com/angular/angular/commit/e06512b)) * **ngcc:** read dependencies from entry-point manifest ([#36486](https://github.com/angular/angular/issues/36486)) ([918e628](https://github.com/angular/angular/commit/918e628)), closes [#issuecomment-608401834](https://github.com/angular/angular#issuecomment-608401834)
|
||||
|
||||
* **ngcc:** only load if it is needed ([#36486](https://github.com/angular/angular/issues/36486)) ([e06512b](https://github.com/angular/angular/commit/e06512b))
|
||||
* **ngcc:** read dependencies from entry-point manifest ([#36486](https://github.com/angular/angular/issues/36486)) ([918e628](https://github.com/angular/angular/commit/918e628)), closes [#issuecomment-608401834](https://github.com/angular/angular/issues/issuecomment-608401834)
|
||||
* **ngcc:** reduce the size of the entry-point manifest file ([#36486](https://github.com/angular/angular/issues/36486)) ([603b094](https://github.com/angular/angular/commit/603b094))
|
||||
|
||||
|
||||
|
||||
<a name="9.1.1"></a>
|
||||
## [9.1.1](https://github.com/angular/angular/compare/9.1.0...9.1.1) (2020-04-07)
|
||||
|
||||
@ -576,13 +179,13 @@ This release contains various API docs improvements.
|
||||
* **core:** undecorated-classes migration should handle derived abstract classes ([#35339](https://github.com/angular/angular/issues/35339)) ([a631b99](https://github.com/angular/angular/commit/a631b99))
|
||||
* **language-service:** infer type of elements of array-like objects ([#36312](https://github.com/angular/angular/issues/36312)) ([ff523c9](https://github.com/angular/angular/commit/ff523c9)), closes [#36191](https://github.com/angular/angular/issues/36191)
|
||||
* **language-service:** use the `HtmlAst` to get the span of HTML tag ([#36371](https://github.com/angular/angular/issues/36371)) ([ffa4e11](https://github.com/angular/angular/commit/ffa4e11))
|
||||
* **ngcc:** add process title ([#36448](https://github.com/angular/angular/issues/36448)) ([136596d](https://github.com/angular/angular/commit/136596d)), closes [36414#issuecomment-609644282](https://github.com/angular/angular/issues/36414#issuecomment-609644282)
|
||||
* **ngcc:** add process title ([#36448](https://github.com/angular/angular/issues/36448)) ([136596d](https://github.com/angular/angular/commit/136596d)), closes [/github.com/angular/angular/issues/36414#issuecomment-609644282](https://github.com//github.com/angular/angular/issues/36414/issues/issuecomment-609644282)
|
||||
* **ngcc:** allow ngcc configuration to match pre-release versions of packages ([#36370](https://github.com/angular/angular/issues/36370)) ([cb0a2a0](https://github.com/angular/angular/commit/cb0a2a0))
|
||||
* **ngcc:** correctly detect imported TypeScript helpers ([#36284](https://github.com/angular/angular/issues/36284)) ([879457c](https://github.com/angular/angular/commit/879457c)), closes [#36089](https://github.com/angular/angular/issues/36089)
|
||||
* **ngcc:** correctly identify relative Windows-style import paths ([#36372](https://github.com/angular/angular/issues/36372)) ([0daa488](https://github.com/angular/angular/commit/0daa488))
|
||||
* **ngcc:** correctly identify the package path of secondary entry-points ([#36249](https://github.com/angular/angular/issues/36249)) ([e53b686](https://github.com/angular/angular/commit/e53b686)), closes [#35747](https://github.com/angular/angular/issues/35747)
|
||||
* **ngcc:** detect non-emitted, non-imported TypeScript helpers ([#36418](https://github.com/angular/angular/issues/36418)) ([93b32d3](https://github.com/angular/angular/commit/93b32d3))
|
||||
* **ngcc:** do not spawn more processes than intended in parallel mode ([#36280](https://github.com/angular/angular/issues/36280)) ([6ea232e](https://github.com/angular/angular/commit/6ea232e)), closes [#35719](https://github.com/angular/angular/issues/35719) [#36278](https://github.com/angular/angular/issues/36278) [/github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/main.ts#L429](https://github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/main.ts/issues/L429) [/github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts#L108](https://github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts/issues/L108) [/github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts#L110](https://github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts/issues/L110) [/github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts#L199](https://github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts/issues/L199)
|
||||
* **ngcc:** do not spawn more processes than intended in parallel mode ([#36280](https://github.com/angular/angular/issues/36280)) ([6ea232e](https://github.com/angular/angular/commit/6ea232e)), closes [#35719](https://github.com/angular/angular/issues/35719) [#36278](https://github.com/angular/angular/issues/36278) [/github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/main.ts#L429](https://github.com//github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/main.ts/issues/L429) [/github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts#L108](https://github.com//github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts/issues/L108) [/github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts#L110](https://github.com//github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts/issues/L110) [/github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts#L199](https://github.com//github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts/issues/L199)
|
||||
* **ngcc:** do not write entry-point manifest outside node_modules ([#36299](https://github.com/angular/angular/issues/36299)) ([bb8744d](https://github.com/angular/angular/commit/bb8744d)), closes [#36296](https://github.com/angular/angular/issues/36296)
|
||||
* **ngcc:** don't crash on cyclic source-map references ([#36452](https://github.com/angular/angular/issues/36452)) ([56af303](https://github.com/angular/angular/commit/56af303)), closes [#35727](https://github.com/angular/angular/issues/35727) [#35757](https://github.com/angular/angular/issues/35757)
|
||||
* **ngcc:** handle bad path mappings when finding entry-points ([#36331](https://github.com/angular/angular/issues/36331)) ([7bb3588](https://github.com/angular/angular/commit/7bb3588)), closes [#36313](https://github.com/angular/angular/issues/36313) [#36283](https://github.com/angular/angular/issues/36283)
|
||||
@ -594,6 +197,7 @@ This release contains various API docs improvements.
|
||||
* **router:** state data missing in routerLink ([#36462](https://github.com/angular/angular/issues/36462)) ([0e7a89a](https://github.com/angular/angular/commit/0e7a89a)), closes [#33173](https://github.com/angular/angular/issues/33173)
|
||||
|
||||
|
||||
|
||||
<a name="9.1.0"></a>
|
||||
# [9.1.0](https://github.com/angular/angular/compare/9.0.0...9.1.0) (2020-03-25)
|
||||
|
||||
@ -752,7 +356,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* **ngcc:** use path-mappings from tsconfig in dependency resolution ([#36180](https://github.com/angular/angular/issues/36180)) ([6defe96](https://github.com/angular/angular/commit/6defe96)), closes [#36119](https://github.com/angular/angular/issues/36119)
|
||||
* **ngcc:** use preserve whitespaces from tsconfig if provided ([#36189](https://github.com/angular/angular/issues/36189)) ([aef4323](https://github.com/angular/angular/commit/aef4323)), closes [#35871](https://github.com/angular/angular/issues/35871)
|
||||
* **platform-browser:** add missing peerDependency on `[@angular](https://github.com/angular)/animations` ([#35949](https://github.com/angular/angular/issues/35949)) ([64d6f13](https://github.com/angular/angular/commit/64d6f13)), closes [#35888](https://github.com/angular/angular/issues/35888)
|
||||
* **router:** removed unused ApplicationRef dependency ([#35642](https://github.com/angular/angular/issues/35642)) ([c839c05](https://github.com/angular/angular/commit/c839c05)), closes [/github.com/angular/angular/commit/5a849829c42330d7e88e83e916e6e36380c97a97#diff-c0baae5e1df628e1a217e8dc38557](https://github.com/angular/angular/commit/5a849829c42330d7e88e83e916e6e36380c97a97/issues/diff-c0baae5e1df628e1a217e8dc38557)
|
||||
* **router:** removed unused ApplicationRef dependency ([#35642](https://github.com/angular/angular/issues/35642)) ([c839c05](https://github.com/angular/angular/commit/c839c05)), closes [/github.com/angular/angular/commit/5a849829c42330d7e88e83e916e6e36380c97a97#diff-c0baae5e1df628e1a217e8dc38557](https://github.com//github.com/angular/angular/commit/5a849829c42330d7e88e83e916e6e36380c97a97/issues/diff-c0baae5e1df628e1a217e8dc38557)
|
||||
* **router:** state data missing in routerLink ([#33203](https://github.com/angular/angular/issues/33203)) ([de67978](https://github.com/angular/angular/commit/de67978))
|
||||
* **service-worker:** treat 503 as offline ([#35595](https://github.com/angular/angular/issues/35595)) ([96cdf03](https://github.com/angular/angular/commit/96cdf03)), closes [#35571](https://github.com/angular/angular/issues/35571)
|
||||
* fix flaky test cases of passive events ([#35679](https://github.com/angular/angular/issues/35679)) ([8ef29b6](https://github.com/angular/angular/commit/8ef29b6))
|
||||
@ -887,7 +491,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* **ngcc:** correctly detect emitted TS helpers in ES5 ([#35191](https://github.com/angular/angular/issues/35191)) ([af4fe3a](https://github.com/angular/angular/commit/af4fe3a))
|
||||
* **ngcc:** correctly detect outer aliased class identifiers in ES5 ([#35527](https://github.com/angular/angular/issues/35527)) ([39bd9a7](https://github.com/angular/angular/commit/39bd9a7)), closes [#35399](https://github.com/angular/angular/issues/35399)
|
||||
* **ngcc:** handle imports in dts files when processing CommonJS ([#35191](https://github.com/angular/angular/issues/35191)) ([12e3db8](https://github.com/angular/angular/commit/12e3db8)), closes [#34356](https://github.com/angular/angular/issues/34356)
|
||||
* **router:** removed unused ApplicationRef dependency ([#35642](https://github.com/angular/angular/issues/35642)) ([2f140f5](https://github.com/angular/angular/commit/2f140f5)), closes [/github.com/angular/angular/commit/5a849829c42330d7e88e83e916e6e36380c97a97#diff-c0baae5e1df628e1a217e8dc38557](https://github.com/angular/angular/commit/5a849829c42330d7e88e83e916e6e36380c97a97/issues/diff-c0baae5e1df628e1a217e8dc38557)
|
||||
* **router:** removed unused ApplicationRef dependency ([#35642](https://github.com/angular/angular/issues/35642)) ([2f140f5](https://github.com/angular/angular/commit/2f140f5)), closes [/github.com/angular/angular/commit/5a849829c42330d7e88e83e916e6e36380c97a97#diff-c0baae5e1df628e1a217e8dc38557](https://github.com//github.com/angular/angular/commit/5a849829c42330d7e88e83e916e6e36380c97a97/issues/diff-c0baae5e1df628e1a217e8dc38557)
|
||||
* **service-worker:** treat 503 as offline ([#35595](https://github.com/angular/angular/issues/35595)) ([64a415b](https://github.com/angular/angular/commit/64a415b)), closes [#35571](https://github.com/angular/angular/issues/35571)
|
||||
|
||||
|
||||
@ -964,7 +568,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* **ivy:** support emitting a reference to interface declarations ([#34849](https://github.com/angular/angular/issues/34849)) ([ad9ec52](https://github.com/angular/angular/commit/ad9ec52)), closes [#34021](https://github.com/angular/angular/issues/34021) [#34837](https://github.com/angular/angular/issues/34837)
|
||||
* **ivy:** template type-check errors from TS should not use NG error codes ([#35146](https://github.com/angular/angular/issues/35146)) ([cf3071f](https://github.com/angular/angular/commit/cf3071f))
|
||||
* **ivy:** host-styling throws assert exception inside *ngFor ([#35133](https://github.com/angular/angular/issues/35133)) ([31e9873](https://github.com/angular/angular/commit/31e9873)), closes [#35118](https://github.com/angular/angular/issues/35118)
|
||||
* **ngcc:** correctly invalidate cache when moving/removing files/directories ([#35106](https://github.com/angular/angular/issues/35106)) ([22357d4](https://github.com/angular/angular/commit/22357d4)), closes [/github.com/angular/angular/blob/4d36b2f6e/packages/compiler-cli/ngcc/src/writing/cleaning/cleaning_strategies.ts#L54](https://github.com/angular/angular/blob/4d36b2f6e/packages/compiler-cli/ngcc/src/writing/cleaning/cleaning_strategies.ts/issues/L54) [/github.com/angular/angular/blob/4d36b2f6e/packages/compiler-cli/ngcc/src/writing/cleaning/cleaning_strategies.ts#L61](https://github.com/angular/angular/blob/4d36b2f6e/packages/compiler-cli/ngcc/src/writing/cleaning/cleaning_strategies.ts/issues/L61) [#35095](https://github.com/angular/angular/issues/35095)
|
||||
* **ngcc:** correctly invalidate cache when moving/removing files/directories ([#35106](https://github.com/angular/angular/issues/35106)) ([22357d4](https://github.com/angular/angular/commit/22357d4)), closes [/github.com/angular/angular/blob/4d36b2f6e/packages/compiler-cli/ngcc/src/writing/cleaning/cleaning_strategies.ts#L54](https://github.com//github.com/angular/angular/blob/4d36b2f6e/packages/compiler-cli/ngcc/src/writing/cleaning/cleaning_strategies.ts/issues/L54) [/github.com/angular/angular/blob/4d36b2f6e/packages/compiler-cli/ngcc/src/writing/cleaning/cleaning_strategies.ts#L61](https://github.com//github.com/angular/angular/blob/4d36b2f6e/packages/compiler-cli/ngcc/src/writing/cleaning/cleaning_strategies.ts/issues/L61) [#35095](https://github.com/angular/angular/issues/35095)
|
||||
* **ngcc:** do not lock if the target is not compiled by Angular ([#35057](https://github.com/angular/angular/issues/35057)) ([c30c518](https://github.com/angular/angular/commit/c30c518)), closes [#35000](https://github.com/angular/angular/issues/35000)
|
||||
* **compiler-cli:** add `sass` as a valid css preprocessor extension ([#35052](https://github.com/angular/angular/issues/35052)) ([7f96fbb](https://github.com/angular/angular/commit/7f96fbb))
|
||||
* should also allow subclass Promise without Symbol.species ([#34533](https://github.com/angular/angular/issues/34533)) ([0de632a](https://github.com/angular/angular/commit/0de632a))
|
||||
@ -974,10 +578,10 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* **ivy:** ensure `DebugNode`/`DebugElement` are tree-shakeable in Ivy ([#35003](https://github.com/angular/angular/issues/35003)) ([23c0147](https://github.com/angular/angular/commit/23c0147)), closes [#30130](https://github.com/angular/angular/issues/30130)
|
||||
* **ivy:** ensure multi providers in ModuleWithProviders are not duplicated ([#34914](https://github.com/angular/angular/issues/34914)) ([4975f89](https://github.com/angular/angular/commit/4975f89))
|
||||
* **ivy:** update ViewContainerRef to get the correct parentInjector ([#35013](https://github.com/angular/angular/issues/35013)) ([eaa4a5a](https://github.com/angular/angular/commit/eaa4a5a))
|
||||
* **language-service:** prune duplicate returned definitions ([#34995](https://github.com/angular/angular/issues/34995)) ([71f5417](https://github.com/angular/angular/commit/71f5417)), closes [/github.com/angular/angular/pull/34847#discussion_r371006680](https://github.com/angular/angular/pull/34847/issues/discussion_r371006680)
|
||||
* **language-service:** prune duplicate returned definitions ([#34995](https://github.com/angular/angular/issues/34995)) ([71f5417](https://github.com/angular/angular/commit/71f5417)), closes [/github.com/angular/angular/pull/34847#discussion_r371006680](https://github.com//github.com/angular/angular/pull/34847/issues/discussion_r371006680)
|
||||
* **language-service:** remove repeated symbol definitions for structural directive ([#34847](https://github.com/angular/angular/issues/34847)) ([35916d3](https://github.com/angular/angular/commit/35916d3))
|
||||
* **language-service:** warn, not error, on missing context members ([#35036](https://github.com/angular/angular/issues/35036)) ([0e76821](https://github.com/angular/angular/commit/0e76821))
|
||||
* **localize:** re-enable filename in code-frame error messages ([#34994](https://github.com/angular/angular/issues/34994)) ([c7c7b20](https://github.com/angular/angular/commit/c7c7b20)), closes [/github.com/angular/angular/pull/34974/files#r371034476](https://github.com/angular/angular/pull/34974/files/issues/r371034476)
|
||||
* **localize:** re-enable filename in code-frame error messages ([#34994](https://github.com/angular/angular/issues/34994)) ([c7c7b20](https://github.com/angular/angular/commit/c7c7b20)), closes [/github.com/angular/angular/pull/34974/files#r371034476](https://github.com//github.com/angular/angular/pull/34974/files/issues/r371034476)
|
||||
* **ngcc:** improve lockfile error message ([#35001](https://github.com/angular/angular/issues/35001)) ([1d31c81](https://github.com/angular/angular/commit/1d31c81)), closes [#35000](https://github.com/angular/angular/issues/35000)
|
||||
* **ivy:** correctly emit component when it's removed from its module ([#34912](https://github.com/angular/angular/issues/34912)) ([adc663e](https://github.com/angular/angular/commit/adc663e)), closes [#34813](https://github.com/angular/angular/issues/34813)
|
||||
* **ivy:** DebugNode.classes not working on SVG elements ([#34872](https://github.com/angular/angular/issues/34872)) ([7e8aac1](https://github.com/angular/angular/commit/7e8aac1)), closes [#34868](https://github.com/angular/angular/issues/34868)
|
||||
@ -1000,7 +604,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* **compiler-cli:** require node 10 as runtime engine ([#34722](https://github.com/angular/angular/issues/34722)) ([7b77b3d](https://github.com/angular/angular/commit/7b77b3d))
|
||||
* **language-service:** specific suggestions for template context diags ([#34751](https://github.com/angular/angular/issues/34751)) ([cc7fca4](https://github.com/angular/angular/commit/cc7fca4))
|
||||
* **language-service:** support multiple symbol definitions ([#34782](https://github.com/angular/angular/issues/34782)) ([2f2396c](https://github.com/angular/angular/commit/2f2396c))
|
||||
* **ngcc:** lock ngcc when processing ([#34722](https://github.com/angular/angular/issues/34722)) ([6dd51f1](https://github.com/angular/angular/commit/6dd51f1)), closes [32431#issuecomment-571825781](https://github.com/angular/angular/issues/32431#issuecomment-571825781)
|
||||
* **ngcc:** lock ngcc when processing ([#34722](https://github.com/angular/angular/issues/34722)) ([6dd51f1](https://github.com/angular/angular/commit/6dd51f1)), closes [/github.com/angular/angular/issues/32431#issuecomment-571825781](https://github.com//github.com/angular/angular/issues/32431/issues/issuecomment-571825781)
|
||||
* work around 'noImplicityAny' incompatibility due to ts3.7 update ([#34798](https://github.com/angular/angular/issues/34798)) ([251d548](https://github.com/angular/angular/commit/251d548))
|
||||
* **animations:** not waiting for child animations to finish when removing parent in Ivy ([#34702](https://github.com/angular/angular/issues/34702)) ([92c17fe](https://github.com/angular/angular/commit/92c17fe)), closes [#33597](https://github.com/angular/angular/issues/33597)
|
||||
* **common:** ensure diffing in ngStyle/ngClass correctly emits value changes ([#34307](https://github.com/angular/angular/issues/34307)) ([93a035f](https://github.com/angular/angular/commit/93a035f)), closes [#34336](https://github.com/angular/angular/issues/34336) [#34444](https://github.com/angular/angular/issues/34444)
|
||||
@ -1015,19 +619,19 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* **ivy:** ngClass not applying classes with trailing/leading spaces ([#34539](https://github.com/angular/angular/issues/34539)) ([98ed7c6](https://github.com/angular/angular/commit/98ed7c6)), closes [#34476](https://github.com/angular/angular/issues/34476)
|
||||
* **ivy:** Prevent errors when querying DebugElement roots that were outside angular context ([#34687](https://github.com/angular/angular/issues/34687)) ([f1cdb8f](https://github.com/angular/angular/commit/f1cdb8f))
|
||||
* **ivy:** properly bootstrap components with attribute selectors ([#34450](https://github.com/angular/angular/issues/34450)) ([2c0b9ea](https://github.com/angular/angular/commit/2c0b9ea)), closes [#34349](https://github.com/angular/angular/issues/34349)
|
||||
* **ivy:** warn instead of throwing for unknown elements ([#34524](https://github.com/angular/angular/issues/34524)) ([d9ae70e](https://github.com/angular/angular/commit/d9ae70e)), closes [/github.com/angular/angular/pull/33419#discussion_r339296216](https://github.com/angular/angular/pull/33419/issues/discussion_r339296216)
|
||||
* **ivy:** warn instead of throwing for unknown elements ([#34524](https://github.com/angular/angular/issues/34524)) ([d9ae70e](https://github.com/angular/angular/commit/d9ae70e)), closes [/github.com/angular/angular/pull/33419#discussion_r339296216](https://github.com//github.com/angular/angular/pull/33419/issues/discussion_r339296216)
|
||||
* **language-service:** apply suggested change. ([#34564](https://github.com/angular/angular/issues/34564)) ([b3af220](https://github.com/angular/angular/commit/b3af220))
|
||||
* **language-service:** break the hover/definitions for two-way binding ([#34564](https://github.com/angular/angular/issues/34564)) ([eb5c20c](https://github.com/angular/angular/commit/eb5c20c))
|
||||
* **language-service:** CRLF offset in inline template ([#34737](https://github.com/angular/angular/issues/34737)) ([80315b5](https://github.com/angular/angular/commit/80315b5))
|
||||
* **language-service:** do not use an i18n parser for templates ([#34531](https://github.com/angular/angular/issues/34531)) ([cb7dcb3](https://github.com/angular/angular/commit/cb7dcb3))
|
||||
* **language-service:** only visit directives ([#34564](https://github.com/angular/angular/issues/34564)) ([76d7aa7](https://github.com/angular/angular/commit/76d7aa7))
|
||||
* **ngcc:** avoid error due to circular dependency in `EsmDependencyHost` ([#34512](https://github.com/angular/angular/issues/34512)) ([7c3172a](https://github.com/angular/angular/commit/7c3172a)), closes [/github.com/angular/angular/blob/18d89c9c8/packages/compiler-cli/ngcc/src/utils.ts#L10](https://github.com/angular/angular/blob/18d89c9c8/packages/compiler-cli/ngcc/src/utils.ts/issues/L10) [/github.com/angular/angular/blob/18d89c9c8/packages/compiler-cli/ngcc/src/dependencies/esm_dependency_host.ts#L10](https://github.com/angular/angular/blob/18d89c9c8/packages/compiler-cli/ngcc/src/dependencies/esm_dependency_host.ts/issues/L10) [/github.com/angular/angular/blob/18d89c9c8/packages/compiler-cli/ngcc/src/dependencies/dependency_host.ts#L9](https://github.com/angular/angular/blob/18d89c9c8/packages/compiler-cli/ngcc/src/dependencies/dependency_host.ts/issues/L9)
|
||||
* **ngcc:** avoid error due to circular dependency in `EsmDependencyHost` ([#34512](https://github.com/angular/angular/issues/34512)) ([7c3172a](https://github.com/angular/angular/commit/7c3172a)), closes [/github.com/angular/angular/blob/18d89c9c8/packages/compiler-cli/ngcc/src/utils.ts#L10](https://github.com//github.com/angular/angular/blob/18d89c9c8/packages/compiler-cli/ngcc/src/utils.ts/issues/L10) [/github.com/angular/angular/blob/18d89c9c8/packages/compiler-cli/ngcc/src/dependencies/esm_dependency_host.ts#L10](https://github.com//github.com/angular/angular/blob/18d89c9c8/packages/compiler-cli/ngcc/src/dependencies/esm_dependency_host.ts/issues/L10) [/github.com/angular/angular/blob/18d89c9c8/packages/compiler-cli/ngcc/src/dependencies/dependency_host.ts#L9](https://github.com//github.com/angular/angular/blob/18d89c9c8/packages/compiler-cli/ngcc/src/dependencies/dependency_host.ts/issues/L9)
|
||||
* **ngcc:** correctly detect dependencies in CommonJS ([#34528](https://github.com/angular/angular/issues/34528)) ([ff02ddf](https://github.com/angular/angular/commit/ff02ddf))
|
||||
* **ngcc:** correctly handle inline exports in UMD ([#34512](https://github.com/angular/angular/issues/34512)) ([7bbfccf](https://github.com/angular/angular/commit/7bbfccf))
|
||||
* **ngcc:** don't crash if symbol has no declarations ([#34658](https://github.com/angular/angular/issues/34658)) ([4def99e](https://github.com/angular/angular/commit/4def99e)), closes [/github.com/angular/angular/blob/8d0de89e/packages/compiler-cli/src/ngtsc/reflection/src/typescript.ts#L309](https://github.com/angular/angular/blob/8d0de89e/packages/compiler-cli/src/ngtsc/reflection/src/typescript.ts/issues/L309) [#34560](https://github.com/angular/angular/issues/34560)
|
||||
* **ngcc:** don't crash if symbol has no declarations ([#34658](https://github.com/angular/angular/issues/34658)) ([4def99e](https://github.com/angular/angular/commit/4def99e)), closes [/github.com/angular/angular/blob/8d0de89e/packages/compiler-cli/src/ngtsc/reflection/src/typescript.ts#L309](https://github.com//github.com/angular/angular/blob/8d0de89e/packages/compiler-cli/src/ngtsc/reflection/src/typescript.ts/issues/L309) [#34560](https://github.com/angular/angular/issues/34560)
|
||||
* **ngcc:** handle UMD factories that do not use all params ([#34660](https://github.com/angular/angular/issues/34660)) ([83868be](https://github.com/angular/angular/commit/83868be)), closes [#34653](https://github.com/angular/angular/issues/34653)
|
||||
* **ngcc:** insert definitions after statement ([#34677](https://github.com/angular/angular/issues/34677)) ([f295240](https://github.com/angular/angular/commit/f295240)), closes [#34648](https://github.com/angular/angular/issues/34648)
|
||||
* **ngcc:** recognize re-exports with `require()` calls in UMD ([#34512](https://github.com/angular/angular/issues/34512)) ([79be354](https://github.com/angular/angular/commit/79be354)), closes [/github.com/angular/angular/pull/34254/files#r359515373](https://github.com/angular/angular/pull/34254/files/issues/r359515373)
|
||||
* **ngcc:** recognize re-exports with `require()` calls in UMD ([#34512](https://github.com/angular/angular/issues/34512)) ([79be354](https://github.com/angular/angular/commit/79be354)), closes [/github.com/angular/angular/pull/34254/files#r359515373](https://github.com//github.com/angular/angular/pull/34254/files/issues/r359515373)
|
||||
* **ngcc:** recognize re-exports with imported TS helpers in CommonJS and UMD ([#34527](https://github.com/angular/angular/issues/34527)) ([a88dc17](https://github.com/angular/angular/commit/a88dc17))
|
||||
* **common:** remove trailing whitespace for CurrencyPipe ([#34642](https://github.com/angular/angular/issues/34642)) ([c42b90b](https://github.com/angular/angular/commit/c42b90b)), closes [#34641](https://github.com/angular/angular/issues/34641)
|
||||
* **ivy:** append `advance` instructions before `i18nExp` ([#34436](https://github.com/angular/angular/issues/34436)) ([ba4c31c](https://github.com/angular/angular/commit/ba4c31c))
|
||||
@ -1074,7 +678,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* **ivy:** add flag to skip non-exported classes ([#33921](https://github.com/angular/angular/issues/33921)) ([#34340](https://github.com/angular/angular/issues/34340)) ([7ed984b](https://github.com/angular/angular/commit/7ed984b)), closes [#33724](https://github.com/angular/angular/issues/33724)
|
||||
* **ivy:** align TestBed.overrideProvider with what happens with providers in TestBed providers array ([#33769](https://github.com/angular/angular/issues/33769)) ([10a33ef](https://github.com/angular/angular/commit/10a33ef))
|
||||
* **ivy:** do not invoke change detection for destroyed views ([#34241](https://github.com/angular/angular/issues/34241)) ([24bbcaf](https://github.com/angular/angular/commit/24bbcaf))
|
||||
* **ivy:** handle SafeStyles in [style.prop] correctly ([#34286](https://github.com/angular/angular/issues/34286)) ([b0d5784](https://github.com/angular/angular/commit/b0d5784)), closes [/github.com/angular/angular/blob/master/packages/core/src/render3/styling/bindings.ts#L620](https://github.com/angular/angular/blob/master/packages/core/src/render3/styling/bindings.ts/issues/L620)
|
||||
* **ivy:** handle SafeStyles in [style.prop] correctly ([#34286](https://github.com/angular/angular/issues/34286)) ([b0d5784](https://github.com/angular/angular/commit/b0d5784)), closes [/github.com/angular/angular/blob/master/packages/core/src/render3/styling/bindings.ts#L620](https://github.com//github.com/angular/angular/blob/master/packages/core/src/render3/styling/bindings.ts/issues/L620)
|
||||
* **ivy:** inherit static coercion members from base classes ([#34296](https://github.com/angular/angular/issues/34296)) ([edfaab6](https://github.com/angular/angular/commit/edfaab6)), closes [#33830](https://github.com/angular/angular/issues/33830)
|
||||
* **ivy:** properly parenthesize ternary expressions when emitted ([#34221](https://github.com/angular/angular/issues/34221)) ([af36bc6](https://github.com/angular/angular/commit/af36bc6)), closes [#34087](https://github.com/angular/angular/issues/34087)
|
||||
* **ivy:** throw a better error when DI can't inject a ctor param ([#33739](https://github.com/angular/angular/issues/33739)) ([#34340](https://github.com/angular/angular/issues/34340)) ([676aca1](https://github.com/angular/angular/commit/676aca1)), closes [#33637](https://github.com/angular/angular/issues/33637)
|
||||
@ -1087,7 +691,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* **ngcc:** log Angular error codes correctly ([#34014](https://github.com/angular/angular/issues/34014)) ([3cd43c1](https://github.com/angular/angular/commit/3cd43c1))
|
||||
* **ngcc:** report diagnostics from migrations ([#34014](https://github.com/angular/angular/issues/34014)) ([599dcd0](https://github.com/angular/angular/commit/599dcd0))
|
||||
* **bazel:** don't rely on [@angular](https://github.com/angular)/core being as a depedency to install [@angular](https://github.com/angular)/bazel ([#34181](https://github.com/angular/angular/issues/34181)) ([716fc84](https://github.com/angular/angular/commit/716fc84)), closes [#34164](https://github.com/angular/angular/issues/34164)
|
||||
* **bazel:** reenable template type checking in ng_module ([#34144](https://github.com/angular/angular/issues/34144)) ([572e731](https://github.com/angular/angular/commit/572e731)), closes [/github.com/angular/angular/blob/168abc6d6f52713383411b14980e104c99bfeef5/packages/compiler-cli/src/ngtsc/program.ts#L430-L434](https://github.com/angular/angular/blob/168abc6d6f52713383411b14980e104c99bfeef5/packages/compiler-cli/src/ngtsc/program.ts/issues/L430-L434)
|
||||
* **bazel:** reenable template type checking in ng_module ([#34144](https://github.com/angular/angular/issues/34144)) ([572e731](https://github.com/angular/angular/commit/572e731)), closes [/github.com/angular/angular/blob/168abc6d6f52713383411b14980e104c99bfeef5/packages/compiler-cli/src/ngtsc/program.ts#L430-L434](https://github.com//github.com/angular/angular/blob/168abc6d6f52713383411b14980e104c99bfeef5/packages/compiler-cli/src/ngtsc/program.ts/issues/L430-L434)
|
||||
* **common:** reflect input type in NgForOf context ([#33997](https://github.com/angular/angular/issues/33997)) ([b640d38](https://github.com/angular/angular/commit/b640d38))
|
||||
* **common:** reflect input type in NgIf context ([#33997](https://github.com/angular/angular/issues/33997)) ([7504543](https://github.com/angular/angular/commit/7504543)), closes [#31556](https://github.com/angular/angular/issues/31556)
|
||||
* **compiler:** i18n - trim whitespace from i18n custom ids ([#34154](https://github.com/angular/angular/issues/34154)) ([64317c6](https://github.com/angular/angular/commit/64317c6)), closes [#34147](https://github.com/angular/angular/issues/34147)
|
||||
@ -1123,7 +727,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* **ivy:** support inserting a `viewRef` that is already present ([#34052](https://github.com/angular/angular/issues/34052)) ([978b500](https://github.com/angular/angular/commit/978b500)), closes [#33924](https://github.com/angular/angular/issues/33924)
|
||||
* **ivy:** take styles extracted from template into account in JIT mode ([#34017](https://github.com/angular/angular/issues/34017)) ([b659aa3](https://github.com/angular/angular/commit/b659aa3))
|
||||
* **ivy:** track changes across failed builds ([#33971](https://github.com/angular/angular/issues/33971)) ([1ffbde1](https://github.com/angular/angular/commit/1ffbde1)), closes [#32214](https://github.com/angular/angular/issues/32214)
|
||||
* **ivy:** wrap functions from "providers" in parentheses in Closure mode ([#33609](https://github.com/angular/angular/issues/33609)) ([fc6ad19](https://github.com/angular/angular/commit/fc6ad19)), closes [/github.com/angular/tsickle/blob/d7974262571c8a17d684e5ba07680e1b1993afdd/src/jsdoc_transformer.ts#L1021](https://github.com/angular/tsickle/blob/d7974262571c8a17d684e5ba07680e1b1993afdd/src/jsdoc_transformer.ts/issues/L1021)
|
||||
* **ivy:** wrap functions from "providers" in parentheses in Closure mode ([#33609](https://github.com/angular/angular/issues/33609)) ([fc6ad19](https://github.com/angular/angular/commit/fc6ad19)), closes [/github.com/angular/tsickle/blob/d7974262571c8a17d684e5ba07680e1b1993afdd/src/jsdoc_transformer.ts#L1021](https://github.com//github.com/angular/tsickle/blob/d7974262571c8a17d684e5ba07680e1b1993afdd/src/jsdoc_transformer.ts/issues/L1021)
|
||||
* **language-service:** determine index types accessed using dot notation ([#33884](https://github.com/angular/angular/issues/33884)) ([e8ec296](https://github.com/angular/angular/commit/e8ec296)), closes [#29811](https://github.com/angular/angular/issues/29811) [#29811](https://github.com/angular/angular/issues/29811)
|
||||
* **language-service:** fix error of array-index out of bounds exception ([#33928](https://github.com/angular/angular/issues/33928)) ([b05ce85](https://github.com/angular/angular/commit/b05ce85))
|
||||
* **language-service:** function.bind() should not be an error ([#34041](https://github.com/angular/angular/issues/34041)) ([#34046](https://github.com/angular/angular/issues/34046)) ([d22f3d6](https://github.com/angular/angular/commit/d22f3d6))
|
||||
@ -1131,7 +735,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* **ngcc:** do not output duplicate ɵprov properties ([#34085](https://github.com/angular/angular/issues/34085)) ([5a8d25d](https://github.com/angular/angular/commit/5a8d25d))
|
||||
* **ngcc:** render localized strings when in ES5 format ([#33857](https://github.com/angular/angular/issues/33857)) ([c6695fa](https://github.com/angular/angular/commit/c6695fa))
|
||||
* **ngcc:** render UMD global imports correctly ([#34012](https://github.com/angular/angular/issues/34012)) ([83989b8](https://github.com/angular/angular/commit/83989b8))
|
||||
* **ngcc:** report errors from `analyze` and `resolve` processing ([#33964](https://github.com/angular/angular/issues/33964)) ([ca5d772](https://github.com/angular/angular/commit/ca5d772)), closes [33685#issuecomment-557091719](https://github.com/angular/angular/issues/33685#issuecomment-557091719)
|
||||
* **ngcc:** report errors from `analyze` and `resolve` processing ([#33964](https://github.com/angular/angular/issues/33964)) ([ca5d772](https://github.com/angular/angular/commit/ca5d772)), closes [/github.com/angular/angular/issues/33685#issuecomment-557091719](https://github.com//github.com/angular/angular/issues/33685/issues/issuecomment-557091719)
|
||||
* **router:** make routerLinkActive work with query params which contain arrays ([#22666](https://github.com/angular/angular/issues/22666)) ([f1bf5b2](https://github.com/angular/angular/commit/f1bf5b2)), closes [#22223](https://github.com/angular/angular/issues/22223)
|
||||
* **service-worker:** allow creating post api requests after cache failure ([#33930](https://github.com/angular/angular/issues/33930)) ([63c9123](https://github.com/angular/angular/commit/63c9123)), closes [#33793](https://github.com/angular/angular/issues/33793)
|
||||
* **service-worker:** throw when using the unsupported `versionedFiles` option in config ([#33903](https://github.com/angular/angular/issues/33903)) ([250e6fd](https://github.com/angular/angular/commit/250e6fd))
|
||||
@ -1210,7 +814,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* **language-service:** Should not crash if expr ends unexpectedly ([#33524](https://github.com/angular/angular/issues/33524)) ([9ebac71](https://github.com/angular/angular/commit/9ebac71))
|
||||
* **ngcc:** handle new `__spreadArrays` tslib helper ([#33617](https://github.com/angular/angular/issues/33617)) ([d749dd3](https://github.com/angular/angular/commit/d749dd3)), closes [#33614](https://github.com/angular/angular/issues/33614)
|
||||
* **ngcc:** override `getInternalNameOfClass()` and `getAdjacentNameOfClass()` for ES5 ([#33533](https://github.com/angular/angular/issues/33533)) ([93a23b9](https://github.com/angular/angular/commit/93a23b9))
|
||||
* **ngcc:** render adjacent statements after static properties ([#33630](https://github.com/angular/angular/issues/33630)) ([fe12d0d](https://github.com/angular/angular/commit/fe12d0d)), closes [/github.com/angular/angular/pull/33337#issuecomment-545487737](https://github.com/angular/angular/pull/33337#issuecomment-545487737)
|
||||
* **ngcc:** render adjacent statements after static properties ([#33630](https://github.com/angular/angular/issues/33630)) ([fe12d0d](https://github.com/angular/angular/commit/fe12d0d)), closes [/github.com/angular/angular/pull/33337#issuecomment-545487737](https://github.com//github.com/angular/angular/pull/33337/issues/issuecomment-545487737)
|
||||
* **ngcc:** render new definitions using the inner name of the class ([#33533](https://github.com/angular/angular/issues/33533)) ([85298e3](https://github.com/angular/angular/commit/85298e3))
|
||||
* **service-worker:** ensure initialization before handling messages ([#32525](https://github.com/angular/angular/issues/32525)) ([72eba77](https://github.com/angular/angular/commit/72eba77)), closes [#25611](https://github.com/angular/angular/issues/25611)
|
||||
* **compiler:** i18n - ignore `alt-trans` tags in XLIFF 1.2 ([#33450](https://github.com/angular/angular/issues/33450)) ([936700a](https://github.com/angular/angular/commit/936700a)), closes [#33161](https://github.com/angular/angular/issues/33161)
|
||||
@ -1240,7 +844,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* **language-service:** Add directive selectors & banana-in-a-box to completions ([#33311](https://github.com/angular/angular/issues/33311)) ([49eec5d](https://github.com/angular/angular/commit/49eec5d))
|
||||
* **language-service:** Add global symbol for $any() ([#33245](https://github.com/angular/angular/issues/33245)) ([3f257e9](https://github.com/angular/angular/commit/3f257e9))
|
||||
* **language-service:** Preserve CRLF in templates for language-service ([#33241](https://github.com/angular/angular/issues/33241)) ([65a0d2b](https://github.com/angular/angular/commit/65a0d2b))
|
||||
* **ngcc:** do not fail when multiple workers try to create the same directory ([#33237](https://github.com/angular/angular/issues/33237)) ([8017229](https://github.com/angular/angular/commit/8017229)), closes [/github.com/angular/angular/pull/33049#issuecomment-540485703](https://github.com/angular/angular/pull/33049#issuecomment-540485703)
|
||||
* **ngcc:** do not fail when multiple workers try to create the same directory ([#33237](https://github.com/angular/angular/issues/33237)) ([8017229](https://github.com/angular/angular/commit/8017229)), closes [/github.com/angular/angular/pull/33049#issuecomment-540485703](https://github.com//github.com/angular/angular/pull/33049/issues/issuecomment-540485703)
|
||||
* **bazel:** Remove angular devkit and restore ngc postinstall ([#32946](https://github.com/angular/angular/issues/32946)) ([f036684](https://github.com/angular/angular/commit/f036684))
|
||||
* **common:** remove deprecated support for intl API ([#29250](https://github.com/angular/angular/issues/29250)) ([9e7668f](https://github.com/angular/angular/commit/9e7668f)), closes [#18284](https://github.com/angular/angular/issues/18284)
|
||||
* **compiler:** absolute source span for template attribute expressions ([#33189](https://github.com/angular/angular/issues/33189)) ([fd4fed1](https://github.com/angular/angular/commit/fd4fed1))
|
||||
@ -1254,7 +858,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* **ivy:** use ReflectionHost to check exports when writing an import ([#33192](https://github.com/angular/angular/issues/33192)) ([de44570](https://github.com/angular/angular/commit/de44570))
|
||||
* **language-service:** Increase project/script version in MockHost.reset() ([#33200](https://github.com/angular/angular/issues/33200)) ([43241a5](https://github.com/angular/angular/commit/43241a5))
|
||||
* **language-service:** reset MockHost after every spec instead of creating new LS ([#33200](https://github.com/angular/angular/issues/33200)) ([11bf767](https://github.com/angular/angular/commit/11bf767))
|
||||
* **ngcc:** avoid warning when reflecting on index signature member ([#33198](https://github.com/angular/angular/issues/33198)) ([78214e7](https://github.com/angular/angular/commit/78214e7)), closes [/github.com/angular/angular/blob/4659cc26e/packages/common/http/src/jsonp.ts#L39](https://github.com/angular/angular/blob/4659cc26e/packages/common/http/src/jsonp.ts/issues/L39)
|
||||
* **ngcc:** avoid warning when reflecting on index signature member ([#33198](https://github.com/angular/angular/issues/33198)) ([78214e7](https://github.com/angular/angular/commit/78214e7)), closes [/github.com/angular/angular/blob/4659cc26e/packages/common/http/src/jsonp.ts#L39](https://github.com//github.com/angular/angular/blob/4659cc26e/packages/common/http/src/jsonp.ts/issues/L39)
|
||||
* **ngcc:** better detection of end of decorator expression ([#33192](https://github.com/angular/angular/issues/33192)) ([5071083](https://github.com/angular/angular/commit/5071083))
|
||||
* **ngcc:** Esm5ReflectionHost.getDeclarationOfIdentifier should handle aliased inner declarations ([#33252](https://github.com/angular/angular/issues/33252)) ([bfd07b3](https://github.com/angular/angular/commit/bfd07b3))
|
||||
* **ngcc:** report the correct viaModule when reflecting over commonjs ([#33192](https://github.com/angular/angular/issues/33192)) ([afcff73](https://github.com/angular/angular/commit/afcff73))
|
||||
@ -1273,7 +877,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* google3 sync which requires type hints ([#33108](https://github.com/angular/angular/issues/33108)) ([0c69ec2](https://github.com/angular/angular/commit/0c69ec2))
|
||||
* **ngcc:** rename the executable from `ivy-ngcc` to `ngcc` ([#33140](https://github.com/angular/angular/issues/33140)) ([1a34fbc](https://github.com/angular/angular/commit/1a34fbc))
|
||||
* **service-worker:** continue serving api requests on cache failure ([#32996](https://github.com/angular/angular/issues/32996)) ([52483bf](https://github.com/angular/angular/commit/52483bf)), closes [#21412](https://github.com/angular/angular/issues/21412)
|
||||
* **common:** expand type for "ngForOf" input to work with strict null checks ([#31371](https://github.com/angular/angular/issues/31371)) ([c1bb886](https://github.com/angular/angular/commit/c1bb886)), closes [#16373](https://github.com/angular/components/pull/16373)
|
||||
* **common:** expand type for "ngForOf" input to work with strict null checks ([#31371](https://github.com/angular/angular/issues/31371)) ([c1bb886](https://github.com/angular/angular/commit/c1bb886)), closes [#16373](https://github.com//github.com/angular/components/pull/16373)
|
||||
* **core:** ngNoopZone should have the same signature with ngZone ([#32068](https://github.com/angular/angular/issues/32068)) ([3a53e2c](https://github.com/angular/angular/commit/3a53e2c)), closes [#32063](https://github.com/angular/angular/issues/32063)
|
||||
* **core:** set migration schematic versions to valid semver versions ([#32991](https://github.com/angular/angular/issues/32991)) ([0119f46](https://github.com/angular/angular/commit/0119f46))
|
||||
* **core:** update migration descriptions with links to AIO documentation ([#32991](https://github.com/angular/angular/issues/32991)) ([f8eca84](https://github.com/angular/angular/commit/f8eca84))
|
||||
@ -1297,7 +901,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* **language-service:** Turn on strict mode for test project ([#32783](https://github.com/angular/angular/issues/32783)) ([28358b6](https://github.com/angular/angular/commit/28358b6))
|
||||
* **ngcc:** ensure private exports are added for `ModuleWithProviders` ([#32902](https://github.com/angular/angular/issues/32902)) ([002a97d](https://github.com/angular/angular/commit/002a97d))
|
||||
* **ngcc:** handle presence of both `ctorParameters` and `__decorate` ([#32901](https://github.com/angular/angular/issues/32901)) ([747f0cf](https://github.com/angular/angular/commit/747f0cf))
|
||||
* **ngcc:** make the build-marker error more clear ([#32712](https://github.com/angular/angular/issues/32712)) ([0ea4875](https://github.com/angular/angular/commit/0ea4875)), closes [31354#issuecomment-532080537](https://github.com/angular/angular/issues/31354#issuecomment-532080537)
|
||||
* **ngcc:** make the build-marker error more clear ([#32712](https://github.com/angular/angular/issues/32712)) ([0ea4875](https://github.com/angular/angular/commit/0ea4875)), closes [/github.com/angular/angular/issues/31354#issuecomment-532080537](https://github.com//github.com/angular/angular/issues/31354/issues/issuecomment-532080537)
|
||||
* **upgrade:** fix AngularJsUrlCodec to support Safari ([#32959](https://github.com/angular/angular/issues/32959)) ([39e8ceb](https://github.com/angular/angular/commit/39e8ceb))
|
||||
* **ivy:** ensure `window.ng.getDebugNode` returns debug info for component elements ([#32780](https://github.com/angular/angular/issues/32780)) ([5651fa3](https://github.com/angular/angular/commit/5651fa3))
|
||||
* **ivy:** ensure multiple map-based bindings do not skip intermediate values ([#32774](https://github.com/angular/angular/issues/32774)) ([86fd571](https://github.com/angular/angular/commit/86fd571))
|
||||
@ -1406,7 +1010,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* **ivy:** graceful evaluation of unknown or invalid expressions ([#33453](https://github.com/angular/angular/issues/33453)) ([ce30888](https://github.com/angular/angular/commit/ce30888))
|
||||
* **ivy:** implement unknown element detection in jit mode ([#33419](https://github.com/angular/angular/issues/33419)) ([c83f501](https://github.com/angular/angular/commit/c83f501))
|
||||
* add a flag in bootstrap to enable coalesce event change detection to improve performance ([#30533](https://github.com/angular/angular/issues/30533)) ([44623a1](https://github.com/angular/angular/commit/44623a1))
|
||||
* **bazel:** update [@bazel](https://github.com/bazel)/schematics to Bazel 1.0.0 ([#33476](https://github.com/angular/angular/issues/33476)) ([540d104](https://github.com/angular/angular/commit/540d104)), closes [/github.com/angular/angular/pull/33367#issuecomment-547643246](https://github.com/angular/angular/pull/33367#issuecomment-547643246)
|
||||
* **bazel:** update [@bazel](https://github.com/bazel)/schematics to Bazel 1.0.0 ([#33476](https://github.com/angular/angular/issues/33476)) ([540d104](https://github.com/angular/angular/commit/540d104)), closes [/github.com/angular/angular/pull/33367#issuecomment-547643246](https://github.com//github.com/angular/angular/pull/33367/issues/issuecomment-547643246)
|
||||
* **bazel:** update bazel-schematics to use Ivy and new rollup_bundle ([#33435](https://github.com/angular/angular/issues/33435)) ([bf913cc](https://github.com/angular/angular/commit/bf913cc))
|
||||
* **ivy:** i18n - support inlining of XTB formatted translation files ([#33444](https://github.com/angular/angular/issues/33444)) ([2c623fd](https://github.com/angular/angular/commit/2c623fd))
|
||||
* **language-service:** add support for text replacement ([#33091](https://github.com/angular/angular/issues/33091)) ([da4eb91](https://github.com/angular/angular/commit/da4eb91))
|
||||
@ -1448,7 +1052,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* **ivy:** i18n - implement compile-time inlining ([#32881](https://github.com/angular/angular/issues/32881)) ([2cdb3a0](https://github.com/angular/angular/commit/2cdb3a0))
|
||||
* **ivy:** i18n - render legacy message ids in `$localize` if requested ([#32937](https://github.com/angular/angular/issues/32937)) ([bcbf3e4](https://github.com/angular/angular/commit/bcbf3e4))
|
||||
* **language-service:** module definitions on directive hover ([#32763](https://github.com/angular/angular/issues/32763)) ([0d186dd](https://github.com/angular/angular/commit/0d186dd)), closes [#32565](https://github.com/angular/angular/issues/32565)
|
||||
* **ngcc:** expose `--create-ivy-entry-points` option on ivy-ngcc ([#33049](https://github.com/angular/angular/issues/33049)) ([b2b917d](https://github.com/angular/angular/commit/b2b917d)), closes [/github.com/angular/angular/pull/32999#issuecomment-539937368](https://github.com/angular/angular/pull/32999#issuecomment-539937368)
|
||||
* **ngcc:** expose `--create-ivy-entry-points` option on ivy-ngcc ([#33049](https://github.com/angular/angular/issues/33049)) ([b2b917d](https://github.com/angular/angular/commit/b2b917d)), closes [/github.com/angular/angular/pull/32999#issuecomment-539937368](https://github.com//github.com/angular/angular/pull/32999/issues/issuecomment-539937368)
|
||||
* update rxjs peerDependencies minimum requirment to 6.5.3 ([#32812](https://github.com/angular/angular/issues/32812)) ([66658c4](https://github.com/angular/angular/commit/66658c4))
|
||||
* **ivy:** support ng-add in localize package ([#32791](https://github.com/angular/angular/issues/32791)) ([e41cbfb](https://github.com/angular/angular/commit/e41cbfb))
|
||||
* **language-service:** allow retreiving synchronized analyzed NgModules ([#32779](https://github.com/angular/angular/issues/32779)) ([98feee7](https://github.com/angular/angular/commit/98feee7))
|
||||
@ -1857,7 +1461,7 @@ This release contains various API docs improvements.
|
||||
|
||||
* use the correct WTF array to iterate over ([#31208](https://github.com/angular/angular/issues/31208)) ([4aed480](https://github.com/angular/angular/commit/4aed480))
|
||||
* **compiler-cli:** Return original sourceFile instead of redirected sourceFile from getSourceFile ([#26036](https://github.com/angular/angular/issues/26036)) ([13dbb98](https://github.com/angular/angular/commit/13dbb98)), closes [#22524](https://github.com/angular/angular/issues/22524)
|
||||
* **core:** export provider interfaces that are part of the public API types ([#31377](https://github.com/angular/angular/issues/31377)) ([bebf089](https://github.com/angular/angular/commit/bebf089)), closes [/github.com/angular/angular/pull/31377#discussion_r299254408](https://github.com/angular/angular/pull/31377/issues/discussion_r299254408) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L365-L366](https://github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L365-L366) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L283-L284](https://github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L283-L284) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts#L23](https://github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts/issues/L23)
|
||||
* **core:** export provider interfaces that are part of the public API types ([#31377](https://github.com/angular/angular/issues/31377)) ([bebf089](https://github.com/angular/angular/commit/bebf089)), closes [/github.com/angular/angular/pull/31377#discussion_r299254408](https://github.com//github.com/angular/angular/pull/31377/issues/discussion_r299254408) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L365-L366](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L365-L366) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L283-L284](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L283-L284) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts#L23](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts/issues/L23)
|
||||
|
||||
|
||||
<a name="8.1.1"></a>
|
||||
@ -1866,7 +1470,7 @@ This release contains various API docs improvements.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** export provider interfaces that are part of the public API types ([#31377](https://github.com/angular/angular/issues/31377)) ([bebf089](https://github.com/angular/angular/commit/bebf089)), closes [/github.com/angular/angular/pull/31377#discussion_r299254408](https://github.com/angular/angular/pull/31377/issues/discussion_r299254408) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L365-L366](https://github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L365-L366) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L283-L284](https://github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L283-L284) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts#L23](https://github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts/issues/L23)
|
||||
* **core:** export provider interfaces that are part of the public API types ([#31377](https://github.com/angular/angular/issues/31377)) ([bebf089](https://github.com/angular/angular/commit/bebf089)), closes [/github.com/angular/angular/pull/31377#discussion_r299254408](https://github.com//github.com/angular/angular/pull/31377/issues/discussion_r299254408) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L365-L366](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L365-L366) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L283-L284](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L283-L284) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts#L23](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts/issues/L23)
|
||||
|
||||
|
||||
|
||||
@ -1962,7 +1566,7 @@ This release contains various API docs improvements.
|
||||
* **bazel:** do not modify tsconfig.json ([#30984](https://github.com/angular/angular/issues/30984)) ([49307f0](https://github.com/angular/angular/commit/49307f0))
|
||||
* **bazel:** Load global stylesheet in dev and prod ([#30879](https://github.com/angular/angular/issues/30879)) ([5a7bcd1](https://github.com/angular/angular/commit/5a7bcd1))
|
||||
* **common:** expose the `HttpUploadProgressEvent` interface as public API ([#30852](https://github.com/angular/angular/issues/30852)) ([4e8614b](https://github.com/angular/angular/commit/4e8614b)), closes [#30814](https://github.com/angular/angular/issues/30814)
|
||||
* **core:** TypeScript related migrations should cater for BOM ([#30719](https://github.com/angular/angular/issues/30719)) ([26e3615](https://github.com/angular/angular/commit/26e3615)), closes [/github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/src/tree/recorder.ts#L72](https://github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/src/tree/recorder.ts/issues/L72) [#30713](https://github.com/angular/angular/issues/30713)
|
||||
* **core:** TypeScript related migrations should cater for BOM ([#30719](https://github.com/angular/angular/issues/30719)) ([26e3615](https://github.com/angular/angular/commit/26e3615)), closes [/github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/src/tree/recorder.ts#L72](https://github.com//github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/src/tree/recorder.ts/issues/L72) [#30713](https://github.com/angular/angular/issues/30713)
|
||||
* **service-worker:** avoid uncaught rejection warning when registration fails ([#30876](https://github.com/angular/angular/issues/30876)) ([08c38a1](https://github.com/angular/angular/commit/08c38a1))
|
||||
|
||||
|
||||
@ -1973,7 +1577,7 @@ This release contains various API docs improvements.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** TypeScript related migrations should cater for BOM ([#30719](https://github.com/angular/angular/issues/30719)) ([80394ce](https://github.com/angular/angular/commit/80394ce)), closes [/github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/src/tree/recorder.ts#L72](https://github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/src/tree/recorder.ts/issues/L72) [#30713](https://github.com/angular/angular/issues/30713)
|
||||
* **core:** TypeScript related migrations should cater for BOM ([#30719](https://github.com/angular/angular/issues/30719)) ([80394ce](https://github.com/angular/angular/commit/80394ce)), closes [/github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/src/tree/recorder.ts#L72](https://github.com//github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/src/tree/recorder.ts/issues/L72) [#30713](https://github.com/angular/angular/issues/30713)
|
||||
|
||||
|
||||
|
||||
@ -2126,7 +1730,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* **common:** add upgrade sub-package to `ng_package` rule for @angular/common ([#30117](https://github.com/angular/angular/issues/30117)) ([6de4cbd](https://github.com/angular/angular/commit/6de4cbd)), closes [#30055](https://github.com/angular/angular/issues/30055) [#30116](https://github.com/angular/angular/issues/30116)
|
||||
* **common:** adjust `MockPlatformLocation` to set state to new object ([#30055](https://github.com/angular/angular/issues/30055)) ([825efa8](https://github.com/angular/angular/commit/825efa8))
|
||||
* **compiler:** Fix compiler crash due to isSkipSelf of null ([#30075](https://github.com/angular/angular/issues/30075)) ([28fd5ab](https://github.com/angular/angular/commit/28fd5ab))
|
||||
* **upgrade:** do not break if `onMicrotaskEmpty` emits while a `$digest` is in progress ([#29794](https://github.com/angular/angular/issues/29794)) ([0ddf2e7](https://github.com/angular/angular/commit/0ddf2e7)), closes [#24680](https://github.com/angular/angular/issues/24680) [/github.com/angular/angular/blob/78146c189/packages/core/src/util/ng_dev_mode.ts#L12](https://github.com/angular/angular/blob/78146c189/packages/core/src/util/ng_dev_mode.ts/issues/L12) [#24680](https://github.com/angular/angular/issues/24680)
|
||||
* **upgrade:** do not break if `onMicrotaskEmpty` emits while a `$digest` is in progress ([#29794](https://github.com/angular/angular/issues/29794)) ([0ddf2e7](https://github.com/angular/angular/commit/0ddf2e7)), closes [#24680](https://github.com/angular/angular/issues/24680) [/github.com/angular/angular/blob/78146c189/packages/core/src/util/ng_dev_mode.ts#L12](https://github.com//github.com/angular/angular/blob/78146c189/packages/core/src/util/ng_dev_mode.ts/issues/L12) [#24680](https://github.com/angular/angular/issues/24680)
|
||||
* **bazel:** do not typecheck core schematic files ([#29876](https://github.com/angular/angular/issues/29876)) ([2ba799d](https://github.com/angular/angular/commit/2ba799d))
|
||||
* **bazel:** restore `ng build --prod` ([#30005](https://github.com/angular/angular/issues/30005)) ([96a8289](https://github.com/angular/angular/commit/96a8289))
|
||||
* **common:** prevent repeated application of `HttpParams` mutations ([#29045](https://github.com/angular/angular/issues/29045)) ([8e8e89a](https://github.com/angular/angular/commit/8e8e89a)), closes [#20430](https://github.com/angular/angular/issues/20430)
|
||||
@ -2180,7 +1784,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* **platform-server:** update minimum domino version to latest released ([#28893](https://github.com/angular/angular/issues/28893)) ([79e2ca0](https://github.com/angular/angular/commit/79e2ca0))
|
||||
* **router:** removed obsolete TODO comment ([#29085](https://github.com/angular/angular/issues/29085)) ([72ecc45](https://github.com/angular/angular/commit/72ecc45))
|
||||
* **service-worker:** detect new version even if files are identical to an old one ([#26006](https://github.com/angular/angular/issues/26006)) ([586234b](https://github.com/angular/angular/commit/586234b)), closes [#24338](https://github.com/angular/angular/issues/24338)
|
||||
* **service-worker:** ignore passive mixed content requests ([#25994](https://github.com/angular/angular/issues/25994)) ([48214e2](https://github.com/angular/angular/commit/48214e2)), closes [23012#issuecomment-376430187](https://github.com/angular/angular/issues/23012#issuecomment-376430187) [#23012](https://github.com/angular/angular/issues/23012)
|
||||
* **service-worker:** ignore passive mixed content requests ([#25994](https://github.com/angular/angular/issues/25994)) ([48214e2](https://github.com/angular/angular/commit/48214e2)), closes [/github.com/angular/angular/issues/23012#issuecomment-376430187](https://github.com//github.com/angular/angular/issues/23012/issues/issuecomment-376430187) [#23012](https://github.com/angular/angular/issues/23012)
|
||||
* **bazel:** Pin browsers for schematics ([#28913](https://github.com/angular/angular/issues/28913)) ([1145bdb](https://github.com/angular/angular/commit/1145bdb))
|
||||
* **bazel:** rxjs_umd_modules should always be present ([#28881](https://github.com/angular/angular/issues/28881)) ([9ae14db](https://github.com/angular/angular/commit/9ae14db))
|
||||
* **compiler:** use correct variable in invalid function ([#28656](https://github.com/angular/angular/issues/28656)) ([f75acbd](https://github.com/angular/angular/commit/f75acbd))
|
||||
@ -2188,7 +1792,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
||||
* **language-service:** Fix completions for input/output with alias ([#28904](https://github.com/angular/angular/issues/28904)) ([ad4a9bf](https://github.com/angular/angular/commit/ad4a9bf)), closes [#27959](https://github.com/angular/angular/issues/27959)
|
||||
* **bazel:** Add postinstall step to generate summaries ([#28850](https://github.com/angular/angular/issues/28850)) ([96b597c](https://github.com/angular/angular/commit/96b597c))
|
||||
* **bazel:** Schematics should upgrade rxjs to 6.4.0 ([#28841](https://github.com/angular/angular/issues/28841)) ([2d80419](https://github.com/angular/angular/commit/2d80419))
|
||||
* **compiler-cli:** incorrect bundled metadata for static class member call expressions ([#28762](https://github.com/angular/angular/issues/28762)) ([4131715](https://github.com/angular/angular/commit/4131715)), closes [/github.com/angular/angular/blob/master/packages/core/src/change_detection/differs/keyvalue_differs.ts#L121](https://github.com/angular/angular/blob/master/packages/core/src/change_detection/differs/keyvalue_differs.ts/issues/L121) [#28741](https://github.com/angular/angular/issues/28741)
|
||||
* **compiler-cli:** incorrect bundled metadata for static class member call expressions ([#28762](https://github.com/angular/angular/issues/28762)) ([4131715](https://github.com/angular/angular/commit/4131715)), closes [/github.com/angular/angular/blob/master/packages/core/src/change_detection/differs/keyvalue_differs.ts#L121](https://github.com//github.com/angular/angular/blob/master/packages/core/src/change_detection/differs/keyvalue_differs.ts/issues/L121) [#28741](https://github.com/angular/angular/issues/28741)
|
||||
* **bazel:** Install angular repo before yarn_install ([#28670](https://github.com/angular/angular/issues/28670)) ([49fb8c3](https://github.com/angular/angular/commit/49fb8c3))
|
||||
* **bazel:** Turn on strict action env ([#28675](https://github.com/angular/angular/issues/28675)) ([2ea030c](https://github.com/angular/angular/commit/2ea030c))
|
||||
* **compiler:** ensure that event handlers have the correct source spans ([#28055](https://github.com/angular/angular/issues/28055)) ([cffd862](https://github.com/angular/angular/commit/cffd862))
|
||||
@ -2341,7 +1945,7 @@ For details on how to migrate, please refer to [the deprecations guide](https://
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **upgrade:** do not break if `onMicrotaskEmpty` emits while a `$digest` is in progress ([#29794](https://github.com/angular/angular/issues/29794)) ([#30107](https://github.com/angular/angular/issues/30107)) ([1084c19](https://github.com/angular/angular/commit/1084c19)), closes [#24680](https://github.com/angular/angular/issues/24680) [/github.com/angular/angular/blob/78146c189/packages/core/src/util/ng_dev_mode.ts#L12](https://github.com/angular/angular/blob/78146c189/packages/core/src/util/ng_dev_mode.ts/issues/L12) [#24680](https://github.com/angular/angular/issues/24680)
|
||||
* **upgrade:** do not break if `onMicrotaskEmpty` emits while a `$digest` is in progress ([#29794](https://github.com/angular/angular/issues/29794)) ([#30107](https://github.com/angular/angular/issues/30107)) ([1084c19](https://github.com/angular/angular/commit/1084c19)), closes [#24680](https://github.com/angular/angular/issues/24680) [/github.com/angular/angular/blob/78146c189/packages/core/src/util/ng_dev_mode.ts#L12](https://github.com//github.com/angular/angular/blob/78146c189/packages/core/src/util/ng_dev_mode.ts/issues/L12) [#24680](https://github.com/angular/angular/issues/24680)
|
||||
|
||||
|
||||
<a name="7.2.13"></a>
|
||||
@ -2395,7 +1999,7 @@ This release contains various API docs improvements.
|
||||
* **animations:** ensure `position` and `display` styles are handled outside of keyframes/web-animations ([#28911](https://github.com/angular/angular/issues/28911)) ([86981b3](https://github.com/angular/angular/commit/86981b3)), closes [#24923](https://github.com/angular/angular/issues/24923) [#25635](https://github.com/angular/angular/issues/25635)
|
||||
* **router:** removed obsolete TODO comment ([#29085](https://github.com/angular/angular/issues/29085)) ([2a25ac2](https://github.com/angular/angular/commit/2a25ac2))
|
||||
* **service-worker:** detect new version even if files are identical to an old one ([#26006](https://github.com/angular/angular/issues/26006)) ([5669333](https://github.com/angular/angular/commit/5669333)), closes [#24338](https://github.com/angular/angular/issues/24338)
|
||||
* **service-worker:** ignore passive mixed content requests ([#25994](https://github.com/angular/angular/issues/25994)) ([b598e88](https://github.com/angular/angular/commit/b598e88)), closes [23012#issuecomment-376430187](https://github.com/angular/angular/issues/23012#issuecomment-376430187) [#23012](https://github.com/angular/angular/issues/23012)
|
||||
* **service-worker:** ignore passive mixed content requests ([#25994](https://github.com/angular/angular/issues/25994)) ([b598e88](https://github.com/angular/angular/commit/b598e88)), closes [/github.com/angular/angular/issues/23012#issuecomment-376430187](https://github.com//github.com/angular/angular/issues/23012/issues/issuecomment-376430187) [#23012](https://github.com/angular/angular/issues/23012)
|
||||
|
||||
|
||||
<a name="7.2.7"></a>
|
||||
@ -2415,7 +2019,7 @@ This release contains various API docs improvements.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler-cli:** incorrect bundled metadata for static class member call expressions ([#28762](https://github.com/angular/angular/issues/28762)) ([ab69c31](https://github.com/angular/angular/commit/ab69c31)), closes [/github.com/angular/angular/blob/master/packages/core/src/change_detection/differs/keyvalue_differs.ts#L121](https://github.com/angular/angular/blob/master/packages/core/src/change_detection/differs/keyvalue_differs.ts/issues/L121) [#28741](https://github.com/angular/angular/issues/28741)
|
||||
* **compiler-cli:** incorrect bundled metadata for static class member call expressions ([#28762](https://github.com/angular/angular/issues/28762)) ([ab69c31](https://github.com/angular/angular/commit/ab69c31)), closes [/github.com/angular/angular/blob/master/packages/core/src/change_detection/differs/keyvalue_differs.ts#L121](https://github.com//github.com/angular/angular/blob/master/packages/core/src/change_detection/differs/keyvalue_differs.ts/issues/L121) [#28741](https://github.com/angular/angular/issues/28741)
|
||||
|
||||
|
||||
<a name="7.2.5"></a>
|
||||
@ -2558,7 +2162,7 @@ This release contains various API docs improvements.
|
||||
* **bazel:** emit full node stack traces when Angular compilation crashes ([#27678](https://github.com/angular/angular/issues/27678)) ([522919a](https://github.com/angular/angular/commit/522919a))
|
||||
* **bazel:** fix major/minor semver check between @angular/bazel npm packager version and angular bazel repo version ([#27635](https://github.com/angular/angular/issues/27635)) ([1cc08b4](https://github.com/angular/angular/commit/1cc08b4))
|
||||
* **bazel:** Load http_archive and rules_nodejs dependencies ([#27609](https://github.com/angular/angular/issues/27609)) ([8313ffc](https://github.com/angular/angular/commit/8313ffc))
|
||||
* **bazel:** ng_package writes unrelevant definitions to bazel out ([#27519](https://github.com/angular/angular/issues/27519)) ([44dfa60](https://github.com/angular/angular/commit/44dfa60)), closes [/github.com/angular/angular/blob/4f9374951d67c75f67a31c110bd61ab72563db7d/packages/bazel/src/ng_package/packager.ts#L105-L124](https://github.com/angular/angular/blob/4f9374951d67c75f67a31c110bd61ab72563db7d/packages/bazel/src/ng_package/packager.ts/issues/L105-L124)
|
||||
* **bazel:** ng_package writes unrelevant definitions to bazel out ([#27519](https://github.com/angular/angular/issues/27519)) ([44dfa60](https://github.com/angular/angular/commit/44dfa60)), closes [/github.com/angular/angular/blob/4f9374951d67c75f67a31c110bd61ab72563db7d/packages/bazel/src/ng_package/packager.ts#L105-L124](https://github.com//github.com/angular/angular/blob/4f9374951d67c75f67a31c110bd61ab72563db7d/packages/bazel/src/ng_package/packager.ts/issues/L105-L124)
|
||||
* **bazel:** Set module_name and enable ng test ([#27715](https://github.com/angular/angular/issues/27715)) ([85866de](https://github.com/angular/angular/commit/85866de))
|
||||
* **bazel:** fix TS errors in the `schematics/bazel-workspace` files ([#27600](https://github.com/angular/angular/issues/27600)) ([3290fc3](https://github.com/angular/angular/commit/3290fc3))
|
||||
* **bazel:** Read latest versions from latest-versions.ts & use semver check ([#27526](https://github.com/angular/angular/issues/27526)) ([30a3b49](https://github.com/angular/angular/commit/30a3b49))
|
||||
@ -2598,7 +2202,7 @@ This release contains various API docs improvements.
|
||||
* **bazel:** emit full node stack traces when Angular compilation crashes ([#27678](https://github.com/angular/angular/issues/27678)) ([0d8528b](https://github.com/angular/angular/commit/0d8528b))
|
||||
* **bazel:** fix major/minor semver check between @angular/bazel npm packager version and angular bazel repo version ([#27635](https://github.com/angular/angular/issues/27635)) ([3ed1e84](https://github.com/angular/angular/commit/3ed1e84))
|
||||
* **bazel:** Load http_archive and rules_nodejs dependencies ([#27609](https://github.com/angular/angular/issues/27609)) ([89ace1a](https://github.com/angular/angular/commit/89ace1a))
|
||||
* **bazel:** ng_package writes unrelevant definitions to bazel out ([#27519](https://github.com/angular/angular/issues/27519)) ([ef056c5](https://github.com/angular/angular/commit/ef056c5)), closes [/github.com/angular/angular/blob/4f9374951d67c75f67a31c110bd61ab72563db7d/packages/bazel/src/ng_package/packager.ts#L105-L124](https://github.com/angular/angular/blob/4f9374951d67c75f67a31c110bd61ab72563db7d/packages/bazel/src/ng_package/packager.ts/issues/L105-L124)
|
||||
* **bazel:** ng_package writes unrelevant definitions to bazel out ([#27519](https://github.com/angular/angular/issues/27519)) ([ef056c5](https://github.com/angular/angular/commit/ef056c5)), closes [/github.com/angular/angular/blob/4f9374951d67c75f67a31c110bd61ab72563db7d/packages/bazel/src/ng_package/packager.ts#L105-L124](https://github.com//github.com/angular/angular/blob/4f9374951d67c75f67a31c110bd61ab72563db7d/packages/bazel/src/ng_package/packager.ts/issues/L105-L124)
|
||||
* **bazel:** Read latest versions from latest-versions.ts & use semver check ([#27591](https://github.com/angular/angular/issues/27591)) ([93078e3](https://github.com/angular/angular/commit/93078e3))
|
||||
* **bazel:** Set module_name and enable ng test ([#27715](https://github.com/angular/angular/issues/27715)) ([183f278](https://github.com/angular/angular/commit/183f278))
|
||||
* **common:** KeyValuePipe should return empty array for empty objects ([#27258](https://github.com/angular/angular/issues/27258)) ([fa3af8b](https://github.com/angular/angular/commit/fa3af8b))
|
||||
@ -2627,7 +2231,7 @@ This release contains various API docs improvements.
|
||||
* **bazel:** ng_package not generating UMD bundles on windows ([#27200](https://github.com/angular/angular/issues/27200)) ([e476c38](https://github.com/angular/angular/commit/e476c38))
|
||||
* **bazel:** ng_package should correctly map to source maps in secondary entry-points ([#27313](https://github.com/angular/angular/issues/27313)) ([fc2c23e](https://github.com/angular/angular/commit/fc2c23e)), closes [#25510](https://github.com/angular/angular/issues/25510)
|
||||
* **compiler-cli:** flatModuleIndex files not generated on windows with multiple input files ([#27200](https://github.com/angular/angular/issues/27200)) ([8087b6b](https://github.com/angular/angular/commit/8087b6b))
|
||||
* **compiler-cli:** ngtsc shim files not being generated on case-insensitive platforms ([#27466](https://github.com/angular/angular/issues/27466)) ([84f2928](https://github.com/angular/angular/commit/84f2928)), closes [/github.com/Microsoft/TypeScript/blob/3e4c5c95abd515eb9713b881d27ab3a93cc00461/src/compiler/sys.ts#L681-L682](https://github.com/Microsoft/TypeScript/blob/3e4c5c95abd515eb9713b881d27ab3a93cc00461/src/compiler/sys.ts/issues/L681-L682)
|
||||
* **compiler-cli:** ngtsc shim files not being generated on case-insensitive platforms ([#27466](https://github.com/angular/angular/issues/27466)) ([84f2928](https://github.com/angular/angular/commit/84f2928)), closes [/github.com/Microsoft/TypeScript/blob/3e4c5c95abd515eb9713b881d27ab3a93cc00461/src/compiler/sys.ts#L681-L682](https://github.com//github.com/Microsoft/TypeScript/blob/3e4c5c95abd515eb9713b881d27ab3a93cc00461/src/compiler/sys.ts/issues/L681-L682)
|
||||
* **platform-server:** add @angular/http to the list of peerDependencies ([#27307](https://github.com/angular/angular/issues/27307)) ([236ac06](https://github.com/angular/angular/commit/236ac06)), closes [#26154](https://github.com/angular/angular/issues/26154)
|
||||
|
||||
|
||||
@ -2851,7 +2455,7 @@ To learn about the release highlights and our new CLI-powered update workflow fo
|
||||
* **compiler:** update compiler to flatten nested template fns ([#24943](https://github.com/angular/angular/issues/24943)) ([fe14f18](https://github.com/angular/angular/commit/fe14f18))
|
||||
* **compiler:** update compiler to generate new slot allocations ([#25607](https://github.com/angular/angular/issues/25607)) ([27e2039](https://github.com/angular/angular/commit/27e2039))
|
||||
* **core:** In Testability.whenStable update callback, pass more complete ([#25010](https://github.com/angular/angular/issues/25010)) ([16c03c0](https://github.com/angular/angular/commit/16c03c0))
|
||||
* **core:** add missing `peerDependency ` to `@angular/compiler` ([#26033](https://github.com/angular/angular/issues/26033)) ([549de1e](https://github.com/angular/angular/commit/549de1e)), closes [/github.com/angular/angular/commit/919f42fea1df4b9e38b7d688aef5f2de668e9d3e#diff-58563046c4439699f2e6a89187099a54](https://github.com/angular/angular/commit/919f42fea1df4b9e38b7d688aef5f2de668e9d3e/issues/diff-58563046c4439699f2e6a89187099a54)
|
||||
* **core:** add missing `peerDependency ` to `@angular/compiler` ([#26033](https://github.com/angular/angular/issues/26033)) ([549de1e](https://github.com/angular/angular/commit/549de1e)), closes [/github.com/angular/angular/commit/919f42fea1df4b9e38b7d688aef5f2de668e9d3e#diff-58563046c4439699f2e6a89187099a54](https://github.com//github.com/angular/angular/commit/919f42fea1df4b9e38b7d688aef5f2de668e9d3e/issues/diff-58563046c4439699f2e6a89187099a54)
|
||||
* **core:** allow null value for renderer setElement(…) ([#17065](https://github.com/angular/angular/issues/17065)) ([ff15043](https://github.com/angular/angular/commit/ff15043)), closes [#13686](https://github.com/angular/angular/issues/13686)
|
||||
* **core:** do not clear element content when using shadow dom ([#24861](https://github.com/angular/angular/issues/24861)) ([6e828bb](https://github.com/angular/angular/commit/6e828bb))
|
||||
* **core:** size regression with closure compiler ([#25531](https://github.com/angular/angular/issues/25531)) ([1f59f2f](https://github.com/angular/angular/commit/1f59f2f))
|
||||
|
279
CONTRIBUTING.md
279
CONTRIBUTING.md
@ -1,7 +1,7 @@
|
||||
# Contributing to Angular
|
||||
|
||||
We would love for you to contribute to Angular and help make it even better than it is today!
|
||||
As a contributor, here are the guidelines we would like you to follow:
|
||||
We would love for you to contribute to Angular and help make it even better than it is
|
||||
today! As a contributor, here are the guidelines we would like you to follow:
|
||||
|
||||
- [Code of Conduct](#coc)
|
||||
- [Question or Problem?](#question)
|
||||
@ -12,17 +12,12 @@ As a contributor, here are the guidelines we would like you to follow:
|
||||
- [Commit Message Guidelines](#commit)
|
||||
- [Signing the CLA](#cla)
|
||||
|
||||
|
||||
## <a name="coc"></a> Code of Conduct
|
||||
|
||||
Help us keep Angular open and inclusive.
|
||||
Please read and follow our [Code of Conduct][coc].
|
||||
|
||||
Help us keep Angular open and inclusive. Please read and follow our [Code of Conduct][coc].
|
||||
|
||||
## <a name="question"></a> Got a Question or Problem?
|
||||
|
||||
Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests.
|
||||
Instead, we recommend using [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) to ask support-related questions. When creating a new question on Stack Overflow, make sure to add the `angular` tag.
|
||||
Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests. You've got much better chances of getting your question answered on [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) where the questions should be tagged with tag `angular`.
|
||||
|
||||
Stack Overflow is a much better place to ask questions since:
|
||||
|
||||
@ -34,41 +29,33 @@ To save your and our time, we will systematically close all issues that are requ
|
||||
|
||||
If you would like to chat about the question in real-time, you can reach out via [our gitter channel][gitter].
|
||||
|
||||
|
||||
## <a name="issue"></a> Found a Bug?
|
||||
|
||||
If you find a bug in the source code, you can help us by [submitting an issue](#submit-issue) to our [GitHub Repository][github].
|
||||
Even better, you can [submit a Pull Request](#submit-pr) with a fix.
|
||||
|
||||
If you find a bug in the source code, you can help us by
|
||||
[submitting an issue](#submit-issue) to our [GitHub Repository][github]. Even better, you can
|
||||
[submit a Pull Request](#submit-pr) with a fix.
|
||||
|
||||
## <a name="feature"></a> Missing a Feature?
|
||||
You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub Repository.
|
||||
If you would like to *implement* a new feature, please consider the size of the change in order to determine the right steps to proceed:
|
||||
|
||||
* For a **Major Feature**, first open an issue and outline your proposal so that it can be discussed.
|
||||
This process allows us to better coordinate our efforts, prevent duplication of work, and help you to craft the change so that it is successfully accepted into the project.
|
||||
|
||||
**Note**: Adding a new topic to the documentation, or significantly re-writing a topic, counts as a major feature.
|
||||
You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub
|
||||
Repository. If you would like to *implement* a new feature, please submit an issue with
|
||||
a proposal for your work first, to be sure that we can use it.
|
||||
Please consider what kind of change it is:
|
||||
|
||||
* For a **Major Feature**, first open an issue and outline your proposal so that it can be
|
||||
discussed. This will also allow us to better coordinate our efforts, prevent duplication of work,
|
||||
and help you to craft the change so that it is successfully accepted into the project.
|
||||
* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
|
||||
|
||||
|
||||
## <a name="submit"></a> Submission Guidelines
|
||||
|
||||
|
||||
### <a name="submit-issue"></a> Submitting an Issue
|
||||
|
||||
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 require that you provide a minimal reproduction.
|
||||
Having a minimal reproducible scenario gives us a wealth of important information without going back and forth to you with additional questions.
|
||||
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. Having a minimal reproducible scenario gives us a wealth of important information without going back & forth to you with additional questions.
|
||||
|
||||
A minimal reproduction allows us to quickly confirm a bug (or point out a coding problem) as well as confirm that we are fixing the right problem.
|
||||
|
||||
We require a minimal reproduction to save maintainers' time and ultimately be able to fix more bugs.
|
||||
Often, developers find coding problems themselves while preparing a minimal reproduction.
|
||||
We understand that sometimes it might be hard to extract essential bits of code from a larger codebase but we really need to isolate the problem before we can fix it.
|
||||
We will be insisting on a minimal reproduction 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 reproduction. We understand that sometimes it might be hard to extract essential bits of code from a larger codebase 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 doesn't have enough info to be reproduced.
|
||||
|
||||
@ -76,51 +63,42 @@ You can file new issues by selecting from our [new issue templates](https://gith
|
||||
|
||||
|
||||
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
|
||||
|
||||
Before you submit your Pull Request (PR) consider the following guidelines:
|
||||
|
||||
1. Search [GitHub](https://github.com/angular/angular/pulls) for an open or closed PR that relates to your submission.
|
||||
You don't want to duplicate existing efforts.
|
||||
|
||||
2. Be sure that an issue describes the problem you're fixing, or documents the design for the feature you'd like to add.
|
||||
1. Search [GitHub](https://github.com/angular/angular/pulls) for an open or closed PR
|
||||
that relates to your submission. You don't want to duplicate effort.
|
||||
1. Be sure that an issue describes the problem you're fixing, or documents the design for the feature you'd like to add.
|
||||
Discussing the design up front helps to ensure that we're ready to accept your work.
|
||||
|
||||
3. Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
|
||||
We cannot accept code without a signed CLA.
|
||||
Make sure you author all contributed Git commits with email address associated with your CLA signature.
|
||||
|
||||
4. Fork the angular/angular repo.
|
||||
|
||||
5. Make your changes in a new git branch:
|
||||
1. Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
|
||||
We cannot accept code without this. Make sure you sign with the primary email address of the Git identity that has been granted access to the Angular repository.
|
||||
1. Fork the angular/angular repo.
|
||||
1. Make your changes in a new git branch:
|
||||
|
||||
```shell
|
||||
git checkout -b my-fix-branch master
|
||||
```
|
||||
|
||||
6. Create your patch, **including appropriate test cases**.
|
||||
|
||||
7. Follow our [Coding Rules](#rules).
|
||||
|
||||
8. Run the full Angular test suite, as described in the [developer documentation][dev-doc], and ensure that all tests pass.
|
||||
|
||||
9. Commit your changes using a descriptive commit message that follows our [commit message conventions](#commit).
|
||||
Adherence to these conventions is necessary because release notes are automatically generated from these messages.
|
||||
1. Create your patch, **including appropriate test cases**.
|
||||
1. Follow our [Coding Rules](#rules).
|
||||
1. Run the full Angular test suite, as described in the [developer documentation][dev-doc],
|
||||
and ensure that all tests pass.
|
||||
1. Commit your changes using a descriptive commit message that follows our
|
||||
[commit message conventions](#commit). Adherence to these conventions
|
||||
is necessary because release notes are automatically generated from these messages.
|
||||
|
||||
```shell
|
||||
git commit -a
|
||||
```
|
||||
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
|
||||
|
||||
10. Push your branch to GitHub:
|
||||
1. Push your branch to GitHub:
|
||||
|
||||
```shell
|
||||
git push origin my-fix-branch
|
||||
```
|
||||
|
||||
11. In GitHub, send a pull request to `angular:master`.
|
||||
|
||||
If we ask for changes via code reviews then:
|
||||
|
||||
1. In GitHub, send a pull request to `angular:master`.
|
||||
* If we suggest changes then:
|
||||
* Make the required updates.
|
||||
* Re-run the Angular test suites to ensure tests are still passing.
|
||||
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
|
||||
@ -132,10 +110,10 @@ Before you submit your Pull Request (PR) consider the following guidelines:
|
||||
|
||||
That's it! Thank you for your contribution!
|
||||
|
||||
|
||||
#### After your pull request is merged
|
||||
|
||||
After your pull request is merged, you can safely delete your branch and pull the changes from the main (upstream) repository:
|
||||
After your pull request is merged, you can safely delete your branch and pull the changes
|
||||
from the main (upstream) repository:
|
||||
|
||||
* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
|
||||
|
||||
@ -161,66 +139,55 @@ After your pull request is merged, you can safely delete your branch and pull th
|
||||
git pull --ff upstream master
|
||||
```
|
||||
|
||||
|
||||
## <a name="rules"></a> Coding Rules
|
||||
To ensure consistency throughout the source code, keep these rules in mind as you are working:
|
||||
|
||||
* All features or bug fixes **must be tested** by one or more specs (unit-tests).
|
||||
* All public API methods **must be documented**.
|
||||
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at **100 characters**.
|
||||
* All public API methods **must be documented**. (Details TBC).
|
||||
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at
|
||||
**100 characters**. An automated formatter is available, see
|
||||
[DEVELOPER.md](docs/DEVELOPER.md#clang-format).
|
||||
|
||||
An automated formatter is available, see [DEVELOPER.md](docs/DEVELOPER.md#clang-format).
|
||||
## <a name="commit"></a> Commit Message Guidelines
|
||||
|
||||
We have very precise rules over how our git commit messages can be formatted. This leads to **more
|
||||
readable messages** that are easy to follow when looking through the **project history**. But also,
|
||||
we use the git commit messages to **generate the Angular change log**.
|
||||
|
||||
## <a name="commit"></a> Commit Message Format
|
||||
|
||||
*This specification is inspired and supersedes the [AngularJS commit message format][commit-message-format].*
|
||||
|
||||
We have very precise rules over how our Git commit messages must be formatted.
|
||||
This format leads to **easier to read commit history**.
|
||||
|
||||
Each commit message consists of a **header**, a **body**, and a **footer**.
|
||||
|
||||
### Commit Message Format
|
||||
Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
|
||||
format that includes a **type**, a **scope** and a **subject**:
|
||||
|
||||
```
|
||||
<header>
|
||||
<type>(<scope>): <subject>
|
||||
<BLANK LINE>
|
||||
<body>
|
||||
<BLANK LINE>
|
||||
<footer>
|
||||
```
|
||||
|
||||
The `header` is mandatory and must conform to the [Commit Message Header](#commit-header) format.
|
||||
The **header** is mandatory and the **scope** of the header is optional.
|
||||
|
||||
The `body` is mandatory for all commits except for those of scope "docs".
|
||||
When the body is required it must be at least 20 characters long.
|
||||
Any line of the commit message cannot be longer than 100 characters! This allows the message to be easier
|
||||
to read on GitHub as well as in various git tools.
|
||||
|
||||
The `footer` is optional.
|
||||
The footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.
|
||||
|
||||
Any line of the commit message cannot be longer than 100 characters.
|
||||
|
||||
|
||||
#### <a href="commit-header"></a>Commit Message Header
|
||||
Samples: (even more [samples](https://github.com/angular/angular/commits/master))
|
||||
|
||||
```
|
||||
<type>(<scope>): <short summary>
|
||||
│ │ │
|
||||
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
|
||||
│ │
|
||||
│ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
|
||||
│ elements|forms|http|language-service|localize|platform-browser|
|
||||
│ platform-browser-dynamic|platform-server|platform-webworker|
|
||||
│ platform-webworker-dynamic|router|service-worker|upgrade|zone.js|
|
||||
│ packaging|changelog|dev-infra|docs-infra|migrations|ngcc|ve
|
||||
│
|
||||
└─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
|
||||
docs(changelog): update changelog to beta.5
|
||||
```
|
||||
```
|
||||
fix(release): need to depend on latest rxjs and zone.js
|
||||
|
||||
The version in our package.json gets copied to the one we publish, and users need the latest of these.
|
||||
```
|
||||
|
||||
The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is optional.
|
||||
|
||||
|
||||
##### Type
|
||||
### Revert
|
||||
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.
|
||||
|
||||
### Type
|
||||
Must be one of the following:
|
||||
|
||||
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
|
||||
@ -233,95 +200,66 @@ Must be one of the following:
|
||||
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
|
||||
* **test**: Adding missing tests or correcting existing tests
|
||||
|
||||
|
||||
##### Scope
|
||||
### Scope
|
||||
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:
|
||||
|
||||
* `animations`
|
||||
* `bazel`
|
||||
* `benchpress`
|
||||
* `common`
|
||||
* `compiler`
|
||||
* `compiler-cli`
|
||||
* `core`
|
||||
* `elements`
|
||||
* `forms`
|
||||
* `http`
|
||||
* `language-service`
|
||||
* `localize`
|
||||
* `platform-browser`
|
||||
* `platform-browser-dynamic`
|
||||
* `platform-server`
|
||||
* `platform-webworker`
|
||||
* `platform-webworker-dynamic`
|
||||
* `router`
|
||||
* `service-worker`
|
||||
* `upgrade`
|
||||
* `zone.js`
|
||||
* **animations**
|
||||
* **bazel**
|
||||
* **benchpress**
|
||||
* **common**
|
||||
* **compiler**
|
||||
* **compiler-cli**
|
||||
* **core**
|
||||
* **elements**
|
||||
* **forms**
|
||||
* **http**
|
||||
* **language-service**
|
||||
* **localize**
|
||||
* **platform-browser**
|
||||
* **platform-browser-dynamic**
|
||||
* **platform-server**
|
||||
* **platform-webworker**
|
||||
* **platform-webworker-dynamic**
|
||||
* **router**
|
||||
* **service-worker**
|
||||
* **upgrade**
|
||||
* **zone.js**
|
||||
|
||||
There are currently a few exceptions to the "use package name" rule:
|
||||
|
||||
* `packaging`: used for changes that change the npm package layout in all of our packages, e.g. public path changes, package.json changes done to all packages, d.ts file/format changes, changes to bundles, etc.
|
||||
* **packaging**: used for changes that change the npm package layout in all of our packages, e.g.
|
||||
public path changes, package.json changes done to all packages, d.ts file/format changes, changes
|
||||
to bundles, etc.
|
||||
* **changelog**: used for updating the release notes in CHANGELOG.md
|
||||
* **docs-infra**: used for docs-app (angular.io) related changes within the /aio directory of the
|
||||
repo
|
||||
* **dev-infra**: used for dev-infra related changes within the directories /scripts, /tools and /dev-infra
|
||||
* **ngcc**: used for changes to the [Angular Compatibility Compiler](./packages/compiler-cli/ngcc/README.md)
|
||||
* **ve**: used for changes specific to ViewEngine (legacy compiler/renderer).
|
||||
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all
|
||||
packages (e.g. `style: add missing semicolons`) and for docs changes that are not related to a
|
||||
specific package (e.g. `docs: fix typo in tutorial`).
|
||||
|
||||
* `changelog`: used for updating the release notes in CHANGELOG.md
|
||||
|
||||
* `dev-infra`: used for dev-infra related changes within the directories /scripts, /tools and /dev-infra
|
||||
|
||||
* `docs-infra`: used for docs-app (angular.io) related changes within the /aio directory of the repo
|
||||
|
||||
* `migrations`: used for changes to the `ng update` migrations.
|
||||
|
||||
* `ngcc`: used for changes to the [Angular Compatibility Compiler](./packages/compiler-cli/ngcc/README.md)
|
||||
|
||||
* `ve`: used for changes specific to ViewEngine (legacy compiler/renderer).
|
||||
|
||||
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all packages (e.g. `style: add missing semicolons`) and for docs changes that are not related to a specific package (e.g. `docs: fix typo in tutorial`).
|
||||
|
||||
|
||||
##### Summary
|
||||
|
||||
Use the summary field to provide a succinct description of the change:
|
||||
### Subject
|
||||
The subject contains a succinct description of the change:
|
||||
|
||||
* use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
* don't capitalize the first letter
|
||||
* no dot (.) at the end
|
||||
|
||||
### Body
|
||||
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
|
||||
The body should include the motivation for the change and contrast this with previous behavior.
|
||||
|
||||
#### Commit Message Body
|
||||
### Footer
|
||||
The footer should contain any information about **Breaking Changes** and is also the place to
|
||||
reference GitHub issues that this commit **Closes**.
|
||||
|
||||
Just as in the summary, use the imperative, present tense: "fix" not "fixed" nor "fixes".
|
||||
|
||||
Explain the motivation for the change in the commit message body. This commit message should explain _why_ you are making the change.
|
||||
You can include a comparison of the previous behavior with the new behavior in order to illustrate the impact of the change.
|
||||
|
||||
|
||||
#### Commit Message Footer
|
||||
|
||||
The footer can contain information about breaking changes and is also the place to reference GitHub issues, Jira tickets, and other PRs that this commit closes or is related to.
|
||||
|
||||
```
|
||||
BREAKING CHANGE: <breaking change summary>
|
||||
<BLANK LINE>
|
||||
<breaking change description + migration instructions>
|
||||
<BLANK LINE>
|
||||
<BLANK LINE>
|
||||
Fixes #<issue number>
|
||||
```
|
||||
|
||||
Breaking Change section should start with the phrase "BREAKING CHANGE: " followed by a summary of the breaking change, a blank line, and a detailed description of the breaking change that also includes migration instructions.
|
||||
|
||||
|
||||
### Revert commits
|
||||
|
||||
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit.
|
||||
|
||||
The content of the commit message body should contain:
|
||||
|
||||
- information about the SHA of the commit being reverted in the following format: `This reverts commit <SHA>`,
|
||||
- a clear description of the reason for reverting the commit message.
|
||||
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.
|
||||
|
||||
A detailed explanation can be found in this [document][commit-message-format].
|
||||
|
||||
## <a name="cla"></a> Signing the CLA
|
||||
|
||||
@ -332,17 +270,18 @@ changes to be accepted, the CLA must be signed. It's a quick process, we promise
|
||||
* For corporations, we'll need you to
|
||||
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
|
||||
|
||||
If you have more than one GitHub accounts, or multiple email addresses associated with a single GitHub account, you must sign the CLA using the primary email address of the GitHub account used to author Git commits and send pull requests.
|
||||
<hr>
|
||||
|
||||
The following documents can help you sort out issues with GitHub accounts and multiple email addresses:
|
||||
If you have more than one Git identity, you must make sure that you sign the CLA using the primary email address associated with the ID that has been granted access to the Angular repository. Git identities can be associated with more than one email address, and only one is primary. Here are some links to help you sort out multiple Git identities and email addresses:
|
||||
|
||||
* 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://help.github.com/articles/about-commit-email-addresses/
|
||||
* 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.
|
||||
|
||||
|
||||
<hr>
|
||||
|
||||
[angular-group]: https://groups.google.com/forum/#!forum/angular
|
||||
[coc]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md
|
||||
|
15
WORKSPACE
15
WORKSPACE
@ -8,8 +8,8 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
# Fetch rules_nodejs so we can install our npm dependencies
|
||||
http_archive(
|
||||
name = "build_bazel_rules_nodejs",
|
||||
sha256 = "84abf7ac4234a70924628baa9a73a5a5cbad944c4358cf9abdb4aab29c9a5b77",
|
||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/1.7.0/rules_nodejs-1.7.0.tar.gz"],
|
||||
sha256 = "f9e7b9f42ae202cc2d2ce6d698ccb49a9f7f7ea572a78fd451696d03ef2ee116",
|
||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/1.6.0/rules_nodejs-1.6.0.tar.gz"],
|
||||
)
|
||||
|
||||
# Check the rules_nodejs version and download npm dependencies
|
||||
@ -17,7 +17,7 @@ http_archive(
|
||||
# assert on that.
|
||||
load("@build_bazel_rules_nodejs//:index.bzl", "check_rules_nodejs_version", "node_repositories", "yarn_install")
|
||||
|
||||
check_rules_nodejs_version(minimum_version_string = "1.7.0")
|
||||
check_rules_nodejs_version(minimum_version_string = "1.6.0")
|
||||
|
||||
# Setup the Node.js toolchain
|
||||
node_repositories(
|
||||
@ -64,7 +64,7 @@ load("@io_bazel_rules_webtesting//web:repositories.bzl", "web_test_repositories"
|
||||
|
||||
web_test_repositories()
|
||||
|
||||
load("//dev-infra/browsers:browser_repositories.bzl", "browser_repositories")
|
||||
load("//tools/browsers:browser_repositories.bzl", "browser_repositories")
|
||||
|
||||
browser_repositories()
|
||||
|
||||
@ -91,18 +91,17 @@ rbe_autoconfig(
|
||||
# Need to specify a base container digest in order to ensure that we can use the checked-in
|
||||
# platform configurations for the "ubuntu16_04" image. Otherwise the autoconfig rule would
|
||||
# need to pull the image and run it in order determine the toolchain configuration. See:
|
||||
# https://github.com/bazelbuild/bazel-toolchains/blob/3.2.0/configs/ubuntu16_04_clang/versions.bzl
|
||||
base_container_digest = "sha256:5e750dd878df9fcf4e185c6f52b9826090f6e532b097f286913a428290622332",
|
||||
# https://github.com/bazelbuild/bazel-toolchains/blob/1.1.2/configs/ubuntu16_04_clang/versions.bzl
|
||||
base_container_digest = "sha256:1ab40405810effefa0b2f45824d6d608634ccddbf06366760c341ef6fbead011",
|
||||
# Note that if you change the `digest`, you might also need to update the
|
||||
# `base_container_digest` to make sure marketplace.gcr.io/google/rbe-ubuntu16-04-webtest:<digest>
|
||||
# and marketplace.gcr.io/google/rbe-ubuntu16-04:<base_container_digest> have
|
||||
# the same Clang and JDK installed. Clang is needed because of the dependency on
|
||||
# @com_google_protobuf. Java is needed for the Bazel's test executor Java tool.
|
||||
digest = "sha256:f743114235a43355bf8324e2ba0fa6a597236fe06f7bc99aaa9ac703631c306b",
|
||||
digest = "sha256:0b8fa87db4b8e5366717a7164342a029d1348d2feea7ecc4b18c780bc2507059",
|
||||
env = clang_env(),
|
||||
registry = "marketplace.gcr.io",
|
||||
# We can't use the default "ubuntu16_04" RBE image provided by the autoconfig because we need
|
||||
# a specific Linux kernel that comes with "libx11" in order to run headless browser tests.
|
||||
repository = "google/rbe-ubuntu16-04-webtest",
|
||||
use_checked_in_confs = "Force",
|
||||
)
|
||||
|
@ -58,7 +58,7 @@
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"src/styles/main.scss"
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": [],
|
||||
"budgets": [
|
||||
@ -158,7 +158,7 @@
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"src/styles/main.scss"
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": []
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
# CLI Overview and Command Reference
|
||||
|
||||
The Angular CLI is a command-line interface tool that you use to initialize, develop, scaffold, and maintain Angular applications directly from a command shell.
|
||||
The Angular CLI is a command-line interface tool that you use to initialize, develop, scaffold, and maintain Angular applications. You can use the tool directly in a command shell, or indirectly through an interactive UI such as [Angular Console](https://angularconsole.com).
|
||||
|
||||
## Installing Angular CLI
|
||||
|
||||
@ -109,3 +109,9 @@ Options that specify files can be given as absolute paths, or as paths relative
|
||||
The [ng generate](cli/generate) and [ng add](cli/add) commands take as an argument the artifact or library to be generated or added to the current project.
|
||||
In addition to any general options, each artifact or library defines its own options in a *schematic*.
|
||||
Schematic options are supplied to the command in the same format as immediate command options.
|
||||
|
||||
|
||||
### Building with Bazel
|
||||
|
||||
Optionally, you can configure the Angular CLI to use [Bazel](https://docs.bazel.build) as the build tool. For more information, see [Building with Bazel](guide/bazel).
|
||||
|
||||
|
1
aio/content/examples/.gitignore
vendored
1
aio/content/examples/.gitignore
vendored
@ -18,7 +18,6 @@
|
||||
**/src/karma.conf.js
|
||||
**/.angular-cli.json
|
||||
**/.editorconfig
|
||||
**/.gitignore
|
||||
**/angular.json
|
||||
**/tsconfig.json
|
||||
**/bs-config.e2e.json
|
||||
|
@ -200,4 +200,13 @@
|
||||
(ngModelChange)="model.name = $event">
|
||||
TODO: remove this: {{model.name}}
|
||||
<!-- #enddocregion ngModel-3-->
|
||||
<hr>
|
||||
<!-- #docregion ngModelName-2 -->
|
||||
<input type="text" class="form-control" id="name"
|
||||
required
|
||||
[(ngModel)]="model.name" name="name"
|
||||
#spy>
|
||||
<br>TODO: remove this: {{spy.className}}
|
||||
<!-- #enddocregion ngModelName-2 -->
|
||||
|
||||
</div>
|
||||
|
@ -76,15 +76,15 @@ export class ConfigService {
|
||||
console.error('An error occurred:', error.error.message);
|
||||
} else {
|
||||
// The backend returned an unsuccessful response code.
|
||||
// The response body may contain clues as to what went wrong.
|
||||
// The response body may contain clues as to what went wrong,
|
||||
console.error(
|
||||
`Backend returned code ${error.status}, ` +
|
||||
`body was: ${error.error}`);
|
||||
}
|
||||
// Return an observable with a user-facing error message.
|
||||
// return an observable with a user-facing error message
|
||||
return throwError(
|
||||
'Something bad happened; please try again later.');
|
||||
}
|
||||
};
|
||||
// #enddocregion handleError
|
||||
|
||||
makeIntentionalError() {
|
||||
|
@ -13,13 +13,13 @@ import { searchUrl } from '../package-search/package-search.service';
|
||||
|
||||
|
||||
/**
|
||||
* If request is cacheable (e.g., package search) and
|
||||
* If request is cachable (e.g., package search) and
|
||||
* response is in cache return the cached response as observable.
|
||||
* If has 'x-refresh' header that is true,
|
||||
* then also re-run the package search, using response from next(),
|
||||
* returning an observable that emits the cached response first.
|
||||
*
|
||||
* If not in cache or not cacheable,
|
||||
* If not in cache or not cachable,
|
||||
* pass request through to next()
|
||||
*/
|
||||
// #docregion v1
|
||||
@ -28,8 +28,8 @@ export class CachingInterceptor implements HttpInterceptor {
|
||||
constructor(private cache: RequestCache) {}
|
||||
|
||||
intercept(req: HttpRequest<any>, next: HttpHandler) {
|
||||
// continue if not cacheable.
|
||||
if (!isCacheable(req)) { return next.handle(req); }
|
||||
// continue if not cachable.
|
||||
if (!isCachable(req)) { return next.handle(req); }
|
||||
|
||||
const cachedResponse = this.cache.get(req);
|
||||
// #enddocregion v1
|
||||
@ -51,11 +51,11 @@ export class CachingInterceptor implements HttpInterceptor {
|
||||
// #enddocregion v1
|
||||
|
||||
|
||||
/** Is this request cacheable? */
|
||||
function isCacheable(req: HttpRequest<any>) {
|
||||
// Only GET requests are cacheable
|
||||
/** Is this request cachable? */
|
||||
function isCachable(req: HttpRequest<any>) {
|
||||
// Only GET requests are cachable
|
||||
return req.method === 'GET' &&
|
||||
// Only npm package search is cacheable in this app
|
||||
// Only npm package search is cachable in this app
|
||||
-1 < req.url.indexOf(searchUrl);
|
||||
}
|
||||
|
||||
|
@ -1,12 +0,0 @@
|
||||
{
|
||||
"description": "i18n",
|
||||
"files":[
|
||||
"!**/*.d.ts",
|
||||
"!**/*.js",
|
||||
"!**/*.[0-9].*",
|
||||
"!doc-files/**/*",
|
||||
"**/*.xlf"
|
||||
],
|
||||
"file": "src/app/app.component.ts",
|
||||
"tags": ["Angular", "i18n", "internationalization"]
|
||||
}
|
9
aio/content/examples/i18n/zipper.json
Normal file
9
aio/content/examples/i18n/zipper.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"files": [
|
||||
"!dist/",
|
||||
"!**/*.d.ts",
|
||||
"!src/**/*.js",
|
||||
"!doc-files/**/*",
|
||||
"**/*.xlf"
|
||||
]
|
||||
}
|
@ -3,7 +3,6 @@ import {
|
||||
AfterContentInit,
|
||||
AfterViewChecked,
|
||||
AfterViewInit,
|
||||
Directive,
|
||||
DoCheck,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
@ -16,8 +15,7 @@ import { LoggerService } from './logger.service';
|
||||
let nextId = 1;
|
||||
|
||||
// #docregion ngOnInit
|
||||
@Directive()
|
||||
export class PeekABooDirective implements OnInit {
|
||||
export class PeekABoo implements OnInit {
|
||||
constructor(private logger: LoggerService) { }
|
||||
|
||||
// implement OnInit's `ngOnInit` method
|
||||
@ -36,7 +34,7 @@ export class PeekABooDirective implements OnInit {
|
||||
})
|
||||
// Don't HAVE to mention the Lifecycle Hook interfaces
|
||||
// unless we want typing and tool support.
|
||||
export class PeekABooComponent extends PeekABooDirective implements
|
||||
export class PeekABooComponent extends PeekABoo implements
|
||||
OnChanges, OnInit, DoCheck,
|
||||
AfterContentInit, AfterContentChecked,
|
||||
AfterViewInit, AfterViewChecked,
|
||||
|
@ -23,7 +23,7 @@ export class GreetingModule {
|
||||
// #enddocregion ctor
|
||||
|
||||
// #docregion for-root
|
||||
static forRoot(config: UserServiceConfig): ModuleWithProviders<GreetingModule> {
|
||||
static forRoot(config: UserServiceConfig): ModuleWithProviders {
|
||||
return {
|
||||
ngModule: GreetingModule,
|
||||
providers: [
|
||||
|
@ -6,5 +6,5 @@ import { Component } from '@angular/core';
|
||||
templateUrl: './app.component.html'
|
||||
})
|
||||
export class AppComponent {
|
||||
birthday = new Date(1988, 3, 15); // April 15, 1988 -- since month parameter is zero-based
|
||||
birthday = new Date(1988, 3, 15); // April 15, 1988
|
||||
}
|
||||
|
@ -8,5 +8,5 @@ import { Component } from '@angular/core';
|
||||
// #enddocregion hero-birthday-template
|
||||
})
|
||||
export class HeroBirthdayComponent {
|
||||
birthday = new Date(1988, 3, 15); // April 15, 1988 -- since month parameter is zero-based
|
||||
birthday = new Date(1988, 3, 15); // April 15, 1988
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import { Component } from '@angular/core';
|
||||
})
|
||||
// #docregion class
|
||||
export class HeroBirthday2Component {
|
||||
birthday = new Date(1988, 3, 15); // April 15, 1988 -- since month parameter is zero-based
|
||||
birthday = new Date(1988, 3, 15); // April 15, 1988
|
||||
toggle = true; // start with true == shortDate
|
||||
|
||||
get format() { return this.toggle ? 'shortDate' : 'fullDate'; }
|
||||
|
@ -1,7 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'any',
|
||||
})
|
||||
export class UserService {
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
import { browser, element, by } from 'protractor';
|
||||
|
||||
describe('Router basic tutorial e2e tests', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
browser.get('');
|
||||
});
|
||||
|
||||
it('should display Angular Router Sample', () => {
|
||||
expect(element(by.css('h1')).getText()).toBe('Angular Router Sample');
|
||||
});
|
||||
|
||||
it('should display Crisis Center button', () => {
|
||||
expect(element.all(by.css('a')).get(0).getText()).toBe('Crisis Center');
|
||||
});
|
||||
|
||||
it('should display Heroes button', () => {
|
||||
expect(element.all(by.css('a')).get(1).getText()).toBe('Heroes');
|
||||
});
|
||||
|
||||
it('should display HEROES', () => {
|
||||
expect(element(by.css('h3')).getText()).toBe('HEROES');
|
||||
});
|
||||
|
||||
it('should change to display crisis list component', async () => {
|
||||
const crisisButton = element.all(by.css('a')).get(0);
|
||||
await crisisButton.click();
|
||||
expect(element(by.css('h3')).getText()).toBe('CRISIS CENTER');
|
||||
});
|
||||
|
||||
it('should change to display heroes component', async () => {
|
||||
const heroesButton = element.all(by.css('a')).get(1);
|
||||
await heroesButton.click();
|
||||
expect(element(by.css('h3')).getText()).toBe('HEROES');
|
||||
});
|
||||
|
||||
it('should use wildcard route', async () => {
|
||||
browser.get('/fake-page');
|
||||
expect(browser.getCurrentUrl()).toContain('fake-page');
|
||||
expect(element(by.css('h2')).getText()).toBe('Page Not Found');
|
||||
});
|
||||
});
|
@ -1,34 +0,0 @@
|
||||
.button {
|
||||
box-shadow: inset 0px 1px 0px 0px #ffffff;
|
||||
background: linear-gradient(to bottom, #ffffff 5%, #f6f6f6 100%);
|
||||
background-color: #ffffff;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #dcdcdc;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
color: #666666;
|
||||
font-family: Arial;
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
padding: 6px 24px;
|
||||
text-decoration: none;
|
||||
text-shadow: 0px 1px 0px #ffffff;
|
||||
outline: 0;
|
||||
}
|
||||
.activebutton {
|
||||
box-shadow: inset 0px 1px 0px 0px #dcecfb;
|
||||
background: linear-gradient(to bottom, #bddbfa 5%, #80b5ea 100%);
|
||||
background-color: #bddbfa;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #84bbf3;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
color: #ffffff;
|
||||
font-family: Arial;
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
padding: 6px 24px;
|
||||
text-decoration: none;
|
||||
text-shadow: 0px 1px 0px #528ecc;
|
||||
outline: 0;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
<!-- #docplaster -->
|
||||
<!-- #docregion setup -->
|
||||
<h1>Angular Router Sample</h1>
|
||||
<!-- #enddocregion setup-->
|
||||
<!-- #docregion routeractivelink -->
|
||||
<nav>
|
||||
<a class="button" routerLink="/crisis-list" routerLinkActive="activebutton">Crisis Center</a> |
|
||||
<a class="button" routerLink="/heroes-list" routerLinkActive="activebutton">Heroes</a>
|
||||
</nav>
|
||||
<!-- #enddocregion routeractivelink-->
|
||||
<!-- #docregion router-outlet -->
|
||||
<router-outlet></router-outlet>
|
||||
<!-- #enddocregion router-outlet -->
|
||||
|
||||
<div style="display: none;">
|
||||
<!-- This HTML represents the initial state for the tutorial. It is not intended to appear in the app. -->
|
||||
<!-- #docregion setup, components -->
|
||||
<app-crisis-list></app-crisis-list>
|
||||
<app-heroes-list></app-heroes-list>
|
||||
<!-- #enddocregion setup, components -->
|
||||
|
||||
<!-- This HTML snippet is for when the user first adds the routerlink navigation. -->
|
||||
<!-- #docregion nav -->
|
||||
<nav>
|
||||
<a class="button" routerLink="/crisis-list">Crisis Center</a> |
|
||||
<a class="button" routerLink="/heroes-list">Heroes</a>
|
||||
</nav>
|
||||
<!-- #enddocregion nav-->
|
||||
|
||||
|
||||
</div>
|
@ -1,10 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'angular-router-sample';
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
// #docplaster
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
// #docregion router-import
|
||||
import { RouterModule } from '@angular/router';
|
||||
// #enddocregion router-import
|
||||
import { AppComponent } from './app.component';
|
||||
import { CrisisListComponent } from './crisis-list/crisis-list.component';
|
||||
import { HeroesListComponent } from './heroes-list/heroes-list.component';
|
||||
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
CrisisListComponent,
|
||||
HeroesListComponent,
|
||||
PageNotFoundComponent
|
||||
],
|
||||
// #docplaster
|
||||
// #docregion import-basic, import-redirect, import-wildcard
|
||||
imports: [
|
||||
BrowserModule,
|
||||
RouterModule.forRoot([
|
||||
{path: 'crisis-list', component: CrisisListComponent},
|
||||
{path: 'heroes-list', component: HeroesListComponent},
|
||||
// #enddocregion import-basic
|
||||
{path: '', redirectTo: '/heroes-list', pathMatch: 'full'},
|
||||
// #enddocregion import-redirect
|
||||
{path: '**', component: PageNotFoundComponent}
|
||||
// #enddocregion import-wildcard
|
||||
// #docregion import-basic, import-redirect, import-wildcard
|
||||
]),
|
||||
],
|
||||
// #enddocregion import-basic, import-redirect, import-wildcard
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
@ -1,2 +0,0 @@
|
||||
<h3>CRISIS CENTER</h3>
|
||||
<p>Get your crisis here</p>
|
@ -1,10 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-crisis-list',
|
||||
templateUrl: './crisis-list.component.html',
|
||||
styleUrls: ['./crisis-list.component.css']
|
||||
})
|
||||
export class CrisisListComponent {
|
||||
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
<h3>HEROES</h3>
|
||||
<p>Get your heroes here</p>
|
@ -1,10 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-heroes-list',
|
||||
templateUrl: './heroes-list.component.html',
|
||||
styleUrls: ['./heroes-list.component.css']
|
||||
})
|
||||
export class HeroesListComponent {
|
||||
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
<h2>Page Not Found</h2>
|
||||
<p>We couldn't find that page! Not even with x-ray vision.</p>
|
@ -1,10 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-page-not-found',
|
||||
templateUrl: './page-not-found.component.html',
|
||||
styleUrls: ['./page-not-found.component.css']
|
||||
})
|
||||
export class PageNotFoundComponent {
|
||||
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Angular Router Sample</title>
|
||||
<base href="/">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</html>
|
@ -1,12 +0,0 @@
|
||||
import { enableProdMode } from '@angular/core';
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
import { AppModule } from './app/app.module';
|
||||
import { environment } from './environments/environment';
|
||||
|
||||
if (environment.production) {
|
||||
enableProdMode();
|
||||
}
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule)
|
||||
.catch(err => console.error(err));
|
@ -1,9 +0,0 @@
|
||||
{
|
||||
"description": "Router",
|
||||
"files":[
|
||||
"!**/*.d.ts",
|
||||
"!**/*.js",
|
||||
"!**/*.[0-9].*"
|
||||
],
|
||||
"tags": ["router-tutorial"]
|
||||
}
|
@ -6,11 +6,13 @@ import { Routes, RouterModule } from '@angular/router'; // CLI imports router
|
||||
const routes: Routes = [
|
||||
{ path: 'first-component', component: FirstComponent },
|
||||
{ path: 'second-component', component: SecondComponent },
|
||||
// #enddocregion routes, routes-with-wildcard
|
||||
// #enddocregion routes
|
||||
{ path: '', redirectTo: '/first-component', pathMatch: 'full' }, // redirect to `first-component`
|
||||
// #docregion routes-with-wildcard
|
||||
{ path: '**', component: FirstComponent },
|
||||
// #enddocregion redirect
|
||||
{ path: '**', component: PageNotFoundComponent }, // Wildcard route for a 404 page
|
||||
// #docregion routes
|
||||
// #docregion redirect
|
||||
];
|
||||
// #enddocregion routes, routes-with-wildcard, redirect
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// #docregion
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, UrlTree } from '@angular/router';
|
||||
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
|
||||
|
||||
import { AuthService } from './auth.service';
|
||||
|
||||
@ -12,20 +12,21 @@ export class AuthGuard implements CanActivate {
|
||||
|
||||
canActivate(
|
||||
next: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot): true|UrlTree {
|
||||
state: RouterStateSnapshot): boolean {
|
||||
let url: string = state.url;
|
||||
|
||||
return this.checkLogin(url);
|
||||
}
|
||||
|
||||
checkLogin(url: string): true|UrlTree {
|
||||
checkLogin(url: string): boolean {
|
||||
if (this.authService.isLoggedIn) { return true; }
|
||||
|
||||
// Store the attempted URL for redirecting
|
||||
this.authService.redirectUrl = url;
|
||||
|
||||
// Redirect to the login page
|
||||
return this.router.parseUrl('/login');
|
||||
// Navigate to the login page with extras
|
||||
this.router.navigate(['/login']);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// #enddocregion
|
||||
|
@ -4,8 +4,7 @@ import {
|
||||
CanActivate, Router,
|
||||
ActivatedRouteSnapshot,
|
||||
RouterStateSnapshot,
|
||||
CanActivateChild,
|
||||
UrlTree
|
||||
CanActivateChild
|
||||
} from '@angular/router';
|
||||
import { AuthService } from './auth.service';
|
||||
|
||||
@ -17,7 +16,7 @@ export class AuthGuard implements CanActivate, CanActivateChild {
|
||||
|
||||
canActivate(
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot): true|UrlTree {
|
||||
state: RouterStateSnapshot): boolean {
|
||||
let url: string = state.url;
|
||||
|
||||
return this.checkLogin(url);
|
||||
@ -25,19 +24,20 @@ export class AuthGuard implements CanActivate, CanActivateChild {
|
||||
|
||||
canActivateChild(
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot): true|UrlTree {
|
||||
state: RouterStateSnapshot): boolean {
|
||||
return this.canActivate(route, state);
|
||||
}
|
||||
|
||||
// #enddocregion can-activate-child
|
||||
checkLogin(url: string): true|UrlTree {
|
||||
checkLogin(url: string): boolean {
|
||||
if (this.authService.isLoggedIn) { return true; }
|
||||
|
||||
// Store the attempted URL for redirecting
|
||||
this.authService.redirectUrl = url;
|
||||
|
||||
// Redirect to the login page
|
||||
return this.router.parseUrl('/login');
|
||||
// Navigate to the login page
|
||||
this.router.navigate(['/login']);
|
||||
return false;
|
||||
}
|
||||
// #docregion can-activate-child
|
||||
}
|
||||
|
@ -6,8 +6,7 @@ import {
|
||||
ActivatedRouteSnapshot,
|
||||
RouterStateSnapshot,
|
||||
CanActivateChild,
|
||||
NavigationExtras,
|
||||
UrlTree
|
||||
NavigationExtras
|
||||
} from '@angular/router';
|
||||
import { AuthService } from './auth.service';
|
||||
|
||||
@ -17,17 +16,17 @@ import { AuthService } from './auth.service';
|
||||
export class AuthGuard implements CanActivate, CanActivateChild {
|
||||
constructor(private authService: AuthService, private router: Router) {}
|
||||
|
||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): true|UrlTree {
|
||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
|
||||
let url: string = state.url;
|
||||
|
||||
return this.checkLogin(url);
|
||||
}
|
||||
|
||||
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): true|UrlTree {
|
||||
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
|
||||
return this.canActivate(route, state);
|
||||
}
|
||||
|
||||
checkLogin(url: string): true|UrlTree {
|
||||
checkLogin(url: string): boolean {
|
||||
if (this.authService.isLoggedIn) { return true; }
|
||||
|
||||
// Store the attempted URL for redirecting
|
||||
@ -43,7 +42,8 @@ export class AuthGuard implements CanActivate, CanActivateChild {
|
||||
fragment: 'anchor'
|
||||
};
|
||||
|
||||
// Redirect to the login page with extras
|
||||
return this.router.createUrlTree(['/login'], navigationExtras);
|
||||
// Navigate to the login page with extras
|
||||
this.router.navigate(['/login'], navigationExtras);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -16,12 +16,5 @@
|
||||
"@angular/core": "^7.2.0"
|
||||
},
|
||||
// #docregion collection
|
||||
"schematics": "./schematics/collection.json",
|
||||
// #enddocregion collection
|
||||
// #docregion ng-add
|
||||
"ng-add": {
|
||||
"save": "devDependencies"
|
||||
}
|
||||
// #enddocregion ng-add
|
||||
// #docregion collection
|
||||
"schematics": "./schematics/collection.json"
|
||||
}
|
@ -33,7 +33,7 @@ export class HeroesComponent implements OnInit {
|
||||
|
||||
onSelect(hero: Hero): void {
|
||||
this.selectedHero = hero;
|
||||
this.messageService.add(`HeroesComponent: Selected hero id=${hero.id}`);
|
||||
this.messageService.add(`HeroService: Selected hero id=${hero.id}`);
|
||||
}
|
||||
|
||||
// #docregion getHeroes
|
||||
|
@ -1,7 +1,7 @@
|
||||
// #docregion
|
||||
import nodeResolve from 'rollup-plugin-node-resolve'
|
||||
import commonjs from 'rollup-plugin-commonjs';
|
||||
import {terser} from 'rollup-plugin-terser'
|
||||
import uglify from 'rollup-plugin-uglify'
|
||||
|
||||
//paths are relative to the execution path
|
||||
export default {
|
||||
@ -17,6 +17,6 @@ export default {
|
||||
commonjs({
|
||||
include: ['node_modules/rxjs/**']
|
||||
}),
|
||||
terser()
|
||||
uglify()
|
||||
]
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ work well for all users, including those who rely on assistive technologies.
|
||||
|
||||
Building accessible web experience often involves setting [ARIA attributes](https://developers.google.com/web/fundamentals/accessibility/semantics-aria)
|
||||
to provide semantic meaning where it might otherwise be missing.
|
||||
Use [attribute binding](guide/attribute-binding) template syntax to control the values of accessibility-related attributes.
|
||||
Use [attribute binding](guide/template-syntax#attribute-binding) template syntax to control the values of accessibility-related attributes.
|
||||
|
||||
When binding to ARIA attributes in Angular, you must use the `attr.` prefix, as the ARIA
|
||||
specification depends specifically on HTML attributes rather than properties of DOM elements.
|
||||
@ -44,7 +44,7 @@ NOTE:
|
||||
|
||||
By convention, HTML attributes use lowercase names (`tabindex`), while properties use camelCase names (`tabIndex`).
|
||||
|
||||
See the [Binding syntax](guide/binding-syntax#html-attribute-vs-dom-property) guide for more background on the difference between attributes and properties.
|
||||
See the [Template Syntax](guide/template-syntax#html-attribute-vs-dom-property) guide for more background on the difference between attributes and properties.
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -74,7 +74,8 @@ The following table lists some of the key AngularJS template features with their
|
||||
The context of the binding is implied and is always the
|
||||
associated component, so it needs no reference variable.
|
||||
|
||||
For more information, see the [Interpolation](guide/interpolation) guide.
|
||||
For more information, see the [Interpolation](guide/template-syntax#interpolation)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
@ -140,8 +141,8 @@ The following table lists some of the key AngularJS template features with their
|
||||
|
||||
Angular has true template input variables that are explicitly defined using the `let` keyword.
|
||||
|
||||
For more information, see the [ngFor micro-syntax](guide/built-in-directives#microsyntax)
|
||||
section of the [Built-in Directives](guide/built-in-directives) page.
|
||||
For more information, see the [ngFor micro-syntax](guide/template-syntax#microsyntax)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
@ -257,7 +258,8 @@ The following are some of the key AngularJS built-in directives and their equiva
|
||||
Angular also has **class binding**, which is a good way to add or remove a single class,
|
||||
as shown in the third example.
|
||||
|
||||
For more information see [Attribute, class, and style bindings](guide/attribute-binding) page.
|
||||
For more information see the [Attribute, class, and style bindings](guide/template-syntax#other-bindings)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
|
||||
</td>
|
||||
|
||||
@ -307,7 +309,8 @@ The following are some of the key AngularJS built-in directives and their equiva
|
||||
|
||||
For a list of DOM events, see: https://developer.mozilla.org/en-US/docs/Web/Events.
|
||||
|
||||
For more information, see the [Event binding](guide/event-binding) page.
|
||||
For more information, see the [Event binding](guide/template-syntax#event-binding)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
|
||||
</td>
|
||||
|
||||
@ -404,7 +407,8 @@ The following are some of the key AngularJS built-in directives and their equiva
|
||||
Angular uses property binding; there is no built-in *href* directive.
|
||||
Place the element's `href` property in square brackets and set it to a quoted template expression.
|
||||
|
||||
For more information see the [Property binding](guide/property-binding) page.
|
||||
For more information see the [Property binding](guide/template-syntax#property-binding)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
|
||||
In Angular, `href` is no longer used for routing. Routing uses `routerLink`, as shown in the following example.
|
||||
|
||||
@ -483,8 +487,8 @@ The following are some of the key AngularJS built-in directives and their equiva
|
||||
and event binding (from the view to the component), thereby providing two-way binding.
|
||||
|
||||
For more information on two-way binding with `ngModel`, see the [NgModel—Two-way binding to
|
||||
form elements with `[(ngModel)]`](../guide/built-in-directives#ngModel)
|
||||
section of the [Built-in directives](guide/built-in-directives) page.
|
||||
form elements with `[(ngModel)]`](../guide/template-syntax.html#ngModel)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
@ -566,7 +570,8 @@ The following are some of the key AngularJS built-in directives and their equiva
|
||||
|
||||
In this example, the `<div>` element is hidden if the `favoriteHero` variable is not truthy.
|
||||
|
||||
For more information on property binding, see the [Property binding](guide/property-binding) page.
|
||||
For more information on property binding, see the [Property binding](guide/template-syntax#property-binding)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
@ -599,7 +604,8 @@ The following are some of the key AngularJS built-in directives and their equiva
|
||||
Angular uses property binding; there is no built-in *src* directive.
|
||||
Place the `src` property in square brackets and set it to a quoted template expression.
|
||||
|
||||
For more information on property binding, see the [Property binding](guide/property-binding) page.
|
||||
For more information on property binding, see the [Property binding](guide/template-syntax#property-binding)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
@ -638,11 +644,11 @@ The following are some of the key AngularJS built-in directives and their equiva
|
||||
|
||||
Angular also has **style binding**, which is good way to set a single style. This is shown in the second example.
|
||||
|
||||
For more information on style binding, see the [Style binding](guide/attribute-binding#style-binding) section of the
|
||||
[Attribute binding](guide/attribute-binding) page.
|
||||
For more information on style binding, see the [Style binding](guide/template-syntax#style-binding) section of the
|
||||
[Template Syntax](guide/template-syntax) page.
|
||||
|
||||
For more information on the `ngStyle` directive, see the [NgStyle](guide/built-in-directives#ngStyle)
|
||||
section of the [Built-in directives](guide/built-in-directives) page.
|
||||
For more information on the `ngStyle` directive, see [NgStyle](guide/template-syntax#ngStyle)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
@ -698,8 +704,8 @@ The following are some of the key AngularJS built-in directives and their equiva
|
||||
|
||||
The (*) before `ngSwitchCase` and `ngSwitchDefault` is required in this example.
|
||||
|
||||
For more information, see [The NgSwitch directives](guide/built-in-directives#ngSwitch)
|
||||
section of the [Built-in directives](guide/built-in-directives) page.
|
||||
For more information, see [The NgSwitch directives](guide/template-syntax#ngSwitch)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Angular compiler options
|
||||
|
||||
When you use [AOT compilation](guide/aot-compiler), you can control how your application is compiled by specifying *template* compiler options in the [TypeScript configuration file](guide/typescript-configuration).
|
||||
When you use [AOT compilation](guide/aot-compiler), you can control how your application is compiled by specifying *template* compiler options in the `tsconfig.json` [TypeScript configuration file](guide/typescript-configuration).
|
||||
|
||||
The template options object, `angularCompilerOptions`, is a sibling to the `compilerOptions` object that supplies standard options to the TypeScript compiler.
|
||||
|
||||
@ -21,11 +21,11 @@ The template options object, `angularCompilerOptions`, is a sibling to the `comp
|
||||
{@a tsconfig-extends}
|
||||
## Configuration inheritance with extends
|
||||
|
||||
Like the TypeScript compiler, The Angular AOT compiler also supports `extends` in the `angularCompilerOptions` section of the TypeScript configuration file.
|
||||
Like the TypeScript compiler, The Angular AOT compiler also supports `extends` in the `angularCompilerOptions` section of the TypeScript configuration file, `tsconfig.json`.
|
||||
The `extends` property is at the top level, parallel to `compilerOptions` and `angularCompilerOptions`.
|
||||
|
||||
A TypeScript configuration can inherit settings from another file using the `extends` property.
|
||||
The configuration options from the base file are loaded first, then overridden by those in the inheriting configuration file.
|
||||
The configuration options from the base file are loaded first, then overridden by those in the inheriting `tsconfig` file.
|
||||
|
||||
For example:
|
||||
|
||||
@ -186,7 +186,7 @@ For library projects generated with the CLI, the dev configuration default is `t
|
||||
|
||||
When `true` (recommended), reports an error for a supplied parameter whose injection type cannot be determined. When `false` (currently the default), constructor parameters of classes marked with `@Injectable` whose type cannot be resolved produce a warning.
|
||||
|
||||
When you use the CLI command `ng new --strict`, it is set to `true` in the generated project's configuration.
|
||||
When you use the CLI command `ng new`, it is set to `true` by default in the generated project's configuration.
|
||||
|
||||
### `strictTemplates`
|
||||
|
||||
@ -194,7 +194,6 @@ When `true`, enables [strict template type checking](guide/template-typecheck#st
|
||||
|
||||
Additional strictness flags allow you to enable and disable specific types of strict template type checking. See [troubleshooting template errors](guide/template-typecheck#troubleshooting-template-errors).
|
||||
|
||||
When you use the CLI command `ng new --strict`, it is set to `true` in the generated project's configuration.
|
||||
|
||||
### `trace`
|
||||
|
||||
|
@ -105,7 +105,7 @@ For help in understanding and resolving these problems, see [AOT Metadata Errors
|
||||
|
||||
### Configuring AOT compilation
|
||||
|
||||
You can provide options in the [TypeScript configuration file](guide/typescript-configuration) that controls the compilation process. See [Angular compiler options](guide/angular-compiler-options) for a complete list of available options.
|
||||
You can provide options in the `tsconfig.json` [TypeScript configuration file](guide/typescript-configuration) that control the compilation process. See [Angular compiler options](guide/angular-compiler-options) for a complete list of available options.
|
||||
|
||||
## Phase 1: Code analysis
|
||||
|
||||
@ -211,7 +211,7 @@ The compiler later reports the error if it needs that piece of metadata to gener
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
If you want `ngc` to report syntax errors immediately rather than produce a `.metadata.json` file with errors, set the `strictMetadataEmit` option in the TypeScript configuration file.
|
||||
If you want `ngc` to report syntax errors immediately rather than produce a `.metadata.json` file with errors, set the `strictMetadataEmit` option in the TypeScript configuration file, `tsconfig.json`.
|
||||
|
||||
```
|
||||
"angularCompilerOptions": {
|
||||
@ -548,7 +548,7 @@ It does not, however, rewrite the `.d.ts` file, so TypeScript doesn't recognize
|
||||
One of the Angular compiler's most helpful features is the ability to type-check expressions within templates, and catch any errors before they cause crashes at runtime.
|
||||
In the template type-checking phase, the Angular template compiler uses the TypeScript compiler to validate the binding expressions in templates.
|
||||
|
||||
Enable this phase explicitly by adding the compiler option `"fullTemplateTypeCheck"` in the `"angularCompilerOptions"` of the project's TypeScript configuration file
|
||||
Enable this phase explicitly by adding the compiler option `"fullTemplateTypeCheck"` in the `"angularCompilerOptions"` of the project's `tsconfig.json`
|
||||
(see [Angular Compiler Options](guide/angular-compiler-options)).
|
||||
|
||||
<div class="alert is-helpful">
|
||||
@ -623,7 +623,7 @@ For more information about input type narrowing, see [Input setter coercion](gui
|
||||
|
||||
### Non-null type assertion operator
|
||||
|
||||
Use the [non-null type assertion operator](guide/template-expression-operators#non-null-assertion-operator) to suppress the `Object is possibly 'undefined'` error when it is inconvenient to use `*ngIf` or when some constraint in the component ensures that the expression is always non-null when the binding expression is interpolated.
|
||||
Use the [non-null type assertion operator](guide/template-syntax#non-null-assertion-operator) to suppress the `Object is possibly 'undefined'` error when it is inconvenient to use `*ngIf` or when some constraint in the component ensures that the expression is always non-null when the binding expression is interpolated.
|
||||
|
||||
In the following example, the `person` and `address` properties are always set together, implying that `address` is always non-null if `person` is non-null.
|
||||
There is no convenient way to describe this constraint to TypeScript and the template compiler, but the error is suppressed in the example by using `address!.street`.
|
||||
|
@ -430,7 +430,7 @@ Angular does something similar with the `DOCUMENT` token so you can inject the b
|
||||
|
||||
```ts
|
||||
import { Inject } from '@angular/core';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { DOCUMENT } from '@angular/platform-browser';
|
||||
|
||||
@Component({ ... })
|
||||
export class MyComponent {
|
||||
|
@ -92,7 +92,7 @@ This example from the `HeroListComponent` template uses three of these forms.
|
||||
* The `{{hero.name}}` [*interpolation*](guide/displaying-data#interpolation)
|
||||
displays the component's `hero.name` property value within the `<li>` element.
|
||||
|
||||
* The `[hero]` [*property binding*](guide/property-binding) passes the value of
|
||||
* The `[hero]` [*property binding*](guide/template-syntax#property-binding) passes the value of
|
||||
`selectedHero` from the parent `HeroListComponent` to the `hero` property of the child `HeroDetailComponent`.
|
||||
|
||||
* The `(click)` [*event binding*](guide/user-input#binding-to-user-input-events) calls the component's `selectHero` method when the user clicks a hero's name.
|
||||
@ -126,7 +126,7 @@ Angular pipes let you declare display-value transformations in your template HTM
|
||||
|
||||
Angular defines various pipes, such as the [date](https://angular.io/api/common/DatePipe) pipe and [currency](https://angular.io/api/common/CurrencyPipe) pipe; for a complete list, see the [Pipes API list](https://angular.io/api?type=pipe). You can also define new pipes.
|
||||
|
||||
To specify a value transformation in an HTML template, use the [pipe operator (|)](https://angular.io/guide/template-expression-operators#pipe).
|
||||
To specify a value transformation in an HTML template, use the [pipe operator (|)](https://angular.io/guide/template-syntax#pipe).
|
||||
|
||||
`{{interpolated_value | pipe_name}}`
|
||||
|
||||
@ -179,9 +179,9 @@ The `ngModel` directive, which implements two-way data binding, is an example of
|
||||
<code-example path="architecture/src/app/hero-detail.component.html" header="src/app/hero-detail.component.html (ngModel)" region="ngModel"></code-example>
|
||||
|
||||
Angular has more pre-defined directives that either alter the layout structure
|
||||
(for example, [ngSwitch](guide/built-in-directives#ngSwitch))
|
||||
(for example, [ngSwitch](guide/template-syntax#ngSwitch))
|
||||
or modify aspects of DOM elements and components
|
||||
(for example, [ngStyle](guide/built-in-directives#ngStyle) and [ngClass](guide/built-in-directives#ngClass)).
|
||||
(for example, [ngStyle](guide/template-syntax#ngStyle) and [ngClass](guide/template-syntax#ngClass)).
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
@ -11,7 +11,7 @@ The basic building blocks are *NgModules*, which provide a compilation context f
|
||||
|
||||
* Components use *services*, which provide specific functionality not directly related to views. Service providers can be *injected* into components as *dependencies*, making your code modular, reusable, and efficient.
|
||||
|
||||
Modules, components and services are classes that use *decorators*. These decorators mark their type and provide metadata that tells Angular how to use them.
|
||||
Both components and services are simply classes, with *decorators* that mark their type and provide metadata that tells Angular how to use them.
|
||||
|
||||
* The metadata for a component class associates it with a *template* that defines a view. A template combines ordinary HTML with Angular *directives* and *binding markup* that allow Angular to modify the HTML before rendering it for display.
|
||||
|
||||
|
@ -1,303 +0,0 @@
|
||||
# Attribute, class, and style bindings
|
||||
|
||||
The template syntax provides specialized one-way bindings for scenarios less well-suited to property binding.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
## Attribute binding
|
||||
|
||||
Set the value of an attribute directly with an **attribute binding**. This is the only exception to the rule that a binding sets a target property and the only binding that creates and sets an attribute.
|
||||
|
||||
Usually, setting an element property with a [property binding](guide/property-binding)
|
||||
is preferable to setting the attribute with a string. However, sometimes
|
||||
there is no element property to bind, so attribute binding is the solution.
|
||||
|
||||
Consider the [ARIA](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) and
|
||||
[SVG](https://developer.mozilla.org/en-US/docs/Web/SVG). They are purely attributes, don't correspond to element properties, and don't set element properties. In these cases, there are no property targets to bind to.
|
||||
|
||||
Attribute binding syntax resembles property binding, but
|
||||
instead of an element property between brackets, start with the prefix `attr`,
|
||||
followed by a dot (`.`), and the name of the attribute.
|
||||
You then set the attribute value, using an expression that resolves to a string,
|
||||
or remove the attribute when the expression resolves to `null`.
|
||||
|
||||
One of the primary use cases for attribute binding
|
||||
is to set ARIA attributes, as in this example:
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="attrib-binding-aria" header="src/app/app.component.html"></code-example>
|
||||
|
||||
{@a colspan}
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
#### `colspan` and `colSpan`
|
||||
|
||||
Notice the difference between the `colspan` attribute and the `colSpan` property.
|
||||
|
||||
If you wrote something like this:
|
||||
|
||||
<code-example language="html">
|
||||
<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
|
||||
</code-example>
|
||||
|
||||
You'd get this error:
|
||||
|
||||
<code-example language="bash">
|
||||
Template parse errors:
|
||||
Can't bind to 'colspan' since it isn't a known native property
|
||||
</code-example>
|
||||
|
||||
As the message says, the `<td>` element does not have a `colspan` property. This is true
|
||||
because `colspan` is an attribute—`colSpan`, with a capital `S`, is the
|
||||
corresponding property. Interpolation and property binding can set only *properties*, not attributes.
|
||||
|
||||
Instead, you'd use property binding and write it like this:
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="colSpan" header="src/app/app.component.html"></code-example>
|
||||
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a class-binding}
|
||||
|
||||
## Class binding
|
||||
|
||||
Here's how to set the `class` attribute without a binding in plain HTML:
|
||||
|
||||
```html
|
||||
<!-- standard class attribute setting -->
|
||||
<div class="foo bar">Some text</div>
|
||||
```
|
||||
|
||||
You can also add and remove CSS class names from an element's `class` attribute with a **class binding**.
|
||||
|
||||
To create a single class binding, start with the prefix `class` followed by a dot (`.`) and the name of the CSS class (for example, `[class.foo]="hasFoo"`).
|
||||
Angular adds the class when the bound expression is truthy, and it removes the class when the expression is falsy (with the exception of `undefined`, see [styling delegation](#styling-delegation)).
|
||||
|
||||
To create a binding to multiple classes, use a generic `[class]` binding without the dot (for example, `[class]="classExpr"`).
|
||||
The expression can be a space-delimited string of class names, or you can format it as an object with class names as the keys and truthy/falsy expressions as the values.
|
||||
With object format, Angular will add a class only if its associated value is truthy.
|
||||
|
||||
It's important to note that with any object-like expression (`object`, `Array`, `Map`, `Set`, etc), the identity of the object must change for the class list to be updated.
|
||||
Updating the property without changing object identity will have no effect.
|
||||
|
||||
If there are multiple bindings to the same class name, conflicts are resolved using [styling precedence](#styling-precedence).
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
</style>
|
||||
|
||||
<table width="100%">
|
||||
<col width="15%">
|
||||
</col>
|
||||
<col width="20%">
|
||||
</col>
|
||||
<col width="35%">
|
||||
</col>
|
||||
<col width="30%">
|
||||
</col>
|
||||
<tr>
|
||||
<th>
|
||||
Binding Type
|
||||
</th>
|
||||
<th>
|
||||
Syntax
|
||||
</th>
|
||||
<th>
|
||||
Input Type
|
||||
</th>
|
||||
<th>
|
||||
Example Input Values
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Single class binding</td>
|
||||
<td><code>[class.foo]="hasFoo"</code></td>
|
||||
<td><code>boolean | undefined | null</code></td>
|
||||
<td><code>true</code>, <code>false</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=3>Multi-class binding</td>
|
||||
<td rowspan=3><code>[class]="classExpr"</code></td>
|
||||
<td><code>string</code></td>
|
||||
<td><code>"my-class-1 my-class-2 my-class-3"</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>{[key: string]: boolean | undefined | null}</code></td>
|
||||
<td><code>{foo: true, bar: false}</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Array</code><<code>string</code>></td>
|
||||
<td><code>['foo', 'bar']</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
The [NgClass](guide/built-in-directives/#ngclass) directive can be used as an alternative to direct `[class]` bindings.
|
||||
However, using the above class binding syntax without `NgClass` is preferred because due to improvements in class binding in Angular, `NgClass` no longer provides significant value, and might eventually be removed in the future.
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
## Style binding
|
||||
|
||||
Here's how to set the `style` attribute without a binding in plain HTML:
|
||||
|
||||
```html
|
||||
<!-- standard style attribute setting -->
|
||||
<div style="color: blue">Some text</div>
|
||||
```
|
||||
|
||||
You can also set styles dynamically with a **style binding**.
|
||||
|
||||
To create a single style binding, start with the prefix `style` followed by a dot (`.`) and the name of the CSS style property (for example, `[style.width]="width"`).
|
||||
The property will be set to the value of the bound expression, which is normally a string.
|
||||
Optionally, you can add a unit extension like `em` or `%`, which requires a number type.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Note that a _style property_ name can be written in either
|
||||
[dash-case](guide/glossary#dash-case), as shown above, or
|
||||
[camelCase](guide/glossary#camelcase), such as `fontSize`.
|
||||
|
||||
</div>
|
||||
|
||||
If there are multiple styles you'd like to toggle, you can bind to the `[style]` property directly without the dot (for example, `[style]="styleExpr"`).
|
||||
The expression attached to the `[style]` binding is most often a string list of styles like `"width: 100px; height: 100px;"`.
|
||||
|
||||
You can also format the expression as an object with style names as the keys and style values as the values, like `{width: '100px', height: '100px'}`.
|
||||
It's important to note that with any object-like expression (`object`, `Array`, `Map`, `Set`, etc), the identity of the object must change for the class list to be updated.
|
||||
Updating the property without changing object identity will have no effect.
|
||||
|
||||
If there are multiple bindings to the same style property, conflicts are resolved using [styling precedence rules](#styling-precedence).
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
</style>
|
||||
|
||||
<table width="100%">
|
||||
<col width="15%">
|
||||
</col>
|
||||
<col width="20%">
|
||||
</col>
|
||||
<col width="35%">
|
||||
</col>
|
||||
<col width="30%">
|
||||
</col>
|
||||
<tr>
|
||||
<th>
|
||||
Binding Type
|
||||
</th>
|
||||
<th>
|
||||
Syntax
|
||||
</th>
|
||||
<th>
|
||||
Input Type
|
||||
</th>
|
||||
<th>
|
||||
Example Input Values
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Single style binding</td>
|
||||
<td><code>[style.width]="width"</code></td>
|
||||
<td><code>string | undefined | null</code></td>
|
||||
<td><code>"100px"</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr>
|
||||
<td>Single style binding with units</td>
|
||||
<td><code>[style.width.px]="width"</code></td>
|
||||
<td><code>number | undefined | null</code></td>
|
||||
<td><code>100</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=3>Multi-style binding</td>
|
||||
<td rowspan=3><code>[style]="styleExpr"</code></td>
|
||||
<td><code>string</code></td>
|
||||
<td><code>"width: 100px; height: 100px"</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>{[key: string]: string | undefined | null}</code></td>
|
||||
<td><code>{width: '100px', height: '100px'}</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Array</code><<code>string</code>></td>
|
||||
<td><code>['width', '100px']</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
The [NgStyle](guide/built-in-directives/#ngstyle) directive can be used as an alternative to direct `[style]` bindings.
|
||||
However, using the above style binding syntax without `NgStyle` is preferred because due to improvements in style binding in Angular, `NgStyle` no longer provides significant value, and might eventually be removed in the future.
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a styling-precedence}
|
||||
|
||||
## Styling Precedence
|
||||
|
||||
A single HTML element can have its CSS class list and style values bound to multiple sources (for example, host bindings from multiple directives).
|
||||
|
||||
When there are multiple bindings to the same class name or style property, Angular uses a set of precedence rules to resolve conflicts and determine which classes or styles are ultimately applied to the element.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
<h4>Styling precedence (highest to lowest)</h4>
|
||||
|
||||
1. Template bindings
|
||||
1. Property binding (for example, `<div [class.foo]="hasFoo">` or `<div [style.color]="color">`)
|
||||
1. Map binding (for example, `<div [class]="classExpr">` or `<div [style]="styleExpr">`)
|
||||
1. Static value (for example, `<div class="foo">` or `<div style="color: blue">`)
|
||||
1. Directive host bindings
|
||||
1. Property binding (for example, `host: {'[class.foo]': 'hasFoo'}` or `host: {'[style.color]': 'color'}`)
|
||||
1. Map binding (for example, `host: {'[class]': 'classExpr'}` or `host: {'[style]': 'styleExpr'}`)
|
||||
1. Static value (for example, `host: {'class': 'foo'}` or `host: {'style': 'color: blue'}`)
|
||||
1. Component host bindings
|
||||
1. Property binding (for example, `host: {'[class.foo]': 'hasFoo'}` or `host: {'[style.color]': 'color'}`)
|
||||
1. Map binding (for example, `host: {'[class]': 'classExpr'}` or `host: {'[style]': 'styleExpr'}`)
|
||||
1. Static value (for example, `host: {'class': 'foo'}` or `host: {'style': 'color: blue'}`)
|
||||
|
||||
</div>
|
||||
|
||||
The more specific a class or style binding is, the higher its precedence.
|
||||
|
||||
A binding to a specific class (for example, `[class.foo]`) will take precedence over a generic `[class]` binding, and a binding to a specific style (for example, `[style.bar]`) will take precedence over a generic `[style]` binding.
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="basic-specificity" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Specificity rules also apply when it comes to bindings that originate from different sources.
|
||||
It's possible for an element to have bindings in the template where it's declared, from host bindings on matched directives, and from host bindings on matched components.
|
||||
|
||||
Template bindings are the most specific because they apply to the element directly and exclusively, so they have the highest precedence.
|
||||
|
||||
Directive host bindings are considered less specific because directives can be used in multiple locations, so they have a lower precedence than template bindings.
|
||||
|
||||
Directives often augment component behavior, so host bindings from components have the lowest precedence.
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="source-specificity" header="src/app/app.component.html"></code-example>
|
||||
|
||||
In addition, bindings take precedence over static attributes.
|
||||
|
||||
In the following case, `class` and `[class]` have similar specificity, but the `[class]` binding will take precedence because it is dynamic.
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="dynamic-priority" header="src/app/app.component.html"></code-example>
|
||||
|
||||
{@a styling-delegation}
|
||||
### Delegating to styles with lower precedence
|
||||
|
||||
It is possible for higher precedence styles to "delegate" to lower precedence styles using `undefined` values.
|
||||
Whereas setting a style property to `null` ensures the style is removed, setting it to `undefined` will cause Angular to fall back to the next-highest precedence binding to that style.
|
||||
|
||||
For example, consider the following template:
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="style-delegation" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Imagine that the `dirWithHostBinding` directive and the `comp-with-host-binding` component both have a `[style.width]` host binding.
|
||||
In that case, if `dirWithHostBinding` sets its binding to `undefined`, the `width` property will fall back to the value of the `comp-with-host-binding` host binding.
|
||||
However, if `dirWithHostBinding` sets its binding to `null`, the `width` property will be removed entirely.
|
@ -18,12 +18,12 @@ There are three kinds of directives in Angular:
|
||||
You saw a component for the first time in the [Getting Started](start "Getting Started with Angular") tutorial.
|
||||
|
||||
*Structural Directives* change the structure of the view.
|
||||
Two examples are [NgFor](guide/built-in-directives#ngFor) and [NgIf](guide/built-in-directives#ngIf).
|
||||
Two examples are [NgFor](guide/template-syntax#ngFor) and [NgIf](guide/template-syntax#ngIf).
|
||||
Learn about them in the [Structural Directives](guide/structural-directives) guide.
|
||||
|
||||
*Attribute directives* are used as attributes of elements.
|
||||
The built-in [NgStyle](guide/built-in-directives#ngStyle) directive in the
|
||||
[Built-in directives](guide/built-in-directives) guide, for example,
|
||||
The built-in [NgStyle](guide/template-syntax#ngStyle) directive in the
|
||||
[Template Syntax](guide/template-syntax) guide, for example,
|
||||
can change several element styles at the same time.
|
||||
|
||||
## Build a simple attribute directive
|
||||
|
122
aio/content/guide/bazel.md
Normal file
122
aio/content/guide/bazel.md
Normal file
@ -0,0 +1,122 @@
|
||||
# Building with Bazel
|
||||
|
||||
This guide explains how to build and test Angular apps with Bazel.
|
||||
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
This guide assumes you are already familiar with developing and building Angular applications using the [CLI](cli).
|
||||
|
||||
It describes features which are part of Angular Labs, and are not considered a stable, supported API.
|
||||
|
||||
</div>
|
||||
|
||||
## Using Bazel with the Angular CLI
|
||||
|
||||
The `@angular/bazel` package provides a builder that allows Angular CLI to use Bazel as the build tool.
|
||||
|
||||
To opt-in an existing application, run
|
||||
|
||||
```sh
|
||||
ng add @angular/bazel
|
||||
```
|
||||
|
||||
To use Bazel in a new application, first install `@angular/bazel` globally
|
||||
|
||||
```sh
|
||||
npm install -g @angular/bazel
|
||||
```
|
||||
|
||||
then create the new application with
|
||||
|
||||
```sh
|
||||
ng new --collection=@angular/bazel
|
||||
```
|
||||
|
||||
Now when you use Angular CLI build commands such as `ng build` and `ng serve`,
|
||||
Bazel is used behind the scenes.
|
||||
Outputs from Bazel appear in the `dist/bin` folder.
|
||||
|
||||
> The command-line output includes extra logging from Bazel.
|
||||
> We plan to reduce this in the future.
|
||||
|
||||
### Removing Bazel
|
||||
|
||||
If you need to opt-out from using Bazel, you can restore the backup files:
|
||||
|
||||
- `/angular.json.bak` replaces `/angular.json`
|
||||
|
||||
## Advanced configuration
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Editing the Bazel configuration may prevent you opting out of Bazel.
|
||||
Custom behaviors driven by Bazel won't be available in other Builders.
|
||||
|
||||
This section assumes you are familiar with [Bazel](https://docs.bazel.build).
|
||||
|
||||
</div>
|
||||
|
||||
You can manually adjust the Bazel configuration to:
|
||||
|
||||
* customize the build steps
|
||||
* parallellize the build for scale and incrementality
|
||||
|
||||
Create the initial Bazel configuration files by running the following command:
|
||||
|
||||
```sh
|
||||
ng build --leaveBazelFilesOnDisk
|
||||
```
|
||||
|
||||
Now you'll find new files in the Angular workspace:
|
||||
|
||||
* `/WORKSPACE` tells Bazel how to download external dependencies.
|
||||
* `/BUILD.bazel` and `/src/BUILD.bazel` tell Bazel about your source code.
|
||||
|
||||
You can find a full-featured example with custom Bazel configurations at https://github.com/bazelbuild/rules_nodejs/tree/master/examples/angular.
|
||||
|
||||
Documentation for using Bazel for frontend projects is linked from https://docs.bazel.build/versions/master/bazel-and-javascript.html.
|
||||
|
||||
|
||||
|
||||
## Running Bazel directly
|
||||
|
||||
In some cases you'll want to bypass the Angular CLI builder, and run the Bazel CLI directly.
|
||||
The Bazel tool is managed by the `@bazel/bazelisk` package (similar to how Node.js can be managed by `nvm`).
|
||||
You can install it globally to get the `bazelisk` command in your path, or use `$(npm bin)/bazelisk` in place of bazelisk below.
|
||||
|
||||
The common commands in Bazel are:
|
||||
|
||||
* `bazelisk build [targets]`: Compile the default output artifacts of the given targets.
|
||||
* `bazelisk test [targets]`: For whichever `*_test` targets are found in the patterns, run the tests.
|
||||
* `bazelisk run [target]`: Compile the program represented by target, and then run it.
|
||||
|
||||
To repeat the command any time the inputs change (watch mode), replace `bazelisk` with `ibazel` in these commands.
|
||||
|
||||
The output locations are printed in the output.
|
||||
|
||||
Full documentation for the Bazel CLI is at https://docs.bazel.build/versions/master/command-line-reference.html.
|
||||
|
||||
|
||||
## Querying the build graph
|
||||
|
||||
Because Bazel constructs a graph out of your targets, you can find lots of useful information.
|
||||
|
||||
Using the graphviz optional dependency, you'll have a program `dot`, which you can use with `bazel query`:
|
||||
|
||||
```bash
|
||||
$ bazel query --output=graph ... | dot -Tpng > graph.png
|
||||
```
|
||||
|
||||
See https://docs.bazel.build/versions/master/query-how-to.html for more details on `bazel query`.
|
||||
|
||||
|
||||
## Customizing `BUILD.bazel` files
|
||||
|
||||
"Rules" are like plugins for Bazel. Many rule sets are available. This guide documents the ones maintained by the Angular team at Google.
|
||||
|
||||
Rules are used in `BUILD.bazel` files, which are markers for the packages in your workspace. Each `BUILD.bazel` file declares a separate package to Bazel, though you can have more coarse-grained distributions so that the packages you publish (for example, to `npm`) can be made up of many Bazel packages.
|
||||
|
||||
In the `BUILD.bazel` file, each rule must first be imported, using the `load` statement. Then the rule is called with some attributes, and the result of calling the rule is that you've declared to Bazel how it can derive some outputs given some inputs and dependencies. Then later, when you run a `bazel` command line, Bazel loads all the rules you've declared to determine an absolute ordering of what needs to be run. Note that only the rules needed to produce the requested output will actually be executed.
|
||||
|
||||
A list of common rules for frontend development is documented in the README at https://github.com/bazelbuild/rules_nodejs/.
|
@ -1,318 +0,0 @@
|
||||
|
||||
# Binding syntax: an overview
|
||||
|
||||
Data-binding is a mechanism for coordinating what users see, specifically
|
||||
with application data values.
|
||||
While you could push values to and pull values from HTML,
|
||||
the application is easier to write, read, and maintain if you turn these tasks over to a binding framework.
|
||||
You simply declare bindings between binding sources, target HTML elements, and let the framework do the rest.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
Angular provides many kinds of data-binding. Binding types can be grouped into three categories distinguished by the direction of data flow:
|
||||
|
||||
* From the _source-to-view_
|
||||
* From _view-to-source_
|
||||
* Two-way sequence: _view-to-source-to-view_
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
</style>
|
||||
|
||||
<table width="100%">
|
||||
<col width="30%">
|
||||
</col>
|
||||
<col width="50%">
|
||||
</col>
|
||||
<col width="20%">
|
||||
</col>
|
||||
<tr>
|
||||
<th>
|
||||
Type
|
||||
</th>
|
||||
<th>
|
||||
Syntax
|
||||
</th>
|
||||
<th>
|
||||
Category
|
||||
</th>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Interpolation<br>
|
||||
Property<br>
|
||||
Attribute<br>
|
||||
Class<br>
|
||||
Style
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<code-example>
|
||||
{{expression}}
|
||||
[target]="expression"
|
||||
bind-target="expression"
|
||||
</code-example>
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
One-way<br>from data source<br>to view target
|
||||
</td>
|
||||
<tr>
|
||||
<td>
|
||||
Event
|
||||
</td>
|
||||
<td>
|
||||
<code-example>
|
||||
(target)="statement"
|
||||
on-target="statement"
|
||||
</code-example>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
One-way<br>from view target<br>to data source
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Two-way
|
||||
</td>
|
||||
<td>
|
||||
<code-example>
|
||||
[(target)]="expression"
|
||||
bindon-target="expression"
|
||||
</code-example>
|
||||
</td>
|
||||
<td>
|
||||
Two-way
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Binding types other than interpolation have a **target name** to the left of the equal sign, either surrounded by punctuation, `[]` or `()`,
|
||||
or preceded by a prefix: `bind-`, `on-`, `bindon-`.
|
||||
|
||||
The *target* of a binding is the property or event inside the binding punctuation: `[]`, `()` or `[()]`.
|
||||
|
||||
Every public member of a **source** directive is automatically available for binding.
|
||||
You don't have to do anything special to access a directive member in a template expression or statement.
|
||||
|
||||
|
||||
### Data-binding and HTML
|
||||
|
||||
In the normal course of HTML development, you create a visual structure with HTML elements, and
|
||||
you modify those elements by setting element attributes with string constants.
|
||||
|
||||
```html
|
||||
<div class="special">Plain old HTML</div>
|
||||
<img src="images/item.png">
|
||||
<button disabled>Save</button>
|
||||
```
|
||||
|
||||
With data-binding, you can control things like the state of a button:
|
||||
|
||||
<code-example path="binding-syntax/src/app/app.component.html" region="disabled-button" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Notice that the binding is to the `disabled` property of the button's DOM element,
|
||||
**not** the attribute. This applies to data-binding in general. Data-binding works with *properties* of DOM elements, components, and directives, not HTML *attributes*.
|
||||
|
||||
{@a html-attribute-vs-dom-property}
|
||||
|
||||
### HTML attribute vs. DOM property
|
||||
|
||||
The distinction between an HTML attribute and a DOM property is key to understanding
|
||||
how Angular binding works. **Attributes are defined by HTML. Properties are accessed from DOM (Document Object Model) nodes.**
|
||||
|
||||
* A few HTML attributes have 1:1 mapping to properties; for example, `id`.
|
||||
|
||||
* Some HTML attributes don't have corresponding properties; for example, `aria-*`.
|
||||
|
||||
* Some DOM properties don't have corresponding attributes; for example, `textContent`.
|
||||
|
||||
It is important to remember that *HTML attribute* and the *DOM property* are different things, even when they have the same name.
|
||||
In Angular, the only role of HTML attributes is to initialize element and directive state.
|
||||
|
||||
**Template binding works with *properties* and *events*, not *attributes*.**
|
||||
|
||||
When you write a data-binding, you're dealing exclusively with the *DOM properties* and *events* of the target object.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
This general rule can help you build a mental model of attributes and DOM properties:
|
||||
**Attributes initialize DOM properties and then they are done.
|
||||
Property values can change; attribute values can't.**
|
||||
|
||||
There is one exception to this rule.
|
||||
Attributes can be changed by `setAttribute()`, which re-initializes corresponding DOM properties.
|
||||
|
||||
</div>
|
||||
|
||||
For more information, see the [MDN Interfaces documentation](https://developer.mozilla.org/en-US/docs/Web/API#Interfaces) which has API docs for all the standard DOM elements and their properties.
|
||||
Comparing the [`<td>` attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td) attributes to the [`<td>` properties](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement) provides a helpful example for differentiation.
|
||||
In particular, you can navigate from the attributes page to the properties via "DOM interface" link, and navigate the inheritance hierarchy up to `HTMLTableCellElement`.
|
||||
|
||||
|
||||
#### Example 1: an `<input>`
|
||||
|
||||
When the browser renders `<input type="text" value="Sarah">`, it creates a
|
||||
corresponding DOM node with a `value` property initialized to "Sarah".
|
||||
|
||||
```html
|
||||
<input type="text" value="Sarah">
|
||||
```
|
||||
|
||||
When the user enters "Sally" into the `<input>`, the DOM element `value` *property* becomes "Sally".
|
||||
However, if you look at the HTML attribute `value` using `input.getAttribute('value')`, you can see that the *attribute* remains unchanged—it returns "Sarah".
|
||||
|
||||
The HTML attribute `value` specifies the *initial* value; the DOM `value` property is the *current* value.
|
||||
|
||||
To see attributes versus DOM properties in a functioning app, see the <live-example name="binding-syntax"></live-example> especially for binding syntax.
|
||||
|
||||
#### Example 2: a disabled button
|
||||
|
||||
The `disabled` attribute is another example. A button's `disabled`
|
||||
*property* is `false` by default so the button is enabled.
|
||||
|
||||
When you add the `disabled` *attribute*, its presence alone
|
||||
initializes the button's `disabled` *property* to `true`
|
||||
so the button is disabled.
|
||||
|
||||
```html
|
||||
<button disabled>Test Button</button>
|
||||
```
|
||||
|
||||
Adding and removing the `disabled` *attribute* disables and enables the button.
|
||||
However, the value of the *attribute* is irrelevant,
|
||||
which is why you cannot enable a button by writing `<button disabled="false">Still Disabled</button>`.
|
||||
|
||||
To control the state of the button, set the `disabled` *property*,
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Though you could technically set the `[attr.disabled]` attribute binding, the values are different in that the property binding requires to a boolean value, while its corresponding attribute binding relies on whether the value is `null` or not. Consider the following:
|
||||
|
||||
```html
|
||||
<input [disabled]="condition ? true : false">
|
||||
<input [attr.disabled]="condition ? 'disabled' : null">
|
||||
```
|
||||
|
||||
Generally, use property binding over attribute binding as it is more intuitive (being a boolean value), has a shorter syntax, and is more performant.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
To see the `disabled` button example in a functioning app, see the <live-example name="binding-syntax"></live-example> especially for binding syntax. This example shows you how to toggle the disabled property from the component.
|
||||
|
||||
## Binding types and targets
|
||||
|
||||
The **target of a data-binding** is something in the DOM.
|
||||
Depending on the binding type, the target can be a property (element, component, or directive),
|
||||
an event (element, component, or directive), or sometimes an attribute name.
|
||||
The following table summarizes the targets for the different binding types.
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
</style>
|
||||
|
||||
<table width="100%">
|
||||
<col width="10%">
|
||||
</col>
|
||||
<col width="15%">
|
||||
</col>
|
||||
<col width="75%">
|
||||
</col>
|
||||
<tr>
|
||||
<th>
|
||||
Type
|
||||
</th>
|
||||
<th>
|
||||
Target
|
||||
</th>
|
||||
<th>
|
||||
Examples
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Property
|
||||
</td>
|
||||
<td>
|
||||
Element property<br>
|
||||
Component property<br>
|
||||
Directive property
|
||||
</td>
|
||||
<td>
|
||||
<code>src</code>, <code>hero</code>, and <code>ngClass</code> in the following:
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="property-binding-syntax-1"></code-example>
|
||||
<!-- For more information, see [Property Binding](guide/property-binding). -->
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Event
|
||||
</td>
|
||||
<td>
|
||||
Element event<br>
|
||||
Component event<br>
|
||||
Directive event
|
||||
</td>
|
||||
<td>
|
||||
<code>click</code>, <code>deleteRequest</code>, and <code>myClick</code> in the following:
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="event-binding-syntax-1"></code-example>
|
||||
<!-- KW--Why don't these links work in the table? -->
|
||||
<!-- <div>For more information, see [Event Binding](guide/event-binding).</div> -->
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Two-way
|
||||
</td>
|
||||
<td>
|
||||
Event and property
|
||||
</td>
|
||||
<td>
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="2-way-binding-syntax-1"></code-example>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Attribute
|
||||
</td>
|
||||
<td>
|
||||
Attribute
|
||||
(the exception)
|
||||
</td>
|
||||
<td>
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="attribute-binding-syntax-1"></code-example>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Class
|
||||
</td>
|
||||
<td>
|
||||
<code>class</code> property
|
||||
</td>
|
||||
<td>
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="class-binding-syntax-1"></code-example>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Style
|
||||
</td>
|
||||
<td>
|
||||
<code>style</code> property
|
||||
</td>
|
||||
<td>
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="style-binding-syntax-1"></code-example>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -34,7 +34,7 @@ Angular supports most recent browsers. This includes the following specific vers
|
||||
</td>
|
||||
|
||||
<td>
|
||||
latest and extended support release (ESR)
|
||||
latest
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -53,18 +53,16 @@ Angular supports most recent browsers. This includes the following specific vers
|
||||
IE
|
||||
</td>
|
||||
<td>
|
||||
<div> 11, 10*, 9* ("compatibility view" mode not supported) </div>
|
||||
<div>*deprecated in v10, see the {@link guide/deprecations#ie-9-10-and-mobile deprecations guide}.</div>
|
||||
11, 10, 9 ("compatibility view" mode not supported)
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr>
|
||||
<td>
|
||||
IE Mobile*
|
||||
IE Mobile
|
||||
</td>
|
||||
<td>
|
||||
11
|
||||
<div>*deprecated in v10, see the {@link guide/deprecations#ie-9-10-and-mobile deprecations guide}.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -262,33 +262,6 @@ Each budget entry is a JSON object with the following properties:
|
||||
|
||||
</table>
|
||||
|
||||
{@a commonjs }
|
||||
## Configuring CommonJS dependencies
|
||||
|
||||
<div class="alert is-important">
|
||||
|
||||
It is recommended that you avoid depending on CommonJS modules in your Angular applications.
|
||||
Depending on CommonJS modules can prevent bundlers and minifiers from optimizing your application, which results in larger bundle sizes.
|
||||
Instead, it is recommended that you use [ECMAScript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) in your entire application.
|
||||
For more information, see [How CommonJS is making your bundles larger](https://web.dev/commonjs-larger-bundles/).
|
||||
|
||||
</div>
|
||||
|
||||
The Angular CLI outputs warnings if it detects that your browser application depends on CommonJS modules.
|
||||
To disable these warnings, you can add the CommonJS module name to `allowedCommonJsDependencies` option in the `build` options located in `angular.json` file.
|
||||
|
||||
<code-example lang="json">
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"allowedCommonJsDependencies": [
|
||||
"lodash"
|
||||
]
|
||||
...
|
||||
}
|
||||
...
|
||||
},
|
||||
</code-example>
|
||||
|
||||
{@a browser-compat}
|
||||
|
||||
|
@ -1,435 +0,0 @@
|
||||
# Built-in directives
|
||||
|
||||
Angular offers two kinds of built-in directives: [_attribute_ directives](guide/attribute-directives) and [_structural_ directives](guide/structural-directives).
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
For more detail, including how to build your own custom directives, see [Attribute Directives](guide/attribute-directives) and [Structural Directives](guide/structural-directives).
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a attribute-directives}
|
||||
|
||||
## Built-in attribute directives
|
||||
|
||||
Attribute directives listen to and modify the behavior of
|
||||
other HTML elements, attributes, properties, and components.
|
||||
You usually apply them to elements as if they were HTML attributes, hence the name.
|
||||
|
||||
Many NgModules such as the [`RouterModule`](guide/router "Routing and Navigation")
|
||||
and the [`FormsModule`](guide/forms "Forms") define their own attribute directives.
|
||||
The most common attribute directives are as follows:
|
||||
|
||||
* [`NgClass`](guide/built-in-directives#ngClass)—adds and removes a set of CSS classes.
|
||||
* [`NgStyle`](guide/built-in-directives#ngStyle)—adds and removes a set of HTML styles.
|
||||
* [`NgModel`](guide/built-in-directives#ngModel)—adds two-way data binding to an HTML form element.
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a ngClass}
|
||||
|
||||
## `NgClass`
|
||||
|
||||
Add or remove several CSS classes simultaneously with `ngClass`.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="special-div" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
To add or remove a *single* class, use [class binding](guide/attribute-binding#class-binding) rather than `NgClass`.
|
||||
|
||||
</div>
|
||||
|
||||
Consider a `setCurrentClasses()` component method that sets a component property,
|
||||
`currentClasses`, with an object that adds or removes three classes based on the
|
||||
`true`/`false` state of three other component properties. Each key of the object is a CSS class name; its value is `true` if the class should be added,
|
||||
`false` if it should be removed.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.ts" region="setClasses" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
Adding an `ngClass` property binding to `currentClasses` sets the element's classes accordingly:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgClass-1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Remember that in this situation you'd call `setCurrentClasses()`,
|
||||
both initially and when the dependent properties change.
|
||||
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a ngStyle}
|
||||
|
||||
## `NgStyle`
|
||||
|
||||
Use `NgStyle` to set many inline styles simultaneously and dynamically, based on the state of the component.
|
||||
|
||||
### Without `NgStyle`
|
||||
|
||||
For context, consider setting a *single* style value with [style binding](guide/attribute-binding#style-binding), without `NgStyle`.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="without-ng-style" header="src/app/app.component.html"></code-example>
|
||||
|
||||
However, to set *many* inline styles at the same time, use the `NgStyle` directive.
|
||||
|
||||
The following is a `setCurrentStyles()` method that sets a component
|
||||
property, `currentStyles`, with an object that defines three styles,
|
||||
based on the state of three other component properties:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.ts" region="setStyles" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
Adding an `ngStyle` property binding to `currentStyles` sets the element's styles accordingly:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgStyle-2" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Remember to call `setCurrentStyles()`, both initially and when the dependent properties change.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a ngModel}
|
||||
|
||||
## `[(ngModel)]`: Two-way binding
|
||||
|
||||
The `NgModel` directive allows you to display a data property and
|
||||
update that property when the user makes changes. Here's an example:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" header="src/app/app.component.html (NgModel example)" region="NgModel-1"></code-example>
|
||||
|
||||
|
||||
### Import `FormsModule` to use `ngModel`
|
||||
|
||||
Before using the `ngModel` directive in a two-way data binding,
|
||||
you must import the `FormsModule` and add it to the NgModule's `imports` list.
|
||||
Learn more about the `FormsModule` and `ngModel` in [Forms](guide/forms#ngModel).
|
||||
|
||||
Remember to import the `FormsModule` to make `[(ngModel)]` available as follows:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.module.ts" header="src/app/app.module.ts (FormsModule import)" region="import-forms-module"></code-example>
|
||||
|
||||
|
||||
You could achieve the same result with separate bindings to
|
||||
the `<input>` element's `value` property and `input` event:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="without-NgModel" header="src/app/app.component.html"></code-example>
|
||||
|
||||
To streamline the syntax, the `ngModel` directive hides the details behind its own `ngModel` input and `ngModelChange` output properties:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgModelChange" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The `ngModel` data property sets the element's value property and the `ngModelChange` event property
|
||||
listens for changes to the element's value.
|
||||
|
||||
### `NgModel` and value accessors
|
||||
|
||||
The details are specific to each kind of element and therefore the `NgModel` directive only works for an element
|
||||
supported by a [ControlValueAccessor](api/forms/ControlValueAccessor)
|
||||
that adapts an element to this protocol.
|
||||
Angular provides *value accessors* for all of the basic HTML form elements and the
|
||||
[Forms](guide/forms) guide shows how to bind to them.
|
||||
|
||||
You can't apply `[(ngModel)]` to a non-form native element or a
|
||||
third-party custom component until you write a suitable value accessor. For more information, see
|
||||
the API documentation on [DefaultValueAccessor](https://angular.io/api/forms/DefaultValueAccessor).
|
||||
|
||||
You don't need a value accessor for an Angular component that
|
||||
you write because you can name the value and event properties
|
||||
to suit Angular's basic [two-way binding syntax](guide/two-way-binding)
|
||||
and skip `NgModel` altogether.
|
||||
The `sizer` in the
|
||||
[Two-way Binding](guide/two-way-binding) section is an example of this technique.
|
||||
|
||||
Separate `ngModel` bindings are an improvement over binding to the
|
||||
element's native properties, but you can streamline the binding with a
|
||||
single declaration using the `[(ngModel)]` syntax:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgModel-1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
This `[(ngModel)]` syntax can only _set_ a data-bound property.
|
||||
If you need to do something more, you can write the expanded form;
|
||||
for example, the following changes the `<input>` value to uppercase:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="uppercase" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Here are all variations in action, including the uppercase version:
|
||||
|
||||
<div class="lightbox">
|
||||
<img src='generated/images/guide/built-in-directives/ng-model-anim.gif' alt="NgModel variations">
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a structural-directives}
|
||||
|
||||
## Built-in _structural_ directives
|
||||
|
||||
Structural directives are responsible for HTML layout.
|
||||
They shape or reshape the DOM's structure, typically by adding, removing, and manipulating
|
||||
the host elements to which they are attached.
|
||||
|
||||
This section is an introduction to the common built-in structural directives:
|
||||
|
||||
* [`NgIf`](guide/built-in-directives#ngIf)—conditionally creates or destroys subviews from the template.
|
||||
* [`NgFor`](guide/built-in-directives#ngFor)—repeat a node for each item in a list.
|
||||
* [`NgSwitch`](guide/built-in-directives#ngSwitch)—a set of directives that switch among alternative views.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The deep details of structural directives are covered in the
|
||||
[Structural Directives](guide/structural-directives) guide,
|
||||
which explains the following:
|
||||
|
||||
* Why you
|
||||
[prefix the directive name with an asterisk (\*)](guide/structural-directives#the-asterisk--prefix).
|
||||
* Using [`<ng-container>`](guide/structural-directives#ngcontainer "<ng-container>")
|
||||
to group elements when there is no suitable host element for the directive.
|
||||
* How to write your own structural directive.
|
||||
* That you can only apply [one structural directive](guide/structural-directives#one-per-element "one per host element") to an element.
|
||||
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a ngIf}
|
||||
|
||||
## NgIf
|
||||
|
||||
You can add or remove an element from the DOM by applying an `NgIf` directive to
|
||||
a host element.
|
||||
Bind the directive to a condition expression like `isActive` in this example.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgIf-1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Don't forget the asterisk (`*`) in front of `ngIf`. For more information
|
||||
on the asterisk, see the [asterisk (*) prefix](guide/structural-directives#the-asterisk--prefix) section of
|
||||
[Structural Directives](guide/structural-directives).
|
||||
|
||||
</div>
|
||||
|
||||
When the `isActive` expression returns a truthy value, `NgIf` adds the
|
||||
`ItemDetailComponent` to the DOM.
|
||||
When the expression is falsy, `NgIf` removes the `ItemDetailComponent`
|
||||
from the DOM, destroying that component and all of its sub-components.
|
||||
|
||||
|
||||
### Show/hide vs. `NgIf`
|
||||
|
||||
Hiding an element is different from removing it with `NgIf`.
|
||||
For comparison, the following example shows how to control
|
||||
the visibility of an element with a
|
||||
[class](guide/attribute-binding#class-binding) or [style](guide/attribute-binding#style-binding) binding.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgIf-3" header="src/app/app.component.html"></code-example>
|
||||
|
||||
When you hide an element, that element and all of its descendants remain in the DOM.
|
||||
All components for those elements stay in memory and
|
||||
Angular may continue to check for changes.
|
||||
You could be holding onto considerable computing resources and degrading performance
|
||||
unnecessarily.
|
||||
|
||||
`NgIf` works differently. When `NgIf` is `false`, Angular removes the element and its descendants from the DOM.
|
||||
It destroys their components, freeing up resources, which
|
||||
results in a better user experience.
|
||||
|
||||
If you are hiding large component trees, consider `NgIf` as a more
|
||||
efficient alternative to showing/hiding.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For more information on `NgIf` and `ngIfElse`, see the [API documentation about NgIf](api/common/NgIf).
|
||||
|
||||
</div>
|
||||
|
||||
### Guard against null
|
||||
|
||||
Another advantage of `ngIf` is that you can use it to guard against null. Show/hide
|
||||
is best suited for very simple use cases, so when you need a guard, opt instead for `ngIf`. Angular will throw an error if a nested expression tries to access a property of `null`.
|
||||
|
||||
The following shows `NgIf` guarding two `<div>`s.
|
||||
The `currentCustomer` name appears only when there is a `currentCustomer`.
|
||||
The `nullCustomer` will not be displayed as long as it is `null`.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgIf-2" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgIf-2b" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See also the
|
||||
[safe navigation operator](guide/template-expression-operators#safe-navigation-operator "Safe navigation operator (?.)") below.
|
||||
|
||||
</div>
|
||||
<hr/>
|
||||
|
||||
{@a ngFor}
|
||||
## `NgFor`
|
||||
|
||||
`NgFor` is a repeater directive—a way to present a list of items.
|
||||
You define a block of HTML that defines how a single item should be displayed
|
||||
and then you tell Angular to use that block as a template for rendering each item in the list.
|
||||
The text assigned to `*ngFor` is the instruction that guides the repeater process.
|
||||
|
||||
The following example shows `NgFor` applied to a simple `<div>`. (Don't forget the asterisk (`*`) in front of `ngFor`.)
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgFor-1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Don't forget the asterisk (`*`) in front of `ngFor`. For more information
|
||||
on the asterisk, see the [asterisk (*) prefix](guide/structural-directives#the-asterisk--prefix) section of
|
||||
[Structural Directives](guide/structural-directives).
|
||||
|
||||
</div>
|
||||
|
||||
You can also apply an `NgFor` to a component element, as in the following example.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgFor-2" header="src/app/app.component.html"></code-example>
|
||||
|
||||
{@a microsyntax}
|
||||
|
||||
<div class="callout is-critical">
|
||||
<header>*ngFor microsyntax</header>
|
||||
|
||||
The string assigned to `*ngFor` is not a [template expression](guide/interpolation). Rather,
|
||||
it's a *microsyntax*—a little language of its own that Angular interprets.
|
||||
The string `"let item of items"` means:
|
||||
|
||||
> *Take each item in the `items` array, store it in the local `item` looping variable, and
|
||||
make it available to the templated HTML for each iteration.*
|
||||
|
||||
Angular translates this instruction into an `<ng-template>` around the host element,
|
||||
then uses this template repeatedly to create a new set of elements and bindings for each `item`
|
||||
in the list.
|
||||
For more information about microsyntax, see the [Structural Directives](guide/structural-directives#microsyntax) guide.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
{@a template-input-variable}
|
||||
|
||||
{@a template-input-variables}
|
||||
|
||||
### Template input variables
|
||||
|
||||
The `let` keyword before `item` creates a template input variable called `item`.
|
||||
The `ngFor` directive iterates over the `items` array returned by the parent component's `items` property
|
||||
and sets `item` to the current item from the array during each iteration.
|
||||
|
||||
Reference `item` within the `ngFor` host element
|
||||
as well as within its descendants to access the item's properties.
|
||||
The following example references `item` first in an interpolation
|
||||
and then passes in a binding to the `item` property of the `<app-item-detail>` component.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgFor-1-2" header="src/app/app.component.html"></code-example>
|
||||
|
||||
For more information about template input variables, see
|
||||
[Structural Directives](guide/structural-directives#template-input-variable).
|
||||
|
||||
### `*ngFor` with `index`
|
||||
|
||||
The `index` property of the `NgFor` directive context
|
||||
returns the zero-based index of the item in each iteration.
|
||||
You can capture the `index` in a template input variable and use it in the template.
|
||||
|
||||
The next example captures the `index` in a variable named `i` and displays it with the item name.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgFor-3" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
`NgFor` is implemented by the `NgForOf` directive. Read more about the other `NgForOf` context values such as `last`, `even`,
|
||||
and `odd` in the [NgForOf API reference](api/common/NgForOf).
|
||||
|
||||
</div>
|
||||
|
||||
{@a trackBy}
|
||||
### *ngFor with `trackBy`
|
||||
|
||||
If you use `NgFor` with large lists, a small change to one item, such as removing or adding an item, can trigger a cascade of DOM manipulations. For example, re-querying the server could reset a list with all new item objects, even when those items were previously displayed. In this case, Angular sees only a fresh list of new object references and has no choice but to replace the old DOM elements with all new DOM elements.
|
||||
|
||||
You can make this more efficient with `trackBy`.
|
||||
Add a method to the component that returns the value `NgFor` should track.
|
||||
In this case, that value is the hero's `id`. If the `id` has already been rendered,
|
||||
Angular keeps track of it and doesn't re-query the server for the same `id`.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.ts" region="trackByItems" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
In the microsyntax expression, set `trackBy` to the `trackByItems()` method.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="trackBy" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Here is an illustration of the `trackBy` effect.
|
||||
"Reset items" creates new items with the same `item.id`s.
|
||||
"Change ids" creates new items with new `item.id`s.
|
||||
|
||||
* With no `trackBy`, both buttons trigger complete DOM element replacement.
|
||||
* With `trackBy`, only changing the `id` triggers element replacement.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/built-in-directives/ngfor-trackby.gif" alt="Animation of trackBy">
|
||||
</div>
|
||||
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Built-in directives use only public APIs; that is,
|
||||
they do not have special access to any private APIs that other directives can't access.
|
||||
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a ngSwitch}
|
||||
## The `NgSwitch` directives
|
||||
|
||||
NgSwitch is like the JavaScript `switch` statement.
|
||||
It displays one element from among several possible elements, based on a switch condition.
|
||||
Angular puts only the selected element into the DOM.
|
||||
<!-- API Flagged -->
|
||||
`NgSwitch` is actually a set of three, cooperating directives:
|
||||
`NgSwitch`, `NgSwitchCase`, and `NgSwitchDefault` as in the following example.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgSwitch" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/built-in-directives/ngswitch.gif" alt="Animation of NgSwitch">
|
||||
</div>
|
||||
|
||||
`NgSwitch` is the controller directive. Bind it to an expression that returns
|
||||
the *switch value*, such as `feature`. Though the `feature` value in this
|
||||
example is a string, the switch value can be of any type.
|
||||
|
||||
**Bind to `[ngSwitch]`**. You'll get an error if you try to set `*ngSwitch` because
|
||||
`NgSwitch` is an *attribute* directive, not a *structural* directive.
|
||||
Rather than touching the DOM directly, it changes the behavior of its companion directives.
|
||||
|
||||
**Bind to `*ngSwitchCase` and `*ngSwitchDefault`**.
|
||||
The `NgSwitchCase` and `NgSwitchDefault` directives are _structural_ directives
|
||||
because they add or remove elements from the DOM.
|
||||
|
||||
* `NgSwitchCase` adds its element to the DOM when its bound value equals the switch value and removes
|
||||
its bound value when it doesn't equal the switch value.
|
||||
|
||||
* `NgSwitchDefault` adds its element to the DOM when there is no selected `NgSwitchCase`.
|
||||
|
||||
The switch directives are particularly useful for adding and removing *component elements*.
|
||||
This example switches among four `item` components defined in the `item-switch.components.ts` file.
|
||||
Each component has an `item` [input property](guide/inputs-outputs#input "Input property")
|
||||
which is bound to the `currentItem` of the parent component.
|
||||
|
||||
Switch directives work as well with native elements and web components too.
|
||||
For example, you could replace the `<app-best-item>` switch case with the following.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgSwitch-div" header="src/app/app.component.html"></code-example>
|
@ -25,7 +25,7 @@ in which two or more components share information.
|
||||
## Pass data from parent to child with input binding
|
||||
|
||||
`HeroChildComponent` has two ***input properties***,
|
||||
typically adorned with [@Input() decorator](guide/inputs-outputs#input).
|
||||
typically adorned with [@Input decorations](guide/template-syntax#inputs-outputs).
|
||||
|
||||
|
||||
<code-example path="component-interaction/src/app/hero-child.component.ts" header="component-interaction/src/app/hero-child.component.ts">
|
||||
@ -180,7 +180,7 @@ The child component exposes an `EventEmitter` property with which it `emits` eve
|
||||
The parent binds to that event property and reacts to those events.
|
||||
|
||||
The child's `EventEmitter` property is an ***output property***,
|
||||
typically adorned with an [@Output() decorator](guide/inputs-outputs#output)
|
||||
typically adorned with an [@Output decoration](guide/template-syntax#inputs-outputs)
|
||||
as seen in this `VoterComponent`:
|
||||
|
||||
|
||||
|
@ -109,9 +109,7 @@ To learn more, see [Schematics Overview](guide/schematics) and [Schematics for
|
||||
|
||||
## Publishing your library
|
||||
|
||||
Use the Angular CLI and the npm package manager to build and publish your library as an npm package.
|
||||
|
||||
Before publishing a library to NPM, build it using the `--prod` flag which will use the older compiler and runtime known as View Engine instead of Ivy.
|
||||
Use the Angular CLI and the npm package manager to build and publish your library as an npm package. It is not recommended to publish Ivy libraries to NPM repositories. Before publishing a library to NPM, build it using the `--prod` flag which will use the older compiler and runtime known as View Engine instead of Ivy.
|
||||
|
||||
<code-example language="bash">
|
||||
ng build my-lib --prod
|
||||
@ -121,14 +119,6 @@ npm publish
|
||||
|
||||
If you've never published a package in npm before, you must create a user account. Read more in [Publishing npm Packages](https://docs.npmjs.com/getting-started/publishing-npm-packages).
|
||||
|
||||
<div class="alert is-important">
|
||||
|
||||
For now, it is not recommended to publish Ivy libraries to NPM because Ivy generated code is not backward compatible with View Engine, so apps using View Engine will not be able to consume them. Furthermore, the internal Ivy instructions are not yet stable, which can potentially break consumers using a different Angular version from the one used to build the library.
|
||||
|
||||
When a published library is used in an Ivy app, the Angular CLI will automatically convert it to Ivy using a tool known as the Angular compatibility compiler (`ngcc`). Thus, publishing your libraries using the View Engine compiler ensures that they can be transparently consumed by both View Engine and Ivy apps.
|
||||
|
||||
</div>
|
||||
|
||||
{@a lib-assets}
|
||||
|
||||
## Managing assets in a library
|
||||
|
@ -197,11 +197,11 @@ Like `EvenBetterLogger`, `HeroService` needs to know if the user is authorized
|
||||
That authorization can change during the course of a single application session,
|
||||
as when you log in a different user.
|
||||
|
||||
Imagine that you don't want to inject `UserService` directly into `HeroService`, because you don't want to complicate that service with security-sensitive information.
|
||||
Let's say you don't want to inject `UserService` directly into `HeroService`, because you don't want to complicate that service with security-sensitive information.
|
||||
`HeroService` won't have direct access to the user information to decide
|
||||
who is authorized and who isn't.
|
||||
|
||||
To resolve this, give the `HeroService` constructor a boolean flag to control display of secret heroes.
|
||||
To resolve this, we give the `HeroService` constructor a boolean flag to control display of secret heroes.
|
||||
|
||||
<code-example path="dependency-injection/src/app/heroes/hero.service.ts" region="internals" header="src/app/heroes/hero.service.ts (excerpt)"></code-example>
|
||||
|
||||
@ -284,23 +284,6 @@ Search for [Constants in API documentation](api?type=const) to find more built-i
|
||||
|
||||
</div>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Note that the reference to the array returned for a `multi` provider is shared between all the
|
||||
places where the token is injected. We recommend avoiding mutations of the array (especially for
|
||||
predefined tokens) as it may lead to unexpected behavior in other parts of the app that inject
|
||||
the same token. You can prevent the value from being mutated by setting its type to `ReadonlyArray`.
|
||||
|
||||
</div>
|
||||
|
||||
You can use `ReadonlyArray` to type your `multi` provider, so TypeScript triggers an error in case
|
||||
of unwanted array mutations:
|
||||
|
||||
```
|
||||
constructor(@Inject(MULTI_PROVIDER) multiProvider: ReadonlyArray<MultiProvider>) {
|
||||
}
|
||||
```
|
||||
|
||||
{@a tree-shakable-provider}
|
||||
{@a tree-shakable-providers}
|
||||
|
||||
|
@ -304,7 +304,7 @@ In addition to build optimizations, Angular also has a runtime production mode.
|
||||
|
||||
<code-example format="nocode">
|
||||
|
||||
Angular is running in development mode. Call enableProdMode() to enable production mode.
|
||||
Angular is running in the development mode. Call enableProdMode() to enable the production mode.
|
||||
|
||||
</code-example>
|
||||
|
||||
@ -320,7 +320,7 @@ You can dramatically reduce launch time by only loading the application modules
|
||||
absolutely must be present when the app starts.
|
||||
|
||||
Configure the Angular Router to defer loading of all other modules (and their associated code), either by
|
||||
[waiting until the app has launched](guide/router-tutorial-toh#preloading "Preloading")
|
||||
[waiting until the app has launched](guide/router#preloading "Preloading")
|
||||
or by [_lazy loading_](guide/router#lazy-loading "Lazy loading")
|
||||
them on demand.
|
||||
|
||||
@ -328,7 +328,7 @@ them on demand.
|
||||
|
||||
<header>Don't eagerly import something from a lazy-loaded module</header>
|
||||
|
||||
If you mean to lazy-load a module, be careful not to import it
|
||||
If you mean to lazy-load a module, be careful not import it
|
||||
in a file that's eagerly loaded when the app starts (such as the root `AppModule`).
|
||||
If you do that, the module will be loaded immediately.
|
||||
|
||||
@ -469,7 +469,7 @@ The following configurations determine your requirements.
|
||||
|
||||
* TypeScript configuration
|
||||
|
||||
In the TypeScript configuration file, the "target" option in the `compilerOptions` section determines the ECMAScript target version that the code is compiled to.
|
||||
In the TypeScript configuration file, `tsconfig.json`, the "target" option in the `compilerOptions` section determines the ECMAScript target version that the code is compiled to.
|
||||
Modern browsers support ES2015 natively, while ES5 is more commonly used to support legacy browsers.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
@ -35,24 +35,24 @@ v9 - v12
|
||||
|
||||
| Area | API or Feature | May be removed in |
|
||||
| ----------------------------- | --------------------------------------------------------------------------- | ----------------- |
|
||||
| `@angular/bazel` | [`Bazel builder and schematics`](#bazelbuilder) | v10 |
|
||||
| `@angular/common` | [`ReflectiveInjector`](#reflectiveinjector) | <!--v8--> v11 |
|
||||
| `@angular/common` | [`ReflectiveInjector`](#reflectiveinjector) | <!--v8--> v10 |
|
||||
| `@angular/common` | [`CurrencyPipe` - `DEFAULT_CURRENCY_CODE`](api/common/CurrencyPipe#currency-code-deprecation) | <!--v9--> v11 |
|
||||
| `@angular/core` | [`CollectionChangeRecord`](#core) | <!--v7--> v11 |
|
||||
| `@angular/core` | [`DefaultIterableDiffer`](#core) | <!--v7--> v11 |
|
||||
| `@angular/core` | [`ReflectiveKey`](#core) | <!--v8--> v11 |
|
||||
| `@angular/core` | [`RenderComponentType`](#core) | <!--v7--> v11 |
|
||||
| `@angular/core` | [`ViewEncapsulation.Native`](#core) | <!--v6--> v11 |
|
||||
| `@angular/core` | [`WrappedValue`](#core) | <!--v10--> v12 |
|
||||
| `@angular/forms` | [`ngModel` with reactive forms](#ngmodel-reactive) | <!--v6--> v11 |
|
||||
| `@angular/router` | [`preserveQueryParams`](#router) | <!--v7--> v11 |
|
||||
| `@angular/upgrade` | [`@angular/upgrade`](#upgrade) | <!--v8--> v11 |
|
||||
| `@angular/upgrade` | [`getAngularLib`](#upgrade-static) | <!--v8--> v11 |
|
||||
| `@angular/upgrade` | [`setAngularLib`](#upgrade-static) | <!--v8--> v11 |
|
||||
| `@angular/platform-webworker` | [All entry points](api/platform-webworker) | <!--v8--> v11 |
|
||||
| template syntax | [`<template`>](#template-tag) | <!--v7--> v11 |
|
||||
| polyfills | [reflect-metadata](#reflect-metadata) | <!--v8--> v11 |
|
||||
| npm package format | [`esm5` and `fesm5` entry-points in @angular/* npm packages](guide/deprecations#esm5-fesm5) | <!-- v9 --> v11 |
|
||||
| `@angular/core` | [`CollectionChangeRecord`](#core) | <!--v7--> v10 |
|
||||
| `@angular/core` | [`DefaultIterableDiffer`](#core) | <!--v7--> v10 |
|
||||
| `@angular/core` | [`ReflectiveKey`](#core) | <!--v8--> v10 |
|
||||
| `@angular/core` | [`RenderComponentType`](#core) | <!--v7--> v10 |
|
||||
| `@angular/core` | [`ViewEncapsulation.Native`](#core) | <!--v6--> v10 |
|
||||
| `@angular/core` | [`ModuleWithProviders` without a generic](#moduleWithProviders) | <!--v9--> v10 |
|
||||
| `@angular/core` | [Undecorated base classes that use Angular features](#undecorated-base-classes) | <!--v9--> v10 |
|
||||
| `@angular/forms` | [`ngModel` with reactive forms](#ngmodel-reactive) | <!--v6--> v10 |
|
||||
| `@angular/router` | [`preserveQueryParams`](#router) | <!--v7--> v10 |
|
||||
| `@angular/upgrade` | [`@angular/upgrade`](#upgrade) | <!--v8--> v10 |
|
||||
| `@angular/upgrade` | [`getAngularLib`](#upgrade-static) | <!--v8--> v10 |
|
||||
| `@angular/upgrade` | [`setAngularLib`](#upgrade-static) | <!--v8--> v10 |
|
||||
| `@angular/platform-webworker` | [All entry points](api/platform-webworker) | <!--v8--> v10 |
|
||||
| template syntax | [`<template`>](#template-tag) | <!--v7--> v10 |
|
||||
| polyfills | [reflect-metadata](#reflect-metadata) | <!--v8--> v10 |
|
||||
| npm package format | [`esm5` and `fesm5` entry-points in @angular/* npm packages](guide/deprecations#esm5-fesm5) | <!-- v9 --> v10 |
|
||||
| `@angular/core` | [`defineInjectable`](#core) | <!--v8--> v11 |
|
||||
| `@angular/core` | [`entryComponents`](api/core/NgModule#entryComponents) | <!--v9--> v11 |
|
||||
| `@angular/core` | [`ANALYZE_FOR_ENTRY_COMPONENTS`](api/core/ANALYZE_FOR_ENTRY_COMPONENTS) | <!--v9--> v11 |
|
||||
@ -60,7 +60,6 @@ v9 - v12
|
||||
| `@angular/core/testing` | [`TestBed.get`](#testing) | <!--v9--> v12 |
|
||||
| `@angular/router` | [`ActivatedRoute` params and `queryParams` properties](#activatedroute-props) | unspecified |
|
||||
| template syntax | [`/deep/`, `>>>`, and `::ng-deep`](#deep-component-style-selector) | <!--v7--> unspecified |
|
||||
| browser support | [`IE 9 and 10, IE mobile`](#ie-9-10-and-mobile) | <!--v10--> v11 |
|
||||
|
||||
|
||||
|
||||
@ -97,7 +96,9 @@ Tip: In the [API reference section](api) of this doc site, deprecated APIs are i
|
||||
| [`defineInjectable`](api/core/defineInjectable) | `ɵɵdefineInjectable` | v8 | Used only in generated code. No source code should depend on this API. |
|
||||
| [`entryComponents`](api/core/NgModule#entryComponents) | none | v9 | See [`entryComponents`](#entryComponents) |
|
||||
| [`ANALYZE_FOR_ENTRY_COMPONENTS`](api/core/ANALYZE_FOR_ENTRY_COMPONENTS) | none | v9 | See [`ANALYZE_FOR_ENTRY_COMPONENTS`](#entryComponents) |
|
||||
| [`WrappedValue`](api/core/WrappedValue) | none | v10 | See [removing `WrappedValue`](#wrapped-value) |
|
||||
| `ModuleWithProviders` without a generic | `ModuleWithProviders` with a generic | v9 | See [`ModuleWithProviders` section](#moduleWithProviders) |
|
||||
| Undecorated base classes that use Angular features | Base classes with `@Directive()` decorator that use Angular features | v9 | See [undecorated base classes section](#undecorated-base-classes) |
|
||||
|
||||
|
||||
|
||||
|
||||
@ -161,11 +162,7 @@ Tip: In the [API reference section](api) of this doc site, deprecated APIs are i
|
||||
|
||||
This section lists all of the currently-deprecated features, which includes template syntax, configuration options, and any other deprecations not listed in the [Deprecated APIs](#deprecated-apis) section above. It also includes deprecated API usage scenarios or API combinations, to augment the information above.
|
||||
|
||||
{@a bazelbuilder}
|
||||
### Bazel builder and schematics
|
||||
|
||||
Bazel builder and schematics were introduced in Angular Labs to let users try out Bazel without having to manage Bazel version and BUILD files.
|
||||
This feature has been deprecated. For more information, please refer to the [migration doc](https://github.com/angular/angular/blob/master/packages/bazel/src/schematics/README.md).
|
||||
|
||||
{@a wtf}
|
||||
### Web Tracing Framework integration
|
||||
@ -379,6 +376,60 @@ However, in practice, Angular simply ignores two-way bindings to template variab
|
||||
<option *ngFor="let optionName of options" [value]="optionName"></option>
|
||||
```
|
||||
|
||||
{@a undecorated-base-classes}
|
||||
### Undecorated base classes using Angular features
|
||||
|
||||
As of version 9, it's deprecated to have an undecorated base class that:
|
||||
|
||||
- uses Angular features
|
||||
- is extended by a directive or component
|
||||
|
||||
Angular lifecycle hooks or any of the following Angular field decorators are considered Angular features:
|
||||
|
||||
- `@Input()`
|
||||
- `@Output()`
|
||||
- `@HostBinding()`
|
||||
- `@HostListener()`
|
||||
- `@ViewChild()` / `@ViewChildren()`
|
||||
- `@ContentChild()` / `@ContentChildren()`
|
||||
|
||||
For example, the following case is deprecated because the base class uses `@Input()` and does not have a class-level decorator:
|
||||
|
||||
```ts
|
||||
class Base {
|
||||
@Input()
|
||||
foo: string;
|
||||
}
|
||||
|
||||
@Directive(...)
|
||||
class Dir extends Base {
|
||||
ngOnChanges(): void {
|
||||
// notified when bindings to [foo] are updated
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In a future version of Angular, this code will start to throw an error.
|
||||
To fix this example, add a selectorless `@Directive()` decorator to the base class:
|
||||
|
||||
```ts
|
||||
@Directive()
|
||||
class Base {
|
||||
@Input()
|
||||
foo: string;
|
||||
}
|
||||
|
||||
@Directive(...)
|
||||
class Dir extends Base {
|
||||
ngOnChanges(): void {
|
||||
// notified when bindings to [foo] are updated
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In version 9, the CLI has an automated migration that will update your code for you when `ng update` is run.
|
||||
See [the dedicated migration guide](guide/migration-undecorated-classes) for more information about the change and more examples.
|
||||
|
||||
|
||||
|
||||
{@a binding-to-innertext}
|
||||
@ -463,104 +514,13 @@ export class MyModule {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
{@a ie-9-10-and-mobile}
|
||||
### IE 9, 10, and IE mobile support
|
||||
|
||||
Support for IE 9 and 10 has been deprecated, as well as support for IE Mobile. These will be dropped in a future version.
|
||||
Supporting outdated browsers like these increases bundle size, code complexity, and test load, and also requires time and effort that could be spent on improvements to the framework.
|
||||
For example, fixing issues can be more difficult, as a straightforward fix for modern browsers could break old ones that have quirks due to not receiving updates from vendors.
|
||||
|
||||
The final decision was made on three key points:
|
||||
* __Vendor support__: Microsoft dropped support of IE 9 and 10 on 1/12/16, meaning they no longer provide security updates or technical support. Additionally, Microsoft dropped support for Windows 10 Mobile in December 2019.
|
||||
* __Usage statistics__: We looked at usage trends for IE 9 and 10 (as well as IE Mobile) from various sources and all indicated that usage percentages were extremely small (fractions of 1%).
|
||||
* __Feedback from partners__: We also reached out to some of our Angular customers and none expressed concern about dropping IE 9, 10, nor IE Mobile support.
|
||||
|
||||
|
||||
{@a wrapped-value}
|
||||
### `WrappedValue`
|
||||
|
||||
The purpose of `WrappedValue` is to allow the same object instance to be treated as different for the purposes of change detection.
|
||||
It is commonly used with the `async` pipe in the case where the `Observable` produces the same instance of the value.
|
||||
|
||||
Given that this use case is relatively rare and special handling impacts application performance, we have deprecated it in v10.
|
||||
No replacement is planned for this deprecation.
|
||||
|
||||
If you rely on the behavior that the same object instance should cause change detection, you have two options:
|
||||
- Clone the resulting value so that it has a new identity.
|
||||
- Explicitly call [`ChangeDetectorRef.detectChanges()`](api/core/ChangeDetectorRef#detectchanges) to force the update.
|
||||
|
||||
{@a deprecated-cli-flags}
|
||||
## Deprecated CLI APIs and Options
|
||||
|
||||
This section contains a complete list all of the currently deprecated CLI flags.
|
||||
|
||||
### @angular-devkit/build-angular
|
||||
|
||||
| API/Option | May be removed in | Notes |
|
||||
| ------------------------------- | ----------------- |-------------------------------------------------------------------------------- |
|
||||
| `i18nFile` | <!--v9--> v11 | Specified in the project locale configuration in version 9 and later. |
|
||||
| `i18nFormat` | <!--v9--> v11 | Format is now automatically detected. |
|
||||
| `i18nLocale` | <!--v9--> v11 | New [localization option](/guide/i18n#localize-config) in version 9 and later. |
|
||||
| `lazyModules` | <!--v9--> v11 | Used with deprecated SystemJsNgModuleLoader. |
|
||||
| `rebaseRootRelativeCssUrls` | <!--v8--> v11 | Intended only to assist with specific migration issues. |
|
||||
| `scripts[].lazy` | <!--v8--> v11 | Renamed to `scripts[].inject`. |
|
||||
| `styles[].lazy` | <!--v8--> v11 | Renamed to `styles[].inject`. |
|
||||
| `i18nFormat` | <!--v9--> v11 | Renamed to `format` to simplify the user experience. |
|
||||
| `i18nLocale` | <!--v9--> v11 | Redundant with project’s source locale. |
|
||||
| `scripts[].lazy` | <!--v8--> v11 | Renamed to `scripts[].inject`. |
|
||||
| `styles[].lazy` | <!--v8--> v11 | Renamed to `styles[].inject`. |
|
||||
| `i18nFile` | <!--v9--> v11 | Specified in the project locale configuration in version 9 and later. |
|
||||
| `i18nFormat` | <!--v9--> v11 | Format is now automatically detected. |
|
||||
| `i18nLocale` | <!--v9--> v11 | New [localization option](/guide/i18n#localize-config) in version 9 and later. |
|
||||
| `lazyModules` | <!--v9--> v11 | Used with deprecated SystemJsNgModuleLoader. |
|
||||
|
||||
### @angular-devkit/core
|
||||
|
||||
| API/Option | May be removed in | Notes |
|
||||
| ------------------------------- | ----------------- |-------------------------------------------------------------------------------- |
|
||||
| `ModuleNotFoundException` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Not Yarn PnP compatible and not used in the Angular CLI. Use Node.js [require.resolve](https://nodejs.org/api/modules.html#modules_require_resolve_request_options).|
|
||||
| `resolve` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Not Yarn PnP compatible and not used in the Angular CLI. Use Node.js [require.resolve](https://nodejs.org/api/modules.html#modules_require_resolve_request_options).|
|
||||
| `setResolveHook` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Not Yarn PnP compatible and not used in the Angular CLI. Use Node.js [require.resolve](https://nodejs.org/api/modules.html#modules_require_resolve_request_options).|
|
||||
| `ResolveOptions` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Not Yarn PnP compatible and not used in the Angular CLI. Use Node.js [require.resolve](https://nodejs.org/api/modules.html#modules_require_resolve_request_options).|
|
||||
| `terminal` | <!--v8--> v10 | Unused implementation of terminal codes (color). |
|
||||
| `isObservable` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Use `isObservable` function from the `rxjs` package.|
|
||||
|
||||
### @ngtools/webpack
|
||||
|
||||
| API/Option | May be removed in | Notes |
|
||||
| ------------------------------- | ----------------- |-------------------------------------------------------------------------------- |
|
||||
| `discoverLazyRoutes` | <!--v9--> TBD | Used with deprecated SystemJsNgModuleLoader. |
|
||||
| `additionalLazyModules` | <!--v9--> TBD | Used with deprecated SystemJsNgModuleLoader. |
|
||||
| `additionalLazyModuleResources` | <!--v9--> TBD | Used with deprecated SystemJsNgModuleLoader. |
|
||||
|
||||
### @schematics/angular
|
||||
|
||||
| API/Option | May be removed in | Notes |
|
||||
| ------------------------------- | ----------------- |-------------------------------------------------------------------------------- |
|
||||
| `entryComponent` | <!--v9--> TBD | No longer needed with Ivy. |
|
||||
|
||||
{@a removed}
|
||||
## Removed APIs
|
||||
|
||||
The following APIs have been removed starting with version 10.0.0*:
|
||||
|
||||
| Package | API | Replacement | Notes |
|
||||
| ---------------- | -------------- | ----------- | ----- |
|
||||
| `@angular/core` | Undecorated base classes that use Angular features | Add Angular decorator | See [migration guide](guide/migration-undecorated-classes) for more info |
|
||||
| `@angular/core` | `ModuleWithProviders` without a generic | `ModuleWithProviders` with a generic | See [migration guide](guide/migration-module-with-providers) for more info |
|
||||
| `@angular/core` | Style Sanitization | no action needed | See [style sanitization API removal](#style-sanitization) for more info
|
||||
|
||||
*To see APIs removed in version 9, check out this guide on the [version 9 docs site](https://v9.angular.io/guide/deprecations#removed).
|
||||
|
||||
|
||||
{@a esm5-fesm5}
|
||||
### `esm5` and `fesm5` code formats in @angular/* npm packages
|
||||
|
||||
As of Angular v8, the CLI primarily consumes the `fesm2015` variant of the code distributed via `@angular/*` npm packages.
|
||||
This renders the `esm5` and `fesm5` distributions obsolete and unnecessary, adding bloat to the package size and slowing down npm installations.
|
||||
|
||||
This removal has no impact on CLI users, unless they modified their build configuration to explicitly consume these code distributions.
|
||||
The future removal of this distribution will have no impact on CLI users, unless they modified their build configuration to explicitly consume these code distributions.
|
||||
|
||||
Any application still relying on the `esm5` and `fesm5` as the input to its build system will need to ensure that the build pipeline is capable of accepting JavaScript code conforming to ECMAScript 2015 (ES2015) language specification.
|
||||
|
||||
@ -568,7 +528,7 @@ Note that this change doesn't make existing libraries distributed in this format
|
||||
The CLI will fall back and consume libraries in less desirable formats if others are not available.
|
||||
However, we do recommend that libraries ship their code in ES2015 format in order to make builds faster and build output smaller.
|
||||
|
||||
In practical terms, the `package.json` of all `@angular` packages has changed in the following way:
|
||||
In practical terms, the `package.json` of all `@angular` packages will change in the following way:
|
||||
|
||||
**Before**:
|
||||
```
|
||||
@ -602,18 +562,92 @@ In practical terms, the `package.json` of all `@angular` packages has changed in
|
||||
|
||||
For more information about the npm package format, see the [Angular Package Format spec](https://goo.gl/jB3GVv).
|
||||
|
||||
|
||||
|
||||
{@a removed}
|
||||
## Removed APIs
|
||||
|
||||
The following APIs have been removed starting with version 10.0.0*:
|
||||
The following APIs have been removed starting with version 9.0.0*:
|
||||
|
||||
| Package | API | Replacement | Notes |
|
||||
| ---------------- | -------------- | ----------- | ----- |
|
||||
| `@angular/core` | Undecorated base classes that use Angular features | Add Angular decorator | See [migration guide](guide/migration-undecorated-classes) for more info |
|
||||
| `@angular/core` | `ModuleWithProviders` without a generic | `ModuleWithProviders` with a generic | See [migration guide](guide/migration-module-with-providers) for more info |
|
||||
| `@angular/core` | [`Renderer`](https://v8.angular.io/api/core/Renderer) | [`Renderer2`](https://angular.io/api/core/Renderer2) | [Migration guide](guide/migration-renderer) |
|
||||
| `@angular/core` | [`RootRenderer`](https://v8.angular.io/api/core/RootRenderer) | [`RendererFactory2`](https://angular.io/api/core/RendererFactory2) | none |
|
||||
| `@angular/core` | [`RenderComponentType`](https://v8.angular.io/api/core/RenderComponentType) | [`RendererType2`](https://angular.io/api/core/RendererType2) | none |
|
||||
| `@angular/core` | [`WtfScopeFn`](https://v8.angular.io/api/core/WtfScopeFn) | none | v8 | See [Web Tracing Framework](#wtf) |
|
||||
| `@angular/core` | [`wtfCreateScope`](https://v8.angular.io/api/core/wtfCreateScope) | none | v8 | See [Web Tracing Framework](#wtf) |
|
||||
| `@angular/core` | [`wtfStartTimeRange`](https://v8.angular.io/api/core/wtfStartTimeRange) | none | v8 | See [Web Tracing Framework](#wtf) |
|
||||
| `@angular/core` | [`wtfEndTimeRange`](https://v8.angular.io/api/core/wtfEndTimeRange) | none | v8 | See [Web Tracing Framework](#wtf) |
|
||||
| `@angular/core` | [`wtfLeave`](https://v8.angular.io/api/core/wtfLeave) | none | v8 | See [Web Tracing Framework](#wtf) |
|
||||
| `@angular/common` | `DeprecatedI18NPipesModule` | [`CommonModule`](api/common/CommonModule#pipes) | none |
|
||||
| `@angular/common` | `DeprecatedCurrencyPipe` | [`CurrencyPipe`](api/common/CurrencyPipe) | none |
|
||||
| `@angular/common` | `DeprecatedDatePipe` | [`DatePipe`](api/common/DatePipe) | none |
|
||||
| `@angular/common` | `DeprecatedDecimalPipe` | [`DecimalPipe`](api/common/DecimalPipe) | none |
|
||||
| `@angular/common` | `DeprecatedPercentPipe` | [`PercentPipe`](api/common/PercentPipe) | none |
|
||||
| `@angular/forms` | [`NgFormSelectorWarning`](https://v8.angular.io/api/forms/NgFormSelectorWarning) | none | none |
|
||||
| `@angular/forms` | `ngForm` element selector | `ng-form` element selector | none |
|
||||
| `@angular/service-worker` | `versionedFiles` | `files` | In the service worker configuration file `ngsw-config.json`, replace `versionedFiles` with `files`. See [Service Worker Configuration](guide/service-worker-config#assetgroups). |
|
||||
|
||||
*To see APIs removed in version 9, check out this guide on the [version 9 docs site](https://v9.angular.io/guide/deprecations#removed).
|
||||
*To see APIs removed in version 8, check out this guide on the [version 8 docs site](https://v8.angular.io/guide/deprecations#removed).
|
||||
|
||||
{@a style-sanitization}
|
||||
### Style Sanitization for `[style]` and `[style.prop]` bindings
|
||||
Angular used to sanitize `[style]` and `[style.prop]` bindings to prevent malicious code from being inserted through `javascript:` expressions in CSS `url()` entries. However, most modern browsers no longer support the usage of these expressions, so sanitization was only maintained for the sake of IE 6 and 7. Given that Angular does not support either IE 6 or 7 and sanitization has a performance cost, we will no longer sanitize style bindings as of version 10 of Angular.
|
||||
|
||||
<!-- The following anchor is used by redirects from the removed API pages. Do not change or remove. -->
|
||||
{@a http}
|
||||
### @angular/http
|
||||
|
||||
<!--
|
||||
Deprecation announced in version 5
|
||||
https://blog.angular.io/version-5-0-0-of-angular-now-available-37e414935ced)
|
||||
-->
|
||||
|
||||
|
||||
The entire [`@angular/http`](http://v7.angular.io/api/http) package has been removed. Use [`@angular/common/http`](api/common/http) instead.
|
||||
|
||||
The new API is a smaller, easier, and more powerful way to make HTTP requests in Angular.
|
||||
The new API simplifies the default ergonomics: There is no need to map by invoking the `.json()` method.
|
||||
It also supports typed return values and interceptors.
|
||||
|
||||
To update your apps:
|
||||
* Replace `HttpModule` with [`HttpClientModule`](api/common/http/HttpClientModule) (from [`@angular/common/http`](api/common/http)) in each of your modules.
|
||||
* Replace the `Http` service with the [`HttpClient`](api/common/http/HttpClient) service.
|
||||
* Remove any `map(res => res.json())` calls. They are no longer needed.
|
||||
|
||||
For more information about using `@angular/common/http`, see the [HttpClient guide](guide/http "HTTP Client guide").
|
||||
|
||||
|
||||
| `@angular/http` | Closest replacement in `@angular/common/http` |
|
||||
| ------------- | ------------------------------------------- |
|
||||
| `BaseRequestOptions` | [`HttpRequest`](/api/common/http/HttpRequest) |
|
||||
| `BaseResponseOptions` | [`HttpResponse`](/api/common/http/HttpResponse) |
|
||||
| `BrowserXhr` | |
|
||||
| `Connection` | [`HttpBackend`](/api/common/http/HttpBackend) |
|
||||
| `ConnectionBackend` | [`HttpBackend`](/api/common/http/HttpBackend) |
|
||||
| `CookieXSRFStrategy` | [`HttpClientXsrfModule`](/api/common/http/HttpClientXsrfModule) |
|
||||
| `Headers` | [`HttpHeaders`](/api/common/http/HttpHeaders) |
|
||||
| `Http` | [`HttpClient`](/api/common/http/HttpClient) |
|
||||
| `HttpModule` | [`HttpClientModule`](/api/common/http/HttpClientModule) |
|
||||
| `Jsonp` | [`HttpClient`](/api/common/http/HttpClient) |
|
||||
| `JSONPBackend` | [`JsonpClientBackend`](/api/common/http/JsonpClientBackend) |
|
||||
| `JSONPConnection` | [`JsonpClientBackend`](/api/common/http/JsonpClientBackend) |
|
||||
| `JsonpModule` | [`HttpClientJsonpModule`](/api/common/http/HttpClientJsonpModule) |
|
||||
| `QueryEncoder` | [`HttpUrlEncodingCodec`](/api/common/http/HttpUrlEncodingCodec) |
|
||||
| `ReadyState` | [`HttpBackend`](/api/common/http/HttpBackend) |
|
||||
| `Request` | [`HttpRequest`](/api/common/http/HttpRequest) |
|
||||
| `RequestMethod` | [`HttpClient`](/api/common/http/HttpClient) |
|
||||
| `RequestOptions` | [`HttpRequest`](/api/common/http/HttpRequest) |
|
||||
| `RequestOptionsArgs` | [`HttpRequest`](/api/common/http/HttpRequest) |
|
||||
| `Response` | [`HttpResponse`](/api/common/http/HttpResponse) |
|
||||
| `ResponseContentType` | [`HttpClient`](/api/common/http/HttpClient) |
|
||||
| `ResponseOptions` | [`HttpResponse`](/api/common/http/HttpResponse) |
|
||||
| `ResponseOptionsArgs` | [`HttpResponse`](/api/common/http/HttpResponse) |
|
||||
| `ResponseType` | [`HttpClient`](/api/common/http/HttpClient) |
|
||||
| `URLSearchParams` | [`HttpParams`](/api/common/http/HttpParams) |
|
||||
| `XHRBackend` | [`HttpXhrBackend`](/api/common/http/HttpXhrBackend) |
|
||||
| `XHRConnection` | [`HttpXhrBackend`](/api/common/http/HttpXhrBackend) |
|
||||
| `XSRFStrategy` | [`HttpClientXsrfModule`](/api/common/http/HttpClientXsrfModule) |
|
||||
|
||||
|
||||
| `@angular/http/testing` | Closest replacement in `@angular/common/http/testing` |
|
||||
| --------------------- | ------------------------------------------- |
|
||||
| `MockBackend` | [`HttpTestingController`](/api/common/http/testing/HttpTestingController) |
|
||||
| `MockConnection` | [`HttpTestingController`](/api/common/http/testing/HttpTestingController) |
|
||||
|
@ -153,14 +153,14 @@ It marks that `<li>` element (and its children) as the "repeater template":
|
||||
<div class="alert is-important">
|
||||
|
||||
Don't forget the leading asterisk (\*) in `*ngFor`. It is an essential part of the syntax.
|
||||
Read more about `ngFor` and `*` in the [ngFor section](guide/built-in-directives#ngfor) of the [Built-in directives](guide/built-in-directives) page.
|
||||
Read more about `ngFor` and `*` in the [ngFor section](guide/template-syntax#ngfor) of the [Template Syntax](guide/template-syntax) page.
|
||||
|
||||
</div>
|
||||
|
||||
Notice the `hero` in the `ngFor` double-quoted instruction;
|
||||
it is an example of a template input variable. Read
|
||||
more about template input variables in the [microsyntax](guide/built-in-directives#microsyntax) section of
|
||||
the [Built-in directives](guide/built-in-directives) page.
|
||||
more about template input variables in the [microsyntax](guide/template-syntax#microsyntax) section of
|
||||
the [Template Syntax](guide/template-syntax) page.
|
||||
|
||||
Angular duplicates the `<li>` for each item in the list, setting the `hero` variable
|
||||
to the item (the hero) in the current iteration. Angular uses that variable as the
|
||||
@ -255,7 +255,7 @@ To see it in action, add the following paragraph at the bottom of the template:
|
||||
<div class="alert is-important">
|
||||
|
||||
Don't forget the leading asterisk (\*) in `*ngIf`. It is an essential part of the syntax.
|
||||
Read more about `ngIf` and `*` in the [ngIf section](guide/built-in-directives#ngIf) of the [Built-in directives](guide/built-in-directives) page.
|
||||
Read more about `ngIf` and `*` in the [ngIf section](guide/template-syntax#ngIf) of the [Template Syntax](guide/template-syntax) page.
|
||||
|
||||
</div>
|
||||
|
||||
@ -266,7 +266,7 @@ When the component's list of heroes has more than three items, Angular adds the
|
||||
to the DOM and the message appears.
|
||||
If there are three or fewer items, Angular omits the paragraph, so no message appears.
|
||||
|
||||
For more information, see [template expression operators](guide/interpolation#template-expressions).
|
||||
For more information, see [template expressions](guide/template-syntax#template-expressions).
|
||||
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
@ -931,7 +931,7 @@ If you do, be sure to set the `id` attribute - not the `name` attribute! The doc
|
||||
|
||||
</div>
|
||||
|
||||
## Alerts and Callouts
|
||||
## Alerts and Calllouts
|
||||
|
||||
Alerts and callouts present warnings, extra detail or references to other pages. They can also be used to provide commentary that _enriches_ the reader's understanding of the content being presented.
|
||||
|
||||
|
@ -131,6 +131,22 @@ The `createComponent()` method returns a reference to the loaded component.
|
||||
Use that reference to interact with the component by assigning to its properties or calling its methods.
|
||||
|
||||
|
||||
{@a selector-references}
|
||||
|
||||
|
||||
#### Selector references
|
||||
|
||||
Generally, the Angular compiler generates a `ComponentFactory`
|
||||
for any component referenced in a template. However, there are
|
||||
no selector references in the templates for
|
||||
dynamically loaded components since they load at runtime.
|
||||
|
||||
To ensure that the compiler still generates a factory,
|
||||
add dynamically loaded components to the `NgModule`'s `entryComponents` array:
|
||||
|
||||
<code-example path="dynamic-component-loader/src/app/app.module.ts" region="entry-components" header="src/app/app.module.ts (entry components)"></code-example>
|
||||
|
||||
|
||||
|
||||
{@a common-interface}
|
||||
|
||||
|
@ -117,9 +117,9 @@ The recently-developed [custom elements](https://developer.mozilla.org/en-US/doc
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
In browsers that support Custom Elements natively, the specification requires developers use ES2015 classes to define Custom Elements - developers can opt-in to this by setting the `target: "es2015"` property in their project's [TypeScript configuration file](/guide/typescript-configuration). As Custom Element and ES2015 support may not be available in all browsers, developers can instead choose to use a polyfill to support older browsers and ES5 code.
|
||||
In browsers that support Custom Elements natively, the specification requires developers use ES2015 classes to define Custom Elements - developers can opt-in to this by setting the `target: "es2015"` property in their project's `tsconfig.json`. As Custom Element and ES2015 support may not be available in all browsers, developers can instead choose to use a polyfill to support older browsers and ES5 code.
|
||||
|
||||
Use the [Angular CLI](cli) to automatically set up your project with the correct polyfill: `ng add @angular/elements --project=*your_project_name*`.
|
||||
Use the [Angular CLI](cli) to automatically set up your project with the correct polyfill: `ng add @angular/elements --name=*your_project_name*`.
|
||||
- For more information about polyfills, see [polyfill documentation](https://www.webcomponents.org/polyfills).
|
||||
|
||||
- For more information about Angular browser support, see [Browser Support](guide/browser-support).
|
||||
@ -186,7 +186,7 @@ aDialog.content = 123; // <-- ERROR: TypeScript knows this should be a string.
|
||||
aDialog.body = 'News'; // <-- ERROR: TypeScript knows there is no `body` property on `aDialog`.
|
||||
```
|
||||
|
||||
This is a good way to quickly get TypeScript features, such as type checking and autocomplete support, for your custom element. But it can get cumbersome if you need it in several places, because you have to cast the return type on every occurrence.
|
||||
This is a good way to quickly get TypeScript features, such as type checking and autocomplete support, for you custom element. But it can get cumbersome if you need it in several places, because you have to cast the return type on every occurrence.
|
||||
|
||||
An alternative way, that only requires defining each custom element's type once, is augmenting the `HTMLElementTagNameMap`, which TypeScript uses to infer the type of a returned element based on its tag name (for DOM methods such as `document.createElement()`, `document.querySelector()`, etc.):
|
||||
|
||||
|
@ -1,108 +0,0 @@
|
||||
# Event binding `(event)`
|
||||
|
||||
Event binding allows you to listen for certain events such as
|
||||
keystrokes, mouse movements, clicks, and touches.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
Angular event binding syntax consists of a **target event** name
|
||||
within parentheses on the left of an equal sign, and a quoted
|
||||
template statement on the right.
|
||||
The following event binding listens for the button's click events, calling
|
||||
the component's `onSave()` method whenever a click occurs:
|
||||
|
||||
<div class="lightbox">
|
||||
<img src='generated/images/guide/template-syntax/syntax-diagram.svg' alt="Syntax diagram">
|
||||
</div>
|
||||
|
||||
## Target event
|
||||
|
||||
As above, the target is the button's click event.
|
||||
|
||||
<code-example path="event-binding/src/app/app.component.html" region="event-binding-1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Alternatively, use the `on-` prefix, known as the canonical form:
|
||||
|
||||
<code-example path="event-binding/src/app/app.component.html" region="event-binding-2" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Element events may be the more common targets, but Angular looks first to see if the name matches an event property
|
||||
of a known directive, as it does in the following example:
|
||||
|
||||
<code-example path="event-binding/src/app/app.component.html" region="custom-directive" header="src/app/app.component.html"></code-example>
|
||||
|
||||
If the name fails to match an element event or an output property of a known directive,
|
||||
Angular reports an “unknown directive” error.
|
||||
|
||||
## *$event* and event handling statements
|
||||
|
||||
In an event binding, Angular sets up an event handler for the target event.
|
||||
|
||||
When the event is raised, the handler executes the template statement.
|
||||
The template statement typically involves a receiver, which performs an action
|
||||
in response to the event, such as storing a value from the HTML control
|
||||
into a model.
|
||||
|
||||
The binding conveys information about the event. This information can include data values such as an event object, string, or number named `$event`.
|
||||
|
||||
The target event determines the shape of the `$event` object.
|
||||
If the target event is a native DOM element event, then `$event` is a
|
||||
[DOM event object](https://developer.mozilla.org/en-US/docs/Web/Events),
|
||||
with properties such as `target` and `target.value`.
|
||||
|
||||
Consider this example:
|
||||
|
||||
<code-example path="event-binding/src/app/app.component.html" region="event-binding-3" header="src/app/app.component.html"></code-example>
|
||||
|
||||
This code sets the `<input>` `value` property by binding to the `name` property.
|
||||
To listen for changes to the value, the code binds to the `input`
|
||||
event of the `<input>` element.
|
||||
When the user makes changes, the `input` event is raised, and the binding executes
|
||||
the statement within a context that includes the DOM event object, `$event`.
|
||||
|
||||
To update the `name` property, the changed text is retrieved by following the path `$event.target.value`.
|
||||
|
||||
If the event belongs to a directive—recall that components
|
||||
are directives—`$event` has whatever shape the directive produces.
|
||||
|
||||
## Custom events with `EventEmitter`
|
||||
|
||||
Directives typically raise custom events with an Angular [EventEmitter](api/core/EventEmitter).
|
||||
The directive creates an `EventEmitter` and exposes it as a property.
|
||||
The directive calls `EventEmitter.emit(payload)` to fire an event, passing in a message payload, which can be anything.
|
||||
Parent directives listen for the event by binding to this property and accessing the payload through the `$event` object.
|
||||
|
||||
Consider an `ItemDetailComponent` that presents item information and responds to user actions.
|
||||
Although the `ItemDetailComponent` has a delete button, it doesn't know how to delete the hero. It can only raise an event reporting the user's delete request.
|
||||
|
||||
Here are the pertinent excerpts from that `ItemDetailComponent`:
|
||||
|
||||
<code-example path="event-binding/src/app/item-detail/item-detail.component.html" header="src/app/item-detail/item-detail.component.html (template)" region="line-through"></code-example>
|
||||
|
||||
<code-example path="event-binding/src/app/item-detail/item-detail.component.ts" header="src/app/item-detail/item-detail.component.ts (deleteRequest)" region="deleteRequest"></code-example>
|
||||
|
||||
The component defines a `deleteRequest` property that returns an `EventEmitter`.
|
||||
When the user clicks *delete*, the component invokes the `delete()` method,
|
||||
telling the `EventEmitter` to emit an `Item` object.
|
||||
|
||||
Now imagine a hosting parent component that binds to the `deleteRequest` event
|
||||
of the `ItemDetailComponent`.
|
||||
|
||||
<code-example path="event-binding/src/app/app.component.html" header="src/app/app.component.html (event-binding-to-component)" region="event-binding-to-component"></code-example>
|
||||
|
||||
When the `deleteRequest` event fires, Angular calls the parent component's
|
||||
`deleteItem()` method, passing the *item-to-delete* (emitted by `ItemDetail`)
|
||||
in the `$event` variable.
|
||||
|
||||
## Template statements have side effects
|
||||
|
||||
Though [template expressions](guide/interpolation#template-expressions) shouldn't have [side effects](guide/property-binding#avoid-side-effects), template
|
||||
statements usually do. The `deleteItem()` method does have
|
||||
a side effect: it deletes an item.
|
||||
|
||||
Deleting an item updates the model, and depending on your code, triggers
|
||||
other changes including queries and saving to a remote server.
|
||||
These changes propagate through the system and ultimately display in this and other views.
|
@ -40,8 +40,7 @@ The top level of the workspace contains workspace-wide configuration files, conf
|
||||
| `package-lock.json` | Provides version information for all packages installed into `node_modules` by the npm client. See [npm documentation](https://docs.npmjs.com/files/package-lock.json) for details. If you use the yarn client, this file will be [yarn.lock](https://yarnpkg.com/lang/en/docs/yarn-lock/) instead. |
|
||||
| `src/` | Source files for the root-level application project. |
|
||||
| `node_modules/` | Provides [npm packages](guide/npm-packages) to the entire workspace. Workspace-wide `node_modules` dependencies are visible to all projects. |
|
||||
| `tsconfig.json` | The `tsconfig.json` file is a ["Solution Style"](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#support-for-solution-style-tsconfigjson-files) TypeScript configuration file. Code editors and TypeScript’s language server use this file to improve development experience. Compilers do not use this file. |
|
||||
| `tsconfig.base.json` | The base [TypeScript](https://www.typescriptlang.org/) configuration for projects in the workspace. All other configuration files inherit from this base file. For more information, see the [Configuration inheritance with extends](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#configuration-inheritance-with-extends) section of the TypeScript documentation.|
|
||||
| `tsconfig.json` | Default [TypeScript](https://www.typescriptlang.org/) configuration for projects in the workspace. |
|
||||
| `tslint.json` | Default [TSLint](https://palantir.github.io/tslint/) configuration for projects in the workspace. |
|
||||
|
||||
|
||||
@ -55,7 +54,7 @@ This initial root-level application is the *default app* for CLI commands (unles
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Besides using the CLI on the command line, you can also manipulate files directly in the app's source folder and configuration files.
|
||||
Besides using the CLI on the command line, you can also use an interactive development environment like [Angular Console](https://angularconsole.com/), or manipulate files directly in the app's source folder and configuration files.
|
||||
|
||||
</div>
|
||||
|
||||
@ -78,12 +77,6 @@ Files at the top level of `src/` support testing and running your application. S
|
||||
| `styles.sass` | Lists CSS files that supply styles for a project. The extension reflects the style preprocessor you have configured for the project. |
|
||||
| `test.ts` | The main entry point for your unit tests, with some Angular-specific configuration. You don't typically need to edit this file. |
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
If you create an application using Angular's strict mode, you will also have an additional `package.json` file in the `src/app` directory. For more information, see [Strict mode](/guide/strict-mode).
|
||||
|
||||
</div>
|
||||
|
||||
{@a app-src}
|
||||
|
||||
Inside the `src/` folder, the `app/` folder contains your project's logic and data.
|
||||
@ -96,18 +89,17 @@ Angular components, templates, and styles go here.
|
||||
| `app/app.component.css` | Defines the base CSS stylesheet for the root `AppComponent`. |
|
||||
| `app/app.component.spec.ts` | Defines a unit test for the root `AppComponent`. |
|
||||
| `app/app.module.ts` | Defines the root module, named `AppModule`, that tells Angular how to assemble the application. Initially declares only the `AppComponent`. As you add more components to the app, they must be declared here. |
|
||||
| `app/package.json` | This file is generated only in applications created using `--strict` mode. This file is not used by package managers. It is used to tell the tools and bundlers whether the code under this directory is free of non-local [side-effects](guide/strict-mode#side-effect). |
|
||||
|
||||
### Application configuration files
|
||||
|
||||
The application-specific configuration files for the root application reside at the workspace root level.
|
||||
For a multi-project workspace, project-specific configuration files are in the project root, under `projects/project-name/`.
|
||||
|
||||
Project-specific [TypeScript](https://www.typescriptlang.org/) configuration files inherit from the workspace-wide `tsconfig.base.json`, and project-specific [TSLint](https://palantir.github.io/tslint/) configuration files inherit from the workspace-wide `tslint.json`.
|
||||
Project-specific [TypeScript](https://www.typescriptlang.org/) configuration files inherit from the workspace-wide `tsconfig.json`, and project-specific [TSLint](https://palantir.github.io/tslint/) configuration files inherit from the workspace-wide `tslint.json`.
|
||||
|
||||
| APPLICATION-SPECIFIC CONFIG FILES | PURPOSE |
|
||||
| :--------------------- | :------------------------------------------|
|
||||
| `.browserslistrc` | Configures sharing of target browsers and Node.js versions among various front-end tools. See [Browserslist on GitHub](https://github.com/browserslist/browserslist) for more information. |
|
||||
| `browserslist` | Configures sharing of target browsers and Node.js versions among various front-end tools. See [Browserslist on GitHub](https://github.com/browserslist/browserslist) for more information. |
|
||||
| `karma.conf.js` | Application-specific [Karma](https://karma-runner.github.io/2.0/config/configuration-file.html) configuration. |
|
||||
| `tsconfig.app.json` | Application-specific [TypeScript](https://www.typescriptlang.org/) configuration, including TypeScript and Angular template compiler options. See [TypeScript Configuration](guide/typescript-configuration) and [Angular Compiler Options](guide/angular-compiler-options). |
|
||||
| `tsconfig.spec.json` | [TypeScript](https://www.typescriptlang.org/) configuration for the application tests. See [TypeScript Configuration](guide/typescript-configuration). |
|
||||
|
@ -4,27 +4,22 @@ Handling user input with forms is the cornerstone of many common applications. A
|
||||
|
||||
Angular provides two different approaches to handling user input through forms: reactive and template-driven. Both capture user input events from the view, validate the user input, create a form model and data model to update, and provide a way to track changes.
|
||||
|
||||
Reactive and template-driven forms process and manage form data differently. Each offers different advantages.
|
||||
|
||||
**In general:**
|
||||
|
||||
* **Reactive forms** are more robust: they're more scalable, reusable, and testable. If forms are a key part of your application, or you're already using reactive patterns for building your application, use reactive forms.
|
||||
* **Template-driven forms** are useful for adding a simple form to an app, such as an email list signup form. They're easy to add to an app, but they don't scale as well as reactive forms. If you have very basic form requirements and logic that can be managed solely in the template, use template-driven forms.
|
||||
|
||||
This guide provides information to help you decide which type of form works best for your situation. It introduces the common building blocks used by both approaches. It also summarizes the key differences between the two approaches, and demonstrates those differences in the context of setup, data flow, and testing.
|
||||
|
||||
## Prerequisites
|
||||
<div class="alert is-helpful">
|
||||
|
||||
This guide assumes that you have a basic understanding of the following.
|
||||
**Note:** For complete information about each kind of form, see [Reactive Forms](guide/reactive-forms) and [Template-driven Forms](guide/forms).
|
||||
|
||||
* [TypeScript](https://www.typescriptlang.org/docs/home.html "The TypeScript language") and HTML5 programming.
|
||||
</div>
|
||||
|
||||
* Angular app-design fundamentals, as described in [Angular Concepts](guide/architecture "Introduction to Angular concepts.").
|
||||
|
||||
* The basics of [Angular template syntax](guide/architecture-components#template-syntax "Template syntax intro").
|
||||
|
||||
## Choosing an approach
|
||||
|
||||
Reactive forms and template-driven forms process and manage form data differently. Each approach offers different advantages.
|
||||
|
||||
* **Reactive forms** provide direct, explicit access to the underlying forms object model. Compared to template-driven forms, they are more robust: they're more scalable, reusable, and testable. If forms are a key part of your application, or you're already using reactive patterns for building your application, use reactive forms.
|
||||
|
||||
* **Template-driven forms** rely on directives in the template to create and manipulate the underlying object model. They are useful for adding a simple form to an app, such as an email list signup form. They're easy to add to an app, but they don't scale as well as reactive forms. If you have very basic form requirements and logic that can be managed solely in the template, template-driven forms could be a good fit.
|
||||
|
||||
### Key differences
|
||||
## Key differences
|
||||
|
||||
The table below summarizes the key differences between reactive and template-driven forms.
|
||||
|
||||
@ -35,33 +30,17 @@ The table below summarizes the key differences between reactive and template-dri
|
||||
|
||||
||Reactive|Template-driven|
|
||||
|--- |--- |--- |
|
||||
|[Setup of form model](#setup) | Explicit, created in component class | Implicit, created by directives |
|
||||
|[Data model](#data-flow-in-forms) | Structured and immutable | Unstructured and mutable |
|
||||
|Setup (form model)|More explicit, created in component class|Less explicit, created by directives|
|
||||
|Data model|Structured|Unstructured|
|
||||
|Predictability|Synchronous|Asynchronous|
|
||||
|[Form validation](#validation) | Functions | Directives |
|
||||
|Form validation|Functions|Directives|
|
||||
|Mutability|Immutable|Mutable|
|
||||
|Scalability|Low-level API access|Abstraction on top of APIs|
|
||||
|
||||
### Scalability
|
||||
## Common foundation
|
||||
|
||||
If forms are a central part of your application, scalability is very important. Being able to reuse form models across components is critical.
|
||||
Both reactive and template-driven forms share underlying building blocks.
|
||||
|
||||
Reactive forms are more scalable than template-driven forms. They provide direct access to the underlying form API, and synchronous access to the form data model, making creating large-scale forms easier.
|
||||
Reactive forms require less setup for testing, and testing does not require deep understanding of change detection to properly test form updates and validation.
|
||||
|
||||
Template-driven forms focus on simple scenarios and are not as reusable.
|
||||
They abstract away the underlying form API, and provide only asynchronous access to the form data model.
|
||||
The abstraction of template-driven forms also affects testing.
|
||||
Tests are deeply reliant on manual change detection execution to run properly, and require more setup.
|
||||
|
||||
{@a setup}
|
||||
|
||||
## Setting up the form model
|
||||
|
||||
Both reactive and template-driven forms track value changes between the form input elements that users interact with and the form data in your component model.
|
||||
The two approaches share underlying building blocks, but differ in how you create and manage the common form-control instances.
|
||||
|
||||
### Common form foundation classes
|
||||
|
||||
Both reactive and template-driven forms are built on the following base classes.
|
||||
|
||||
* `FormControl` tracks the value and validation status of an individual form control.
|
||||
|
||||
@ -71,59 +50,59 @@ Both reactive and template-driven forms are built on the following base classes.
|
||||
|
||||
* `ControlValueAccessor` creates a bridge between Angular `FormControl` instances and native DOM elements.
|
||||
|
||||
See the [Form model setup](#setup-the-form-model) section below for an introduction to how these control instances are created and managed with reactive and template-driven forms. Further details are provided in the [data flow section](#data-flow-in-forms) of this guide.
|
||||
|
||||
{@a setup-the-form-model}
|
||||
|
||||
## Form model setup
|
||||
|
||||
Reactive and template-driven forms both use a form model to track value changes between Angular forms and form input elements. The examples below show how the form model is defined and created.
|
||||
|
||||
### Setup in reactive forms
|
||||
|
||||
With reactive forms, you define the form model directly in the component class.
|
||||
The `[formControl]` directive links the explicitly created `FormControl` instance to a specific form element in the view, using an internal value accessor.
|
||||
|
||||
The following component implements an input field for a single control, using reactive forms. In this example, the form model is the `FormControl` instance.
|
||||
Here's a component with an input field for a single control implemented using reactive forms.
|
||||
|
||||
<code-example path="forms-overview/src/app/reactive/favorite-color/favorite-color.component.ts">
|
||||
</code-example>
|
||||
|
||||
Figure 1 shows how, in reactive forms, the form model is the source of truth; it provides the value and status of the form element at any given point in time, through the `[formControl]` directive on the input element.
|
||||
|
||||
**Figure 1.** *Direct access to forms model in a reactive form.*
|
||||
The source of truth provides the value and status of the form element at a given point in time. In reactive forms, the form model is the source of truth. In the example above, the form model is the `FormControl` instance.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/forms-overview/key-diff-reactive-forms.png" alt="Reactive forms key differences">
|
||||
</div>
|
||||
|
||||
With reactive forms, the form model is explicitly defined in the component class. The reactive form directive (in this case, `FormControlDirective`) then links the existing `FormControl` instance to a specific form element in the view using a value accessor (`ControlValueAccessor` instance).
|
||||
|
||||
### Setup in template-driven forms
|
||||
|
||||
In template-driven forms, the form model is implicit, rather than explicit. The directive `NgModel` creates and manages a `FormControl` instance for a given form element.
|
||||
|
||||
The following component implements the same input field for a single control, using template-driven forms.
|
||||
Here's the same component with an input field for a single control implemented using template-driven forms.
|
||||
|
||||
<code-example path="forms-overview/src/app/template/favorite-color/favorite-color.component.ts">
|
||||
</code-example>
|
||||
|
||||
In a template-driven form the source of truth is the template. You do not have direct programmatic access to the `FormControl` instance, as shown in Figure 2.
|
||||
|
||||
**Figure 2.** *Indirect access to forms model in a template-driven form.*
|
||||
In template-driven forms, the source of truth is the template.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/forms-overview/key-diff-td-forms.png" alt="Template-driven forms key differences">
|
||||
</div>
|
||||
|
||||
The abstraction of the form model promotes simplicity over structure. The template-driven form directive `NgModel` is responsible for creating and managing the `FormControl` instance for a given form element. It's less explicit, but you no longer have direct control over the form model.
|
||||
|
||||
{@a data-flow-in-forms}
|
||||
|
||||
## Data flow in forms
|
||||
|
||||
When an application contains a form, Angular must keep the view in sync with the component model and the component model in sync with the view.
|
||||
As users change values and make selections through the view, the new values must be reflected in the data model.
|
||||
Similarly, when the program logic changes values in the data model, those values must be reflected in the view.
|
||||
|
||||
Reactive and template-driven forms differ in how they handle data flowing from the user or from programmatic changes.
|
||||
The following diagrams illustrate both kinds of data flow for each type of form, using the favorite-color input field defined above.
|
||||
When building forms in Angular, it's important to understand how the framework handles data flowing from the user or from programmatic changes. Reactive and template-driven forms follow two different strategies when handling form input. The data flow examples below begin with the favorite color input field example from above, and then show how changes to favorite color are handled in reactive forms compared to template-driven forms.
|
||||
|
||||
### Data flow in reactive forms
|
||||
|
||||
In reactive forms each form element in the view is directly linked to the form model (a `FormControl` instance). Updates from the view to the model and from the model to the view are synchronous and do not depend on how the UI is rendered.
|
||||
As described above, in reactive forms each form element in the view is directly linked to a form model (`FormControl` instance). Updates from the view to the model and from the model to the view are synchronous and aren't dependent on the UI rendered. The diagrams below use the same favorite color example to demonstrate how data flows when an input field's value is changed from the view and then from the model.
|
||||
|
||||
The view-to-model diagram shows how data flows when an input field's value is changed from the view through the following steps.
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/forms-overview/dataflow-reactive-forms-vtm.png" alt="Reactive forms data flow - view to model" width="100%">
|
||||
</div>
|
||||
|
||||
The steps below outline the data flow from view to model.
|
||||
|
||||
1. The user types a value into the input element, in this case the favorite color *Blue*.
|
||||
1. The form input element emits an "input" event with the latest value.
|
||||
@ -132,25 +111,25 @@ The view-to-model diagram shows how data flows when an input field's value is ch
|
||||
1. Any subscribers to the `valueChanges` observable receive the new value.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/forms-overview/dataflow-reactive-forms-vtm.png" alt="Reactive forms data flow - view to model">
|
||||
<img src="generated/images/guide/forms-overview/dataflow-reactive-forms-mtv.png" alt="Reactive forms data flow - model to view" width="100%">
|
||||
</div>
|
||||
|
||||
The model-to-view diagram shows how a programmatic change to the model is propagated to the view through the following steps.
|
||||
The steps below outline the data flow from model to view.
|
||||
|
||||
1. The user calls the `favoriteColorControl.setValue()` method, which updates the `FormControl` value.
|
||||
1. The `FormControl` instance emits the new value through the `valueChanges` observable.
|
||||
1. Any subscribers to the `valueChanges` observable receive the new value.
|
||||
1. The control value accessor on the form input element updates the element with the new value.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/forms-overview/dataflow-reactive-forms-mtv.png" alt="Reactive forms data flow - model to view">
|
||||
</div>
|
||||
|
||||
### Data flow in template-driven forms
|
||||
|
||||
In template-driven forms, each form element is linked to a directive that manages the form model internally.
|
||||
In template-driven forms, each form element is linked to a directive that manages the form model internally. The diagrams below use the same favorite color example to demonstrate how data flows when an input field's value is changed from the view and then from the model.
|
||||
|
||||
The view-to-model diagram shows how data flows when an input field's value is changed from the view through the following steps.
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/forms-overview/dataflow-td-forms-vtm.png" alt="Template-driven forms data flow - view to model" width="100%">
|
||||
</div>
|
||||
|
||||
The steps below outline the data flow from view to model when the input value changes from *Red* to *Blue*.
|
||||
|
||||
1. The user types *Blue* into the input element.
|
||||
1. The input element emits an "input" event with the value *Blue*.
|
||||
@ -162,10 +141,10 @@ The view-to-model diagram shows how data flows when an input field's value is ch
|
||||
is updated to the value emitted by the `ngModelChange` event (*Blue*).
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/forms-overview/dataflow-td-forms-vtm.png" alt="Template-driven forms data flow - view to model" width="100%">
|
||||
<img src="generated/images/guide/forms-overview/dataflow-td-forms-mtv.png" alt="Template-driven forms data flow - model to view" width="100%">
|
||||
</div>
|
||||
|
||||
The model-to-view diagram shows how data flows from model to view when the `favoriteColor` changes from *Blue* to *Red*, through the following steps
|
||||
The steps below outline the data flow from model to view when the `favoriteColor` changes from *Blue* to *Red*.
|
||||
|
||||
1. The `favoriteColor` value is updated in the component.
|
||||
1. Change detection begins.
|
||||
@ -177,30 +156,6 @@ The model-to-view diagram shows how data flows from model to view when the `favo
|
||||
1. Any subscribers to the `valueChanges` observable receive the new value.
|
||||
1. The control value accessor updates the form input element in the view with the latest `favoriteColor` value.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/forms-overview/dataflow-td-forms-mtv.png" alt="Template-driven forms data flow - model to view" width="100%">
|
||||
</div>
|
||||
|
||||
### Mutability of the data model
|
||||
|
||||
The change-tracking method plays a role in the efficiency of your application.
|
||||
|
||||
* **Reactive forms** keep the data model pure by providing it as an immutable data structure.
|
||||
Each time a change is triggered on the data model, the `FormControl` instance returns a new data model rather than updating the existing data model.
|
||||
This gives you the ability to track unique changes to the data model through the control's observable.
|
||||
Change detection is more efficient because it only needs to update on unique changes.
|
||||
Because data updates follow reactive patterns, you can integrate with observable operators to transform data.
|
||||
|
||||
* **Template-driven** forms rely on mutability with two-way data binding to update the data model in the component as changes are made in the template.
|
||||
Because there are no unique changes to track on the data model when using two-way data binding, change detection is less efficient at determining when updates are required.
|
||||
|
||||
The difference is demonstrated in the previous examples that use the favorite-color input element.
|
||||
|
||||
* With reactive forms, the **`FormControl` instance** always returns a new value when the control's value is updated.
|
||||
|
||||
* With template-driven forms, the **favorite color property** is always modified to its new value.
|
||||
|
||||
{@a validation}
|
||||
## Form validation
|
||||
|
||||
Validation is an integral part of managing any set of forms. Whether you're checking for required fields or querying an external API for an existing username, Angular provides a set of built-in validators as well as the ability to create custom validators.
|
||||
@ -212,37 +167,36 @@ For more information, see [Form Validation](guide/form-validation).
|
||||
|
||||
## Testing
|
||||
|
||||
Testing plays a large part in complex applications. A simpler testing strategy is useful when validating that your forms function correctly.
|
||||
Reactive forms and template-driven forms have different levels of reliance on rendering the UI to perform assertions based on form control and form field changes.
|
||||
The following examples demonstrate the process of testing forms with reactive and template-driven forms.
|
||||
Testing plays a large part in complex applications and a simpler testing strategy is useful when validating that your forms function correctly. Reactive forms and template-driven forms have different levels of reliance on rendering the UI to perform assertions based on form control and form field changes. The following examples demonstrate the process of testing forms with reactive and template-driven forms.
|
||||
|
||||
### Testing reactive forms
|
||||
|
||||
Reactive forms provide a relatively easy testing strategy because they provide synchronous access to the form and data models, and they can be tested without rendering the UI.
|
||||
In these tests, status and data are queried and manipulated through the control without interacting with the change detection cycle.
|
||||
Reactive forms provide a relatively easy testing strategy because they provide synchronous access to the form and data models, and they can be tested without rendering the UI. In these tests, status and data are queried and manipulated through the control without interacting with the change detection cycle.
|
||||
|
||||
The following tests use the favorite-color components from previous examples to verify the view-to-model and model-to-view data flows for a reactive form.
|
||||
The following tests use the favorite color components mentioned earlier to verify the data flows from view to model and model to view for a reactive form.
|
||||
|
||||
**Verifying view-to-model data flow**
|
||||
The following test verifies the data flow from view to model.
|
||||
|
||||
The first example performs the following steps to verify the view-to-model data flow.
|
||||
<code-example path="forms-overview/src/app/reactive/favorite-color/favorite-color.component.spec.ts" region="view-to-model" header="Favorite color test - view to model">
|
||||
</code-example>
|
||||
|
||||
Here are the steps performed in the view to model test.
|
||||
|
||||
1. Query the view for the form input element, and create a custom "input" event for the test.
|
||||
1. Set the new value for the input to *Red*, and dispatch the "input" event on the form input element.
|
||||
1. Assert that the component's `favoriteColorControl` value matches the value from the input.
|
||||
|
||||
<code-example path="forms-overview/src/app/reactive/favorite-color/favorite-color.component.spec.ts" region="view-to-model" header="Favorite color test - view to model">
|
||||
The following test verifies the data flow from model to view.
|
||||
|
||||
<code-example path="forms-overview/src/app/reactive/favorite-color/favorite-color.component.spec.ts" region="model-to-view" header="Favorite color test - model to view">
|
||||
</code-example>
|
||||
|
||||
The next example performs the following steps to verify the model-to-view data flow.
|
||||
Here are the steps performed in the model to view test.
|
||||
|
||||
1. Use the `favoriteColorControl`, a `FormControl` instance, to set the new value.
|
||||
1. Query the view for the form input element.
|
||||
1. Assert that the new value set on the control matches the value in the input.
|
||||
|
||||
<code-example path="forms-overview/src/app/reactive/favorite-color/favorite-color.component.spec.ts" region="model-to-view" header="Favorite color test - model to view">
|
||||
</code-example>
|
||||
|
||||
### Testing template-driven forms
|
||||
|
||||
Writing tests with template-driven forms requires a detailed knowledge of the change detection process and an understanding of how directives run on each cycle to ensure that elements are queried, tested, or changed at the correct time.
|
||||
@ -274,17 +228,46 @@ Here are the steps performed in the model to view test.
|
||||
1. Query the view for the form input element.
|
||||
1. Assert that the input value matches the value of the `favoriteColor` property in the component instance.
|
||||
|
||||
## Mutability
|
||||
|
||||
The change tracking method plays a role in the efficiency of your application.
|
||||
|
||||
|
||||
* **Reactive forms** keep the data model pure by providing it as an immutable data structure. Each time a change is triggered on the data model, the `FormControl` instance returns a new data model rather than updating the existing data model. This gives you the ability to track unique changes to the data model through the control's observable. This provides one way for change detection to be more efficient because it only needs to update on unique changes. It also follows reactive patterns that integrate with observable operators to transform data.
|
||||
|
||||
* **Template-driven** forms rely on mutability with two-way data binding to update the data model in the component as changes are made in the template. Because there are no unique changes to track on the data model when using two-way data binding, change detection is less efficient at determining when updates are required.
|
||||
|
||||
The difference is demonstrated in the examples above using the **favorite color** input element.
|
||||
|
||||
|
||||
* With reactive forms, the **`FormControl` instance** always returns a new value when the control's value is updated.
|
||||
|
||||
* With template-driven forms, the **favorite color property** is always modified to its new value.
|
||||
|
||||
## Scalability
|
||||
|
||||
If forms are a central part of your application, scalability is very important. Being able to reuse form models across components is critical.
|
||||
|
||||
|
||||
* **Reactive forms** provide access to low-level APIs and synchronous access to the form model, making creating large-scale forms easier.
|
||||
|
||||
* **Template-driven** forms focus on simple scenarios, are not as reusable, abstract away the low-level APIs, and provide asynchronous access to the form model. The abstraction with template-driven forms also surfaces in testing, where testing reactive forms requires less setup and no dependence on the change detection cycle when updating and validating the form and data models during testing.
|
||||
|
||||
## Final thoughts
|
||||
|
||||
Choosing a strategy begins with understanding the strengths and weaknesses of the options presented. Low-level API and form model access, predictability, mutability, straightforward validation and testing strategies, and scalability are all important considerations in choosing the infrastructure you use to build your forms in Angular. Template-driven forms are similar to patterns in AngularJS, but they have limitations given the criteria of many modern, large-scale Angular apps. Reactive forms minimize these limitations. Reactive forms integrate with reactive patterns already present in other areas of the Angular architecture, and complement those requirements well.
|
||||
|
||||
## Next steps
|
||||
|
||||
|
||||
|
||||
To learn more about reactive forms, see the following guides:
|
||||
|
||||
* [Reactive forms](guide/reactive-forms)
|
||||
* [Form validation](guide/form-validation#reactive-form-validation)
|
||||
* [Dynamic forms](guide/dynamic-form)
|
||||
* [Reactive Forms](guide/reactive-forms)
|
||||
* [Form Validation](guide/form-validation#reactive-form-validation)
|
||||
* [Dynamic Forms](guide/dynamic-form)
|
||||
|
||||
To learn more about template-driven forms, see the following guides:
|
||||
|
||||
* [Building a template-driven form](guide/forms) tutorial
|
||||
* [Form validation](guide/form-validation#template-driven-validation)
|
||||
* `NgForm` directive API reference
|
||||
* [Template-driven Forms](guide/forms#template-driven-forms)
|
||||
* [Form Validation](guide/form-validation#template-driven-validation)
|
||||
|
@ -1,234 +1,389 @@
|
||||
# Building a template-driven form
|
||||
# Template-driven forms
|
||||
|
||||
{@a template-driven}
|
||||
Forms are the mainstay of business applications.
|
||||
You use forms to log in, submit a help request, place an order, book a flight,
|
||||
schedule a meeting, and perform countless other data-entry tasks.
|
||||
|
||||
This tutorial shows you how to create a template-driven form whose control elements are bound to data properties, with input validation to maintain data integrity and styling to improve the user experience.
|
||||
|
||||
Template-driven forms use [two-way data binding](guide/architecture-components#data-binding "Intro to 2-way data binding") to update the data model in the component as changes are made in the template and vice versa.
|
||||
In developing a form, it's important to create a data-entry experience that guides the
|
||||
user efficiently and effectively through the workflow.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Angular supports two design approaches for interactive forms. You can build forms by writing templates using Angular [template syntax and directives](guide/glossary#template "Definition of template terms") with the form-specific directives and techniques described in this tutorial, or you can use a reactive (or model-driven) approach to build forms.
|
||||
|
||||
Template-driven forms are suitable for small or simple forms, while reactive forms are more scalable and suitable for complex forms.
|
||||
For a comparison of the two approaches, see [Introduction to Forms](guide/forms-overview "Overview of Angular forms.")
|
||||
For the sample app that this page describes, see the <live-example></live-example>.
|
||||
|
||||
</div>
|
||||
|
||||
You can build almost any kind of form with an Angular template—login forms, contact forms, and pretty much any business form.
|
||||
You can lay out the controls creatively and bind them to the data in your object model.
|
||||
You can specify validation rules and display validation errors,
|
||||
conditionally enable or disable specific controls, trigger built-in visual feedback, and much more.
|
||||
## Introduction to Template-driven forms
|
||||
|
||||
This tutorial shows you how to build a form from scratch, using a simplified sample form like the one from the [Tour of Heroes tutorial](tutorial "Tour of Heroes") to illustrate the techniques.
|
||||
Developing forms requires design skills (which are out of scope for this page), as well as framework support for
|
||||
*two-way data binding, change tracking, validation, and error handling*,
|
||||
which you'll learn about on this page.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Run or download the example app: <live-example></live-example>.
|
||||
|
||||
</div>
|
||||
|
||||
## Objectives
|
||||
|
||||
This tutorial teaches you how to do the following:
|
||||
This page shows you how to build a simple form from scratch. Along the way you'll learn how to:
|
||||
|
||||
* Build an Angular form with a component and template.
|
||||
* Use `ngModel` to create two-way data bindings for reading and writing input-control values.
|
||||
* Track state changes and the validity of form controls.
|
||||
* Provide visual feedback using special CSS classes that track the state of the controls.
|
||||
* Display validation errors to users and enable or disable form controls based on the form status.
|
||||
* Share information across HTML elements using [template reference variables](guide/template-reference-variables).
|
||||
* Display validation errors to users and enable/disable form controls.
|
||||
* Share information across HTML elements using template reference variables.
|
||||
|
||||
## Prerequisites
|
||||
{@a template-driven}
|
||||
|
||||
Before going further into template-driven forms, you should have a basic understanding of the following.
|
||||
You can build forms by writing templates in the Angular [template syntax](guide/template-syntax) with
|
||||
the form-specific directives and techniques described in this page.
|
||||
|
||||
* TypeScript and HTML5 programming.
|
||||
* Angular app-design fundamentals, as described in [Angular Concepts](guide/architecture "Introduction to Angular concepts.").
|
||||
* The basics of [Angular template syntax](guide/template-syntax "Template syntax guide").
|
||||
* The form-design concepts that are presented in [Introduction to Forms](guide/forms-overview "Overview of Angular forms.").
|
||||
<div class="alert is-helpful">
|
||||
|
||||
{@a intro}
|
||||
You can also use a reactive (or model-driven) approach to build forms.
|
||||
However, this page focuses on template-driven forms.
|
||||
|
||||
## Build a template-driven form
|
||||
</div>
|
||||
|
||||
Template-driven forms rely on directives defined in the `FormsModule`.
|
||||
You can build almost any form with an Angular template—login forms, contact forms, and pretty much any business form.
|
||||
You can lay out the controls creatively, bind them to data, specify validation rules and display validation errors,
|
||||
conditionally enable or disable specific controls, trigger built-in visual feedback, and much more.
|
||||
|
||||
* The `NgModel` directive reconciles value changes in the attached form element with changes in the data model, allowing you to respond to user input with input validation and error handling.
|
||||
Angular makes the process easy by handling many of the repetitive, boilerplate tasks you'd
|
||||
otherwise wrestle with yourself.
|
||||
|
||||
* The `NgForm` directive creates a top-level `FormGroup` instance and binds it to a `<form>` element to track aggregated form value and validation status.
|
||||
As soon as you import `FormsModule`, this directive becomes active by default on all `<form>` tags. You don't need to add a special selector.
|
||||
|
||||
* The `NgModelGroup` directive creates and binds a `FormGroup` instance to a DOM element.
|
||||
|
||||
### The sample application
|
||||
|
||||
The sample form in this guide is used by the *Hero Employment Agency* to maintain personal information about heroes.
|
||||
Every hero needs a job. This form helps the agency match the right hero with the right crisis.
|
||||
You'll learn to build a template-driven form that looks like this:
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/forms/hero-form-1.png" alt="Clean Form">
|
||||
</div>
|
||||
|
||||
The form highlights some design features that make it easier to use. For instance, the two required fields have a green bar on the left to make them easy to spot. These fields have initial values, so the form is valid and the **Submit** button is enabled.
|
||||
The *Hero Employment Agency* uses this form to maintain personal information about heroes.
|
||||
Every hero needs a job. It's the company mission to match the right hero with the right crisis.
|
||||
|
||||
As you work with this form, you will learn how to include validation logic, how to customize the presentation with standard CSS, and how to handle error conditions to ensure valid input.
|
||||
If the user deletes the hero name, for example, the form becomes invalid. The app detects the changed status, and displays a validation error in an attention-grabbing style.
|
||||
In addition, the **Submit** button is disabled, and the "required" bar to the left of the input control changes from green to red.
|
||||
Two of the three fields on this form are required. Required fields have a green bar on the left to make them easy to spot.
|
||||
|
||||
If you delete the hero name, the form displays a validation error in an attention-grabbing style:
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/forms/hero-form-2.png" alt="Invalid, Name Required">
|
||||
</div>
|
||||
|
||||
### Step overview
|
||||
Note that the *Submit* button is disabled, and the "required" bar to the left of the input control changes from green to red.
|
||||
|
||||
In the course of this tutorial, you bind a sample form to data and handle user input using the following steps.
|
||||
<div class="alert is-helpful">
|
||||
|
||||
1. Build the basic form.
|
||||
* Define a sample data model.
|
||||
* Include required infrastructure such as the `FormsModule`.
|
||||
2. Bind form controls to data properties using the `ngModel` directive and two-way data-binding syntax.
|
||||
* Examine how `ngModel` reports control states using CSS classes.
|
||||
* Name controls to make them accessible to `ngModel`.
|
||||
3. Track input validity and control status using `ngModel`.
|
||||
* Add custom CSS to provide visual feedback on the status.
|
||||
* Show and hide validation-error messages.
|
||||
4. Respond to a native HTML button-click event by adding to the model data.
|
||||
5. Handle form submission using the [`ngSubmit`](api/forms/NgForm#properties) output property of the form.
|
||||
* Disable the **Submit** button until the form is valid.
|
||||
* After submit, swap out the finished form for different content on the page.
|
||||
You can customize the colors and location of the "required" bar with standard CSS.
|
||||
|
||||
{@a step1}
|
||||
</div>
|
||||
|
||||
## Build the form
|
||||
You'll build this form in small steps:
|
||||
|
||||
You can recreate the sample application from the code provided here, or you can examine or download the <live-example></live-example>.
|
||||
1. Create the `Hero` model class.
|
||||
1. Create the component that controls the form.
|
||||
1. Create a template with the initial form layout.
|
||||
1. Bind data properties to each form control using the `ngModel` two-way data-binding syntax.
|
||||
1. Add a `name` attribute to each form-input control.
|
||||
1. Add custom CSS to provide visual feedback.
|
||||
1. Show and hide validation-error messages.
|
||||
1. Handle form submission with *ngSubmit*.
|
||||
1. Disable the form’s *Submit* button until the form is valid.
|
||||
|
||||
1. The provided sample application creates the `Hero` class which defines the data model reflected in the form.
|
||||
## Setup
|
||||
|
||||
Create a new project named <code>angular-forms</code>:
|
||||
|
||||
<code-example language="sh" class="code-shell">
|
||||
|
||||
ng new angular-forms
|
||||
|
||||
</code-example>
|
||||
|
||||
## Create the Hero model class
|
||||
|
||||
As users enter form data, you'll capture their changes and update an instance of a model.
|
||||
You can't lay out the form until you know what the model looks like.
|
||||
|
||||
A model can be as simple as a "property bag" that holds facts about a thing of application importance.
|
||||
That describes well the `Hero` class with its three required fields (`id`, `name`, `power`)
|
||||
and one optional field (`alterEgo`).
|
||||
|
||||
Using the Angular CLI command [`ng generate class`](cli/generate), generate a new class named `Hero`:
|
||||
|
||||
<code-example language="sh" class="code-shell">
|
||||
|
||||
ng generate class Hero
|
||||
|
||||
</code-example>
|
||||
|
||||
With this content:
|
||||
|
||||
<code-example path="forms/src/app/hero.ts" header="src/app/hero.ts"></code-example>
|
||||
|
||||
2. The form layout and details are defined in the `HeroFormComponent` class.
|
||||
It's an anemic model with few requirements and no behavior. Perfect for the demo.
|
||||
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.ts" header="src/app/hero-form/hero-form.component.ts (v1)" region="v1"></code-example>
|
||||
The TypeScript compiler generates a public field for each `public` constructor parameter and
|
||||
automatically assigns the parameter’s value to that field when you create heroes.
|
||||
|
||||
The component's `selector` value of "app-hero-form" means you can drop this form in a parent
|
||||
template using the `<app-hero-form>` tag.
|
||||
The `alterEgo` is optional, so the constructor lets you omit it; note the question mark (?) in `alterEgo?`.
|
||||
|
||||
3. The following code creates a new hero instance, so that the initial form can show an example hero.
|
||||
You can create a new hero like this:
|
||||
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.ts" region="SkyDog"></code-example>
|
||||
|
||||
This demo uses dummy data for `model` and `powers`. In a real app, you would inject a data service to get and save real data, or expose these properties as inputs and outputs.
|
||||
## Create a form component
|
||||
|
||||
4. The application enables the Forms feature and registers the created form component.
|
||||
An Angular form has two parts: an HTML-based _template_ and a component _class_
|
||||
to handle data and user interactions programmatically.
|
||||
Begin with the class because it states, in brief, what the hero editor can do.
|
||||
|
||||
Using the Angular CLI command [`ng generate component`](cli/generate), generate a new component named `HeroForm`:
|
||||
|
||||
<code-example language="sh" class="code-shell">
|
||||
|
||||
ng generate component HeroForm
|
||||
|
||||
</code-example>
|
||||
|
||||
With this content:
|
||||
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.ts" header="src/app/hero-form/hero-form.component.ts (v1)" region="v1"></code-example>
|
||||
|
||||
There’s nothing special about this component, nothing form-specific,
|
||||
nothing to distinguish it from any component you've written before.
|
||||
|
||||
Understanding this component requires only the Angular concepts covered in previous pages.
|
||||
|
||||
* The code imports the Angular core library and the `Hero` model you just created.
|
||||
* The `@Component` selector value of "app-hero-form" means you can drop this form in a parent
|
||||
template with a `<app-hero-form>` tag.
|
||||
* The `templateUrl` property points to a separate file for the template HTML.
|
||||
* You defined dummy data for `model` and `powers`, as befits a demo.
|
||||
|
||||
Down the road, you can inject a data service to get and save real data
|
||||
or perhaps expose these properties as inputs and outputs
|
||||
(see [Input and output properties](guide/template-syntax#inputs-outputs) on the
|
||||
[Template Syntax](guide/template-syntax) page) for binding to a
|
||||
parent component. This is not a concern now and these future changes won't affect the form.
|
||||
|
||||
* You added a `diagnostic` property to return a JSON representation of the model.
|
||||
It'll help you see what you're doing during development; you've left yourself a cleanup note to discard it later.
|
||||
|
||||
## Revise *app.module.ts*
|
||||
|
||||
`app.module.ts` defines the application's root module. In it you identify the external modules you'll use in the application
|
||||
and declare the components that belong to this module, such as the `HeroFormComponent`.
|
||||
|
||||
Because template-driven forms are in their own module, you need to add the `FormsModule` to the array of
|
||||
`imports` for the application module before you can use forms.
|
||||
|
||||
Update it with the following:
|
||||
|
||||
<code-example path="forms/src/app/app.module.ts" header="src/app/app.module.ts"></code-example>
|
||||
|
||||
5. The form is displayed in the application layout defined by the root component's template.
|
||||
<div class="alert is-helpful">
|
||||
|
||||
There are two changes:
|
||||
|
||||
1. You import `FormsModule`.
|
||||
|
||||
1. You add the `FormsModule` to the list of `imports` defined in the `@NgModule` decorator. This gives the application
|
||||
access to all of the template-driven forms features, including `ngModel`.
|
||||
|
||||
</div>
|
||||
|
||||
<div class="alert is-important">
|
||||
|
||||
If a component, directive, or pipe belongs to a module in the `imports` array, _don't_ re-declare it in the `declarations` array.
|
||||
If you wrote it and it should belong to this module, _do_ declare it in the `declarations` array.
|
||||
|
||||
</div>
|
||||
|
||||
## Revise *app.component.html*
|
||||
|
||||
`AppComponent` is the application's root component. It will host the new `HeroFormComponent`.
|
||||
|
||||
Replace the contents of its template with the following:
|
||||
|
||||
<code-example path="forms/src/app/app.component.html" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The initial template defines the layout for a form with two form groups and a submit button.
|
||||
The form groups correspond to two properties of the Hero data model, name and alterEgo. Each group has a label and a box for user input.
|
||||
<div class="alert is-helpful">
|
||||
|
||||
* The **Name** `<input>` control element has the HTML5 `required` attribute.
|
||||
* The **Alter Ego** `<input>` control element does not because `alterEgo` is optional.
|
||||
There are only two changes.
|
||||
The `template` is simply the new element tag identified by the component's `selector` property.
|
||||
This displays the hero form when the application component is loaded.
|
||||
Don't forget to remove the `name` field from the class body as well.
|
||||
|
||||
The **Submit** button has some classes on it for styling.
|
||||
At this point, the form layout is all plain HTML5, with no bindings or directives.
|
||||
</div>
|
||||
|
||||
6. The sample form uses some style classes from [Twitter Bootstrap](http://getbootstrap.com/css/): `container`, `form-group`, `form-control`, and `btn`.
|
||||
To use these styles, the app's style sheet imports the library.
|
||||
## Create an initial HTML form template
|
||||
|
||||
Update the template file with the following contents:
|
||||
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.html" region="start" header="src/app/hero-form/hero-form.component.html"></code-example>
|
||||
|
||||
The language is simply HTML5. You're presenting two of the `Hero` fields, `name` and `alterEgo`, and
|
||||
opening them up for user input in input boxes.
|
||||
|
||||
The *Name* `<input>` control has the HTML5 `required` attribute;
|
||||
the *Alter Ego* `<input>` control does not because `alterEgo` is optional.
|
||||
|
||||
You added a *Submit* button at the bottom with some classes on it for styling.
|
||||
|
||||
*You're not using Angular yet*. There are no bindings or extra directives, just layout.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
In template driven forms, if you've imported `FormsModule`, you don't have to do anything
|
||||
to the `<form>` tag in order to make use of `FormsModule`. Continue on to see how this works.
|
||||
|
||||
</div>
|
||||
|
||||
The `container`, `form-group`, `form-control`, and `btn` classes
|
||||
come from [Twitter Bootstrap](http://getbootstrap.com/css/). These classes are purely cosmetic.
|
||||
Bootstrap gives the form a little style.
|
||||
|
||||
<div class="callout is-important">
|
||||
|
||||
<header>
|
||||
Angular forms don't require a style library
|
||||
</header>
|
||||
|
||||
Angular makes no use of the `container`, `form-group`, `form-control`, and `btn` classes or
|
||||
the styles of any external library. Angular apps can use any CSS library or none at all.
|
||||
|
||||
</div>
|
||||
|
||||
To add the stylesheet, open `styles.css` and add the following import line at the top:
|
||||
|
||||
<code-example path="forms/src/styles.1.css" header="src/styles.css"></code-example>
|
||||
|
||||
7. The form makes the hero applicant choose one superpower from a fixed list of agency-approved powers.
|
||||
The predefined list of `powers` is part of the data model, maintained internally in `HeroFormComponent`.
|
||||
The Angular [NgForOf directive](api/common/NgForOf "API reference") iterates over the data values to populate the `<select>` element.
|
||||
## Add powers with _*ngFor_
|
||||
|
||||
The hero must choose one superpower from a fixed list of agency-approved powers.
|
||||
You maintain that list internally (in `HeroFormComponent`).
|
||||
|
||||
You'll add a `select` to the
|
||||
form and bind the options to the `powers` list using `ngFor`,
|
||||
a technique seen previously in the [Displaying Data](guide/displaying-data) page.
|
||||
|
||||
Add the following HTML *immediately below* the *Alter Ego* group:
|
||||
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (powers)" region="powers"></code-example>
|
||||
|
||||
If you run the app right now, you see the list of powers in the selection control. The input elements are not yet bound to data values or events, so they are still blank and have no behavior.
|
||||
This code repeats the `<option>` tag for each power in the list of powers.
|
||||
The `pow` template input variable is a different power in each iteration;
|
||||
you display its name using the interpolation syntax.
|
||||
|
||||
{@a ngModel}
|
||||
|
||||
## Two-way data binding with _ngModel_
|
||||
|
||||
Running the app right now would be disappointing.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/forms/hero-form-3.png" alt="Early form with no binding">
|
||||
</div>
|
||||
|
||||
{@a ngModel}
|
||||
|
||||
## Bind input controls to data properties
|
||||
You don't see hero data because you're not binding to the `Hero` yet.
|
||||
You know how to do that from earlier pages.
|
||||
[Displaying Data](guide/displaying-data) teaches property binding.
|
||||
[User Input](guide/user-input) shows how to listen for DOM events with an
|
||||
event binding and how to update a component property with the displayed value.
|
||||
|
||||
The next step is to bind the input controls to the corresponding `Hero` properties with two-way data binding, so that they respond to user input by updating the data model, and also respond to programmatic changes in the data by updating the display.
|
||||
Now you need to display, listen, and extract at the same time.
|
||||
|
||||
The `ngModel` directive declared in the `FormsModule` lets you bind controls in your template-driven form to properties in your data model.
|
||||
When you include the directive using the syntax for two-way data binding, `[(ngModel)]`, Angular can track the value and user interaction of the control and keep the view synced with the model.
|
||||
You could use the techniques you already know, but
|
||||
instead you'll use the new `[(ngModel)]` syntax, which
|
||||
makes binding the form to the model easy.
|
||||
|
||||
1. Edit the template file `hero-form.component.html`.
|
||||
|
||||
2. Find the `<input>` tag next to the **Name** label.
|
||||
|
||||
3. Add the `ngModel` directive, using two-way data binding syntax `[(ngModel)]="..."`.
|
||||
Find the `<input>` tag for *Name* and update it like this:
|
||||
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (excerpt)" region="ngModelName-1"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
This example has a temporary diagnostic interpolation after each input tag, `{{model.name}}`, to show the current data value of the corresponding property.
|
||||
The note reminds you to remove the diagnostic lines when you have finished observing the two-way data binding at work.
|
||||
You added a diagnostic interpolation after the input tag
|
||||
so you can see what you're doing.
|
||||
You left yourself a note to throw it away when you're done.
|
||||
|
||||
</div>
|
||||
|
||||
{@a ngForm}
|
||||
Focus on the binding syntax: `[(ngModel)]="..."`.
|
||||
|
||||
### Access the overall form status
|
||||
|
||||
When you imported the `FormsModule` in your component, Angular automatically created and attached an [NgForm](api/forms/NgForm "API reference for NgForm") directive to the `<form>` tag in the template (because `NgForm` has the selector `form` that matches `<form>` elements).
|
||||
|
||||
To get access to the `NgForm` and the overall form status, declare a [template reference variable](guide/template-reference-variables).
|
||||
|
||||
1. Edit the template file `hero-form.component.html`.
|
||||
|
||||
2. Update the `<form>` tag with a template reference variable, `#heroForm`, and set its value as follows.
|
||||
You need one more addition to display the data. Declare
|
||||
a template variable for the form. Update the `<form>` tag with
|
||||
`#heroForm="ngForm"` as follows:
|
||||
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (excerpt)" region="template-variable"></code-example>
|
||||
|
||||
The `heroForm` template variable is now a reference to the `NgForm` directive instance that governs the form as a whole.
|
||||
The variable `heroForm` is now a reference to the `NgForm` directive that governs the form as a whole.
|
||||
|
||||
3. Run the app.
|
||||
<div class="alert is-helpful">
|
||||
|
||||
4. Start typing in the **Name** input box.
|
||||
{@a ngForm}
|
||||
|
||||
As you add and delete characters, you can see them appear and disappear from the data model.
|
||||
For example:
|
||||
### The _NgForm_ directive
|
||||
|
||||
What `NgForm` directive?
|
||||
You didn't add an [NgForm](api/forms/NgForm) directive.
|
||||
|
||||
Angular did. Angular automatically creates and attaches an `NgForm` directive to the `<form>` tag.
|
||||
|
||||
The `NgForm` directive supplements the `form` element with additional features.
|
||||
It holds the controls you created for the elements with an `ngModel` directive
|
||||
and `name` attribute, and monitors their properties, including their validity.
|
||||
It also has its own `valid` property which is true only *if every contained
|
||||
control* is valid.
|
||||
|
||||
</div>
|
||||
|
||||
If you ran the app now and started typing in the *Name* input box,
|
||||
adding and deleting characters, you'd see them appear and disappear
|
||||
from the interpolated text.
|
||||
At some point it might look like this:
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/forms/ng-model-in-action.png" alt="ngModel in action">
|
||||
</div>
|
||||
|
||||
The diagnostic line that shows interpolated values demonstrates that values are really flowing from the input box to the model and back again.
|
||||
The diagnostic is evidence that values really are flowing from the input box to the model and
|
||||
back again.
|
||||
|
||||
### Naming control elements
|
||||
<div class="alert is-helpful">
|
||||
|
||||
When you use `[(ngModel)]` on an element, you must define a `name` attribute for that element.
|
||||
Angular uses the assigned name to register the element with the `NgForm` directive attached to the parent `<form>` element.
|
||||
That's *two-way data binding*.
|
||||
For more information, see
|
||||
[Two-way binding with NgModel](guide/template-syntax#ngModel) on the
|
||||
the [Template Syntax](guide/template-syntax) page.
|
||||
|
||||
The example added a `name` attribute to the `<input>` element and set it to "name",
|
||||
which makes sense for the hero's name.
|
||||
Any unique value will do, but using a descriptive name is helpful.
|
||||
</div>
|
||||
|
||||
1. Add similar `[(ngModel)]` bindings and `name` attributes to **Alter Ego** and **Hero Power**.
|
||||
Notice that you also added a `name` attribute to the `<input>` tag and set it to "name",
|
||||
which makes sense for the hero's name. Any unique value will do, but using a descriptive name is helpful.
|
||||
Defining a `name` attribute is a requirement when using `[(ngModel)]` in combination with a form.
|
||||
|
||||
2. You can now remove the diagnostic messages that show interpolated values.
|
||||
<div class="alert is-helpful">
|
||||
|
||||
3. To confirm that two-way data binding works for the entire hero model, add a new binding at the top to the component's `diagnostic` property.
|
||||
Internally, Angular creates `FormControl` instances and
|
||||
registers them with an `NgForm` directive that Angular attached to the `<form>` tag.
|
||||
Each `FormControl` is registered under the name you assigned to the `name` attribute.
|
||||
Read more in the previous section, [The NgForm directive](guide/forms#ngForm).
|
||||
|
||||
After these revisions, the form template should look like the following:
|
||||
</div>
|
||||
|
||||
Add similar `[(ngModel)]` bindings and `name` attributes to *Alter Ego* and *Hero Power*.
|
||||
You'll ditch the input box binding message
|
||||
and add a new binding (at the top) to the component's `diagnostic` property.
|
||||
Then you can confirm that two-way data binding works *for the entire hero model*.
|
||||
|
||||
After revision, the core of the form should look like this:
|
||||
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (excerpt)" region="ngModel-2"></code-example>
|
||||
|
||||
* Notice that each `<input>` element has an `id` property. This is used by the `<label>` element's `for` attribute to match the label to its input control. This is a [standard HTML feature](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label).
|
||||
<div class="alert is-helpful">
|
||||
|
||||
* Each `<input>` element also has the required `name` property that Angular uses to register the control with the form.
|
||||
* Each input element has an `id` property that is used by the `label` element's `for` attribute
|
||||
to match the label to its input control.
|
||||
* Each input element has a `name` property that is required by Angular forms to register the control with the form.
|
||||
|
||||
</div>
|
||||
|
||||
If you run the app now and change every hero model property, the form might display like this:
|
||||
|
||||
@ -236,15 +391,18 @@ If you run the app now and change every hero model property, the form might disp
|
||||
<img src="generated/images/guide/forms/ng-model-in-action-2.png" alt="ngModel in action">
|
||||
</div>
|
||||
|
||||
The diagnostic near the top of the form confirms that all of your changes are reflected in the model.
|
||||
The diagnostic near the top of the form
|
||||
confirms that all of your changes are reflected in the model.
|
||||
|
||||
4. When you have observed the effects, you can delete the `{{diagnostic}}` binding.
|
||||
*Delete* the `{{diagnostic}}` binding at the top as it has served its purpose.
|
||||
|
||||
## Track control states
|
||||
## Track control state and validity with _ngModel_
|
||||
|
||||
The `NgModel` directive on a control tracks the state of that control.
|
||||
It tells you if the user touched the control, if the value changed, or if the value became invalid.
|
||||
Angular sets special CSS classes on the control element to reflect the state, as shown in the following table.
|
||||
Using `ngModel` in a form gives you more than just two-way data binding. It also tells
|
||||
you if the user touched the control, if the value changed, or if the value became invalid.
|
||||
|
||||
The *NgModel* directive doesn't just track state; it updates the control with special Angular CSS classes that reflect the state.
|
||||
You can leverage those class names to change the appearance of the control.
|
||||
|
||||
<table>
|
||||
|
||||
@ -314,32 +472,38 @@ Angular sets special CSS classes on the control element to reflect the state, as
|
||||
|
||||
</table>
|
||||
|
||||
You use these CSS classes to define the styles for your control based on its status.
|
||||
Temporarily add a [template reference variable](guide/template-syntax#ref-vars) named `spy`
|
||||
to the _Name_ `<input>` tag and use it to display the input's CSS classes.
|
||||
|
||||
### Observe control states
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (excerpt)" region="ngModelName-2"></code-example>
|
||||
|
||||
To see how the classes are added and removed by the framework, open the browser's developer tools and inspect the `<input>` element that represents the hero name.
|
||||
Now run the app and look at the _Name_ input box.
|
||||
Follow these steps *precisely*:
|
||||
|
||||
1. Using your browser's developer tools, find the `<input>` element that corresponds to the **Name** input box.
|
||||
You can see that the element has multiple CSS classes in addition to "form-control".
|
||||
1. Look but don't touch.
|
||||
1. Click inside the name box, then click outside it.
|
||||
1. Add slashes to the end of the name.
|
||||
1. Erase the name.
|
||||
|
||||
2. When you first bring it up, the classes indicate that it has a valid value, that the value has not been changed since initialization or reset, and that the control has not been visited since initialization or reset.
|
||||
The actions and effects are as follows:
|
||||
|
||||
```
|
||||
<input ... class="form-control ng-untouched ng-pristine ng-valid" ...>
|
||||
```
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/forms/control-state-transitions-anim.gif" alt="Control State Transition">
|
||||
</div>
|
||||
|
||||
3. Take the following actions on the **Name** `<input>` box, and observe which classes appear.
|
||||
* Look but don't touch. The classes indicate that it is untouched, pristine, and valid.
|
||||
* Click inside the name box, then click outside it. The control has now been visited, and the element has the `ng-touched` class instead of the `ng-untouched` class.
|
||||
* Add slashes to the end of the name. It is now touched and dirty.
|
||||
* Erase the name. This makes the value invalid, so the `ng-invalid` class replaces the `ng-valid` class.
|
||||
You should see the following transitions and class names:
|
||||
|
||||
### Create visual feedback for states
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/forms/ng-control-class-changes.png" alt="Control state transitions">
|
||||
</div>
|
||||
|
||||
The `ng-valid`/`ng-invalid` pair is particularly interesting, because you want to send a
|
||||
strong visual signal when the values are invalid.
|
||||
You also want to mark required fields.
|
||||
The `ng-valid`/`ng-invalid` pair is the most interesting, because you want to send a
|
||||
strong visual signal when the values are invalid. You also want to mark required fields.
|
||||
To create such visual feedback, add definitions for the `ng-*` CSS classes.
|
||||
|
||||
*Delete* the `#spy` template reference variable and the `TODO` as they have served their purpose.
|
||||
|
||||
## Add custom CSS for visual feedback
|
||||
|
||||
You can mark required fields and invalid data at the same time with a colored bar
|
||||
on the left of the input box:
|
||||
@ -348,25 +512,20 @@ on the left of the input box:
|
||||
<img src="generated/images/guide/forms/validity-required-indicator.png" alt="Invalid Form">
|
||||
</div>
|
||||
|
||||
To change the appearance in this way, take the following steps.
|
||||
|
||||
1. Add definitions for the `ng-*` CSS classes.
|
||||
|
||||
2. Add these class definitions to a new `forms.css` file.
|
||||
|
||||
3. Add the new file to the project as a sibling to `index.html`:
|
||||
You achieve this effect by adding these class definitions to a new `forms.css` file
|
||||
that you add to the project as a sibling to `index.html`:
|
||||
|
||||
<code-example path="forms/src/assets/forms.css" header="src/assets/forms.css"></code-example>
|
||||
|
||||
4. In the `index.html` file, update the `<head>` tag to include the new style sheet.
|
||||
Update the `<head>` of `index.html` to include this style sheet:
|
||||
|
||||
<code-example path="forms/src/index.html" header="src/index.html (styles)" region="styles"></code-example>
|
||||
|
||||
### Show and hide validation error messages
|
||||
## Show and hide validation error messages
|
||||
|
||||
The **Name** input box is required and clearing it turns the bar red.
|
||||
That indicates that something is wrong, but the user doesn't know what is wrong or what to do about it.
|
||||
You can provide a helpful message by checking for and responding to the control's state.
|
||||
You can improve the form. The _Name_ input box is required and clearing it turns the bar red.
|
||||
That says something is wrong but the user doesn't know *what* is wrong or what to do about it.
|
||||
Leverage the control's state to reveal a helpful message.
|
||||
|
||||
When the user deletes the name, the form should look like this:
|
||||
|
||||
@ -374,135 +533,166 @@ When the user deletes the name, the form should look like this:
|
||||
<img src="generated/images/guide/forms/name-required-error.png" alt="Name required">
|
||||
</div>
|
||||
|
||||
The **Hero Power** select box is also required, but it doesn't need this kind of error handling because the selection box already constrains the selection to valid values.
|
||||
To achieve this effect, extend the `<input>` tag with the following:
|
||||
|
||||
To define and show an error message when appropriate, take the following steps.
|
||||
* A [template reference variable](guide/template-syntax#ref-vars).
|
||||
* The "*is required*" message in a nearby `<div>`, which you'll display only if the control is invalid.
|
||||
|
||||
1. Extend the `<input>` tag with a template reference variable that you can use to access the input box's Angular control from within the template. In the example, the variable is `#name="ngModel"`.
|
||||
Here's an example of an error message added to the _name_ input box:
|
||||
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (excerpt)" region="name-with-error-msg"></code-example>
|
||||
|
||||
You need a template reference variable to access the input box's Angular control from within the template.
|
||||
Here you created a variable called `name` and gave it the value "ngModel".
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The template reference variable (`#name`) is set to `"ngModel"` because that is the value of the [`NgModel.exportAs`](api/core/Directive#exportAs) property. This property tells Angular how to link a reference variable to a directive.
|
||||
Why "ngModel"?
|
||||
A directive's [exportAs](api/core/Directive) property
|
||||
tells Angular how to link the reference variable to the directive.
|
||||
You set `name` to `ngModel` because the `ngModel` directive's `exportAs` property happens to be "ngModel".
|
||||
|
||||
</div>
|
||||
|
||||
2. Add a `<div>` that contains a suitable error message.
|
||||
3. Show or hide the error message by binding properties of the `name`
|
||||
You control visibility of the name error message by binding properties of the `name`
|
||||
control to the message `<div>` element's `hidden` property.
|
||||
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (hidden-error-msg)" region="hidden-error-msg"></code-example>
|
||||
|
||||
4. Add a conditional error message to the _name_ input box, as in the following example.
|
||||
In this example, you hide the message when the control is valid or pristine;
|
||||
"pristine" means the user hasn't changed the value since it was displayed in this form.
|
||||
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (excerpt)" region="name-with-error-msg"></code-example>
|
||||
|
||||
<div class="callout is-helpful">
|
||||
|
||||
<header>Illustrating the "pristine" state</header>
|
||||
|
||||
In this example, you hide the message when the control is either valid or *pristine*.
|
||||
Pristine means the user hasn't changed the value since it was displayed in this form.
|
||||
This user experience is the developer's choice. Some developers want the message to display at all times.
|
||||
If you ignore the `pristine` state, you would hide the message only when the value is valid.
|
||||
If you arrive in this component with a new (blank) hero or an invalid hero,
|
||||
you'll see the error message immediately, before you've done anything.
|
||||
|
||||
You might want the message to display only when the user makes an invalid change.
|
||||
Hiding the message while the control is in the `pristine` state achieves that goal.
|
||||
You'll see the significance of this choice when you add a new hero to the form in the next step.
|
||||
Some developers want the message to display only when the user makes an invalid change.
|
||||
Hiding the message while the control is "pristine" achieves that goal.
|
||||
You'll see the significance of this choice when you add a new hero to the form.
|
||||
|
||||
</div>
|
||||
The hero *Alter Ego* is optional so you can leave that be.
|
||||
|
||||
## Add a new hero
|
||||
Hero *Power* selection is required.
|
||||
You can add the same kind of error handling to the `<select>` if you want,
|
||||
but it's not imperative because the selection box already constrains the
|
||||
power to valid values.
|
||||
|
||||
This exercise shows how you can respond to a native HTML button-click event by adding to the model data.
|
||||
To let form users add a new hero, you will add a **New Hero** button that responds to a click event.
|
||||
|
||||
1. In the template, place a "New Hero" `<button>` element at the bottom of the form.
|
||||
2. In the component file, add the hero-creation method to the hero data model.
|
||||
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.ts" region="new-hero" header="src/app/hero-form/hero-form.component.ts (New Hero method)"></code-example>
|
||||
|
||||
3. Bind the button's click event to a hero-creation method, `newHero()`.
|
||||
Now you'll add a new hero in this form.
|
||||
Place a *New Hero* button at the bottom of the form and bind its click event to a `newHero` component method.
|
||||
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.html" region="new-hero-button-no-reset" header="src/app/hero-form/hero-form.component.html (New Hero button)"></code-example>
|
||||
|
||||
4. Run the application again and click the **New Hero** button.
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.ts" region="new-hero" header="src/app/hero-form/hero-form.component.ts (New Hero method)"></code-example>
|
||||
|
||||
The form clears, and the *required* bars to the left of the input box are red, indicating invalid `name` and `power` properties.
|
||||
Notice that the error messages are hidden. This is because the form is pristine; you haven't changed anything yet.
|
||||
Run the application again, click the *New Hero* button, and the form clears.
|
||||
The *required* bars to the left of the input box are red, indicating invalid `name` and `power` properties.
|
||||
That's understandable as these are required fields.
|
||||
The error messages are hidden because the form is pristine; you haven't changed anything yet.
|
||||
|
||||
5. Enter a name and click **New Hero** again.
|
||||
Enter a name and click *New Hero* again.
|
||||
The app displays a _Name is required_ error message.
|
||||
You don't want error messages when you create a new (empty) hero.
|
||||
Why are you getting one now?
|
||||
|
||||
Now the app displays a _Name is required_ error message, because the input box is no longer pristine.
|
||||
The form remembers that you entered a name before clicking **New Hero**.
|
||||
Inspecting the element in the browser tools reveals that the *name* input box is _no longer pristine_.
|
||||
The form remembers that you entered a name before clicking *New Hero*.
|
||||
Replacing the hero object *did not restore the pristine state* of the form controls.
|
||||
|
||||
6. To restore the pristine state of the form controls, clear all of the flags imperatively by calling the form's `reset()` method after calling the `newHero()` method.
|
||||
You have to clear all of the flags imperatively, which you can do
|
||||
by calling the form's `reset()` method after calling the `newHero()` method.
|
||||
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.html" region="new-hero-button-form-reset" header="src/app/hero-form/hero-form.component.html (Reset the form)"></code-example>
|
||||
|
||||
Now clicking **New Hero** resets both the form and its control flags.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the [User Input](guide/user-input) guide for more information about listening for DOM events with an event binding and updating a corresponding component property.
|
||||
|
||||
</div>
|
||||
Now clicking "New Hero" resets both the form and its control flags.
|
||||
|
||||
## Submit the form with _ngSubmit_
|
||||
|
||||
The user should be able to submit this form after filling it in.
|
||||
The **Submit** button at the bottom of the form does nothing on its own, but it does
|
||||
trigger a form-submit event because of its type (`type="submit"`).
|
||||
To respond to this event, take the following steps.
|
||||
The *Submit* button at the bottom of the form
|
||||
does nothing on its own, but it will
|
||||
trigger a form submit because of its type (`type="submit"`).
|
||||
|
||||
1. Bind the form's [`ngSubmit`](api/forms/NgForm#properties) event property to the hero-form component's `onSubmit()` method.
|
||||
A "form submit" is useless at the moment.
|
||||
To make it useful, bind the form's `ngSubmit` event property
|
||||
to the hero form component's `onSubmit()` method:
|
||||
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (ngSubmit)" region="ngSubmit"></code-example>
|
||||
|
||||
2. Use the template reference variable, `#heroForm` to access the form that contains the **Submit** button and create an event binding.
|
||||
You will bind the form property that indicates its overall validity to the **Submit** button's `disabled` property.
|
||||
You'd already defined a template reference variable,
|
||||
`#heroForm`, and initialized it with the value "ngForm".
|
||||
Now, use that variable to access the form with the Submit button.
|
||||
|
||||
|
||||
You'll bind the form's overall validity via
|
||||
the `heroForm` variable to the button's `disabled` property
|
||||
using an event binding. Here's the code:
|
||||
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (submit-button)" region="submit-button"></code-example>
|
||||
|
||||
3. Run the application now. Notice that the button is enabled—although
|
||||
If you run the application now, you find that the button is enabled—although
|
||||
it doesn't do anything useful yet.
|
||||
|
||||
4. Delete the **Name** value. This violates the "required" rule, so it displays the error message—and notice that it also disables the **Submit** button.
|
||||
Now if you delete the Name, you violate the "required" rule, which
|
||||
is duly noted in the error message.
|
||||
The *Submit* button is also disabled.
|
||||
|
||||
Not impressed? Think about it for a moment. What would you have to do to
|
||||
wire the button's enable/disabled state to the form's validity without Angular's help?
|
||||
|
||||
You didn't have to explicitly wire the button's enabled state to the form's validity.
|
||||
The `FormsModule` did this automatically when you defined a template reference variable on the enhanced form element, then referred to that variable in the button control.
|
||||
For you, it was as simple as this:
|
||||
|
||||
### Respond to form submission
|
||||
1. Define a template reference variable on the (enhanced) form element.
|
||||
2. Refer to that variable in a button many lines away.
|
||||
|
||||
To show a response to form submission, you can hide the data entry area and display something else in its place.
|
||||
## Toggle two form regions (extra credit)
|
||||
|
||||
1. Wrap the entire form in a `<div>` and bind
|
||||
Submitting the form isn't terribly dramatic at the moment.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
An unsurprising observation for a demo. To be honest,
|
||||
jazzing it up won't teach you anything new about forms.
|
||||
But this is an opportunity to exercise some of your newly won
|
||||
binding skills.
|
||||
If you aren't interested, skip to this page's conclusion.
|
||||
|
||||
</div>
|
||||
|
||||
For a more strikingly visual effect,
|
||||
hide the data entry area and display something else.
|
||||
|
||||
Wrap the form in a `<div>` and bind
|
||||
its `hidden` property to the `HeroFormComponent.submitted` property.
|
||||
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (excerpt)" region="edit-div"></code-example>
|
||||
|
||||
* The main form is visible from the start because the `submitted` property is false until you submit the form, as this fragment from the `HeroFormComponent` shows:
|
||||
The main form is visible from the start because the
|
||||
`submitted` property is false until you submit the form,
|
||||
as this fragment from the `HeroFormComponent` shows:
|
||||
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.ts" header="src/app/hero-form/hero-form.component.ts (submitted)" region="submitted"></code-example>
|
||||
|
||||
* When you click the **Submit** button, the `submitted` flag becomes true and the form disappears.
|
||||
When you click the *Submit* button, the `submitted` flag becomes true and the form disappears
|
||||
as planned.
|
||||
|
||||
2. To show something else while the form is in the submitted state, add the following HTML below the new `<div>` wrapper.
|
||||
Now the app needs to show something else while the form is in the submitted state.
|
||||
Add the following HTML below the `<div>` wrapper you just wrote:
|
||||
|
||||
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (excerpt)" region="submitted"></code-example>
|
||||
|
||||
This `<div>`, which shows a read-only hero with interpolation bindings, appears only while the component is in the submitted state.
|
||||
There's the hero again, displayed read-only with interpolation bindings.
|
||||
This `<div>` appears only while the component is in the submitted state.
|
||||
|
||||
The alternative display includes an *Edit* button whose click event is bound to an expression
|
||||
The HTML includes an *Edit* button whose click event is bound to an expression
|
||||
that clears the `submitted` flag.
|
||||
|
||||
3. Click the *Edit* button to switch the display back to the editable form.
|
||||
When you click the *Edit* button, this block disappears and the editable form reappears.
|
||||
|
||||
## Summary
|
||||
|
||||
The Angular form discussed in this page takes advantage of the following
|
||||
framework features to provide support for data modification, validation, and more.
|
||||
framework features to provide support for data modification, validation, and more:
|
||||
|
||||
* An Angular HTML form template.
|
||||
* A form component class with a `@Component` decorator.
|
||||
@ -510,8 +700,8 @@ framework features to provide support for data modification, validation, and mor
|
||||
* Template-reference variables such as `#heroForm` and `#name`.
|
||||
* `[(ngModel)]` syntax for two-way data binding.
|
||||
* The use of `name` attributes for validation and form-element change tracking.
|
||||
* The reference variable’s `valid` property on input controls to check if a control is valid and show or hide error messages.
|
||||
* Controlling the **Submit** button's enabled state by binding to `NgForm` validity.
|
||||
* The reference variable’s `valid` property on input controls to check if a control is valid and show/hide error messages.
|
||||
* Controlling the *Submit* button's enabled state by binding to `NgForm` validity.
|
||||
* Custom CSS classes that provide visual feedback to users about invalid controls.
|
||||
|
||||
Here’s the code for the final version of the application:
|
||||
@ -551,3 +741,4 @@ Here’s the code for the final version of the application:
|
||||
</code-pane>
|
||||
|
||||
</code-tabs>
|
||||
|
||||
|
@ -210,7 +210,6 @@ An Angular component class is responsible for exposing data and handling most of
|
||||
|
||||
Read more about component classes, templates, and views in [Introduction to Angular concepts](guide/architecture).
|
||||
|
||||
|
||||
## configuration
|
||||
|
||||
See [workspace configuration](#cli-config)
|
||||
@ -253,15 +252,15 @@ Data binding is an alternative to manually pushing application data values into
|
||||
event listeners, pulling changed values from the screen, and
|
||||
updating application data values.
|
||||
|
||||
Read about the following forms of binding in Angular's [Template Syntax](guide/template-syntax):
|
||||
Read about the following forms of binding in [Template Syntax](guide/template-syntax):
|
||||
|
||||
* [Interpolation](guide/interpolation)
|
||||
* [Property binding](guide/property-binding)
|
||||
* [Event binding](guide/event-binding)
|
||||
* [Attribute binding](guide/attribute-binding)
|
||||
* [Class binding](guide/attribute-binding#class-binding)
|
||||
* [Style binding](guide/attribute-binding#style-binding)
|
||||
* [Two-way data binding with ngModel](guide/built-in-directives#ngModel)
|
||||
* [Interpolation](guide/template-syntax#interpolation)
|
||||
* [Property binding](guide/template-syntax#property-binding)
|
||||
* [Event binding](guide/template-syntax#event-binding)
|
||||
* [Attribute binding](guide/template-syntax#attribute-binding)
|
||||
* [Class binding](guide/template-syntax#class-binding)
|
||||
* [Style binding](guide/template-syntax#style-binding)
|
||||
* [Two-way data binding with ngModel](guide/template-syntax#ngModel)
|
||||
|
||||
{@a declarable}
|
||||
|
||||
@ -473,11 +472,11 @@ Learn more about the injector hierarchy in [Hierarchical Dependency Injectors](g
|
||||
## input
|
||||
|
||||
When defining a [directive](#directive), the `@Input()` decorator on a directive property
|
||||
makes that property available as a *target* of a [property binding](guide/property-binding).
|
||||
makes that property available as a *target* of a [property binding](guide/template-syntax#property-binding).
|
||||
Data values flow into an input property from the data source identified
|
||||
in the [template expression](#template-expression) to the right of the equal sign.
|
||||
|
||||
To learn more, see [input and output properties](guide/inputs-outputs).
|
||||
To learn more, see [input and output properties](guide/template-syntax#inputs-outputs).
|
||||
|
||||
{@a interpolation}
|
||||
|
||||
@ -492,7 +491,7 @@ or displayed between element tags, as in this example.
|
||||
```
|
||||
|
||||
|
||||
Read more in the [Interpolation](guide/interpolation) guide.
|
||||
Read more about [interpolation](guide/template-syntax#interpolation) in [Template Syntax](guide/template-syntax).
|
||||
|
||||
{@a ivy}
|
||||
|
||||
@ -579,6 +578,7 @@ Angular calls these hook methods in the following order:
|
||||
|
||||
To learn more, see [Lifecycle Hooks](guide/lifecycle-hooks).
|
||||
|
||||
|
||||
{@a M}
|
||||
|
||||
{@a module}
|
||||
@ -653,11 +653,11 @@ An object passed to the `subscribe()` method for an [observable](#observable). T
|
||||
## output
|
||||
|
||||
When defining a [directive](#directive), the `@Output{}` decorator on a directive property
|
||||
makes that property available as a *target* of [event binding](guide/event-binding).
|
||||
makes that property available as a *target* of [event binding](guide/template-syntax#event-binding).
|
||||
Events stream *out* of this property to the receiver identified
|
||||
in the [template expression](#template-expression) to the right of the equal sign.
|
||||
|
||||
To learn more, see [Input and Output Properties](guide/inputs-outputs).
|
||||
To learn more, see [Input and Output Properties](guide/template-syntax#inputs-outputs).
|
||||
|
||||
|
||||
{@a P}
|
||||
@ -732,33 +732,13 @@ The alternative is a [template-driven form](#template-driven-forms).
|
||||
When using reactive forms:
|
||||
|
||||
* The "source of truth", the form model, is defined in the component class.
|
||||
* Validation is set up through validation functions rather than validation directives.
|
||||
* Validation is set up through validation functions rather than valdation directives.
|
||||
* Each control is explicitly created in the component class by creating a `FormControl` instance manually or with `FormBuilder`.
|
||||
* The template input elements do *not* use `ngModel`.
|
||||
* The associated Angular directives are prefixed with `form`, such as `formControl`, `formGroup`, and `formControlName`.
|
||||
|
||||
The alternative is a template-driven form. For an introduction and comparison of both forms approaches, see [Introduction to Angular Forms](guide/forms-overview).
|
||||
|
||||
{@a resolver}
|
||||
|
||||
## resolver
|
||||
|
||||
A class that implements the [Resolve](api/router/Resolve "API reference") interface (or a function with the same signature as the [resolve() method](api/router/Resolve#resolve "API reference")) that you use to produce or retrieve data that is needed before navigation to a requested route can be completed.
|
||||
|
||||
Resolvers run after all [route guards](#route-guard "Definition") for a route tree have been executed and have succeeded.
|
||||
|
||||
See an example of using a [resolve guard](guide/router-tutorial-toh#resolve-guard "Routing techniques tutorial") to retrieve dynamic data.
|
||||
|
||||
{@a route-guard}
|
||||
|
||||
## route guard
|
||||
|
||||
A method that controls navigation to a requested route in a routing application.
|
||||
Guards determine whether a route can be activated or deactivated, and whether a lazy-loaded module can be loaded.
|
||||
|
||||
Learn more in the [Routing and Navigation](guide/router#preventing-unauthorized-access "Examples") guide.
|
||||
|
||||
|
||||
{@a router}
|
||||
{@a router-module}
|
||||
|
||||
@ -937,20 +917,7 @@ The alternative is a reactive form. For an introduction and comparison of both f
|
||||
|
||||
A TypeScript-like syntax that Angular evaluates within a [data binding](#data-binding).
|
||||
|
||||
Read about how to write template expressions in the [template expressions](guide/interpolation#template-expressions) section of the [Interpolation](guide/interpolation) guide.
|
||||
|
||||
{@a template-reference-variable}
|
||||
|
||||
## template reference variable
|
||||
|
||||
A variable defined in a template that references an instance associated with an element, such as a directive instance, component instance, template as in `TemplateRef`, or DOM element.
|
||||
After declaring a template reference variable on an element in a template,
|
||||
you can access values from that variable elsewhere within the same template.
|
||||
The following example defines a template reference variable named `#phone`.
|
||||
|
||||
<code-example path="template-reference-variables/src/app/app.component.html" region="ref-var" header="src/app/app.component.html"></code-example>
|
||||
|
||||
For more information, see the [Template reference variable](guide/template-reference-variables) guide.
|
||||
Read about how to write template expressions in [Template expressions](guide/template-syntax#template-expressions).
|
||||
|
||||
{@a token}
|
||||
|
||||
@ -983,10 +950,6 @@ Many code editors and IDEs support TypeScript either natively or with plug-ins.
|
||||
TypeScript is the preferred language for Angular development.
|
||||
Read more about TypeScript at [typescriptlang.org](http://www.typescriptlang.org/).
|
||||
|
||||
## TypeScript configuration file
|
||||
|
||||
A file specifies the root files and the compiler options required to compile a TypeScript project. For more information, see [TypeScript configuration](/guide/typescript-configuration).
|
||||
|
||||
|
||||
{@a U}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Communicating with backend services using HTTP
|
||||
|
||||
Most front-end applications need to communicate with a server over the HTTP protocol, in order to download or upload data and access other back-end services.
|
||||
Most front-end applications need to communicate with a server over the HTTP protocol, in order to download or upload data and accesss other back-end services.
|
||||
Angular provides a simplified client HTTP API for Angular applications, the `HttpClient` service class in `@angular/common/http`.
|
||||
|
||||
The HTTP client service offers the following major features.
|
||||
@ -63,7 +63,7 @@ Look at the `AppModule` _imports_ to see how it is configured.
|
||||
## Requesting data from a server
|
||||
|
||||
Use the [`HTTPClient.get()`](api/common/http/HttpClient#get) method to fetch data from a server.
|
||||
The asynchronous method sends an HTTP request, and returns an Observable that emits the requested data when the response is received.
|
||||
The aynchronous method sends an HTTP request, and returns an Observable that emits the requested data when the response is received.
|
||||
The return type varies based on the `observe` and `responseType` values that you pass to the call.
|
||||
|
||||
The `get()` method takes two arguments; the endpoint URL from which to fetch, and an *options* object that you can use to configure the request.
|
||||
@ -277,7 +277,7 @@ searchHeroes(term: string): Observable {
|
||||
return this.http.jsonp(heroesUrl, 'callback').pipe(
|
||||
catchError(this.handleError('searchHeroes', [])) // then handle the error
|
||||
);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
This request passes the `heroesURL` as the first parameter and the callback function name as the second parameter.
|
||||
@ -805,16 +805,16 @@ The `CachingInterceptor` in the following example demonstrates this approach.
|
||||
header="app/http-interceptors/caching-interceptor.ts)">
|
||||
</code-example>
|
||||
|
||||
* The `isCacheable()` function determines if the request is cacheable.
|
||||
In this sample, only GET requests to the npm package search api are cacheable.
|
||||
* The `isCachable()` function determines if the request is cachable.
|
||||
In this sample, only GET requests to the npm package search api are cachable.
|
||||
|
||||
* If the request is not cacheable, the interceptor simply forwards the request
|
||||
* If the request is not cachable, the interceptor simply forwards the request
|
||||
to the next handler in the chain.
|
||||
|
||||
* If a cacheable request is found in the cache, the interceptor returns an `of()` _observable_ with
|
||||
* If a cachable request is found in the cache, the interceptor returns an `of()` _observable_ with
|
||||
the cached response, by-passing the `next` handler (and all other interceptors downstream).
|
||||
|
||||
* If a cacheable request is not in cache, the code calls `sendRequest()`.
|
||||
* If a cachable request is not in cache, the code calls `sendRequest()`.
|
||||
This function creates a [request clone](#immutability) without headers, because the npm API forbids them.
|
||||
The function then forwards the clone of the request to `next.handle()` which ultimately calls the server and returns the server's response.
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,342 +0,0 @@
|
||||
# `@Input()` and `@Output()` properties
|
||||
|
||||
`@Input()` and `@Output()` allow Angular to share data between the parent context
|
||||
and child directives or components. An `@Input()` property is writable
|
||||
while an `@Output()` property is observable.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
Consider this example of a child/parent relationship:
|
||||
|
||||
```html
|
||||
<parent-component>
|
||||
<child-component></child-component>
|
||||
</parent-component>
|
||||
|
||||
```
|
||||
|
||||
Here, the `<child-component>` selector, or child directive, is embedded
|
||||
within a `<parent-component>`, which serves as the child's context.
|
||||
|
||||
`@Input()` and `@Output()` act as
|
||||
the API, or application programming interface, of the child
|
||||
component in that they allow the child to
|
||||
communicate with the parent. Think of `@Input()` and `@Output()` like ports
|
||||
or doorways—`@Input()` is the doorway into the component allowing data
|
||||
to flow in while `@Output()` is the doorway out of the component, allowing the
|
||||
child component to send data out.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
#### `@Input()` and `@Output()` are independent
|
||||
|
||||
Though `@Input()` and `@Output()` often appear together in apps, you can use
|
||||
them separately. If the nested
|
||||
component is such that it only needs to send data to its parent, you wouldn't
|
||||
need an `@Input()`, only an `@Output()`. The reverse is also true in that if the
|
||||
child only needs to receive data from the parent, you'd only need `@Input()`.
|
||||
|
||||
</div>
|
||||
|
||||
{@a input}
|
||||
|
||||
## How to use `@Input()`
|
||||
|
||||
Use the `@Input()` decorator in a child component or directive to let Angular know
|
||||
that a property in that component can receive its value from its parent component.
|
||||
It helps to remember that the data flow is from the perspective of the
|
||||
child component. So an `@Input()` allows data to be input _into_ the
|
||||
child component from the parent component.
|
||||
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/inputs-outputs/input.svg" alt="Input data flow diagram">
|
||||
</div>
|
||||
|
||||
To illustrate the use of `@Input()`, edit these parts of your app:
|
||||
|
||||
* The child component class and template
|
||||
* The parent component class and template
|
||||
|
||||
|
||||
### In the child
|
||||
|
||||
To use the `@Input()` decorator in a child component class, first import
|
||||
`Input` and then decorate the property with `@Input()`:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/item-detail/item-detail.component.ts" region="use-input" header="src/app/item-detail/item-detail.component.ts"></code-example>
|
||||
|
||||
|
||||
In this case, `@Input()` decorates the property <code class="no-auto-link">item</code>, which has
|
||||
a type of `string`, however, `@Input()` properties can have any type, such as
|
||||
`number`, `string`, `boolean`, or `object`. The value for `item` will come from the parent component, which the next section covers.
|
||||
|
||||
Next, in the child component template, add the following:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/item-detail/item-detail.component.html" region="property-in-template" header="src/app/item-detail/item-detail.component.html"></code-example>
|
||||
|
||||
|
||||
|
||||
### In the parent
|
||||
|
||||
The next step is to bind the property in the parent component's template.
|
||||
In this example, the parent component template is `app.component.html`.
|
||||
|
||||
First, use the child's selector, here `<app-item-detail>`, as a directive within the
|
||||
parent component template. Then, use [property binding](guide/property-binding)
|
||||
to bind the property in the child to the property of the parent.
|
||||
|
||||
<code-example path="inputs-outputs/src/app/app.component.html" region="input-parent" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Next, in the parent component class, `app.component.ts`, designate a value for `currentItem`:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/app.component.ts" region="parent-property" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
With `@Input()`, Angular passes the value for `currentItem` to the child so that `item` renders as `Television`.
|
||||
|
||||
The following diagram shows this structure:
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/inputs-outputs/input-diagram-target-source.svg" alt="Property binding diagram">
|
||||
</div>
|
||||
|
||||
The target in the square brackets, `[]`, is the property you decorate
|
||||
with `@Input()` in the child component. The binding source, the part
|
||||
to the right of the equal sign, is the data that the parent
|
||||
component passes to the nested component.
|
||||
|
||||
The key takeaway is that when binding to a child component's property in a parent component—that is, what's
|
||||
in square brackets—you must
|
||||
decorate the property with `@Input()` in the child component.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
### `OnChanges` and `@Input()`
|
||||
|
||||
To watch for changes on an `@Input()` property, use
|
||||
`OnChanges`, one of Angular's [lifecycle hooks](guide/lifecycle-hooks#onchanges).
|
||||
`OnChanges` is specifically designed to work with properties that have the
|
||||
`@Input()` decorator. See the [`OnChanges`](guide/lifecycle-hooks#onchanges) section of the [Lifecycle Hooks](guide/lifecycle-hooks) guide for more details and examples.
|
||||
|
||||
</div>
|
||||
|
||||
{@a output}
|
||||
|
||||
## How to use `@Output()`
|
||||
|
||||
Use the `@Output()` decorator in the child component or directive to allow data to flow from
|
||||
the child _out_ to the parent.
|
||||
|
||||
An `@Output()` property should normally be initialized to an Angular [`EventEmitter`](api/core/EventEmitter) with values flowing out of the component as [events](guide/event-binding).
|
||||
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/inputs-outputs/output.svg" alt="Output diagram">
|
||||
</div>
|
||||
|
||||
Just like with `@Input()`, you can use `@Output()`
|
||||
on a property of the child component but its type should be
|
||||
`EventEmitter`.
|
||||
|
||||
`@Output()` marks a property in a child component as a doorway
|
||||
through which data can travel from the child to the parent.
|
||||
The child component then has to raise an event so the
|
||||
parent knows something has changed. To raise an event,
|
||||
`@Output()` works hand in hand with `EventEmitter`,
|
||||
which is a class in `@angular/core` that you
|
||||
use to emit custom events.
|
||||
|
||||
When you use `@Output()`, edit these parts of your app:
|
||||
|
||||
* The child component class and template
|
||||
* The parent component class and template
|
||||
|
||||
|
||||
The following example shows how to set up an `@Output()` in a child
|
||||
component that pushes data you enter in an HTML `<input>` to an array in the
|
||||
parent component.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The HTML element `<input>` and the Angular decorator `@Input()`
|
||||
are different. This documentation is about component communication in Angular as it pertains to `@Input()` and `@Output()`. For more information on the HTML element `<input>`, see the [W3C Recommendation](https://www.w3.org/TR/html5/sec-forms.html#the-input-element).
|
||||
|
||||
</div>
|
||||
|
||||
## In the child
|
||||
|
||||
This example features an `<input>` where a user can enter a value and click a `<button>` that raises an event. The `EventEmitter` then relays the data to the parent component.
|
||||
|
||||
First, be sure to import `Output` and `EventEmitter`
|
||||
in the child component class:
|
||||
|
||||
```js
|
||||
import { Output, EventEmitter } from '@angular/core';
|
||||
|
||||
```
|
||||
|
||||
Next, still in the child, decorate a property with `@Output()` in the component class.
|
||||
The following example `@Output()` is called `newItemEvent` and its type is
|
||||
`EventEmitter`, which means it's an event.
|
||||
|
||||
|
||||
<code-example path="inputs-outputs/src/app/item-output/item-output.component.ts" region="item-output" header="src/app/item-output/item-output.component.ts"></code-example>
|
||||
|
||||
The different parts of the above declaration are as follows:
|
||||
|
||||
* `@Output()`—a decorator function marking the property as a way for data to go from the child to the parent
|
||||
* `newItemEvent`—the name of the `@Output()`
|
||||
* `EventEmitter<string>`—the `@Output()`'s type
|
||||
* `new EventEmitter<string>()`—tells Angular to create a new event emitter and that the data it emits is of type string. The type could be any type, such as `number`, `boolean`, and so on. For more information on `EventEmitter`, see the [EventEmitter API documentation](api/core/EventEmitter).
|
||||
|
||||
Next, create an `addNewItem()` method in the same component class:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/item-output/item-output.component.ts" region="item-output-class" header="src/app/item-output/item-output.component.ts"></code-example>
|
||||
|
||||
The `addNewItem()` function uses the `@Output()`, `newItemEvent`,
|
||||
to raise an event in which it emits the value the user
|
||||
types into the `<input>`. In other words, when
|
||||
the user clicks the add button in the UI, the child lets the parent know
|
||||
about the event and gives that data to the parent.
|
||||
|
||||
### In the child's template
|
||||
|
||||
The child's template has two controls. The first is an HTML `<input>` with a
|
||||
[template reference variable](guide/template-reference-variables) , `#newItem`,
|
||||
where the user types in an item name. Whatever the user types
|
||||
into the `<input>` gets stored in the `#newItem` variable.
|
||||
|
||||
<code-example path="inputs-outputs/src/app/item-output/item-output.component.html" region="child-output" header="src/app/item-output/item-output.component.html"></code-example>
|
||||
|
||||
The second element is a `<button>`
|
||||
with an [event binding](guide/event-binding). You know it's
|
||||
an event binding because the part to the left of the equal
|
||||
sign is in parentheses, `(click)`.
|
||||
|
||||
The `(click)` event is bound to the `addNewItem()` method in the child component class which
|
||||
takes as its argument whatever the value of `#newItem` is.
|
||||
|
||||
Now the child component has an `@Output()`
|
||||
for sending data to the parent and a method for raising an event.
|
||||
The next step is in the parent.
|
||||
|
||||
## In the parent
|
||||
|
||||
In this example, the parent component is `AppComponent`, but you could use
|
||||
any component in which you could nest the child.
|
||||
|
||||
The `AppComponent` in this example features a list of `items`
|
||||
in an array and a method for adding more items to the array.
|
||||
|
||||
<code-example path="inputs-outputs/src/app/app.component.ts" region="add-new-item" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
The `addItem()` method takes an argument in the form of a string
|
||||
and then pushes, or adds, that string to the `items` array.
|
||||
|
||||
### In the parent's template
|
||||
|
||||
Next, in the parent's template, bind the parent's
|
||||
method to the child's event. Put the child selector, here `<app-item-output>`,
|
||||
within the parent component's
|
||||
template, `app.component.html`.
|
||||
|
||||
<code-example path="inputs-outputs/src/app/app.component.html" region="output-parent" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The event binding, `(newItemEvent)='addItem($event)'`, tells
|
||||
Angular to connect the event in the child, `newItemEvent`, to
|
||||
the method in the parent, `addItem()`, and that the event that the child
|
||||
is notifying the parent about is to be the argument of `addItem()`.
|
||||
In other words, this is where the actual hand off of data takes place.
|
||||
The `$event` contains the data that the user types into the `<input>`
|
||||
in the child template UI.
|
||||
|
||||
Now, in order to see the `@Output()` working, add the following to the parent's template:
|
||||
|
||||
```html
|
||||
<ul>
|
||||
<li *ngFor="let item of items">{{item}}</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
The `*ngFor` iterates over the items in the `items` array. When you enter a value in the child's `<input>` and click the button, the child emits the event and the parent's `addItem()` method pushes the value to the `items` array and it renders in the list.
|
||||
|
||||
|
||||
## `@Input()` and `@Output()` together
|
||||
|
||||
You can use `@Input()` and `@Output()` on the same child component as in the following:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/app.component.html" region="together" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The target, `item`, which is an `@Input()` property in the child component class, receives its value from the parent's property, `currentItem`. When you click delete, the child component raises an event, `deleteRequest`, which is the argument for the parent's `crossOffItem()` method.
|
||||
|
||||
The following diagram is of an `@Input()` and an `@Output()` on the same
|
||||
child component and shows the different parts of each:
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/inputs-outputs/input-output-diagram.svg" alt="Input/Output diagram">
|
||||
</div>
|
||||
|
||||
As the diagram shows, use inputs and outputs together in the same manner as using them separately. Here, the child selector is `<app-input-output>` with `item` and `deleteRequest` being `@Input()` and `@Output()`
|
||||
properties in the child component class. The property `currentItem` and the method `crossOffItem()` are both in the parent component class.
|
||||
|
||||
To combine property and event bindings using the banana-in-a-box
|
||||
syntax, `[()]`, see [Two-way Binding](guide/two-way-binding).
|
||||
|
||||
## `@Input()` and `@Output()` declarations
|
||||
|
||||
Instead of using the `@Input()` and `@Output()` decorators
|
||||
to declare inputs and outputs, you can identify
|
||||
members in the `inputs` and `outputs` arrays
|
||||
of the directive metadata, as in this example:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/in-the-metadata/in-the-metadata.component.ts" region="metadata" header="src/app/in-the-metadata/in-the-metadata.component.ts"></code-example>
|
||||
|
||||
While declaring `inputs` and `outputs` in the `@Directive` and `@Component`
|
||||
metadata is possible, it is a better practice to use the `@Input()` and `@Output()`
|
||||
class decorators instead, as follows:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/input-output/input-output.component.ts" region="input-output" header="src/app/input-output/input-output.component.ts"></code-example>
|
||||
|
||||
See the [Decorate input and output properties](guide/styleguide#decorate-input-and-output-properties) section of the
|
||||
[Style Guide](guide/styleguide) for details.
|
||||
|
||||
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
If you get a template parse error when trying to use inputs or outputs, but you know that the
|
||||
properties do indeed exist, double check
|
||||
that your properties are annotated with `@Input()` / `@Output()` or that you've declared
|
||||
them in an `inputs`/`outputs` array:
|
||||
|
||||
<code-example language="bash">
|
||||
Uncaught Error: Template parse errors:
|
||||
Can't bind to 'item' since it isn't a known property of 'app-item-detail'
|
||||
</code-example>
|
||||
|
||||
</div>
|
||||
|
||||
{@a aliasing-io}
|
||||
|
||||
## Aliasing inputs and outputs
|
||||
|
||||
Sometimes the public name of an input/output property should be different from the internal name. While it is a best practice to avoid this situation, Angular does
|
||||
offer a solution.
|
||||
|
||||
### Aliasing in the metadata
|
||||
|
||||
Alias inputs and outputs in the metadata using a colon-delimited (`:`) string with
|
||||
the directive property name on the left and the public alias on the right:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/aliasing/aliasing.component.ts" region="alias" header="src/app/aliasing/aliasing.component.ts"></code-example>
|
||||
|
||||
|
||||
### Aliasing with the `@Input()`/`@Output()` decorator
|
||||
|
||||
You can specify the alias for the property name by passing the alias name to the `@Input()`/`@Output()` decorator. The internal name remains as usual.
|
||||
|
||||
<code-example path="inputs-outputs/src/app/aliasing/aliasing.component.ts" region="alias-input-output" header="src/app/aliasing/aliasing.component.ts"></code-example>
|
@ -1,175 +0,0 @@
|
||||
# Interpolation and template expressions
|
||||
|
||||
Interpolation allows you to incorporate calculated strings into the text
|
||||
between HTML element tags and within attribute assignments. Template
|
||||
expressions are what you use to calculate those strings.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for all of
|
||||
the syntax and code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
## Interpolation `{{...}}`
|
||||
|
||||
Interpolation refers to embedding expressions into marked up text.
|
||||
By default, interpolation uses as its delimiter the double curly braces, `{{` and `}}`.
|
||||
|
||||
In the following snippet, `{{ currentCustomer }}` is an example of interpolation.
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="interpolation-example1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The text between the braces is often the name of a component
|
||||
property. Angular replaces that name with the
|
||||
string value of the corresponding component property.
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="component-property" header="src/app/app.component.html"></code-example>
|
||||
|
||||
In the example above, Angular evaluates the `title` and `itemImageUrl` properties
|
||||
and fills in the blanks, first displaying some title text and then an image.
|
||||
|
||||
More generally, the text between the braces is a **template expression**
|
||||
that Angular first **evaluates** and then **converts to a string**.
|
||||
The following interpolation illustrates the point by adding two numbers:
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="convert-string" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The expression can invoke methods of the host component such as `getVal()` in
|
||||
the following example:
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="invoke-method" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Angular evaluates all expressions in double curly braces,
|
||||
converts the expression results to strings, and links them with neighboring literal strings. Finally,
|
||||
it assigns this composite interpolated result to an **element or directive property**.
|
||||
|
||||
You appear to be inserting the result between element tags and assigning it to attributes.
|
||||
However, interpolation is a special syntax that Angular converts into a *property binding*.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
If you'd like to use something other than `{{` and `}}`, you can
|
||||
configure the interpolation delimiter via the
|
||||
[interpolation](api/core/Component#interpolation)
|
||||
option in the `Component` metadata.
|
||||
|
||||
</div>
|
||||
|
||||
## Template expressions
|
||||
|
||||
A template **expression** produces a value and appears within the double
|
||||
curly braces, `{{ }}`.
|
||||
Angular executes the expression and assigns it to a property of a binding target;
|
||||
the target could be an HTML element, a component, or a directive.
|
||||
|
||||
The interpolation braces in `{{1 + 1}}` surround the template expression `1 + 1`.
|
||||
In the property binding,
|
||||
a template expression appears in quotes to the right of the `=` symbol as in `[property]="expression"`.
|
||||
|
||||
In terms of syntax, template expressions are similar to JavaScript.
|
||||
Many JavaScript expressions are legal template expressions, with a few exceptions.
|
||||
|
||||
You can't use JavaScript expressions that have or promote side effects,
|
||||
including:
|
||||
|
||||
* Assignments (`=`, `+=`, `-=`, `...`)
|
||||
* Operators such as `new`, `typeof`, `instanceof`, etc.
|
||||
* Chaining expressions with <code>;</code> or <code>,</code>
|
||||
* The increment and decrement operators `++` and `--`
|
||||
* Some of the ES2015+ operators
|
||||
|
||||
Other notable differences from JavaScript syntax include:
|
||||
|
||||
* No support for the bitwise operators such as `|` and `&`
|
||||
* New [template expression operators](guide/template-expression-operators), such as `|`, `?.` and `!`
|
||||
|
||||
|
||||
## Expression context
|
||||
|
||||
The *expression context* is typically the _component_ instance.
|
||||
In the following snippets, the `recommended` within double curly braces and the
|
||||
`itemImageUrl2` in quotes refer to properties of the `AppComponent`.
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="component-context" header="src/app/app.component.html"></code-example>
|
||||
|
||||
An expression may also refer to properties of the _template's_ context
|
||||
such as a template input variable,
|
||||
<!-- link to built-in-directives#template-input-variables -->
|
||||
`let customer`, or a template reference variable, `#customerInput`.
|
||||
<!-- link to guide/template-ref-variables -->
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="template-input-variable" header="src/app/app.component.html (template input variable)"></code-example>
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="template-reference-variable" header="src/app/app.component.html (template reference variable)"></code-example>
|
||||
|
||||
The context for terms in an expression is a blend of the _template variables_,
|
||||
the directive's _context_ object (if it has one), and the component's _members_.
|
||||
If you reference a name that belongs to more than one of these namespaces,
|
||||
the template variable name takes precedence, followed by a name in the directive's _context_,
|
||||
and, lastly, the component's member names.
|
||||
|
||||
The previous example presents such a name collision. The component has a `customer`
|
||||
property and the `*ngFor` defines a `customer` template variable.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The `customer` in `{{customer.name}}`
|
||||
refers to the template input variable, not the component's property.
|
||||
|
||||
Template expressions cannot refer to anything in
|
||||
the global namespace, except `undefined`. They can't refer to
|
||||
`window` or `document`. Additionally, they
|
||||
can't call `console.log()` or `Math.max()` and they are restricted to referencing
|
||||
members of the expression context.
|
||||
|
||||
</div>
|
||||
|
||||
## Expression guidelines
|
||||
|
||||
When using template expressions follow these guidelines:
|
||||
|
||||
* [Simplicity](guide/interpolation#simplicity)
|
||||
* [Quick execution](guide/interpolation#quick-execution)
|
||||
* [No visible side effects](guide/interpolation#no-visible-side-effects)
|
||||
|
||||
### Simplicity
|
||||
|
||||
Although it's possible to write complex template expressions, it's a better
|
||||
practice to avoid them.
|
||||
|
||||
A property name or method call should be the norm, but an occasional Boolean negation, `!`, is OK.
|
||||
Otherwise, confine application and business logic to the component,
|
||||
where it is easier to develop and test.
|
||||
|
||||
### Quick execution
|
||||
|
||||
Angular executes template expressions after every change detection cycle.
|
||||
Change detection cycles are triggered by many asynchronous activities such as
|
||||
promise resolutions, HTTP results, timer events, key presses and mouse moves.
|
||||
|
||||
Expressions should finish quickly or the user experience may drag, especially on slower devices.
|
||||
Consider caching values when their computation is expensive.
|
||||
|
||||
### No visible side effects
|
||||
|
||||
A template expression should not change any application state other than the value of the
|
||||
target property.
|
||||
|
||||
This rule is essential to Angular's "unidirectional data flow" policy.
|
||||
You should never worry that reading a component value might change some other displayed value.
|
||||
The view should be stable throughout a single rendering pass.
|
||||
|
||||
An [idempotent](https://en.wikipedia.org/wiki/Idempotence) expression is ideal because
|
||||
it is free of side effects and improves Angular's change detection performance.
|
||||
In Angular terms, an idempotent expression always returns
|
||||
*exactly the same thing* until one of its dependent values changes.
|
||||
|
||||
Dependent values should not change during a single turn of the event loop.
|
||||
If an idempotent expression returns a string or a number, it returns the same string or number when called twice in a row. If the expression returns an object, including an `array`, it returns the same object *reference* when called twice in a row.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
There is one exception to this behavior that applies to `*ngFor`. `*ngFor` has `trackBy` functionality that can deal with referential inequality of objects when iterating over them. See [*ngFor with `trackBy`](guide/built-in-directives#ngfor-with-trackby) for details.
|
||||
|
||||
</div>
|
@ -292,59 +292,3 @@ To fix this problem, we recommend binding to the `selected` property on the `<op
|
||||
<option>
|
||||
</select>
|
||||
```
|
||||
|
||||
{@a forward-refs-directive-inputs}
|
||||
## Forward references to directive inputs accessed through local refs are no longer supported.
|
||||
|
||||
|
||||
### Basic example of change
|
||||
|
||||
|
||||
```ts
|
||||
@Directive({
|
||||
selector: '[myDir]',
|
||||
exportAs: 'myDir'
|
||||
})
|
||||
export class MyDir {
|
||||
@Input() message: string;
|
||||
}
|
||||
```
|
||||
|
||||
```html
|
||||
{{ myDir.name }}
|
||||
<div myDir #myDir="myDir" [name]="myName"></div>
|
||||
```
|
||||
|
||||
In the View Engine runtime, the above code would print out the name without any errors.
|
||||
In Ivy, the `myDir.name` binding will throw an `ExpressionChangedAfterItHasBeenCheckedError`.
|
||||
|
||||
|
||||
### Background
|
||||
|
||||
In the ViewEngine runtime, directive input bindings and element bindings were executed in different stages. Angular would process the template one full time to check directive inputs only (e.g. `[name]`), then process the whole template again to check element and text bindings only (e.g.`{{ myDir.name }}`). This meant that the `name` directive input would be checked before the `myDir.name` text binding despite their relative order in the template, which some users felt to be counterintuitive.
|
||||
|
||||
In contrast, Ivy processes the template in just one pass, so that bindings are checked in the same order that they are written in the template. In this case, it means that the `myDir.name` binding will be checked before the `name` input sets the property on the directive (and thus it will be `undefined`). Since the `myDir.name` property will be set by the time the next change detection pass runs, a change detection error is thrown.
|
||||
|
||||
### Example of error
|
||||
|
||||
Assuming that the value for `myName` is `Angular`, you should see an error that looks like
|
||||
|
||||
```
|
||||
Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: 'Angular'.
|
||||
```
|
||||
|
||||
### Recommended fix
|
||||
|
||||
To fix this problem, we recommend either getting the information for the binding directly from the host component (e.g. the `myName` property from our example) or to move the data binding after the directive has been declared so that the initial value is available on the first pass.
|
||||
|
||||
*Before*
|
||||
```html
|
||||
{{ myDir.name }}
|
||||
<div myDir #myDir="myDir" [name]="myName"></div>
|
||||
```
|
||||
|
||||
*After*
|
||||
```html
|
||||
{{ myName }}
|
||||
<div myDir [name]="myName"></div>
|
||||
```
|
||||
|
@ -2,20 +2,20 @@
|
||||
|
||||
The Angular team has worked hard to ensure Ivy is as backwards-compatible with the previous rendering engine ("View Engine") as possible.
|
||||
However, in rare cases, minor changes were necessary to ensure that the Angular's behavior was predictable and consistent, correcting issues in the View Engine implementation.
|
||||
In order to smooth the transition, we have provided [automated migrations](guide/updating-to-version-10#migrations) wherever possible so your application and library code is migrated automatically by the CLI.
|
||||
In order to smooth the transition, we have provided [automated migrations](guide/updating-to-version-9#migrations) wherever possible so your application and library code is migrated automatically by the CLI.
|
||||
That said, some applications will likely need to apply some manual updates.
|
||||
|
||||
{@a debugging}
|
||||
## How to debug errors with Ivy
|
||||
|
||||
In version 10, [a few deprecated APIs have been removed](guide/updating-to-version-10#removals) and there are a [few breaking changes](guide/updating-to-version-10#breaking-changes) unrelated to Ivy.
|
||||
In version 9, [a few deprecated APIs have been removed](guide/updating-to-version-9#removals) and there are a [few breaking changes](guide/updating-to-version-9#breaking-changes) unrelated to Ivy.
|
||||
If you're seeing errors after updating to version 9, you'll first want to rule those changes out.
|
||||
|
||||
To do so, temporarily [turn off Ivy](guide/ivy#opting-out-of-angular-ivy) in your `tsconfig.base.json` and re-start your app.
|
||||
To do so, temporarily [turn off Ivy](guide/ivy#opting-out-of-angular-ivy) in your `tsconfig.json` and re-start your app.
|
||||
|
||||
If you're still seeing the errors, they are not specific to Ivy. In this case, you may want to consult the [general version 10 guide](guide/updating-to-version-10). If you've opted into any of the new, stricter type-checking settings, you may also want to check out the [template type-checking guide](guide/template-typecheck).
|
||||
If you're still seeing the errors, they are not specific to Ivy. In this case, you may want to consult the [general version 9 guide](guide/updating-to-version-9). If you've opted into any of the stricter type-checking settings that are new with v9, you may also want to check out the [template type-checking guide](guide/template-typecheck).
|
||||
|
||||
If the errors are gone, switch back to Ivy by removing the changes to the `tsconfig.base.json` and review the list of expected changes below.
|
||||
If the errors are gone, switch back to Ivy by removing the changes to the `tsconfig.json` and review the list of expected changes below.
|
||||
|
||||
{@a payload-size-debugging}
|
||||
### Payload size debugging
|
||||
@ -63,7 +63,7 @@ Please note that these constants are not meant to be used by 3rd party library o
|
||||
|
||||
* Foreign functions or foreign constants in decorator metadata aren't statically resolvable (previously, you could import a constant or function from another compilation unit, like a library, and use that constant/function in your `@NgModule` definition).
|
||||
|
||||
* Forward references to directive inputs accessed through local refs are no longer supported by default. [details](guide/ivy-compatibility-examples#forward-refs-directive-inputs)
|
||||
* Forward references to directive inputs accessed through local refs are no longer supported by default.
|
||||
|
||||
* If there is both an unbound class attribute and a `[class]` binding, the classes in the unbound attribute will also be added (previously, the class binding would overwrite classes in the unbound attribute).
|
||||
|
||||
|
@ -311,7 +311,7 @@ ngOnInit() {
|
||||
}
|
||||
</code-example>
|
||||
|
||||
For more information with a working example, see the [routing tutorial section on preloading](guide/router-tutorial-toh#preloading-background-loading-of-feature-areas).
|
||||
For more information with a working example, see the [routing tutorial section on preloading](guide/router#preloading-background-loading-of-feature-areas).
|
||||
|
||||
|
||||
<hr>
|
||||
|
@ -495,7 +495,7 @@ for one turn of the browser's JavaScript cycle, which triggers a new change-dete
|
||||
|
||||
#### Write lean hook methods to avoid performance problems
|
||||
|
||||
When you run the *AfterView* sample, notice how frequently Angular calls `AfterViewChecked()`-often when there are no changes of interest.
|
||||
When you run the *AfterView* sample, notice how frequently Angular calls `AfterViewChecked()`$emdash;often when there are no changes of interest.
|
||||
Be very careful about how much logic or computation you put into one of these methods.
|
||||
|
||||
<div class="lightbox">
|
||||
@ -569,7 +569,7 @@ which can only be reached by querying for them via the property decorated with
|
||||
|
||||
{@a no-unidirectional-flow-worries}
|
||||
|
||||
<div class="alert is-helpful">
|
||||
<div class="alert is-helpful>
|
||||
|
||||
<header>No need to wait for content updates</header>
|
||||
|
||||
|
@ -1,55 +0,0 @@
|
||||
# Solution-style `tsconfig.json` migration
|
||||
|
||||
## What does this migration do?
|
||||
|
||||
This migration adds support to existing projects for TypeScript's new ["solution-style" tsconfig feature](https://devblogs.microsoft.com/typescript/announcing-typescript-3-9/#solution-style-tsconfig).
|
||||
|
||||
Support is added by making two changes:
|
||||
|
||||
1. Renaming the workspace-level `tsconfig.json` to `tsconfig.base.json`.
|
||||
All project [TypeScript configuration files](guide/typescript-configuration) will extend from this base which contains the common options used throughout the workspace.
|
||||
|
||||
2. Adding the solution `tsconfig.json` file at the root of the workspace.
|
||||
This `tsconfig.json` file will only contain references to project-level TypeScript configuration files and is only used by editors/IDEs.
|
||||
|
||||
As an example, the solution `tsconfig.json` for a new project is as follows:
|
||||
```json
|
||||
// This is a "Solution Style" tsconfig.json file, and is used by editors and TypeScript’s language server to improve development experience.
|
||||
// It is not intended to be used to perform a compilation.
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
},
|
||||
{
|
||||
"path": "./e2e/tsconfig.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Why is this migration necessary?
|
||||
|
||||
Solution-style `tsconfig.json` files provide an improved editing experience and fix several long-standing defects when editing files in an IDE.
|
||||
IDEs that leverage the TypeScript language service (for example, [Visual Studio Code](https://code.visualstudio.com)), will only use TypeScript configuration files that are named `tsconfig.json`.
|
||||
In complex projects, there may be more than one compilation unit and each of these units may have different settings and options.
|
||||
|
||||
With the Angular CLI, a project will have application code that will target a browser.
|
||||
It will also have unit tests that should not be included within the built application and that also need additional type information present (`jasmine` in this case).
|
||||
Both parts of the project also share some but not all of the code within the project.
|
||||
As a result, two separate TypeScript configuration files (`tsconfig.app.json` and `tsconfig.spec.json`) are needed to ensure that each part of the application is configured properly and that the right types are used for each part.
|
||||
Also if web workers are used within a project, an additional tsconfig (`tsconfig.worker.json`) is needed.
|
||||
Web workers use similar but incompatible types to the main browser application.
|
||||
This requires the additional configuration file to ensure that the web worker files use the appropriate types and will build successfully.
|
||||
|
||||
While the Angular build system knows about all of these TypeScript configuration files, an IDE using TypeScript's language service does not.
|
||||
Because of this, an IDE will not be able to properly analyze the code from each part of the project and may generate false errors or make suggestions that are incorrect for certain files.
|
||||
By leveraging the new solution-style tsconfig, the IDE can now be aware of the configuration of each part of a project.
|
||||
This allows each file to be treated appropriately based on its tsconfig.
|
||||
IDE features such as error/warning reporting and auto-suggestion will operate more effectively as well.
|
||||
|
||||
The TypeScript 3.9 release [blog post](https://devblogs.microsoft.com/typescript/announcing-typescript-3-9/#solution-style-tsconfig) also contains some additional information regarding this new feature.
|
@ -1,52 +0,0 @@
|
||||
# `tslib` direct dependency migration
|
||||
|
||||
## What does this migration do?
|
||||
|
||||
If you have any libraries within your workspace, this migration will convert `tslib` peer dependencies to direct dependencies for the libraries.
|
||||
TypeScript uses the `tslib` package to provide common helper functions used in compiled TypeScript code.
|
||||
The `tslib` version is also updated to `2.0.0` to support TypeScript 3.9.
|
||||
|
||||
Before:
|
||||
```json
|
||||
{
|
||||
"name": "my-lib",
|
||||
"version": "0.0.1",
|
||||
"peerDependencies": {
|
||||
"@angular/common": "^9.0.0",
|
||||
"@angular/core": "^9.0.0",
|
||||
"tslib": "^1.12.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
```json
|
||||
{
|
||||
"name": "my-lib",
|
||||
"version": "0.0.1",
|
||||
"peerDependencies": {
|
||||
"@angular/common": "^9.0.0",
|
||||
"@angular/core": "^9.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": "^2.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Why is this migration necessary?
|
||||
|
||||
The [`tslib`](https://github.com/Microsoft/tslib) is a runtime library for Typescript.
|
||||
The version of this library is bound to the version of the TypeScript compiler used to compile a library.
|
||||
Peer dependencies do not accurately represent this relationship between the runtime and the compiler.
|
||||
If `tslib` remained declared as a library peer dependency, it would be possible for some Angular workspaces to get into a state where the workspace could not satisfy `tslib` peer dependency requirements for multiple libraries, resulting in build-time or run-time errors.
|
||||
|
||||
As of TypeScript 3.9 (used by Angular v10), `tslib` version of 2.x is required to build new applications.
|
||||
However, older libraries built with previous version of TypeScript and already published to npm might need `tslib` 1.x.
|
||||
This migration makes it possible for code depending on incompatible versions of the `tslib` runtime library to remain interoperable.
|
||||
|
||||
|
||||
## Do I still need `tslib` as a dependency in my workspace `package.json`?
|
||||
|
||||
Yes.
|
||||
The `tslib` dependency declared in the `package.json` file of the workspace is used to build applications within this workspace, as well as run unit tests for workspace libraries, and is required.
|
@ -1,33 +0,0 @@
|
||||
# Update `module` and `target` compiler options migration
|
||||
|
||||
## What does this migration do?
|
||||
|
||||
This migration adjusts the [`target`](https://www.typescriptlang.org/v2/en/tsconfig#target) and [`module`](https://www.typescriptlang.org/v2/en/tsconfig#module) settings within the [TypeScript configuration files](guide/typescript-configuration) for the workspace.
|
||||
The changes to each option vary based on the builder or command that uses the TypeScript configuration file.
|
||||
Unless otherwise noted, changes are only made if the existing value was not changed since the project was created.
|
||||
This process helps ensure that intentional changes to the options are kept in place.
|
||||
|
||||
TypeScript Configuration File(s) | Changed Property | Existing Value | New Value
|
||||
------------- | ------------- | ------------- | ------------- | -------------
|
||||
`<workspace base>/tsconfig.base.json` | `"module"` | `"esnext"` | `"es2020"`
|
||||
Used in `browser` builder options (`ng build` for applications) | `"module"` | `"esnext"` | `"es2020"`
|
||||
Used in `ng-packgr` builder options (`ng build` for libraries) | `"module"` | `"esnext"` | `"es2020"`
|
||||
Used in `karma` builder options (`ng test` for applications) | `"module"` | `"esnext"` | `"es2020"`
|
||||
Used in `server` builder options (universal) | `"module"` | `"commonjs"` | _removed_
|
||||
Used in `server` builder options (universal) | `"target"` | _any_ | `"es2016"`
|
||||
Used in `protractor` builder options (`ng e2e` for applications) | `"target"` | `"es5"` | `"es2018"`
|
||||
|
||||
## Why is this migration necessary?
|
||||
|
||||
This migration provides improvements to the long-term supportability of projects by updating the projects to use recommended best practice compilation options.
|
||||
|
||||
For the functionality that executes on Node.js, such as Universal and Protractor, the new settings provide performance and troubleshooting benefits as well.
|
||||
The minimum Node.js version for the Angular CLI (v10.13) supports features in ES2018 and earlier.
|
||||
By targeting later ES versions, the compiler transforms less code and can use newer features directly.
|
||||
Since zone.js does not support native `async` and `await`, the universal builds still target ES2016.
|
||||
|
||||
## Why `"es2020"` instead of `"esnext"`?
|
||||
|
||||
In TypeScript 3.9, the behavior of the TypeScript compiler controlled by `module` is the same with both `"esnext"` and `"es2020"` values.
|
||||
This behavior can change in the future, because the `"esnext"` option could evolve in a backwards incompatible ways, resulting in build-time or run-time errors during a TypeScript update.
|
||||
As a result, code can become unstable. Using the `"es2020"` option mitigates this risk.
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user