Compare commits
298 Commits
10.0.8
...
9.0.0-rc.4
Author | SHA1 | Date | |
---|---|---|---|
7385e9d06d | |||
ef8b95abae | |||
fc2db27446 | |||
b05ce85391 | |||
7faa9bbc09 | |||
7402430d06 | |||
5a8d25dfc6 | |||
955a3129f0 | |||
e059df3bad | |||
a7b298a4fd | |||
00f8d6ac64 | |||
1b4fac192a | |||
7e6350ce2e | |||
9e5065a778 | |||
1eddb1ae15 | |||
9255dc3468 | |||
c5584b2dbc | |||
60db3505f6 | |||
6904319847 | |||
dda9b9ea7e | |||
e8ec296fdd | |||
4745aef9e8 | |||
a122311773 | |||
6bf258178d | |||
fec9f7dce5 | |||
d2784c7894 | |||
5cc362fbbf | |||
dee0c33a1d | |||
1d14f85dd6 | |||
5e530e917b | |||
781003fd2f | |||
cbc28f255d | |||
8a565c8814 | |||
d228801af4 | |||
978b500961 | |||
b659aa32c9 | |||
1d513e8978 | |||
d22f3d6f85 | |||
bbc8b0f142 | |||
ebe3229da5 | |||
caf5cffd53 | |||
cf420194ed | |||
420750bd05 | |||
7d8b112a91 | |||
abb8c90df9 | |||
efd626c4bc | |||
8c2ff79d04 | |||
457ac3ac46 | |||
688b188484 | |||
f63fca1e3a | |||
60570d0cb2 | |||
00f1ffbbb4 | |||
9d41b5bdd4 | |||
83989b879b | |||
290739f301 | |||
8ed7b73dc1 | |||
7b77ead88f | |||
27f775a65d | |||
f2bb9cc95e | |||
9248dba8fa | |||
1ffbde14ab | |||
4946be0b35 | |||
274ed2ca74 | |||
21ec7d92dd | |||
85a4a1ac60 | |||
e24ed8d0e2 | |||
229bfd507f | |||
af77e5289d | |||
b4c839ccb9 | |||
99e68d0318 | |||
971228b4f4 | |||
bda3c2245d | |||
63c9123924 | |||
aa4d2b785b | |||
719ca1d23c | |||
18574cfed1 | |||
ad9b9a3534 | |||
a54096ab5b | |||
e456e5833a | |||
4a42be27ee | |||
9719047df8 | |||
f1bf5b26d1 | |||
a528006d7a | |||
c1c04dc8ad | |||
90a9043abb | |||
a172644c6c | |||
d3825c20d5 | |||
c01fa1823f | |||
9a5334c75e | |||
250e6fdd39 | |||
196808eebb | |||
c6695faf47 | |||
3814674f9a | |||
e17f051601 | |||
ca5d7723ff | |||
1394781cef | |||
197f042fb1 | |||
fc6ad19089 | |||
90cd9682d2 | |||
80ecf12b4b | |||
b12fde4ceb | |||
94257ac8d3 | |||
fbd2133610 | |||
a09d60cb50 | |||
61cc7a3437 | |||
4e0eb3627d | |||
05a18cc4cb | |||
6da5230003 | |||
b8ba6b036c | |||
b31afc2aa9 | |||
3b5e1668ed | |||
7c7d432085 | |||
213e3c3e49 | |||
5267c92a93 | |||
595375f7a3 | |||
d92da1335d | |||
30ddadc4d7 | |||
dc8e300029 | |||
a7e2327212 | |||
a7d6829cde | |||
bc97c25efe | |||
49571bf11a | |||
14156bd262 | |||
e42fa81aa9 | |||
c7a3694eb9 | |||
839ac3c0a7 | |||
105616cd2b | |||
edd624b254 | |||
56801c74b9 | |||
01af94ccd7 | |||
456ea5cce4 | |||
1e78fafd37 | |||
83140f7926 | |||
b08bb411b9 | |||
1b4d264ccf | |||
05d5c4fc76 | |||
c126a6e3fc | |||
97ff04a7bd | |||
b744505620 | |||
b707c48817 | |||
2d7b015ed7 | |||
b53a1ac999 | |||
bc28ca7b0c | |||
b7c1a5e45f | |||
f136ddad0d | |||
5be23a309e | |||
6d06d9d3c6 | |||
b7c012f91b | |||
1b7aa05699 | |||
1218ce4f5f | |||
7ffbe54ef0 | |||
2f8c9e1990 | |||
bde55ecc91 | |||
aeaf530de6 | |||
66ecab6e8c | |||
f3d8f6adca | |||
a05e42ad09 | |||
0854dc8688 | |||
5926b2897f | |||
0405ddb521 | |||
1a9904d2f1 | |||
37243ce680 | |||
59a4b76b57 | |||
80cd7d7a40 | |||
e47638ec7c | |||
7567f2b8c8 | |||
ebf3afb7f0 | |||
d562625960 | |||
e57a8350e1 | |||
dafdf9a87b | |||
0e20453273 | |||
5bfcd8231a | |||
e641eaaae0 | |||
3074cdfea9 | |||
c182dea146 | |||
502fa906cd | |||
430293abe2 | |||
cba6b7dd20 | |||
09480d3a9d | |||
ca633535c5 | |||
9761ebe7bd | |||
9882a8215a | |||
0688a28be3 | |||
af2cca0c7a | |||
4a4888b276 | |||
d45bbccb58 | |||
d49c830064 | |||
12d67e0d31 | |||
d39b643553 | |||
84524583e9 | |||
a61fb76d51 | |||
b1d0a4f84d | |||
63c3569e2a | |||
aaa38cf3f3 | |||
a9d834fe69 | |||
987d2bd181 | |||
a16a57e52a | |||
1860a9edbc | |||
5fd0d15d86 | |||
8e5ed203bc | |||
06e36e5972 | |||
21bd8c9a2e | |||
1c1240c21a | |||
4c706086a7 | |||
93ba4c2418 | |||
3f6d9a9870 | |||
ba4f171fac | |||
744a3854f3 | |||
ac9fa2f2eb | |||
de8cf75ff5 | |||
5ad1e5f5ec | |||
b4d7a684f8 | |||
49e517d049 | |||
e1df98be17 | |||
1b489083bc | |||
9f10aa0d8c | |||
ecf38d48cf | |||
5f9a2d1cf8 | |||
8ed32e5e71 | |||
d67a38b7f5 | |||
f750f187d5 | |||
4e027fe3e4 | |||
1b0255c3b0 | |||
29852960c3 | |||
508bbfd92f | |||
e4cb91d373 | |||
71238a95d9 | |||
c22f15812c | |||
da01dbc459 | |||
37ae45e2ec | |||
4ec079f852 | |||
b75a21294f | |||
faaa96c737 | |||
c315881d04 | |||
bb9b8030d0 | |||
20e27a86d4 | |||
7c4366dce8 | |||
f8e9c1e6f1 | |||
4988094e7d | |||
9ab49def61 | |||
66157436f8 | |||
72796b98b1 | |||
ea83125df3 | |||
83626962cf | |||
5b292bf125 | |||
3160193719 | |||
9045e3e495 | |||
c5400616f8 | |||
f67802ddc0 | |||
ffb010d3ab | |||
f45d5dc331 | |||
9396b19631 | |||
343483cae0 | |||
682eaef690 | |||
011ecdf939 | |||
cdceb60bd0 | |||
4613639a02 | |||
f32ce01d93 | |||
3d13a6d318 | |||
46b5e4ae69 | |||
e6f383fe20 | |||
86d656bc67 | |||
c5737f4a19 | |||
0b998844c8 | |||
fc24a69a6b | |||
b789c891bb | |||
eb9ed8cc13 | |||
139b2e4f40 | |||
290ae43db3 | |||
c7f913d1ec | |||
ba68b560bc | |||
69fdcbd71c | |||
a6ddda8834 | |||
2910d1a65f | |||
811275cd15 | |||
c8c51a9879 | |||
33f6cd4799 | |||
c1bd3bc76a | |||
0248d6b8a7 | |||
4f69ff7e85 | |||
9df1178fe7 | |||
76e52c5297 | |||
83b635cb3f | |||
09cf0cd878 | |||
cb55f60c74 | |||
cd8333cf0d | |||
854a377232 | |||
8164d28b6c | |||
59b25da76b | |||
68380e4af2 | |||
4029c98f16 | |||
99ead47bff | |||
d09ad82293 | |||
4924d73b8e | |||
7bccef516f | |||
204620291e | |||
3419b5002f | |||
687582fd99 |
@ -6,4 +6,5 @@ aio/node_modules
|
|||||||
aio/tools/examples/shared/node_modules
|
aio/tools/examples/shared/node_modules
|
||||||
integration/bazel
|
integration/bazel
|
||||||
integration/bazel-schematics/demo
|
integration/bazel-schematics/demo
|
||||||
|
integration/platform-server/node_modules
|
||||||
packages/bazel/node_modules
|
packages/bazel/node_modules
|
||||||
|
33
.bazelrc
33
.bazelrc
@ -64,31 +64,12 @@ test --test_output=errors
|
|||||||
################################
|
################################
|
||||||
# Temporary Settings for Ivy #
|
# Temporary Settings for Ivy #
|
||||||
################################
|
################################
|
||||||
# to determine if the compiler used should be Ivy or ViewEngine one can use `--define=compile=aot` on
|
# To determine if the compiler used should be Ivy instead of ViewEngine, one can use `--config=ivy`
|
||||||
# any bazel target. This is a temporary flag until codebase is permanently switched to Ivy.
|
# on any bazel target. This is a temporary flag until codebase is permanently switched to Ivy.
|
||||||
build --define=compile=legacy
|
build --define=angular_ivy_enabled=False
|
||||||
|
|
||||||
################################
|
build:view-engine --define=angular_ivy_enabled=False
|
||||||
# Settings for rules_nodejs #
|
build:ivy --define=angular_ivy_enabled=True
|
||||||
################################
|
|
||||||
# Temporary define while angular depends on the legacy rollup_bundle rule.
|
|
||||||
# TODO: remove this setting after https://github.com/angular/angular/pull/33201 lands.
|
|
||||||
build --define=enable_legacy_rollup_rule=1
|
|
||||||
|
|
||||||
#######################
|
|
||||||
# Remote HTTP Caching #
|
|
||||||
#######################
|
|
||||||
build --remote_http_cache=https://storage.googleapis.com/angular-team-cache
|
|
||||||
build --remote_accept_cached=true
|
|
||||||
build --remote_upload_local_results=false
|
|
||||||
|
|
||||||
######################################
|
|
||||||
# Remote HTTP Caching writes support #
|
|
||||||
# Turn on these settings with #
|
|
||||||
# --config=-http-caching #
|
|
||||||
######################################
|
|
||||||
build:remote-http-caching --remote_upload_local_results=true
|
|
||||||
build:remote-http-caching --google_default_credentials
|
|
||||||
|
|
||||||
##################################
|
##################################
|
||||||
# Remote Build Execution support #
|
# Remote Build Execution support #
|
||||||
@ -108,6 +89,10 @@ build:remote --remote_timeout=600
|
|||||||
build:remote --jobs=150
|
build:remote --jobs=150
|
||||||
build:remote --google_default_credentials
|
build:remote --google_default_credentials
|
||||||
|
|
||||||
|
# Force remote exeuctions to consider the entire run as linux
|
||||||
|
build:remote --cpu=k8
|
||||||
|
build:remote --host_cpu=k8
|
||||||
|
|
||||||
# Toolchain and platform related flags
|
# Toolchain and platform related flags
|
||||||
build:remote --host_javabase=@rbe_ubuntu1604_angular//java:jdk
|
build:remote --host_javabase=@rbe_ubuntu1604_angular//java:jdk
|
||||||
build:remote --javabase=@rbe_ubuntu1604_angular//java:jdk
|
build:remote --javabase=@rbe_ubuntu1604_angular//java:jdk
|
||||||
|
@ -11,4 +11,7 @@ import %workspace%/.circleci/bazel.common.rc
|
|||||||
build --repository_cache=C:/Users/circleci/bazel_repository_cache
|
build --repository_cache=C:/Users/circleci/bazel_repository_cache
|
||||||
|
|
||||||
# All windows jobs run on master and should use http caching
|
# All windows jobs run on master and should use http caching
|
||||||
build --config=remote-http-caching
|
build --remote_http_cache=https://storage.googleapis.com/angular-team-cache
|
||||||
|
build --remote_accept_cached=true
|
||||||
|
build --remote_upload_local_results=true
|
||||||
|
build --google_default_credentials
|
||||||
|
@ -29,7 +29,7 @@ var_4_win: &cache_key_win_fallback v5-angular-win-node-12.0-
|
|||||||
|
|
||||||
# Cache key for the Material unit tests job. **Note** when updating the SHA in the cache keys,
|
# Cache key for the Material unit tests job. **Note** when updating the SHA in the cache keys,
|
||||||
# also update the SHA for the "MATERIAL_REPO_COMMIT" environment variable.
|
# also update the SHA for the "MATERIAL_REPO_COMMIT" environment variable.
|
||||||
var_5: &material_unit_tests_cache_key v5-angular-material-bc1c454391370e75cf604f94bc2e9131e9aef94e
|
var_5: &material_unit_tests_cache_key v5-angular-material-a5cad10cf9ca5db84c307d38d5594c3f1d89ae2b
|
||||||
var_6: &material_unit_tests_cache_key_fallback v5-angular-material-
|
var_6: &material_unit_tests_cache_key_fallback v5-angular-material-
|
||||||
|
|
||||||
# Workspace initially persisted by the `setup` job, and then enhanced by `build-npm-packages` and
|
# Workspace initially persisted by the `setup` job, and then enhanced by `build-npm-packages` and
|
||||||
@ -365,7 +365,7 @@ jobs:
|
|||||||
# Compile dependencies to ivy
|
# Compile dependencies to ivy
|
||||||
# Running `ngcc` here (instead of implicitly via `ng build`) allows us to take advantage of
|
# Running `ngcc` here (instead of implicitly via `ng build`) allows us to take advantage of
|
||||||
# the parallel, async mode speed-up (~20-25s on CI).
|
# the parallel, async mode speed-up (~20-25s on CI).
|
||||||
- run: yarn --cwd aio ivy-ngcc --properties es2015
|
- run: yarn --cwd aio ngcc --properties es2015
|
||||||
# Build aio
|
# Build aio
|
||||||
- run: yarn --cwd aio build --progress=false
|
- run: yarn --cwd aio build --progress=false
|
||||||
# Lint the code
|
# Lint the code
|
||||||
@ -502,13 +502,14 @@ jobs:
|
|||||||
- setup_circleci_bazel_config
|
- setup_circleci_bazel_config
|
||||||
- setup_bazel_rbe
|
- setup_bazel_rbe
|
||||||
|
|
||||||
- run: scripts/build-packages-dist.sh
|
- run: node scripts/build-packages-dist.js
|
||||||
|
|
||||||
# Save the npm packages from //packages/... for other workflow jobs to read
|
# Save the npm packages from //packages/... for other workflow jobs to read
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
root: *workspace_location
|
root: *workspace_location
|
||||||
paths:
|
paths:
|
||||||
- ng/dist/packages-dist
|
- ng/dist/packages-dist
|
||||||
|
- ng/dist/zone.js-dist
|
||||||
|
|
||||||
# Save dependencies and bazel repository cache to use on subsequent runs.
|
# Save dependencies and bazel repository cache to use on subsequent runs.
|
||||||
- save_cache:
|
- save_cache:
|
||||||
@ -529,7 +530,7 @@ jobs:
|
|||||||
- setup_circleci_bazel_config
|
- setup_circleci_bazel_config
|
||||||
- setup_bazel_rbe
|
- setup_bazel_rbe
|
||||||
|
|
||||||
- run: scripts/build-ivy-npm-packages.sh
|
- run: node scripts/build-ivy-npm-packages.js
|
||||||
|
|
||||||
# Save the npm packages from //packages/... for other workflow jobs to read
|
# Save the npm packages from //packages/... for other workflow jobs to read
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
@ -569,15 +570,25 @@ jobs:
|
|||||||
environment:
|
environment:
|
||||||
NG_PACKAGES_DIR: &ng_packages_dir 'dist/packages-dist'
|
NG_PACKAGES_DIR: &ng_packages_dir 'dist/packages-dist'
|
||||||
NG_PACKAGES_ARCHIVES_DIR: &ng_packages_archives_dir 'dist/packages-dist-archives'
|
NG_PACKAGES_ARCHIVES_DIR: &ng_packages_archives_dir 'dist/packages-dist-archives'
|
||||||
|
ZONEJS_PACKAGES_DIR: &zonejs_packages_dir 'dist/zone.js-dist'
|
||||||
|
ZONEJS_PACKAGES_ARCHIVES_DIR: &zonejs_packages_archives_dir 'dist/zone.js-dist-archives'
|
||||||
steps:
|
steps:
|
||||||
- custom_attach_workspace
|
- custom_attach_workspace
|
||||||
- init_environment
|
- init_environment
|
||||||
|
# Publish `@angular/*` packages.
|
||||||
- run:
|
- run:
|
||||||
name: Create artifacts
|
name: Create artifacts for @angular/* packages
|
||||||
command: ./scripts/ci/create-package-archives.sh $CI_PULL_REQUEST $CI_COMMIT $NG_PACKAGES_DIR $NG_PACKAGES_ARCHIVES_DIR
|
command: ./scripts/ci/create-package-archives.sh $CI_BRANCH $CI_COMMIT $NG_PACKAGES_DIR $NG_PACKAGES_ARCHIVES_DIR
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: *ng_packages_archives_dir
|
path: *ng_packages_archives_dir
|
||||||
destination: angular
|
destination: angular
|
||||||
|
# Publish `zone.js` package.
|
||||||
|
- run:
|
||||||
|
name: Create artifacts for zone.js package
|
||||||
|
command: ./scripts/ci/create-package-archives.sh $CI_BRANCH $CI_COMMIT $ZONEJS_PACKAGES_DIR $ZONEJS_PACKAGES_ARCHIVES_DIR
|
||||||
|
- store_artifacts:
|
||||||
|
path: *zonejs_packages_archives_dir
|
||||||
|
destination: zone.js
|
||||||
|
|
||||||
# This job updates the content of repos like github.com/angular/core-builds
|
# This job updates the content of repos like github.com/angular/core-builds
|
||||||
# for every green build on angular/angular.
|
# for every green build on angular/angular.
|
||||||
|
@ -84,7 +84,7 @@ setPublicVar MATERIAL_REPO_TMP_DIR "/tmp/material2"
|
|||||||
setPublicVar MATERIAL_REPO_URL "https://github.com/angular/material2.git"
|
setPublicVar MATERIAL_REPO_URL "https://github.com/angular/material2.git"
|
||||||
setPublicVar MATERIAL_REPO_BRANCH "master"
|
setPublicVar MATERIAL_REPO_BRANCH "master"
|
||||||
# **NOTE**: When updating the commit SHA, also update the cache key in the CircleCI "config.yml".
|
# **NOTE**: When updating the commit SHA, also update the cache key in the CircleCI "config.yml".
|
||||||
setPublicVar MATERIAL_REPO_COMMIT "bc1c454391370e75cf604f94bc2e9131e9aef94e"
|
setPublicVar MATERIAL_REPO_COMMIT "a5cad10cf9ca5db84c307d38d5594c3f1d89ae2b"
|
||||||
|
|
||||||
# Source `$BASH_ENV` to make the variables available immediately.
|
# Source `$BASH_ENV` to make the variables available immediately.
|
||||||
source $BASH_ENV;
|
source $BASH_ENV;
|
||||||
|
31
.devcontainer/README.md
Normal file
31
.devcontainer/README.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# VSCode Remote Development - Developing inside a Containers
|
||||||
|
|
||||||
|
This folder contains configuration files that can be used to opt into working on this repository in a [Docker container](https://www.docker.com/resources/what-container) via [VSCode](https://code.visualstudio.com/)'s Remote Development feature (see below).
|
||||||
|
|
||||||
|
Info on remote development and developing inside a container with VSCode:
|
||||||
|
- [VSCode: Remote Development](https://code.visualstudio.com/docs/remote/remote-overview)
|
||||||
|
- [VSCode: Developing inside a Container](https://code.visualstudio.com/docs/remote/containers)
|
||||||
|
- [VSCode: Remote Development FAQ](https://code.visualstudio.com/docs/remote/faq)
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
_Prerequisite: [Install Docker](https://docs.docker.com/install) on your local environment._
|
||||||
|
|
||||||
|
To get started, read and follow the instuctions in [Developing inside a Container](https://code.visualstudio.com/docs/remote/containers). The [.devcontainer/](.) directory contains pre-configured `devcontainer.json` and `Dockerfile` files, which you can use to set up remote development with a docker container.
|
||||||
|
|
||||||
|
In a nutshell, you need to:
|
||||||
|
- Install the [Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension.
|
||||||
|
- Copy [recommended-Dockerfile](./recommended-Dockerfile) to `Dockerfile` (and optionally tweak to suit your needs).
|
||||||
|
- Copy [recommended-devcontainer.json](./recommended-devcontainer.json) to `devcontainer.json` (and optionally tweak to suit your needs).
|
||||||
|
- Open VSCode and bring up the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette).
|
||||||
|
- Type `Remote-Containers: Open Folder in Container` and choose your local clone of [angular/angular](https://github.com/angular/angular).
|
||||||
|
|
||||||
|
The `.devcontainer/devcontainer.json` and `.devcontainer/Dockerfile` files are ignored by git, so you can have your own local versions. We may occasionally update the template files ([recommended-devcontainer.json](./recommended-devcontainer.json), [recommended-Dockerfile](./recommended-Dockerfile)), in which case you will need to manually update your local copies (if desired).
|
||||||
|
|
||||||
|
|
||||||
|
## Updating `recommended-devcontainer.json` and `recommended-Dockerfile`
|
||||||
|
|
||||||
|
You can update and commit the recommended config files (which people use as basis for their local configs), if you find that something is broken, out-of-date or can be improved.
|
||||||
|
|
||||||
|
Please, keep in mind that any changes you make will potentially be used by many people on different environments. Try to keep these config files cross-platform compatible and free of personal preferences.
|
@ -1,5 +1,5 @@
|
|||||||
# Image metadata and config.
|
# Image metadata and config.
|
||||||
FROM circleci/node:10-browsers
|
FROM circleci/node:10-browsers # This needs to be in sync with what we use on CI.
|
||||||
|
|
||||||
LABEL name="Angular dev environment" \
|
LABEL name="Angular dev environment" \
|
||||||
description="This image can be used to create a dev environment for building Angular." \
|
description="This image can be used to create a dev environment for building Angular." \
|
||||||
@ -15,7 +15,7 @@ USER root
|
|||||||
|
|
||||||
# Configure `Node.js`/`npm` and install utilities.
|
# Configure `Node.js`/`npm` and install utilities.
|
||||||
RUN npm config --global set user root
|
RUN npm config --global set user root
|
||||||
RUN npm install --global yarn@1.13.0 # This needs to be in sync with what we use on CI.
|
RUN npm install --global yarn@1.19.1 # This needs to be in sync with what we use on CI.
|
||||||
|
|
||||||
|
|
||||||
# Go! (And keep going.)
|
# Go! (And keep going.)
|
||||||
|
21
.github/CODEOWNERS
vendored
21
.github/CODEOWNERS
vendored
@ -50,6 +50,7 @@
|
|||||||
# gkalpak - George Kalpakas
|
# gkalpak - George Kalpakas
|
||||||
# IgorMinar - Igor Minar
|
# IgorMinar - Igor Minar
|
||||||
# JiaLiPassion - Jia Li
|
# JiaLiPassion - Jia Li
|
||||||
|
# JoostK - Joost Koehoorn
|
||||||
# josephperrott - Joey Perrott
|
# josephperrott - Joey Perrott
|
||||||
# kapunahelewong - Kapunahele Wong
|
# kapunahelewong - Kapunahele Wong
|
||||||
# kara - Kara Erickson
|
# kara - Kara Erickson
|
||||||
@ -131,6 +132,9 @@
|
|||||||
# ===========================================================
|
# ===========================================================
|
||||||
#
|
#
|
||||||
# - alxhub
|
# - alxhub
|
||||||
|
# - AndrewKushnir
|
||||||
|
# - kara
|
||||||
|
# - JoostK
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -344,6 +348,14 @@
|
|||||||
# - josephperrott
|
# - josephperrott
|
||||||
|
|
||||||
|
|
||||||
|
# ===========================================================
|
||||||
|
# @angular/fw-size-tracking
|
||||||
|
# ===========================================================
|
||||||
|
#
|
||||||
|
# - IgorMinar
|
||||||
|
# - kara
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
######################################################################################################
|
######################################################################################################
|
||||||
@ -887,7 +899,6 @@ testing/** @angular/fw-test
|
|||||||
/aio/content/guide/migration-injectable.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/migration-injectable.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/migration-localize.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/migration-localize.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/migration-module-with-providers.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/migration-module-with-providers.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/migration-ngcc.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/guide/updating-to-version-9.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/updating-to-version-9.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/ivy-compatibility.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/ivy-compatibility.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/ivy-compatibility-examples.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/ivy-compatibility-examples.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -946,6 +957,14 @@ testing/** @angular/fw-test
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ================================================
|
||||||
|
# Size tracking
|
||||||
|
# ================================================
|
||||||
|
|
||||||
|
/aio/scripts/_payload-limits.json @angular/fw-size-tracking
|
||||||
|
/integration/_payload-limits.json @angular/fw-size-tracking
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
# Special cases
|
# Special cases
|
||||||
# ================================================
|
# ================================================
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -13,11 +13,13 @@ pubspec.lock
|
|||||||
.c9
|
.c9
|
||||||
.idea/
|
.idea/
|
||||||
.devcontainer/*
|
.devcontainer/*
|
||||||
|
!.devcontainer/README.md
|
||||||
!.devcontainer/recommended-devcontainer.json
|
!.devcontainer/recommended-devcontainer.json
|
||||||
!.devcontainer/recommended-Dockerfile
|
!.devcontainer/recommended-Dockerfile
|
||||||
.settings/
|
.settings/
|
||||||
.vscode/launch.json
|
.vscode/launch.json
|
||||||
.vscode/settings.json
|
.vscode/settings.json
|
||||||
|
.vscode/tasks.json
|
||||||
*.swo
|
*.swo
|
||||||
modules/.settings
|
modules/.settings
|
||||||
modules/.vscode
|
modules/.vscode
|
||||||
|
18
.vscode/README.md
vendored
18
.vscode/README.md
vendored
@ -1,23 +1,25 @@
|
|||||||
# VSCode Configuration
|
# VSCode Configuration
|
||||||
|
|
||||||
This folder contains opt-in [Workspace Settings](https://code.visualstudio.com/docs/getstarted/settings) and [Extension Recommendations](https://code.visualstudio.com/docs/editor/extension-gallery#_workspace-recommended-extensions) that the Angular team recommends using when working on this repository.
|
This folder contains opt-in [Workspace Settings](https://code.visualstudio.com/docs/getstarted/settings), [Tasks](https://code.visualstudio.com/docs/editor/tasks), [Launch Configurations](https://code.visualstudio.com/Docs/editor/debugging#_launch-configurations) and [Extension Recommendations](https://code.visualstudio.com/docs/editor/extension-gallery#_workspace-recommended-extensions) that the Angular team recommends using when working on this repository.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
To use the recommended settings follow the steps below:
|
To use the recommended configurations follow the steps below:
|
||||||
|
|
||||||
- install <https://marketplace.visualstudio.com/items?itemName=xaver.clang-format>
|
- install the recommneded extensions in `.vscode/extensions.json`
|
||||||
- copy `.vscode/recommended-settings.json` to `.vscode/settings.json`
|
- copy (or link) `.vscode/recommended-settings.json` to `.vscode/settings.json`
|
||||||
|
- copy (or link) `.vscode/recommended-launch.json` to `.vscode/launch.json`
|
||||||
|
- copy (or link) `.vscode/recommended-tasks.json` to `.vscode/tasks.json`
|
||||||
- restart the editor
|
- restart the editor
|
||||||
|
|
||||||
If you already have your custom workspace settings you should instead manually merge the file content.
|
If you already have your custom workspace settings you should instead manually merge the file contents.
|
||||||
|
|
||||||
This isn't an automatic process so you will need to repeat it when settings are updated.
|
This isn't an automatic process so you will need to repeat it when settings are updated.
|
||||||
|
|
||||||
To see the recommended extensions select "Extensions: Show Recommended Extensions" in the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette).
|
To see the recommended extensions select "Extensions: Show Recommended Extensions" in the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette).
|
||||||
|
|
||||||
## Editing `.vscode/recommended-settings.json`
|
## Editing `.vscode/recommended-*.json` files
|
||||||
|
|
||||||
If you wish to add extra configuration items please keep in mind any settings you add here will be used by many users.
|
If you wish to add extra configuration items please keep in mind any modifications you make here will be used by many users.
|
||||||
|
|
||||||
Try to keep these settings to things that help facilitate the development process and avoid altering the user workflow whenever possible.
|
Try to keep these settings/configuations to things that help facilitate the development process and avoid altering the user workflow whenever possible.
|
||||||
|
85
.vscode/recommended-launch.json
vendored
Normal file
85
.vscode/recommended-launch.json
vendored
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Attach to bazel test ... --config=debug",
|
||||||
|
"type": "node",
|
||||||
|
"request": "attach",
|
||||||
|
"port": 9229,
|
||||||
|
"address": "localhost",
|
||||||
|
"restart": false,
|
||||||
|
"sourceMaps": true,
|
||||||
|
"localRoot": "${workspaceRoot}",
|
||||||
|
"remoteRoot": "${workspaceRoot}",
|
||||||
|
"stopOnEntry": false,
|
||||||
|
"timeout": 600000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Attach to bazel test ... --config=debug (no source maps)",
|
||||||
|
"type": "node",
|
||||||
|
"request": "attach",
|
||||||
|
"port": 9229,
|
||||||
|
"address": "localhost",
|
||||||
|
"restart": false,
|
||||||
|
"sourceMaps": false,
|
||||||
|
"localRoot": "${workspaceRoot}",
|
||||||
|
"remoteRoot": "${workspaceRoot}",
|
||||||
|
"stopOnEntry": false,
|
||||||
|
"timeout": 600000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "IVY:packages/core/test/acceptance",
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/node_modules/.bin/bazel",
|
||||||
|
"args": [
|
||||||
|
"test",
|
||||||
|
"--config=ivy",
|
||||||
|
"packages/core/test/acceptance",
|
||||||
|
"--config=debug"
|
||||||
|
],
|
||||||
|
"port": 9229,
|
||||||
|
"address": "localhost",
|
||||||
|
"restart": true,
|
||||||
|
"sourceMaps": true,
|
||||||
|
"timeout": 600000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "IVY:packages/core/test/render3",
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/node_modules/.bin/bazel",
|
||||||
|
"args": [
|
||||||
|
"test",
|
||||||
|
"--config=ivy",
|
||||||
|
"packages/core/test/render3",
|
||||||
|
"--config=debug"
|
||||||
|
],
|
||||||
|
"port": 9229,
|
||||||
|
"address": "localhost",
|
||||||
|
"restart": true,
|
||||||
|
"sourceMaps": true,
|
||||||
|
"timeout": 600000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "IVY:packages/core/test",
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/node_modules/.bin/bazel",
|
||||||
|
"args": [
|
||||||
|
"test",
|
||||||
|
"--config=ivy",
|
||||||
|
"packages/core/test",
|
||||||
|
"--config=debug"
|
||||||
|
],
|
||||||
|
"port": 9229,
|
||||||
|
"address": "localhost",
|
||||||
|
"restart": true,
|
||||||
|
"sourceMaps": true,
|
||||||
|
"timeout": 600000,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
113
.vscode/recommended-tasks.json
vendored
Normal file
113
.vscode/recommended-tasks.json
vendored
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
{
|
||||||
|
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
|
// for the documentation about the tasks.json format
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "IVY:packages/core/test/...",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "${workspaceFolder}/node_modules/.bin/bazel",
|
||||||
|
"args": [
|
||||||
|
"test",
|
||||||
|
"--config=ivy",
|
||||||
|
"packages/core/test",
|
||||||
|
"packages/core/test/acceptance",
|
||||||
|
"packages/core/test/render3",
|
||||||
|
],
|
||||||
|
"group": "test",
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "dedicated",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "VE:packages/core/test/...",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "${workspaceFolder}/node_modules/.bin/bazel",
|
||||||
|
"args": [
|
||||||
|
"test",
|
||||||
|
"packages/core/test",
|
||||||
|
"packages/core/test/acceptance",
|
||||||
|
"packages/core/test/render3",
|
||||||
|
],
|
||||||
|
"group": "test",
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "dedicated",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "IVY:packages/core/test/acceptance",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "${workspaceFolder}/node_modules/.bin/bazel",
|
||||||
|
"args": [
|
||||||
|
"test",
|
||||||
|
"--config=ivy",
|
||||||
|
"packages/core/test/acceptance",
|
||||||
|
],
|
||||||
|
"group": "test",
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "dedicated",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "VE:packages/core/test/acceptance",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "${workspaceFolder}/node_modules/.bin/bazel",
|
||||||
|
"args": [
|
||||||
|
"test",
|
||||||
|
"packages/core/test/acceptance",
|
||||||
|
],
|
||||||
|
"group": "test",
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "dedicated",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "IVY:packages/core/test",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "${workspaceFolder}/node_modules/.bin/bazel",
|
||||||
|
"args": [
|
||||||
|
"test",
|
||||||
|
"--config=ivy",
|
||||||
|
"packages/core/test",
|
||||||
|
],
|
||||||
|
"group": "test",
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "dedicated",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "VE:packages/core/test",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "${workspaceFolder}/node_modules/.bin/bazel",
|
||||||
|
"args": [
|
||||||
|
"test",
|
||||||
|
"packages/core/test",
|
||||||
|
],
|
||||||
|
"group": "test",
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "dedicated",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "IVY:packages/core/test/render3",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "${workspaceFolder}/node_modules/.bin/bazel",
|
||||||
|
"args": [
|
||||||
|
"test",
|
||||||
|
"--config=ivy",
|
||||||
|
"packages/core/test/render3",
|
||||||
|
],
|
||||||
|
"group": "test",
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "dedicated",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
161
CHANGELOG.md
161
CHANGELOG.md
@ -1,3 +1,162 @@
|
|||||||
|
<a name="9.0.0-rc.4"></a>
|
||||||
|
# [9.0.0-rc.4](https://github.com/angular/angular/compare/9.0.0-rc.3...9.0.0-rc.4) (2019-11-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** ng_module should not emit shim files under bazel and Ivy ([#33765](https://github.com/angular/angular/issues/33765)) ([e24ed8d](https://github.com/angular/angular/commit/e24ed8d))
|
||||||
|
* **bazel:** update to tsickle 0.37.1 to fix peerDep warnings ([#33788](https://github.com/angular/angular/issues/33788)) ([719ca1d](https://github.com/angular/angular/commit/719ca1d))
|
||||||
|
* **core:** allow css custom variables/properties in the style sanitizer ([#33841](https://github.com/angular/angular/issues/33841)) ([61cc7a3](https://github.com/angular/angular/commit/61cc7a3)), closes [#23485](https://github.com/angular/angular/issues/23485) [#23485](https://github.com/angular/angular/issues/23485)
|
||||||
|
* **core:** remove deprecated and defunct wtf* apis ([#33949](https://github.com/angular/angular/issues/33949)) ([cf42019](https://github.com/angular/angular/commit/cf42019))
|
||||||
|
* **ivy:** avoid infinite recursion when evaluation source files ([#33772](https://github.com/angular/angular/issues/33772)) ([b12fde4](https://github.com/angular/angular/commit/b12fde4)), closes [#33734](https://github.com/angular/angular/issues/33734)
|
||||||
|
* **ivy:** avoid using stale cache in TestBed if module overrides are defined ([#33787](https://github.com/angular/angular/issues/33787)) ([fbd2133](https://github.com/angular/angular/commit/fbd2133))
|
||||||
|
* **ivy:** handle non-standard input/output names in template type checking ([#33741](https://github.com/angular/angular/issues/33741)) ([94257ac](https://github.com/angular/angular/commit/94257ac)), closes [#33590](https://github.com/angular/angular/issues/33590)
|
||||||
|
* **ivy:** i18n - ensure that escaped chars are handled in localized strings ([#34065](https://github.com/angular/angular/issues/34065)) ([00f8d6a](https://github.com/angular/angular/commit/00f8d6a))
|
||||||
|
* **ivy:** prevent unknown element check for AOT-compiled components ([#34024](https://github.com/angular/angular/issues/34024)) ([955a312](https://github.com/angular/angular/commit/955a312))
|
||||||
|
* **ivy:** remove TNodeType assertion from `directiveInject` instruction ([#33948](https://github.com/angular/angular/issues/33948)) ([90a9043](https://github.com/angular/angular/commit/90a9043))
|
||||||
|
* **ivy:** reset style property using ngStyle fix ([#33920](https://github.com/angular/angular/issues/33920)) ([b8ba6b0](https://github.com/angular/angular/commit/b8ba6b0))
|
||||||
|
* **ivy:** run pre-order hooks in injection order ([#34026](https://github.com/angular/angular/issues/34026)) ([ebe3229](https://github.com/angular/angular/commit/ebe3229)), closes [#32522](https://github.com/angular/angular/issues/32522)
|
||||||
|
* **ivy:** support ICUs without "other" cases ([#34042](https://github.com/angular/angular/issues/34042)) ([781003f](https://github.com/angular/angular/commit/781003f))
|
||||||
|
* **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//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))
|
||||||
|
* **ngcc:** do not crash on packages that specify typings as an array ([#33973](https://github.com/angular/angular/issues/33973)) ([e456e58](https://github.com/angular/angular/commit/e456e58)), closes [#33646](https://github.com/angular/angular/issues/33646)
|
||||||
|
* **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 [/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))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **language-service:** completions support for indexed types ([#34047](https://github.com/angular/angular/issues/34047)) ([8a565c8](https://github.com/angular/angular/commit/8a565c8)), closes [angular/vscode-ng-language-service#110](https://github.com/angular/vscode-ng-language-service/issues/110) [angular/vscode-ng-language-service#277](https://github.com/angular/vscode-ng-language-service/issues/277)
|
||||||
|
* **language-service:** completions support for tuple array ([#33928](https://github.com/angular/angular/issues/33928)) ([7faa9bb](https://github.com/angular/angular/commit/7faa9bb))
|
||||||
|
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* **ivy:** do no work if moving a `viewRef` to the same position ([#34052](https://github.com/angular/angular/issues/34052)) ([d228801](https://github.com/angular/angular/commit/d228801))
|
||||||
|
* **ivy:** fix creation time micro-benchmarks ([#34031](https://github.com/angular/angular/issues/34031)) ([457ac3a](https://github.com/angular/angular/commit/457ac3a))
|
||||||
|
* **ivy:** R3TestBed - Do not process NgModuleDefs that have already been processed ([#33863](https://github.com/angular/angular/issues/33863)) ([05a18cc](https://github.com/angular/angular/commit/05a18cc))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="9.0.0-rc.3"></a>
|
||||||
|
# [9.0.0-rc.3](https://github.com/angular/angular/compare/9.0.0-rc.2...9.0.0-rc.3) (2019-11-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** add terser as an optional peer dependency ([#33891](https://github.com/angular/angular/issues/33891)) ([2d7b015](https://github.com/angular/angular/commit/2d7b015))
|
||||||
|
* **compiler-cli:** Refactor getTsTypeFromBuiltinType ([#33778](https://github.com/angular/angular/issues/33778)) ([09480d3](https://github.com/angular/angular/commit/09480d3))
|
||||||
|
* **core:** make QueryList implement Iterable in the type system ([#33536](https://github.com/angular/angular/issues/33536)) ([49571bf](https://github.com/angular/angular/commit/49571bf)), closes [#29842](https://github.com/angular/angular/issues/29842)
|
||||||
|
* **ivy:** always re-analyze the program during incremental rebuilds ([#33862](https://github.com/angular/angular/issues/33862)) ([30ddadc](https://github.com/angular/angular/commit/30ddadc)), closes [#32388](https://github.com/angular/angular/issues/32388)
|
||||||
|
* **ivy:** avoid cyclical dependency in imports ([#33831](https://github.com/angular/angular/issues/33831)) ([a61fb76](https://github.com/angular/angular/commit/a61fb76))
|
||||||
|
* **ivy:** constant object literals shared across element and component instances ([#33705](https://github.com/angular/angular/issues/33705)) ([93ba4c2](https://github.com/angular/angular/commit/93ba4c2))
|
||||||
|
* **ivy:** don't infer template context types when in full mode ([#33537](https://github.com/angular/angular/issues/33537)) ([595375f](https://github.com/angular/angular/commit/595375f)), closes [#33527](https://github.com/angular/angular/issues/33527)
|
||||||
|
* **ivy:** emit fs-relative paths when rootDir(s) aren't in effect ([#33828](https://github.com/angular/angular/issues/33828)) ([14156bd](https://github.com/angular/angular/commit/14156bd)), closes [#33659](https://github.com/angular/angular/issues/33659) [#33562](https://github.com/angular/angular/issues/33562)
|
||||||
|
* **ivy:** ExpressionChangedAfterItHasBeenCheckedError for SafeValue ([#33749](https://github.com/angular/angular/issues/33749)) ([cba6b7d](https://github.com/angular/angular/commit/cba6b7d)), closes [#33448](https://github.com/angular/angular/issues/33448)
|
||||||
|
* **ivy:** extend assertion in `directiveInject` function to support IcuContainers ([#33832](https://github.com/angular/angular/issues/33832)) ([8452458](https://github.com/angular/angular/commit/8452458))
|
||||||
|
* **ivy:** i18n - ensure that colons in i18n metadata are not rendered ([#33820](https://github.com/angular/angular/issues/33820)) ([bc28ca7](https://github.com/angular/angular/commit/bc28ca7))
|
||||||
|
* **ivy:** i18n - support "\", "`" and "${" sequences in i18n messages ([#33820](https://github.com/angular/angular/issues/33820)) ([b53a1ac](https://github.com/angular/angular/commit/b53a1ac))
|
||||||
|
* **ivy:** move setClassMetadata calls into a pure iife ([#33337](https://github.com/angular/angular/issues/33337)) ([213e3c3](https://github.com/angular/angular/commit/213e3c3))
|
||||||
|
* **ivy:** properly insert views before ng-container with injected ViewContainerRef ([#33853](https://github.com/angular/angular/issues/33853)) ([c7a3694](https://github.com/angular/angular/commit/c7a3694))
|
||||||
|
* **ivy:** properly insert views into ViewContainerRef injected by querying <ng-container> ([#33816](https://github.com/angular/angular/issues/33816)) ([f136dda](https://github.com/angular/angular/commit/f136dda))
|
||||||
|
* **ivy:** report watch mode diagnostics correctly ([#33862](https://github.com/angular/angular/issues/33862)) ([d92da13](https://github.com/angular/angular/commit/d92da13)), closes [#32213](https://github.com/angular/angular/issues/32213)
|
||||||
|
* **ivy:** reset style property value defined using [style.prop.px] ([#33780](https://github.com/angular/angular/issues/33780)) ([de8cf75](https://github.com/angular/angular/commit/de8cf75))
|
||||||
|
* **ivy:** retain JIT metadata unless JIT mode is explicitly disabled ([#33671](https://github.com/angular/angular/issues/33671)) ([5267c92](https://github.com/angular/angular/commit/5267c92))
|
||||||
|
* **ivy:** shadow all DOM properties in `DebugElement.properties` ([#33781](https://github.com/angular/angular/issues/33781)) ([5be23a3](https://github.com/angular/angular/commit/5be23a3)), closes [#33695](https://github.com/angular/angular/issues/33695)
|
||||||
|
* **ivy:** support for #id bootstrap selectors ([#33784](https://github.com/angular/angular/issues/33784)) ([9761ebe](https://github.com/angular/angular/commit/9761ebe)), closes [#33485](https://github.com/angular/angular/issues/33485)
|
||||||
|
* **language-service:** Function alias should be callable ([#33782](https://github.com/angular/angular/issues/33782)) ([ca63353](https://github.com/angular/angular/commit/ca63353))
|
||||||
|
* **language-service:** Provide completions for attribute values ([#33839](https://github.com/angular/angular/issues/33839)) ([0e20453](https://github.com/angular/angular/commit/0e20453))
|
||||||
|
* **language-service:** Recompute analyzed modules only when source files change ([#33806](https://github.com/angular/angular/issues/33806)) ([9882a82](https://github.com/angular/angular/commit/9882a82))
|
||||||
|
* **language-service:** Remove getTemplateReferences() from LanguageService API ([#33807](https://github.com/angular/angular/issues/33807)) ([0688a28](https://github.com/angular/angular/commit/0688a28))
|
||||||
|
* **ngcc:** always add exports for `ModuleWithProviders` references ([#33875](https://github.com/angular/angular/issues/33875)) ([f3d8f6a](https://github.com/angular/angular/commit/f3d8f6a)), closes [#33701](https://github.com/angular/angular/issues/33701)
|
||||||
|
* **ngcc:** correctly associate decorators with aliased classes ([#33878](https://github.com/angular/angular/issues/33878)) ([59a4b76](https://github.com/angular/angular/commit/59a4b76))
|
||||||
|
* **ngcc:** correctly include internal .d.ts files ([#33875](https://github.com/angular/angular/issues/33875)) ([0854dc8](https://github.com/angular/angular/commit/0854dc8))
|
||||||
|
* **ngcc:** do not emit ES2015 code in ES5 files ([#33514](https://github.com/angular/angular/issues/33514)) ([06e36e5](https://github.com/angular/angular/commit/06e36e5)), closes [#32665](https://github.com/angular/angular/issues/32665)
|
||||||
|
* **ngcc:** generate correct metadata for classes with getter/setter properties ([#33514](https://github.com/angular/angular/issues/33514)) ([21bd8c9](https://github.com/angular/angular/commit/21bd8c9)), closes [#30569](https://github.com/angular/angular/issues/30569)
|
||||||
|
* **ngcc:** properly detect origin of constructor param types ([#33901](https://github.com/angular/angular/issues/33901)) ([05d5c4f](https://github.com/angular/angular/commit/05d5c4f)), closes [#33677](https://github.com/angular/angular/issues/33677)
|
||||||
|
* **router:** make routerLinkActive work with query params which contain arrays ([#22666](https://github.com/angular/angular/issues/22666)) ([8e5ed20](https://github.com/angular/angular/commit/8e5ed20)), closes [#22223](https://github.com/angular/angular/issues/22223)
|
||||||
|
* **zone.js:** fixes typo of zone.js patch vrdisplaydisconnected property ([#33581](https://github.com/angular/angular/issues/33581)) ([1b7aa05](https://github.com/angular/angular/commit/1b7aa05)), closes [#33579](https://github.com/angular/angular/issues/33579)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **bazel:** update ng-add to use bazel v1.1.0 ([#33813](https://github.com/angular/angular/issues/33813)) ([b1d0a4f](https://github.com/angular/angular/commit/b1d0a4f))
|
||||||
|
* **core:** missing-injectable migration should migrate empty object literal providers ([#33709](https://github.com/angular/angular/issues/33709)) ([b7c012f](https://github.com/angular/angular/commit/b7c012f))
|
||||||
|
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* **ivy:** add micro-benchmark focused on directive input update ([#33798](https://github.com/angular/angular/issues/33798)) ([edd624b](https://github.com/angular/angular/commit/edd624b))
|
||||||
|
* **ivy:** don't store public input names in two places ([#33798](https://github.com/angular/angular/issues/33798)) ([105616c](https://github.com/angular/angular/commit/105616c))
|
||||||
|
* **ivy:** extract template's instruction first create pass processing ([#33856](https://github.com/angular/angular/issues/33856)) ([01af94c](https://github.com/angular/angular/commit/01af94c))
|
||||||
|
* **ivy:** Improve performance of transplanted views ([#33702](https://github.com/angular/angular/issues/33702)) ([a16a57e](https://github.com/angular/angular/commit/a16a57e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="9.0.0-rc.2"></a>
|
||||||
|
# [9.0.0-rc.2](https://github.com/angular/angular/compare/9.0.0-rc.1...9.0.0-rc.2) (2019-11-13)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **common:** rerun cldr to remove <20> characters ([#33699](https://github.com/angular/angular/issues/33699)) ([011ecdf](https://github.com/angular/angular/commit/011ecdf))
|
||||||
|
* **common:** update CLDR generated files after change to npm sources ([#33634](https://github.com/angular/angular/issues/33634)) ([59b25da](https://github.com/angular/angular/commit/59b25da))
|
||||||
|
* **common:** update CLDR generated files to 36.0.0 ([#33584](https://github.com/angular/angular/issues/33584)) ([c1bd3bc](https://github.com/angular/angular/commit/c1bd3bc))
|
||||||
|
* **compiler:** correctly parse attributes with a dot in the name ([#32256](https://github.com/angular/angular/issues/32256)) ([687582f](https://github.com/angular/angular/commit/687582f))
|
||||||
|
* **compiler-cli:** Fix typo $implict ([#33633](https://github.com/angular/angular/issues/33633)) ([7bccef5](https://github.com/angular/angular/commit/7bccef5))
|
||||||
|
* **compiler-cli:** Pass SourceFile to getFullText() ([#33660](https://github.com/angular/angular/issues/33660)) ([33f6cd4](https://github.com/angular/angular/commit/33f6cd4))
|
||||||
|
* **core:** remove ngcc postinstall migration ([#33727](https://github.com/angular/angular/issues/33727)) ([508bbfd](https://github.com/angular/angular/commit/508bbfd))
|
||||||
|
* **core:** support `ngInjectableDef` on types with inherited `ɵprov` ([#33732](https://github.com/angular/angular/issues/33732)) ([4ec079f](https://github.com/angular/angular/commit/4ec079f))
|
||||||
|
* **ivy:** auto register NgModules with ID ([#33663](https://github.com/angular/angular/issues/33663)) ([4988094](https://github.com/angular/angular/commit/4988094))
|
||||||
|
* **ivy:** better support for i18n attributes on <ng-container>s ([#33599](https://github.com/angular/angular/issues/33599)) ([2046202](https://github.com/angular/angular/commit/2046202))
|
||||||
|
* **ivy:** ComponentFactory.create should clear host element content ([#33487](https://github.com/angular/angular/issues/33487)) ([d67a38b](https://github.com/angular/angular/commit/d67a38b))
|
||||||
|
* **ivy:** ensure module scope is rebuilt on dependent change ([#33522](https://github.com/angular/angular/issues/33522)) ([71238a9](https://github.com/angular/angular/commit/71238a9)), closes [#32416](https://github.com/angular/angular/issues/32416)
|
||||||
|
* **ivy:** ensure that the correct `document` is available ([#33712](https://github.com/angular/angular/issues/33712)) ([8362696](https://github.com/angular/angular/commit/8362696)), closes [#33651](https://github.com/angular/angular/issues/33651)
|
||||||
|
* **ivy:** Handle overrides for {providedIn: AModule} in R3TestBed ([#33606](https://github.com/angular/angular/issues/33606)) ([d09ad82](https://github.com/angular/angular/commit/d09ad82))
|
||||||
|
* **ivy:** match directives on namespaced elements ([#33555](https://github.com/angular/angular/issues/33555)) ([99ead47](https://github.com/angular/angular/commit/99ead47)), closes [#32061](https://github.com/angular/angular/issues/32061)
|
||||||
|
* **ivy:** properly determine the first native node of a view ([#33627](https://github.com/angular/angular/issues/33627)) ([811275c](https://github.com/angular/angular/commit/811275c))
|
||||||
|
* **ivy:** properly insert views in front of empty views ([#33647](https://github.com/angular/angular/issues/33647)) ([c5737f4](https://github.com/angular/angular/commit/c5737f4))
|
||||||
|
* **ivy:** properly insert views in front of views with an empty element container ([#33647](https://github.com/angular/angular/issues/33647)) ([0b99884](https://github.com/angular/angular/commit/0b99884))
|
||||||
|
* **ivy:** provider override via TestBed should remove old providers from the list ([#33706](https://github.com/angular/angular/issues/33706)) ([f45d5dc](https://github.com/angular/angular/commit/f45d5dc))
|
||||||
|
* **ivy:** recompile component when template changes in ngc watch mode ([#33551](https://github.com/angular/angular/issues/33551)) ([da01dbc](https://github.com/angular/angular/commit/da01dbc)), closes [#32869](https://github.com/angular/angular/issues/32869)
|
||||||
|
* **ivy:** recompile component when template changes in ngc watch mode ([#33551](https://github.com/angular/angular/issues/33551)) ([cd8333c](https://github.com/angular/angular/commit/cd8333c)), closes [#32869](https://github.com/angular/angular/issues/32869)
|
||||||
|
* **ivy:** Run ChangeDetection on transplanted views ([#33644](https://github.com/angular/angular/issues/33644)) ([37ae45e](https://github.com/angular/angular/commit/37ae45e)), closes [#33393](https://github.com/angular/angular/issues/33393)
|
||||||
|
* **language-service:** Resolve template variable in nested ngFor ([#33676](https://github.com/angular/angular/issues/33676)) ([6615743](https://github.com/angular/angular/commit/6615743))
|
||||||
|
* **ngcc:** add default config for `ng2-dragula` ([#33797](https://github.com/angular/angular/issues/33797)) ([ecf38d4](https://github.com/angular/angular/commit/ecf38d4)), closes [#33718](https://github.com/angular/angular/issues/33718)
|
||||||
|
* **ngcc:** add reexports only once ([#33658](https://github.com/angular/angular/issues/33658)) ([83b635c](https://github.com/angular/angular/commit/83b635c))
|
||||||
|
* **ngcc:** ensure that adjacent statements go after helper calls ([#33689](https://github.com/angular/angular/issues/33689)) ([c540061](https://github.com/angular/angular/commit/c540061))
|
||||||
|
* generate the new locale files ([#33682](https://github.com/angular/angular/issues/33682)) ([72796b9](https://github.com/angular/angular/commit/72796b9))
|
||||||
|
* resolve event listeners not correct when registered outside of ngZone ([#33711](https://github.com/angular/angular/issues/33711)) ([9045e3e](https://github.com/angular/angular/commit/9045e3e)), closes [#33687](https://github.com/angular/angular/issues/33687)
|
||||||
|
* use full cldr data to support all locales ([#33682](https://github.com/angular/angular/issues/33682)) ([ea83125](https://github.com/angular/angular/commit/ea83125)), closes [#33681](https://github.com/angular/angular/issues/33681)
|
||||||
|
* **ngcc:** remove `__decorator` calls even when part of the IIFE return statement ([#33777](https://github.com/angular/angular/issues/33777)) ([e1df98b](https://github.com/angular/angular/commit/e1df98b))
|
||||||
|
* **ngcc:** support minified ES5 scenarios ([#33777](https://github.com/angular/angular/issues/33777)) ([49e517d](https://github.com/angular/angular/commit/49e517d))
|
||||||
|
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* **core:** Avoid unnecessary creating provider factory ([#33742](https://github.com/angular/angular/issues/33742)) ([c315881](https://github.com/angular/angular/commit/c315881))
|
||||||
|
|
||||||
|
|
||||||
|
### Reverts
|
||||||
|
|
||||||
|
* "fix(ivy): recompile component when template changes in ngc watch mode ([#33551](https://github.com/angular/angular/issues/33551))" ([#33661](https://github.com/angular/angular/issues/33661)) ([cb55f60](https://github.com/angular/angular/commit/cb55f60))
|
||||||
|
* fix(ivy): Only restore registered modules if user compiles modules with TestBed ([#32944](https://github.com/angular/angular/issues/32944)) ([#33663](https://github.com/angular/angular/issues/33663)) ([f8e9c1e](https://github.com/angular/angular/commit/f8e9c1e))
|
||||||
|
* fix(ivy): R3TestBed should clean up registered modules after each test ([#32872](https://github.com/angular/angular/issues/32872)) ([#33663](https://github.com/angular/angular/issues/33663)) ([7c4366d](https://github.com/angular/angular/commit/7c4366d))
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* **i18n:** The CLDR data has been updated to v36.0.0, which may cause some localized data strings to change. For example, the space separator used in numbers in the `fr` locales changed from `\xa0` to `\u202f` ([c1bd3bc](https://github.com/angular/angular/commit/c1bd3bc))
|
||||||
|
|
||||||
<a name="9.0.0-rc.1"></a>
|
<a name="9.0.0-rc.1"></a>
|
||||||
# [9.0.0-rc.1](https://github.com/angular/angular/compare/9.0.0-rc.0...9.0.0-rc.1) (2019-11-06)
|
# [9.0.0-rc.1](https://github.com/angular/angular/compare/9.0.0-rc.0...9.0.0-rc.1) (2019-11-06)
|
||||||
|
|
||||||
@ -298,7 +457,7 @@ or
|
|||||||
npm install tslib --save
|
npm install tslib --save
|
||||||
```
|
```
|
||||||
* **forms:** * `<ngForm></ngForm>` can no longer be used as a selector. Use `<ng-form></ng-form>` instead.
|
* **forms:** * `<ngForm></ngForm>` can no longer be used as a selector. Use `<ng-form></ng-form>` instead.
|
||||||
* The `NgFromSelectorWarning` directive has been removed.
|
* The `NgFormSelectorWarning` directive has been removed.
|
||||||
* `FormsModule.withConfig` has been removed. Use the `FormsModule` directly.
|
* `FormsModule.withConfig` has been removed. Use the `FormsModule` directly.
|
||||||
|
|
||||||
|
|
||||||
|
49
WORKSPACE
49
WORKSPACE
@ -5,24 +5,11 @@ workspace(
|
|||||||
|
|
||||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||||
|
|
||||||
# Uncomment for local bazel rules development
|
|
||||||
#local_repository(
|
|
||||||
# name = "build_bazel_rules_nodejs",
|
|
||||||
# path = "../rules_nodejs",
|
|
||||||
#)
|
|
||||||
#local_repository(
|
|
||||||
# name = "npm_bazel_typescript",
|
|
||||||
# path = "../rules_typescript",
|
|
||||||
#)
|
|
||||||
|
|
||||||
# Fetch rules_nodejs so we can install our npm dependencies
|
# Fetch rules_nodejs so we can install our npm dependencies
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "build_bazel_rules_nodejs",
|
name = "build_bazel_rules_nodejs",
|
||||||
patch_args = ["-p1"],
|
sha256 = "8dc1466f8563f3aa4ac7ab7aa3c96651eb7764108219f40b2d1c918e1a81c601",
|
||||||
# Patch https://github.com/bazelbuild/rules_nodejs/pull/903
|
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.41.0/rules_nodejs-0.41.0.tar.gz"],
|
||||||
patches = ["//tools:rollup_bundle_commonjs_ignoreGlobal.patch"],
|
|
||||||
sha256 = "3d7296d834208792fa3b2ded8ec04e75068e3de172fae79db217615bd75a6ff7",
|
|
||||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.39.1/rules_nodejs-0.39.1.tar.gz"],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check the bazel version and download npm dependencies
|
# Check the bazel version and download npm dependencies
|
||||||
@ -39,25 +26,10 @@ Try running `yarn bazel` instead.
|
|||||||
(If you did run that, check that you've got a fresh `yarn install`)
|
(If you did run that, check that you've got a fresh `yarn install`)
|
||||||
|
|
||||||
""",
|
""",
|
||||||
minimum_bazel_version = "0.27.0",
|
minimum_bazel_version = "1.1.0",
|
||||||
)
|
)
|
||||||
|
|
||||||
# The NodeJS rules version must be at least the following version because:
|
check_rules_nodejs_version(minimum_version_string = "0.41.0")
|
||||||
# - 0.15.2 Re-introduced the prod_only attribute on yarn_install
|
|
||||||
# - 0.15.3 Includes a fix for the `jasmine_node_test` rule ignoring target tags
|
|
||||||
# - 0.16.8 Supports npm installed bazel workspaces
|
|
||||||
# - 0.26.0 Fix for data files in yarn_install and npm_install
|
|
||||||
# - 0.27.12 Adds NodeModuleSources provider for transtive npm deps support
|
|
||||||
# - 0.30.0 yarn_install now uses symlinked node_modules with new managed directories Bazel 0.26.0 feature
|
|
||||||
# - 0.31.1 entry_point attribute of nodejs_binary & rollup_bundle is now a label
|
|
||||||
# - 0.32.0 yarn_install and npm_install no longer puts build files under symlinked node_modules
|
|
||||||
# - 0.32.1 remove override of @bazel/tsetse & exclude typescript lib declarations in node_module_library transitive_declarations
|
|
||||||
# - 0.32.2 resolves bug in @bazel/hide-bazel-files postinstall step
|
|
||||||
# - 0.34.0 introduces protractor rule
|
|
||||||
# - 0.37.1 windows fixes
|
|
||||||
# - 0.38.2 Adds NpmPackageInfo & JSNamedModuleInfo providers
|
|
||||||
# - 0.38.3 all providers loaded from //:providers.bzl
|
|
||||||
check_rules_nodejs_version(minimum_version_string = "0.38.3")
|
|
||||||
|
|
||||||
# Setup the Node.js toolchain
|
# Setup the Node.js toolchain
|
||||||
node_repositories(
|
node_repositories(
|
||||||
@ -113,12 +85,9 @@ load("@io_bazel_rules_webtesting//web:repositories.bzl", "web_test_repositories"
|
|||||||
|
|
||||||
web_test_repositories()
|
web_test_repositories()
|
||||||
|
|
||||||
load("@io_bazel_rules_webtesting//web/versioned:browsers-0.3.2.bzl", "browser_repositories")
|
load("//tools/browsers:browser_repositories.bzl", "browser_repositories")
|
||||||
|
|
||||||
browser_repositories(
|
browser_repositories()
|
||||||
chromium = True,
|
|
||||||
firefox = True,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Setup the rules_typescript tooolchain
|
# Setup the rules_typescript tooolchain
|
||||||
load("@npm_bazel_typescript//:index.bzl", "ts_setup_workspace")
|
load("@npm_bazel_typescript//:index.bzl", "ts_setup_workspace")
|
||||||
@ -143,14 +112,14 @@ rbe_autoconfig(
|
|||||||
# Need to specify a base container digest in order to ensure that we can use the checked-in
|
# 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
|
# 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:
|
# need to pull the image and run it in order determine the toolchain configuration. See:
|
||||||
# https://github.com/bazelbuild/bazel-toolchains/blob/0.27.0/configs/ubuntu16_04_clang/versions.bzl
|
# https://github.com/bazelbuild/bazel-toolchains/blob/1.1.2/configs/ubuntu16_04_clang/versions.bzl
|
||||||
base_container_digest = "sha256:94d7d8552902d228c32c8c148cc13f0effc2b4837757a6e95b73fdc5c5e4b07b",
|
base_container_digest = "sha256:1ab40405810effefa0b2f45824d6d608634ccddbf06366760c341ef6fbead011",
|
||||||
# Note that if you change the `digest`, you might also need to update the
|
# 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>
|
# `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
|
# 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
|
# 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.
|
# @com_google_protobuf. Java is needed for the Bazel's test executor Java tool.
|
||||||
digest = "sha256:76e2e4a894f9ffbea0a0cb2fbde741b5d223d40f265dbb9bca78655430173990",
|
digest = "sha256:0b8fa87db4b8e5366717a7164342a029d1348d2feea7ecc4b18c780bc2507059",
|
||||||
env = clang_env(),
|
env = clang_env(),
|
||||||
registry = "marketplace.gcr.io",
|
registry = "marketplace.gcr.io",
|
||||||
# We can't use the default "ubuntu16_04" RBE image provided by the autoconfig because we need
|
# We can't use the default "ubuntu16_04" RBE image provided by the autoconfig because we need
|
||||||
|
@ -104,7 +104,7 @@ You also want to see those changes displayed properly in the doc viewer
|
|||||||
with a quick, edit/view cycle time.
|
with a quick, edit/view cycle time.
|
||||||
|
|
||||||
For this purpose, use the `yarn docs-watch` task, which watches for changes to source files and only
|
For this purpose, use the `yarn docs-watch` task, which watches for changes to source files and only
|
||||||
re-processes the the files necessary to generate the docs that are related to the file that has changed.
|
re-processes the files necessary to generate the docs that are related to the file that has changed.
|
||||||
Since this task takes shortcuts, it is much faster (often less than 1 second) but it won't produce full
|
Since this task takes shortcuts, it is much faster (often less than 1 second) but it won't produce full
|
||||||
fidelity content. For example, links to other docs and code examples may not render correctly. This is
|
fidelity content. For example, links to other docs and code examples may not render correctly. This is
|
||||||
most particularly noticed in links to other docs and in the embedded examples, which may not always render
|
most particularly noticed in links to other docs and in the embedded examples, which may not always render
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import { protractor, browser, element, by, ElementFinder } from 'protractor';
|
|||||||
|
|
||||||
const nameSuffix = 'X';
|
const nameSuffix = 'X';
|
||||||
|
|
||||||
class Hero {
|
interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
export class Hero {
|
export interface Hero {
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
isSecret = false;
|
isSecret: boolean;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -2,21 +2,23 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
import { QuestionService } from './question.service';
|
import { QuestionService } from './question.service';
|
||||||
|
import { QuestionBase } from './question-base';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
template: `
|
template: `
|
||||||
<div>
|
<div>
|
||||||
<h2>Job Application for Heroes</h2>
|
<h2>Job Application for Heroes</h2>
|
||||||
<app-dynamic-form [questions]="questions"></app-dynamic-form>
|
<app-dynamic-form [questions]="questions$ | async"></app-dynamic-form>
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
providers: [QuestionService]
|
providers: [QuestionService]
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
questions: any[];
|
questions$: Observable<QuestionBase<any>[]>;
|
||||||
|
|
||||||
constructor(service: QuestionService) {
|
constructor(service: QuestionService) {
|
||||||
this.questions = service.getQuestions();
|
this.questions$ = service.getQuestions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import { QuestionBase } from './question-base';
|
|||||||
templateUrl: './dynamic-form-question.component.html'
|
templateUrl: './dynamic-form-question.component.html'
|
||||||
})
|
})
|
||||||
export class DynamicFormQuestionComponent {
|
export class DynamicFormQuestionComponent {
|
||||||
@Input() question: QuestionBase<any>;
|
@Input() question: QuestionBase<string>;
|
||||||
@Input() form: FormGroup;
|
@Input() form: FormGroup;
|
||||||
get isValid() { return this.form.controls[this.question.key].valid; }
|
get isValid() { return this.form.controls[this.question.key].valid; }
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import { QuestionControlService } from './question-control.service';
|
|||||||
})
|
})
|
||||||
export class DynamicFormComponent implements OnInit {
|
export class DynamicFormComponent implements OnInit {
|
||||||
|
|
||||||
@Input() questions: QuestionBase<any>[] = [];
|
@Input() questions: QuestionBase<string>[] = [];
|
||||||
form: FormGroup;
|
form: FormGroup;
|
||||||
payLoad = '';
|
payLoad = '';
|
||||||
|
|
||||||
@ -23,6 +23,6 @@ export class DynamicFormComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
this.payLoad = JSON.stringify(this.form.value);
|
this.payLoad = JSON.stringify(this.form.getRawValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@ export class QuestionBase<T> {
|
|||||||
required: boolean;
|
required: boolean;
|
||||||
order: number;
|
order: number;
|
||||||
controlType: string;
|
controlType: string;
|
||||||
|
type: string;
|
||||||
|
options: {key: string, value: string}[];
|
||||||
|
|
||||||
constructor(options: {
|
constructor(options: {
|
||||||
value?: T,
|
value?: T,
|
||||||
@ -13,7 +15,8 @@ export class QuestionBase<T> {
|
|||||||
label?: string,
|
label?: string,
|
||||||
required?: boolean,
|
required?: boolean,
|
||||||
order?: number,
|
order?: number,
|
||||||
controlType?: string
|
controlType?: string,
|
||||||
|
type?: string
|
||||||
} = {}) {
|
} = {}) {
|
||||||
this.value = options.value;
|
this.value = options.value;
|
||||||
this.key = options.key || '';
|
this.key = options.key || '';
|
||||||
@ -21,5 +24,6 @@ export class QuestionBase<T> {
|
|||||||
this.required = !!options.required;
|
this.required = !!options.required;
|
||||||
this.order = options.order === undefined ? 1 : options.order;
|
this.order = options.order === undefined ? 1 : options.order;
|
||||||
this.controlType = options.controlType || '';
|
this.controlType = options.controlType || '';
|
||||||
|
this.type = options.type || '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import { QuestionBase } from './question-base';
|
|||||||
export class QuestionControlService {
|
export class QuestionControlService {
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
toFormGroup(questions: QuestionBase<any>[] ) {
|
toFormGroup(questions: QuestionBase<string>[] ) {
|
||||||
let group: any = {};
|
let group: any = {};
|
||||||
|
|
||||||
questions.forEach(question => {
|
questions.forEach(question => {
|
||||||
|
@ -4,15 +4,15 @@ import { Injectable } from '@angular/core';
|
|||||||
import { DropdownQuestion } from './question-dropdown';
|
import { DropdownQuestion } from './question-dropdown';
|
||||||
import { QuestionBase } from './question-base';
|
import { QuestionBase } from './question-base';
|
||||||
import { TextboxQuestion } from './question-textbox';
|
import { TextboxQuestion } from './question-textbox';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class QuestionService {
|
export class QuestionService {
|
||||||
|
|
||||||
// TODO: get from a remote source of question metadata
|
// TODO: get from a remote source of question metadata
|
||||||
// TODO: make asynchronous
|
|
||||||
getQuestions() {
|
getQuestions() {
|
||||||
|
|
||||||
let questions: QuestionBase<any>[] = [
|
let questions: QuestionBase<string>[] = [
|
||||||
|
|
||||||
new DropdownQuestion({
|
new DropdownQuestion({
|
||||||
key: 'brave',
|
key: 'brave',
|
||||||
@ -42,6 +42,6 @@ export class QuestionService {
|
|||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
return questions.sort((a, b) => a.order - b.order);
|
return of(questions.sort((a, b) => a.order - b.order));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
|
|
||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
tid: string; // tax id
|
tid: string; // tax id
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"description": "Http Guide Testing",
|
"description": "Http Guide Testing",
|
||||||
"files":[
|
"files":[
|
||||||
|
"src/app/heroes/hero.ts",
|
||||||
"src/app/heroes/heroes.service.ts",
|
"src/app/heroes/heroes.service.ts",
|
||||||
"src/app/heroes/heroes.service.spec.ts",
|
"src/app/heroes/heroes.service.spec.ts",
|
||||||
|
|
||||||
|
@ -28,9 +28,9 @@ describe('HeroesService', () => {
|
|||||||
|
|
||||||
// Inject the http, test controller, and service-under-test
|
// Inject the http, test controller, and service-under-test
|
||||||
// as they will be referenced by each test.
|
// as they will be referenced by each test.
|
||||||
httpClient = TestBed.inject(HttpClient);
|
httpClient = TestBed.get(HttpClient);
|
||||||
httpTestingController = TestBed.inject(HttpTestingController);
|
httpTestingController = TestBed.get(HttpTestingController);
|
||||||
heroService = TestBed.inject(HeroesService);
|
heroService = TestBed.get(HeroesService);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -44,7 +44,7 @@ describe('HeroesService', () => {
|
|||||||
let expectedHeroes: Hero[];
|
let expectedHeroes: Hero[];
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
heroService = TestBed.inject(HeroesService);
|
heroService = TestBed.get(HeroesService);
|
||||||
expectedHeroes = [
|
expectedHeroes = [
|
||||||
{ id: 1, name: 'A' },
|
{ id: 1, name: 'A' },
|
||||||
{ id: 2, name: 'B' },
|
{ id: 2, name: 'B' },
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
|
import { enableProdMode } from '@angular/core';
|
||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
|
||||||
import { AppModule } from './app/app.module';
|
import { AppModule } from './app/app.module';
|
||||||
|
import { environment } from './environments/environment';
|
||||||
|
|
||||||
|
if (environment.production) {
|
||||||
|
enableProdMode();
|
||||||
|
}
|
||||||
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
platformBrowserDynamic().bootstrapModule(AppModule);
|
||||||
|
@ -27,8 +27,8 @@ describe('HttpClient testing', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Inject the http service and test controller for each test
|
// Inject the http service and test controller for each test
|
||||||
httpClient = TestBed.inject(HttpClient);
|
httpClient = TestBed.get(HttpClient);
|
||||||
httpTestingController = TestBed.inject(HttpTestingController);
|
httpTestingController = TestBed.get(HttpTestingController);
|
||||||
});
|
});
|
||||||
// #enddocregion setup
|
// #enddocregion setup
|
||||||
// #docregion afterEach
|
// #docregion afterEach
|
||||||
@ -67,6 +67,7 @@ describe('HttpClient testing', () => {
|
|||||||
httpTestingController.verify();
|
httpTestingController.verify();
|
||||||
});
|
});
|
||||||
// #enddocregion get-test
|
// #enddocregion get-test
|
||||||
|
|
||||||
it('can test HttpClient.get with matching header', () => {
|
it('can test HttpClient.get with matching header', () => {
|
||||||
const testData: Data = {name: 'Test Data'};
|
const testData: Data = {name: 'Test Data'};
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
"!**/*.js",
|
"!**/*.js",
|
||||||
|
|
||||||
"!src/testing/*.*",
|
"!src/testing/*.*",
|
||||||
"!src/index-specs.html"
|
"!src/index-specs.html",
|
||||||
|
"!src/main-specs.ts"
|
||||||
],
|
],
|
||||||
"tags": ["http"]
|
"tags": ["http"]
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
import { registerLocaleData } from '@angular/common';
|
import { registerLocaleData } from '@angular/common';
|
||||||
import localeFr from '@angular/common/locales/fr';
|
import localeFr from '@angular/common/locales/fr';
|
||||||
|
|
||||||
// the second parameter 'fr' is optional
|
// the second parameter 'fr-FR' is optional
|
||||||
registerLocaleData(localeFr, 'fr');
|
registerLocaleData(localeFr, 'fr-FR');
|
||||||
// #enddocregion import-locale
|
// #enddocregion import-locale
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
emotion?: string;
|
emotion?: string;
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
<div formArrayName="aliases">
|
<div formArrayName="aliases">
|
||||||
<h3>Aliases</h3> <button (click)="addAlias()">Add Alias</button>
|
<h3>Aliases</h3> <button (click)="addAlias()">Add Alias</button>
|
||||||
|
|
||||||
<div *ngFor="let address of aliases.controls; let i=index">
|
<div *ngFor="let alias of aliases.controls; let i=index">
|
||||||
<!-- The repeated alias template -->
|
<!-- The repeated alias template -->
|
||||||
<label>
|
<label>
|
||||||
Alias:
|
Alias:
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
|
// #docplaster
|
||||||
// #docregion
|
// #docregion
|
||||||
|
// #docregion remove-heroes
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
|
// #enddocregion remove-heroes
|
||||||
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
|
|
||||||
|
// #docregion remove-heroes
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
import { HeroesModule } from './heroes/heroes.module';
|
import { HeroesModule } from './heroes/heroes.module';
|
||||||
@ -14,6 +19,13 @@ import { PageNotFoundComponent } from './page-not-found/page-not-found.component
|
|||||||
// #docregion module-imports
|
// #docregion module-imports
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
// #enddocregion module-imports
|
||||||
|
// #enddocregion remove-heroes
|
||||||
|
// #docregion animation-import
|
||||||
|
BrowserAnimationsModule,
|
||||||
|
// #enddocregion animation-import
|
||||||
|
// #docregion remove-heroes
|
||||||
|
// #docregion module-imports
|
||||||
FormsModule,
|
FormsModule,
|
||||||
HeroesModule,
|
HeroesModule,
|
||||||
AppRoutingModule
|
AppRoutingModule
|
||||||
@ -27,6 +39,7 @@ import { PageNotFoundComponent } from './page-not-found/page-not-found.component
|
|||||||
bootstrap: [ AppComponent ]
|
bootstrap: [ AppComponent ]
|
||||||
})
|
})
|
||||||
export class AppModule { }
|
export class AppModule { }
|
||||||
|
// #enddocregion remove-heroes
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
emotion?: string;
|
emotion?: string;
|
||||||
|
@ -4,7 +4,7 @@ import { Component, NgModule, OnInit } from '@angular/core';
|
|||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
|
||||||
class Hero {
|
interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
// #docregion example
|
// #docregion example
|
||||||
export class Hero {
|
export interface Hero {
|
||||||
name: string;
|
name: string;
|
||||||
power: string;
|
power: string;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
// #docregion example
|
// #docregion example
|
||||||
export class Hero {
|
export interface Hero {
|
||||||
name: string;
|
name: string;
|
||||||
power: string;
|
power: string;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,11 @@ import { Component, EventEmitter } from '@angular/core';
|
|||||||
'label'
|
'label'
|
||||||
],
|
],
|
||||||
outputs: [
|
outputs: [
|
||||||
'change'
|
'heroChange'
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class HeroButtonComponent {
|
export class HeroButtonComponent {
|
||||||
change = new EventEmitter<any>();
|
heroChange = new EventEmitter<any>();
|
||||||
label: string;
|
label: string;
|
||||||
}
|
}
|
||||||
// #enddocregion example
|
// #enddocregion example
|
||||||
|
@ -7,7 +7,7 @@ import { Component, EventEmitter, Input, Output } from '@angular/core';
|
|||||||
template: `<button>{{label}}</button>`
|
template: `<button>{{label}}</button>`
|
||||||
})
|
})
|
||||||
export class HeroButtonComponent {
|
export class HeroButtonComponent {
|
||||||
@Output() change = new EventEmitter<any>();
|
@Output() heroChange = new EventEmitter<any>();
|
||||||
@Input() label: string;
|
@Input() label: string;
|
||||||
}
|
}
|
||||||
// #enddocregion example
|
// #enddocregion example
|
||||||
|
@ -8,7 +8,7 @@ import { Component, EventEmitter, Input, Output } from '@angular/core';
|
|||||||
})
|
})
|
||||||
export class HeroButtonComponent {
|
export class HeroButtonComponent {
|
||||||
// Pointless aliases
|
// Pointless aliases
|
||||||
@Output('changeEvent') change = new EventEmitter<any>();
|
@Output('heroChangeEvent') heroChange = new EventEmitter<any>();
|
||||||
@Input('labelAttribute') label: string;
|
@Input('labelAttribute') label: string;
|
||||||
}
|
}
|
||||||
// #enddocregion example
|
// #enddocregion example
|
||||||
|
@ -8,7 +8,7 @@ import { Component, EventEmitter, Input, Output } from '@angular/core';
|
|||||||
})
|
})
|
||||||
export class HeroButtonComponent {
|
export class HeroButtonComponent {
|
||||||
// No aliases
|
// No aliases
|
||||||
@Output() change = new EventEmitter<any>();
|
@Output() heroChange = new EventEmitter<any>();
|
||||||
@Input() label: string;
|
@Input() label: string;
|
||||||
}
|
}
|
||||||
// #enddocregion example
|
// #enddocregion example
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import { delay } from 'rxjs/operators';
|
|||||||
|
|
||||||
////////// The App: Services and Components for the tests. //////////////
|
////////// The App: Services and Components for the tests. //////////////
|
||||||
|
|
||||||
export class Hero {
|
export interface Hero {
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
export class Hero {
|
export interface Hero {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ The following options are available for configuring the AoT template compiler.
|
|||||||
|
|
||||||
### `allowEmptyCodegenFiles`
|
### `allowEmptyCodegenFiles`
|
||||||
|
|
||||||
When true, generate all possible files even if they are empty. Default is false. Used by the Bazel build rules to simplify how Bazel rules track file dependencies. Do not use this option outside of the Bazel rules.
|
When `true`, generate all possible files even if they are empty. Default is `false`. Used by the Bazel build rules to simplify how Bazel rules track file dependencies. Do not use this option outside of the Bazel rules.
|
||||||
|
|
||||||
### `annotationsAs`
|
### `annotationsAs`
|
||||||
|
|
||||||
@ -64,40 +64,48 @@ Modifies how Angular-specific annotations are emitted to improve tree-shaking. N
|
|||||||
|
|
||||||
### `annotateForClosureCompiler`
|
### `annotateForClosureCompiler`
|
||||||
|
|
||||||
When true, use [Tsickle](https://github.com/angular/tsickle) to annotate the emitted JavaScript with [JSDoc](http://usejsdoc.org/) comments needed by the
|
When `true`, use [Tsickle](https://github.com/angular/tsickle) to annotate the emitted JavaScript with [JSDoc](http://usejsdoc.org/) comments needed by the
|
||||||
[Closure Compiler](https://github.com/google/closure-compiler). Default is false.
|
[Closure Compiler](https://github.com/google/closure-compiler). Default is `false`.
|
||||||
|
|
||||||
### `disableExpressionLowering`
|
### `disableExpressionLowering`
|
||||||
|
|
||||||
When true (the default), transforms code that is or could be used in an annotation, to allow it to be imported from template factory modules. See [metadata rewriting](guide/aot-compiler#metadata-rewriting) for more information.
|
When `true` (the default), transforms code that is or could be used in an annotation, to allow it to be imported from template factory modules. See [metadata rewriting](guide/aot-compiler#metadata-rewriting) for more information.
|
||||||
|
|
||||||
When `false`, disables this rewriting, requiring the rewriting to be done manually.
|
When `false`, disables this rewriting, requiring the rewriting to be done manually.
|
||||||
|
|
||||||
### `disableTypeScriptVersionCheck`
|
### `disableTypeScriptVersionCheck`
|
||||||
|
|
||||||
When `true`, the compiler does not check the TypeScript version and does not report an error when an unsupported version of TypeScript is used. Not recommended, as unsupported versions of TypeScript might have undefined behavior. Default is false.
|
When `true`, the compiler does not check the TypeScript version and does not report an error when an unsupported version of TypeScript is used. Not recommended, as unsupported versions of TypeScript might have undefined behavior. Default is `false`.
|
||||||
|
|
||||||
|
### `enableIvy`
|
||||||
|
|
||||||
|
Enables the [Ivy](guide/ivy) compilation and rendering pipeline. Default is `true`, as of version 9. In version 9, you can [opt out of Ivy](guide/ivy#opting-out-of-angular-ivy) to continue using the previous compiler, View Engine.
|
||||||
|
|
||||||
|
For library projects generated with the CLI, the `prod` configuration default is `false` in version 9.
|
||||||
|
|
||||||
### `enableResourceInlining`
|
### `enableResourceInlining`
|
||||||
|
|
||||||
When true, replaces the `templateUrl` and `styleUrls` property in all `@Component` decorators with inlined contents in `template` and `styles` properties.
|
When `true`, replaces the `templateUrl` and `styleUrls` property in all `@Component` decorators with inlined contents in `template` and `styles` properties.
|
||||||
|
|
||||||
When enabled, the `.js` output of `ngc` does not include any lazy-loaded template or style URLs.
|
When enabled, the `.js` output of `ngc` does not include any lazy-loaded template or style URLs.
|
||||||
|
|
||||||
|
For library projects generated with the CLI, the dev configuration default is `true`.
|
||||||
|
|
||||||
|
|
||||||
{@a enablelegacytemplate}
|
{@a enablelegacytemplate}
|
||||||
|
|
||||||
### `enableLegacyTemplate`
|
### `enableLegacyTemplate`
|
||||||
|
|
||||||
When true, enables use of the `<template>` element, which was deprecated in Angular 4.0, in favor of `<ng-template>` (to avoid colliding with the DOM's element of the same name). Default is false. Might be required by some third-party Angular libraries.
|
When `true`, enables use of the `<template>` element, which was deprecated in Angular 4.0, in favor of `<ng-template>` (to avoid colliding with the DOM's element of the same name). Default is `false`. Might be required by some third-party Angular libraries.
|
||||||
|
|
||||||
### `flatModuleId`
|
### `flatModuleId`
|
||||||
|
|
||||||
The module ID to use for importing a flat module (when `flatModuleOutFile` is true). References generated by the template compiler use this module name when importing symbols
|
The module ID to use for importing a flat module (when `flatModuleOutFile` is `true`). References generated by the template compiler use this module name when importing symbols
|
||||||
from the flat module. Ignored if `flatModuleOutFile` is false.
|
from the flat module. Ignored if `flatModuleOutFile` is `false`.
|
||||||
|
|
||||||
### `flatModuleOutFile`
|
### `flatModuleOutFile`
|
||||||
|
|
||||||
When true, generates a flat module index of the given file name and the corresponding flat module metadata. Use to create flat modules that are packaged similarly to `@angular/core` and `@angular/common`. When this option is used, the `package.json` for the library should refer
|
When `true`, generates a flat module index of the given file name and the corresponding flat module metadata. Use to create flat modules that are packaged similarly to `@angular/core` and `@angular/common`. When this option is used, the `package.json` for the library should refer
|
||||||
to the generated flat module index instead of the library index file.
|
to the generated flat module index instead of the library index file.
|
||||||
|
|
||||||
Produces only one `.metadata.json` file, which contains all the metadata necessary
|
Produces only one `.metadata.json` file, which contains all the metadata necessary
|
||||||
@ -112,31 +120,31 @@ If more than one `.ts` file is supplied without a `libraryIndex`, an error is pr
|
|||||||
A flat module index `.d.ts` and `.js` is created with the given `flatModuleOutFile` name in the same location as the library index `.d.ts` file.
|
A flat module index `.d.ts` and `.js` is created with the given `flatModuleOutFile` name in the same location as the library index `.d.ts` file.
|
||||||
|
|
||||||
For example, if a library uses the `public_api.ts` file as the library index of the module, the `tsconfig.json` `files` field would be `["public_api.ts"]`.
|
For example, if a library uses the `public_api.ts` file as the library index of the module, the `tsconfig.json` `files` field would be `["public_api.ts"]`.
|
||||||
The `flatModuleOutFile` options could then be set to (for example) `"index.js"`, which produces `index.d.ts` and `index.metadata.json` files.
|
The `flatModuleOutFile` option could then be set to (for example) `"index.js"`, which produces `index.d.ts` and `index.metadata.json` files.
|
||||||
The `module` field of the library's `package.json` would be `"index.js"` and the `typings` field
|
The `module` field of the library's `package.json` would be `"index.js"` and the `typings` field
|
||||||
would be `"index.d.ts"`.
|
would be `"index.d.ts"`.
|
||||||
|
|
||||||
### `fullTemplateTypeCheck`
|
### `fullTemplateTypeCheck`
|
||||||
|
|
||||||
When true (recommended), enables the [binding expression validation](guide/aot-compiler#binding-expression-validation) phase of the template compiler, which uses TypeScript to validate binding expressions.
|
When `true` (recommended), enables the [binding expression validation](guide/aot-compiler#binding-expression-validation) phase of the template compiler, which uses TypeScript to validate binding expressions. For more information, see [Template type checking](guide/template-typecheck).
|
||||||
|
|
||||||
Default is currently false.
|
Default is `false`, but when you use the CLI command `ng new`, it is set to `true` by default in the generated project's configuration.
|
||||||
|
|
||||||
### `generateCodeForLibraries`
|
### `generateCodeForLibraries`
|
||||||
|
|
||||||
When true (the default), generates factory files (`.ngfactory.js` and `.ngstyle.js`)
|
When `true` (the default), generates factory files (`.ngfactory.js` and `.ngstyle.js`)
|
||||||
for `.d.ts` files with a corresponding `.metadata.json` file.
|
for `.d.ts` files with a corresponding `.metadata.json` file.
|
||||||
|
|
||||||
When false, factory files are generated only for `.ts` files. Do this when using factory summaries.
|
When `false`, factory files are generated only for `.ts` files. Do this when using factory summaries.
|
||||||
|
|
||||||
|
|
||||||
### `preserveWhitespaces`
|
### `preserveWhitespaces`
|
||||||
|
|
||||||
When false (the default), removes blank text nodes from compiled templates, which results in smaller emitted template factory modules. Set to true to preserve blank text nodes.
|
When `false` (the default), removes blank text nodes from compiled templates, which results in smaller emitted template factory modules. Set to `true` to preserve blank text nodes.
|
||||||
|
|
||||||
### `skipMetadataEmit`
|
### `skipMetadataEmit`
|
||||||
|
|
||||||
When true, does not to produce `.metadata.json` files. Default is `false`.
|
When `true`, does not produce `.metadata.json` files. Default is `false`.
|
||||||
|
|
||||||
The `.metadata.json` files contain information needed by the template compiler from a `.ts`
|
The `.metadata.json` files contain information needed by the template compiler from a `.ts`
|
||||||
file that is not included in the `.d.ts` file produced by the TypeScript compiler.
|
file that is not included in the `.d.ts` file produced by the TypeScript compiler.
|
||||||
@ -150,14 +158,16 @@ are not valid for this style of TypeScript output. However, we do not recommend
|
|||||||
|
|
||||||
### `skipTemplateCodegen`
|
### `skipTemplateCodegen`
|
||||||
|
|
||||||
When true, does not emit `.ngfactory.js` and `.ngstyle.js` files. This turns off most of the template compiler and disables the reporting of template diagnostics.
|
When `true`, does not emit `.ngfactory.js` and `.ngstyle.js` files. This turns off most of the template compiler and disables the reporting of template diagnostics.
|
||||||
|
|
||||||
Can be used to instruct the template compiler to produce `.metadata.json` files for distribution with an `npm` package while avoiding the production of `.ngfactory.js` and `.ngstyle.js` files that cannot be distributed to `npm`.
|
Can be used to instruct the template compiler to produce `.metadata.json` files for distribution with an `npm` package while avoiding the production of `.ngfactory.js` and `.ngstyle.js` files that cannot be distributed to `npm`.
|
||||||
|
|
||||||
|
For library projects generated with the CLI, the dev configuration default is `true`.
|
||||||
|
|
||||||
### `strictMetadataEmit`
|
### `strictMetadataEmit`
|
||||||
|
|
||||||
When true, reports an error to the `.metadata.json` file if `"skipMetadataEmit"` is `false`.
|
When `true`, reports an error to the `.metadata.json` file if `"skipMetadataEmit"` is `false`.
|
||||||
Default is false. Use only when `"skipMetadataEmit"` is false and `"skipTemplateCodeGen"` is true.
|
Default is `false`. Use only when `"skipMetadataEmit"` is `false` and `"skipTemplateCodeGen"` is `true`.
|
||||||
|
|
||||||
This option is intended to validate the `.metadata.json` files emitted for bundling with an `npm` package. The validation is strict and can emit errors for metadata that would never produce an error when used by the template compiler. You can choose to suppress the error emitted by this option for an exported symbol by including `@dynamic` in the comment documenting the symbol.
|
This option is intended to validate the `.metadata.json` files emitted for bundling with an `npm` package. The validation is strict and can emit errors for metadata that would never produce an error when used by the template compiler. You can choose to suppress the error emitted by this option for an exported symbol by including `@dynamic` in the comment documenting the symbol.
|
||||||
|
|
||||||
@ -170,10 +180,21 @@ If the client of a library intends to use a symbol in an annotation, the templat
|
|||||||
This option allows detection of these errors during the build phase of
|
This option allows detection of these errors during the build phase of
|
||||||
the library and is used, for example, in producing Angular libraries themselves.
|
the library and is used, for example, in producing Angular libraries themselves.
|
||||||
|
|
||||||
|
For library projects generated with the CLI, the dev configuration default is `true`.
|
||||||
|
|
||||||
### `strictInjectionParameters`
|
### `strictInjectionParameters`
|
||||||
|
|
||||||
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 `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`, it is set to `true` by default in the generated project's configuration.
|
||||||
|
|
||||||
|
### `strictTemplates`
|
||||||
|
|
||||||
|
When `true`, enables [strict template type checking](guide/template-typecheck#strict-mode) in Angular version 9. Strict mode is only available when using [Ivy](guide/ivy).
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
|
||||||
### `trace`
|
### `trace`
|
||||||
|
|
||||||
When true, prints extra information while compiling templates. Default is false.
|
When `true`, prints extra information while compiling templates. Default is `false`.
|
||||||
|
@ -69,11 +69,9 @@ Let's animate a simple transition that changes a single HTML element from one st
|
|||||||
|
|
||||||
In HTML, these attributes are set using ordinary CSS styles such as color and opacity. In Angular, use the `style()` function to specify a set of CSS styles for use with animations. You can collect a set of styles in an animation state, and give the state a name, such as `open` or `closed`.
|
In HTML, these attributes are set using ordinary CSS styles such as color and opacity. In Angular, use the `style()` function to specify a set of CSS styles for use with animations. You can collect a set of styles in an animation state, and give the state a name, such as `open` or `closed`.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/animations/open-closed.png" alt="open and closed states">
|
<img src="generated/images/guide/animations/open-closed.png" alt="open and closed states">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
### Animation state and styles
|
### Animation state and styles
|
||||||
|
|
||||||
@ -168,11 +166,9 @@ The `trigger()` function describes the property name to watch for changes. When
|
|||||||
|
|
||||||
In this example, we'll name the trigger `openClose`, and attach it to the `button` element. The trigger describes the open and closed states, and the timings for the two transitions.
|
In this example, we'll name the trigger `openClose`, and attach it to the `button` element. The trigger describes the open and closed states, and the timings for the two transitions.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/animations/triggering-the-animation.png" alt="triggering the animation">
|
<img src="generated/images/guide/animations/triggering-the-animation.png" alt="triggering the animation">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
@ -51,11 +51,9 @@ You define a component's view with its companion template. A template is a form
|
|||||||
|
|
||||||
Views are typically arranged hierarchically, allowing you to modify or show and hide entire UI sections or pages as a unit. The template immediately associated with a component defines that component's *host view*. The component can also define a *view hierarchy*, which contains *embedded views*, hosted by other components.
|
Views are typically arranged hierarchically, allowing you to modify or show and hide entire UI sections or pages as a unit. The template immediately associated with a component defines that component's *host view*. The component can also define a *view hierarchy*, which contains *embedded views*, hosted by other components.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/architecture/component-tree.png" alt="Component tree" class="left">
|
<img src="generated/images/guide/architecture/component-tree.png" alt="Component tree" class="left">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
A view hierarchy can include views from components in the same NgModule, but it also can (and often does) include views from components that are defined in different NgModules.
|
A view hierarchy can include views from components in the same NgModule, but it also can (and often does) include views from components that are defined in different NgModules.
|
||||||
|
|
||||||
@ -83,11 +81,9 @@ Angular supports *two-way data binding*, a mechanism for coordinating the parts
|
|||||||
|
|
||||||
The following diagram shows the four forms of data binding markup. Each form has a direction: to the DOM, from the DOM, or both.
|
The following diagram shows the four forms of data binding markup. Each form has a direction: to the DOM, from the DOM, or both.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/architecture/databinding.png" alt="Data Binding" class="left">
|
<img src="generated/images/guide/architecture/databinding.png" alt="Data Binding" class="left">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
This example from the `HeroListComponent` template uses three of these forms.
|
This example from the `HeroListComponent` template uses three of these forms.
|
||||||
|
|
||||||
@ -114,19 +110,15 @@ as with event binding.
|
|||||||
Angular processes *all* data bindings once for each JavaScript event cycle,
|
Angular processes *all* data bindings once for each JavaScript event cycle,
|
||||||
from the root of the application component tree through all child components.
|
from the root of the application component tree through all child components.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/architecture/component-databinding.png" alt="Data Binding" class="left">
|
<img src="generated/images/guide/architecture/component-databinding.png" alt="Data Binding" class="left">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
Data binding plays an important role in communication between a template and its component, and is also important for communication between parent and child components.
|
Data binding plays an important role in communication between a template and its component, and is also important for communication between parent and child components.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/architecture/parent-child-binding.png" alt="Parent/Child binding" class="left">
|
<img src="generated/images/guide/architecture/parent-child-binding.png" alt="Parent/Child binding" class="left">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
### Pipes
|
### Pipes
|
||||||
|
|
||||||
|
@ -35,21 +35,17 @@ Here's a simple root NgModule definition.
|
|||||||
|
|
||||||
NgModules provide a *compilation context* for their components. A root NgModule always has a root component that is created during bootstrap, but any NgModule can include any number of additional components, which can be loaded through the router or created through the template. The components that belong to an NgModule share a compilation context.
|
NgModules provide a *compilation context* for their components. A root NgModule always has a root component that is created during bootstrap, but any NgModule can include any number of additional components, which can be loaded through the router or created through the template. The components that belong to an NgModule share a compilation context.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/architecture/compilation-context.png" alt="Component compilation context" class="left">
|
<img src="generated/images/guide/architecture/compilation-context.png" alt="Component compilation context" class="left">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
A component and its template together define a *view*. A component can contain a *view hierarchy*, which allows you to define arbitrarily complex areas of the screen that can be created, modified, and destroyed as a unit. A view hierarchy can mix views defined in components that belong to different NgModules. This is often the case, especially for UI libraries.
|
A component and its template together define a *view*. A component can contain a *view hierarchy*, which allows you to define arbitrarily complex areas of the screen that can be created, modified, and destroyed as a unit. A view hierarchy can mix views defined in components that belong to different NgModules. This is often the case, especially for UI libraries.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/architecture/view-hierarchy.png" alt="View hierarchy" class="left">
|
<img src="generated/images/guide/architecture/view-hierarchy.png" alt="View hierarchy" class="left">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
|
@ -70,11 +70,9 @@ When all requested services have been resolved and returned, Angular can call th
|
|||||||
|
|
||||||
The process of `HeroService` injection looks something like this.
|
The process of `HeroService` injection looks something like this.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/architecture/injector-injects.png" alt="Service" class="left">
|
<img src="generated/images/guide/architecture/injector-injects.png" alt="Service" class="left">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
### Providing services
|
### Providing services
|
||||||
|
|
||||||
|
@ -113,11 +113,9 @@ To define navigation rules, you associate *navigation paths* with your component
|
|||||||
|
|
||||||
You've learned the basics about the main building blocks of an Angular application. The following diagram shows how these basic pieces are related.
|
You've learned the basics about the main building blocks of an Angular application. The following diagram shows how these basic pieces are related.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/architecture/overview2.png" alt="overview">
|
<img src="generated/images/guide/architecture/overview2.png" alt="overview">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
* Together, a component and template define an Angular view.
|
* Together, a component and template define an Angular view.
|
||||||
* A decorator on a component class adds the metadata, including a pointer to the associated template.
|
* A decorator on a component class adds the metadata, including a pointer to the associated template.
|
||||||
|
@ -175,11 +175,9 @@ Here's the updated directive in full:
|
|||||||
Run the app and confirm that the background color appears when
|
Run the app and confirm that the background color appears when
|
||||||
the mouse hovers over the `p` and disappears as it moves out.
|
the mouse hovers over the `p` and disappears as it moves out.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/attribute-directives/highlight-directive-anim.gif" alt="Second Highlight">
|
<img src="generated/images/guide/attribute-directives/highlight-directive-anim.gif" alt="Second Highlight">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
{@a bindings}
|
{@a bindings}
|
||||||
|
|
||||||
@ -273,11 +271,9 @@ Revise the `AppComponent.color` so that it has no initial value.
|
|||||||
|
|
||||||
Here are the harness and directive in action.
|
Here are the harness and directive in action.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/attribute-directives/highlight-directive-v2-anim.gif" alt="Highlight v.2">
|
<img src="generated/images/guide/attribute-directives/highlight-directive-v2-anim.gif" alt="Highlight v.2">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
{@a second-property}
|
{@a second-property}
|
||||||
|
|
||||||
@ -311,11 +307,9 @@ because you made it _public_ with the `@Input` decorator.
|
|||||||
|
|
||||||
Here's how the harness should work when you're done coding.
|
Here's how the harness should work when you're done coding.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/attribute-directives/highlight-directive-final-anim.gif" alt="Final Highlight">
|
<img src="generated/images/guide/attribute-directives/highlight-directive-final-anim.gif" alt="Final Highlight">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
|
@ -50,11 +50,9 @@ and each iteration's `hero` instance to the child's `hero` property.
|
|||||||
The running application displays three heroes:
|
The running application displays three heroes:
|
||||||
|
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/component-interaction/parent-to-child.png" alt="Parent-to-child">
|
<img src="generated/images/guide/component-interaction/parent-to-child.png" alt="Parent-to-child">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -96,11 +94,9 @@ Here's the `NameParentComponent` demonstrating name variations including a name
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/component-interaction/setter.png" alt="Parent-to-child-setter">
|
<img src="generated/images/guide/component-interaction/setter.png" alt="Parent-to-child-setter">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -156,11 +152,9 @@ The `VersionParentComponent` supplies the `minor` and `major` values and binds b
|
|||||||
Here's the output of a button-pushing sequence:
|
Here's the output of a button-pushing sequence:
|
||||||
|
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/component-interaction/parent-to-child-on-changes.gif" alt="Parent-to-child-onchanges">
|
<img src="generated/images/guide/component-interaction/parent-to-child-on-changes.gif" alt="Parent-to-child-onchanges">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -212,11 +206,9 @@ The framework passes the event argument—represented by `$event`—to t
|
|||||||
and the method processes it:
|
and the method processes it:
|
||||||
|
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/component-interaction/child-to-parent.gif" alt="Child-to-parent">
|
<img src="generated/images/guide/component-interaction/child-to-parent.gif" alt="Child-to-parent">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -276,11 +268,9 @@ uses interpolation to display the child's `seconds` property.
|
|||||||
Here we see the parent and child working together.
|
Here we see the parent and child working together.
|
||||||
|
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/component-interaction/countdown-timer-anim.gif" alt="countdown timer">
|
<img src="generated/images/guide/component-interaction/countdown-timer-anim.gif" alt="countdown timer">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -431,11 +421,9 @@ the parent `MissionControlComponent` and the `AstronautComponent` children,
|
|||||||
facilitated by the service:
|
facilitated by the service:
|
||||||
|
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/component-interaction/bidirectional-service.gif" alt="bidirectional-service">
|
<img src="generated/images/guide/component-interaction/bidirectional-service.gif" alt="bidirectional-service">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -109,11 +109,10 @@ To learn more, see [Schematics Overview](guide/schematics) and [Schematics for
|
|||||||
|
|
||||||
## Publishing your library
|
## Publishing your library
|
||||||
|
|
||||||
Use the Angular CLI and the npm package manager to build and publish your library as an npm package.
|
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.
|
||||||
Libraries are built in [AoT mode](guide/aot-compiler) by default, so you do not need to specify the `-prod` flag when building for publication.
|
|
||||||
|
|
||||||
<code-example language="bash">
|
<code-example language="bash">
|
||||||
ng build my-lib
|
ng build my-lib --prod
|
||||||
cd dist/my-lib
|
cd dist/my-lib
|
||||||
npm publish
|
npm publish
|
||||||
</code-example>
|
</code-example>
|
||||||
|
@ -40,11 +40,9 @@ and the framework resolves the nested dependencies.
|
|||||||
|
|
||||||
When all dependencies are in place, `AppComponent` displays the user information.
|
When all dependencies are in place, `AppComponent` displays the user information.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/logged-in-user.png" alt="Logged In User">
|
<img src="generated/images/guide/dependency-injection-in-action/logged-in-user.png" alt="Logged In User">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
{@a service-scope}
|
{@a service-scope}
|
||||||
|
|
||||||
@ -133,11 +131,9 @@ The template displays this data-bound property.
|
|||||||
Find this example in <live-example name="dependency-injection-in-action">live code</live-example>
|
Find this example in <live-example name="dependency-injection-in-action">live code</live-example>
|
||||||
and confirm that the three `HeroBioComponent` instances have their own cached hero data.
|
and confirm that the three `HeroBioComponent` instances have their own cached hero data.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/hero-bios.png" alt="Bios">
|
<img src="generated/images/guide/dependency-injection-in-action/hero-bios.png" alt="Bios">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
{@a qualify-dependency-lookup}
|
{@a qualify-dependency-lookup}
|
||||||
|
|
||||||
@ -195,11 +191,9 @@ placing it in the `<ng-content>` slot of the `HeroBioComponent` template.
|
|||||||
|
|
||||||
The result is shown below, with the hero's telephone number from `HeroContactComponent` projected above the hero description.
|
The result is shown below, with the hero's telephone number from `HeroContactComponent` projected above the hero description.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/hero-bio-and-content.png" alt="bio and contact">
|
<img src="generated/images/guide/dependency-injection-in-action/hero-bio-and-content.png" alt="bio and contact">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
Here's `HeroContactComponent`, which demonstrates the qualifying decorators.
|
Here's `HeroContactComponent`, which demonstrates the qualifying decorators.
|
||||||
@ -227,11 +221,9 @@ When the property is marked as optional, Angular sets `loggerService` to null an
|
|||||||
|
|
||||||
Here's `HeroBiosAndContactsComponent` in action.
|
Here's `HeroBiosAndContactsComponent` in action.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/hero-bios-and-contacts.png" alt="Bios with contact into">
|
<img src="generated/images/guide/dependency-injection-in-action/hero-bios-and-contacts.png" alt="Bios with contact into">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -240,11 +232,9 @@ until it finds the logger at the `AppComponent` level.
|
|||||||
The logger logic kicks in and the hero display updates
|
The logger logic kicks in and the hero display updates
|
||||||
with the "!!!" marker to indicate that the logger was found.
|
with the "!!!" marker to indicate that the logger was found.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/hero-bio-contact-no-host.png" alt="Without @Host">
|
<img src="generated/images/guide/dependency-injection-in-action/hero-bio-contact-no-host.png" alt="Without @Host">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
If you restore the `@Host()` decorator and comment out `@Optional`,
|
If you restore the `@Host()` decorator and comment out `@Optional`,
|
||||||
@ -304,11 +294,9 @@ first without a value (yielding the default color) and then with an assigned col
|
|||||||
|
|
||||||
The following image shows the effect of mousing over the `<hero-bios-and-contacts>` tag.
|
The following image shows the effect of mousing over the `<hero-bios-and-contacts>` tag.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/highlight.png" alt="Highlighted bios">
|
<img src="generated/images/guide/dependency-injection-in-action/highlight.png" alt="Highlighted bios">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
{@a providers}
|
{@a providers}
|
||||||
|
|
||||||
@ -359,11 +347,9 @@ You learned about some other methods in [Dependency Providers](guide/dependency-
|
|||||||
The following `HeroOfTheMonthComponent` example demonstrates many of the alternatives and why you need them.
|
The following `HeroOfTheMonthComponent` example demonstrates many of the alternatives and why you need them.
|
||||||
It's visually simple: a few properties and the logs produced by a logger.
|
It's visually simple: a few properties and the logs produced by a logger.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/hero-of-month.png" alt="Hero of the month">
|
<img src="generated/images/guide/dependency-injection-in-action/hero-of-month.png" alt="Hero of the month">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
The code behind it customizes how and where the DI framework provides dependencies.
|
The code behind it customizes how and where the DI framework provides dependencies.
|
||||||
The use cases illustrate different ways to use the [*provide* object literal](guide/dependency-injection-providers#provide) to associate a definition object with a DI token.
|
The use cases illustrate different ways to use the [*provide* object literal](guide/dependency-injection-providers#provide) to associate a definition object with a DI token.
|
||||||
@ -474,11 +460,9 @@ The following example puts `MinimalLogger` to use in a simplified version of `He
|
|||||||
|
|
||||||
The `HeroOfTheMonthComponent` constructor's `logger` parameter is typed as `MinimalLogger`, so only the `logs` and `logInfo` members are visible in a TypeScript-aware editor.
|
The `HeroOfTheMonthComponent` constructor's `logger` parameter is typed as `MinimalLogger`, so only the `logs` and `logInfo` members are visible in a TypeScript-aware editor.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/minimal-logger-intellisense.png" alt="MinimalLogger restricted API">
|
<img src="generated/images/guide/dependency-injection-in-action/minimal-logger-intellisense.png" alt="MinimalLogger restricted API">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
Behind the scenes, Angular sets the `logger` parameter to the full service registered under the `LoggingService` token, which happens to be the `DateLoggerService` instance that was [provided above](guide/dependency-injection-in-action#useclass).
|
Behind the scenes, Angular sets the `logger` parameter to the full service registered under the `LoggingService` token, which happens to be the `DateLoggerService` instance that was [provided above](guide/dependency-injection-in-action#useclass).
|
||||||
@ -488,11 +472,9 @@ Behind the scenes, Angular sets the `logger` parameter to the full service regis
|
|||||||
|
|
||||||
This is illustrated in the following image, which displays the logging date.
|
This is illustrated in the following image, which displays the logging date.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/date-logger-entry.png" alt="DateLoggerService entry">
|
<img src="generated/images/guide/dependency-injection-in-action/date-logger-entry.png" alt="DateLoggerService entry">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -645,11 +627,9 @@ and then pass them down to the base class through the constructor.
|
|||||||
In this contrived example, `SortedHeroesComponent` inherits from `HeroesBaseComponent`
|
In this contrived example, `SortedHeroesComponent` inherits from `HeroesBaseComponent`
|
||||||
to display a *sorted* list of heroes.
|
to display a *sorted* list of heroes.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/sorted-heroes.png" alt="Sorted Heroes">
|
<img src="generated/images/guide/dependency-injection-in-action/sorted-heroes.png" alt="Sorted Heroes">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
The `HeroesBaseComponent` can stand on its own.
|
The `HeroesBaseComponent` can stand on its own.
|
||||||
It demands its own instance of `HeroService` to get heroes
|
It demands its own instance of `HeroService` to get heroes
|
||||||
|
@ -145,11 +145,9 @@ the same way you've done it before.
|
|||||||
|
|
||||||
Here's *Alex* and family in action.
|
Here's *Alex* and family in action.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/alex.png" alt="Alex in action">
|
<img src="generated/images/guide/dependency-injection-in-action/alex.png" alt="Alex in action">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -203,13 +201,9 @@ which *is* what parent means.
|
|||||||
Here's *Alice*, *Barry*, and family in action.
|
Here's *Alice*, *Barry*, and family in action.
|
||||||
|
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/alice.png" alt="Alice in action">
|
<img src="generated/images/guide/dependency-injection-in-action/alice.png" alt="Alice in action">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{@a parent-token}
|
{@a parent-token}
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ Check out [angular-cli-ghpages](https://github.com/angular-buch/angular-cli-ghpa
|
|||||||
|
|
||||||
## Server configuration
|
## Server configuration
|
||||||
|
|
||||||
This section covers changes you may have make to the server or to files deployed to the server.
|
This section covers changes you may have to make to the server or to files deployed on the server.
|
||||||
|
|
||||||
{@a fallback}
|
{@a fallback}
|
||||||
|
|
||||||
@ -434,11 +434,9 @@ showing exactly which classes are included in the bundle.
|
|||||||
|
|
||||||
Here's the output for the _main_ bundle of an example app called `cli-quickstart`.
|
Here's the output for the _main_ bundle of an example app called `cli-quickstart`.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/deployment/quickstart-sourcemap-explorer.png" alt="quickstart sourcemap explorer">
|
<img src="generated/images/guide/deployment/quickstart-sourcemap-explorer.png" alt="quickstart sourcemap explorer">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
{@a base-tag}
|
{@a base-tag}
|
||||||
|
|
||||||
@ -669,7 +667,7 @@ In `angular.json` add two new configuration sections under the `build` and `serv
|
|||||||
...
|
...
|
||||||
},
|
},
|
||||||
"es5": {
|
"es5": {
|
||||||
"browserTarget": "<app-name>:build:es5"
|
"browserTarget": "<app-name>:build:es5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -741,7 +739,7 @@ Create an [ES5 serve configuration](guide/deployment#configuring-serve-for-es5)
|
|||||||
...
|
...
|
||||||
},
|
},
|
||||||
"es5": {
|
"es5": {
|
||||||
"devServerTarget": "<app-name>:serve:es5"
|
"devServerTarget": "<app-name>:serve:es5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -41,11 +41,6 @@ v9 - v12
|
|||||||
| `@angular/core` | [`ReflectiveKey`](#core) | <!--v8--> v10 |
|
| `@angular/core` | [`ReflectiveKey`](#core) | <!--v8--> v10 |
|
||||||
| `@angular/core` | [`RenderComponentType`](#core) | <!--v7--> v10 |
|
| `@angular/core` | [`RenderComponentType`](#core) | <!--v7--> v10 |
|
||||||
| `@angular/core` | [`ViewEncapsulation.Native`](#core) | <!--v6--> v10 |
|
| `@angular/core` | [`ViewEncapsulation.Native`](#core) | <!--v6--> v10 |
|
||||||
| `@angular/core` | [`WtfScopeFn`](api/core/WtfScopeFn) | <!--v8--> v10 |
|
|
||||||
| `@angular/core` | [`wtfCreateScope`](api/core/wtfCreateScope) | <!--v8--> v10 |
|
|
||||||
| `@angular/core` | [`wtfStartTimeRange`](api/core/wtfStartTimeRange) | <!--v8--> v10 |
|
|
||||||
| `@angular/core` | [`wtfEndTimeRange`](api/core/wtfEndTimeRange) | <!--v8--> v10 |
|
|
||||||
| `@angular/core` | [`wtfLeave`](api/core/wtfLeave) | <!--v8--> v10 |
|
|
||||||
| `@angular/core` | [`ModuleWithProviders` without a generic](#moduleWithProviders) | <!--v9--> v10 |
|
| `@angular/core` | [`ModuleWithProviders` without a generic](#moduleWithProviders) | <!--v9--> v10 |
|
||||||
| `@angular/forms` | [`ngModel` with reactive forms](#ngmodel-reactive) | <!--v6--> v10 |
|
| `@angular/forms` | [`ngModel` with reactive forms](#ngmodel-reactive) | <!--v6--> v10 |
|
||||||
| `@angular/router` | [`preserveQueryParams`](#router) | <!--v7--> v10 |
|
| `@angular/router` | [`preserveQueryParams`](#router) | <!--v7--> v10 |
|
||||||
@ -89,11 +84,6 @@ Tip: In the [API reference section](api) of this doc site, deprecated APIs are i
|
|||||||
| [`ReflectiveKey`](api/core/ReflectiveKey) | none | v5 | none |
|
| [`ReflectiveKey`](api/core/ReflectiveKey) | none | v5 | none |
|
||||||
| [`ViewEncapsulation.Native`](api/core/ViewEncapsulation#Native) | [`ViewEncapsulation.ShadowDom`](api/core/ViewEncapsulation#ShadowDom) | v6 | Use the native encapsulation mechanism of the renderer. See [view.ts](https://github.com/angular/angular/blob/3e992e18ebf51d6036818f26c3d77b52d3ec48eb/packages/core/src/metadata/view.ts#L32).
|
| [`ViewEncapsulation.Native`](api/core/ViewEncapsulation#Native) | [`ViewEncapsulation.ShadowDom`](api/core/ViewEncapsulation#ShadowDom) | v6 | Use the native encapsulation mechanism of the renderer. See [view.ts](https://github.com/angular/angular/blob/3e992e18ebf51d6036818f26c3d77b52d3ec48eb/packages/core/src/metadata/view.ts#L32).
|
||||||
| [`defineInjectable`](api/core/defineInjectable) | `ɵɵdefineInjectable` | v8 | Used only in generated code. No source code should depend on this API. |
|
| [`defineInjectable`](api/core/defineInjectable) | `ɵɵdefineInjectable` | v8 | Used only in generated code. No source code should depend on this API. |
|
||||||
| [`WtfScopeFn`](api/core/WtfScopeFn) | none | v8 | See [Web Tracing Framework](#wtf) |
|
|
||||||
| [`wtfCreateScope`](api/core/wtfCreateScope) | none | v8 | See [Web Tracing Framework](#wtf) |
|
|
||||||
| [`wtfStartTimeRange`](api/core/wtfStartTimeRange) | none | v8 | See [Web Tracing Framework](#wtf) |
|
|
||||||
| [`wtfEndTimeRange`](api/core/wtfEndTimeRange) | none | v8 | See [Web Tracing Framework](#wtf) |
|
|
||||||
| [`wtfLeave`](api/core/wtfLeave) | none | v8 | See [Web Tracing Framework](#wtf) |
|
|
||||||
| [`entryComponents`](api/core/NgModule#entryComponents) | none | v9 | See [`entryComponents`](#entryComponents) |
|
| [`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) |
|
| [`ANALYZE_FOR_ENTRY_COMPONENTS`](api/core/ANALYZE_FOR_ENTRY_COMPONENTS) | none | v9 | See [`ANALYZE_FOR_ENTRY_COMPONENTS`](#entryComponents) |
|
||||||
| `ModuleWithProviders` without a generic | `ModuleWithProviders` with a generic | v9 | See [`ModuleWithProviders` section](#moduleWithProviders) |
|
| `ModuleWithProviders` without a generic | `ModuleWithProviders` with a generic | v9 | See [`ModuleWithProviders` section](#moduleWithProviders) |
|
||||||
@ -166,7 +156,7 @@ This section lists all of the currently-deprecated features, which includes temp
|
|||||||
{@a wtf}
|
{@a wtf}
|
||||||
### Web Tracing Framework integration
|
### Web Tracing Framework integration
|
||||||
|
|
||||||
Angular previously has supported an integration with the Web Tracing Framework (WTF) for performance testing of Angular applications. This integration has not been maintained and likely does not work for the majority of Angular applications today. As a result, we are deprecating the integration in Angular version 8.
|
Angular previously has supported an integration with the [Web Tracing Framework (WTF)](https://google.github.io/tracing-framework/) for performance testing of Angular applications. This integration has not been maintained and defunct. As a result, the integration was deprecated in Angular version 8 and due to no evidence of any existing usage removed in version 9.
|
||||||
|
|
||||||
|
|
||||||
{@a deep-component-style-selector}
|
{@a deep-component-style-selector}
|
||||||
@ -454,6 +444,11 @@ The following APIs have been removed starting with version 9.0.0*:
|
|||||||
| `@angular/core` | [`Renderer`](https://v8.angular.io/api/core/Renderer) | [`Renderer2`](https://angular.io/api/core/Renderer2) | [Migration guide](guide/migration-renderer) |
|
| `@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` | [`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` | [`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` | `DeprecatedI18NPipesModule` | [`CommonModule`](api/common/CommonModule#pipes) | none |
|
||||||
| `@angular/common` | `DeprecatedCurrencyPipe` | [`CurrencyPipe`](api/common/CurrencyPipe) | none |
|
| `@angular/common` | `DeprecatedCurrencyPipe` | [`CurrencyPipe`](api/common/CurrencyPipe) | none |
|
||||||
| `@angular/common` | `DeprecatedDatePipe` | [`DatePipe`](api/common/DatePipe) | none |
|
| `@angular/common` | `DeprecatedDatePipe` | [`DatePipe`](api/common/DatePipe) | none |
|
||||||
|
@ -8,12 +8,9 @@ conditionally show a message below the list.
|
|||||||
|
|
||||||
The final UI looks like this:
|
The final UI looks like this:
|
||||||
|
|
||||||
|
<div class="lightbox">
|
||||||
<figure class="lightbox">
|
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/displaying-data/final.png" alt="Final UI">
|
<img src="generated/images/guide/displaying-data/final.png" alt="Final UI">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
@ -105,13 +102,9 @@ inside the `<app-root>` tag.
|
|||||||
|
|
||||||
Now run the app. It should display the title and hero name:
|
Now run the app. It should display the title and hero name:
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/displaying-data/title-and-hero.png" alt="Title and Hero">
|
<img src="generated/images/guide/displaying-data/title-and-hero.png" alt="Title and Hero">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
The next few sections review some of the coding choices in the app.
|
The next few sections review some of the coding choices in the app.
|
||||||
|
|
||||||
@ -215,14 +208,9 @@ repeat items for any [iterable](https://developer.mozilla.org/en-US/docs/Web/Jav
|
|||||||
|
|
||||||
Now the heroes appear in an unordered list.
|
Now the heroes appear in an unordered list.
|
||||||
|
|
||||||
|
<div class="lightbox">
|
||||||
<figure class="lightbox">
|
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/displaying-data/hero-names-list.png" alt="After ngfor">
|
<img src="generated/images/guide/displaying-data/hero-names-list.png" alt="After ngfor">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Creating a class for the data
|
## Creating a class for the data
|
||||||
|
@ -1244,19 +1244,20 @@ Images should be specified in an `<img>` tag.
|
|||||||
|
|
||||||
For accessibility, always set the `alt` attribute with a meaningful description of the image.
|
For accessibility, always set the `alt` attribute with a meaningful description of the image.
|
||||||
|
|
||||||
You should nest the `<img>` tag within a `<figure>` tag, which styles the image within a drop-shadow frame. You'll need the editor's permission to skip the `<figure>` tag.
|
You should nest the `<img>` tag within a `<div class="lightbox">` tag, which styles the image within a drop-shadow frame. You'll need the editor's permission to skip the `lightbox` class on its `div` encapsulation.
|
||||||
|
|
||||||
Here's a conforming example
|
Here's a conforming example
|
||||||
|
|
||||||
<figure>
|
<div class="lightbox">
|
||||||
<img src="generated/images/guide/docs-style-guide/flying-hero.png" alt="flying hero">
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
```html
|
|
||||||
<figure>
|
|
||||||
<img src="generated/images/guide/docs-style-guide/flying-hero.png"
|
<img src="generated/images/guide/docs-style-guide/flying-hero.png"
|
||||||
alt="flying hero">
|
alt="flying hero">
|
||||||
</figure>
|
</div>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div class="lightbox">
|
||||||
|
<img src="generated/images/guide/docs-style-guide/flying-hero.png"
|
||||||
|
alt="flying hero">
|
||||||
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
_Note that the HTML image element does not have a closing tag._
|
_Note that the HTML image element does not have a closing tag._
|
||||||
@ -1267,17 +1268,19 @@ The doc generator reads the image dimensions from the file and adds width and he
|
|||||||
|
|
||||||
Here's the "flying hero" at a more reasonable scale.
|
Here's the "flying hero" at a more reasonable scale.
|
||||||
|
|
||||||
<figure>
|
<div class="lightbox">
|
||||||
<img src="generated/images/guide/docs-style-guide/flying-hero.png" alt="flying Angular hero" width="200">
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
```html
|
|
||||||
|
|
||||||
<figure>
|
|
||||||
<img src="generated/images/guide/docs-style-guide/flying-hero.png"
|
<img src="generated/images/guide/docs-style-guide/flying-hero.png"
|
||||||
alt="flying Angular hero"
|
alt="flying Angular hero"
|
||||||
width="200">
|
width="200">
|
||||||
</figure>
|
</div>
|
||||||
|
|
||||||
|
```html
|
||||||
|
|
||||||
|
<div class="lightbox">
|
||||||
|
<img src="generated/images/guide/docs-style-guide/flying-hero.png"
|
||||||
|
alt="flying Angular hero"
|
||||||
|
width="200">
|
||||||
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
Wide images can be a problem. Most browsers try to rescale the image but wide images may overflow the document in certain viewports.
|
Wide images can be a problem. Most browsers try to rescale the image but wide images may overflow the document in certain viewports.
|
||||||
@ -1285,9 +1288,9 @@ Wide images can be a problem. Most browsers try to rescale the image but wide im
|
|||||||
**Do not set a width greater than 700px**. If you wish to display a larger image, provide a link to the actual image that the user can click on to see the full size image separately as in this example of `source-map-explorer` output from the "Ahead-of-time Compilation" guide:
|
**Do not set a width greater than 700px**. If you wish to display a larger image, provide a link to the actual image that the user can click on to see the full size image separately as in this example of `source-map-explorer` output from the "Ahead-of-time Compilation" guide:
|
||||||
|
|
||||||
<a href="generated/images/guide/docs-style-guide/toh-pt6-bundle.png" title="Click to view larger image">
|
<a href="generated/images/guide/docs-style-guide/toh-pt6-bundle.png" title="Click to view larger image">
|
||||||
<figure>
|
<div class="lightbox">
|
||||||
<img src="generated/images/guide/docs-style-guide/toh-pt6-bundle-700w.png" alt="toh-pt6-bundle" width="300px">
|
<img src="generated/images/guide/docs-style-guide/toh-pt6-bundle-700w.png" alt="toh-pt6-bundle" width="300px">
|
||||||
</figure>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<h3 class="no-toc">Image compression</h3>
|
<h3 class="no-toc">Image compression</h3>
|
||||||
|
@ -183,12 +183,8 @@ Here are two sample components and the `AdComponent` interface for reference:
|
|||||||
## Final ad banner
|
## Final ad banner
|
||||||
The final ad banner looks like this:
|
The final ad banner looks like this:
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/dynamic-component-loader/ads-example.gif" alt="Ads">
|
<img src="generated/images/guide/dynamic-component-loader/ads-example.gif" alt="Ads">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
See the <live-example name="dynamic-component-loader"></live-example>.
|
See the <live-example name="dynamic-component-loader"></live-example>.
|
||||||
|
@ -197,12 +197,9 @@ Saving and retrieving the data is an exercise for another time.
|
|||||||
|
|
||||||
The final form looks like this:
|
The final form looks like this:
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/dynamic-form/dynamic-form.png" alt="Dynamic-Form">
|
<img src="generated/images/guide/dynamic-form/dynamic-form.png" alt="Dynamic-Form">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[Back to top](guide/dynamic-form#top)
|
[Back to top](guide/dynamic-form#top)
|
||||||
|
@ -42,11 +42,9 @@ After you register your configured class with the browser's custom-element regis
|
|||||||
|
|
||||||
When your custom element is placed on a page, the browser creates an instance of the registered class and adds it to the DOM. The content is provided by the component's template, which uses Angular template syntax, and is rendered using the component and DOM data. Input properties in the component correspond to input attributes for the element.
|
When your custom element is placed on a page, the browser creates an instance of the registered class and adds it to the DOM. The content is provided by the component's template, which uses Angular template syntax, and is rendered using the component and DOM data. Input properties in the component correspond to input attributes for the element.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/elements/customElement1.png" alt="Custom element in browser" class="left">
|
<img src="generated/images/guide/elements/customElement1.png" alt="Custom element in browser" class="left">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
<hr class="clear">
|
<hr class="clear">
|
||||||
|
|
||||||
@ -64,11 +62,9 @@ Use a JavaScript function, `customElements.define()`, to register the configure
|
|||||||
and its associated custom-element tag with the browser's `CustomElementRegistry`.
|
and its associated custom-element tag with the browser's `CustomElementRegistry`.
|
||||||
When the browser encounters the tag for the registered element, it uses the constructor to create a custom-element instance.
|
When the browser encounters the tag for the registered element, it uses the constructor to create a custom-element instance.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/elements/createElement.png" alt="Transform a component to a custom element" class="left">
|
<img src="generated/images/guide/elements/createElement.png" alt="Transform a component to a custom element" class="left">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
### Mapping
|
### Mapping
|
||||||
|
|
||||||
|
@ -102,12 +102,9 @@ Next, in the `AppComponent`, `app.component.html`, add the tag `<app-customer-da
|
|||||||
|
|
||||||
Now, in addition to the title that renders by default, the `CustomerDashboardComponent` template renders too:
|
Now, in addition to the title that renders by default, the `CustomerDashboardComponent` template renders too:
|
||||||
|
|
||||||
|
<div class="lightbox">
|
||||||
<figure class="lightbox">
|
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/feature-modules/feature-module.png" alt="feature module component">
|
<img src="generated/images/guide/feature-modules/feature-module.png" alt="feature module component">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ Project-specific [TypeScript](https://www.typescriptlang.org/) configuration fil
|
|||||||
| :--------------------- | :------------------------------------------|
|
| :--------------------- | :------------------------------------------|
|
||||||
| `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. |
|
| `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. |
|
| `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). |
|
| `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). |
|
| `tsconfig.spec.json` | [TypeScript](https://www.typescriptlang.org/) configuration for the application tests. See [TypeScript Configuration](guide/typescript-configuration). |
|
||||||
| `tslint.json` | Application-specific [TSLint](https://palantir.github.io/tslint/) configuration. |
|
| `tslint.json` | Application-specific [TSLint](https://palantir.github.io/tslint/) configuration. |
|
||||||
|
|
||||||
|
@ -67,11 +67,9 @@ Here's a component with an input field for a single control implemented using re
|
|||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/forms-overview/key-diff-reactive-forms.png" alt="Reactive forms key differences">
|
<img src="generated/images/guide/forms-overview/key-diff-reactive-forms.png" alt="Reactive forms key differences">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
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).
|
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).
|
||||||
|
|
||||||
@ -84,11 +82,9 @@ Here's the same component with an input field for a single control implemented u
|
|||||||
|
|
||||||
In template-driven forms, the source of truth is the template.
|
In template-driven forms, the source of truth is the template.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/forms-overview/key-diff-td-forms.png" alt="Template-driven forms key differences">
|
<img src="generated/images/guide/forms-overview/key-diff-td-forms.png" alt="Template-driven forms key differences">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
@ -102,11 +98,9 @@ When building forms in Angular, it's important to understand how the framework h
|
|||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/forms-overview/dataflow-reactive-forms-vtm.png" alt="Reactive forms data flow - view to model" width="100%">
|
<img src="generated/images/guide/forms-overview/dataflow-reactive-forms-vtm.png" alt="Reactive forms data flow - view to model" width="100%">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
The steps below outline the data flow from view to model.
|
The steps below outline the data flow from view to model.
|
||||||
|
|
||||||
@ -116,11 +110,9 @@ The steps below outline the data flow from view to model.
|
|||||||
1. The `FormControl` instance emits the new value through the `valueChanges` observable.
|
1. The `FormControl` instance emits the new value through the `valueChanges` observable.
|
||||||
1. Any subscribers to the `valueChanges` observable receive the new value.
|
1. Any subscribers to the `valueChanges` observable receive the new value.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/forms-overview/dataflow-reactive-forms-mtv.png" alt="Reactive forms data flow - model to view" width="100%">
|
<img src="generated/images/guide/forms-overview/dataflow-reactive-forms-mtv.png" alt="Reactive forms data flow - model to view" width="100%">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
The steps below outline the data flow from model to view.
|
The steps below outline the data flow from model to view.
|
||||||
|
|
||||||
@ -133,11 +125,9 @@ The steps below outline the data flow from model to view.
|
|||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<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-vtm.png" alt="Template-driven forms data flow - view to model" width="100%">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
The steps below outline the data flow from view to model when the input value changes from *Red* to *Blue*.
|
The steps below outline the data flow from view to model when the input value changes from *Red* to *Blue*.
|
||||||
|
|
||||||
@ -150,11 +140,9 @@ The steps below outline the data flow from view to model when the input value ch
|
|||||||
1. Because the component template uses two-way data binding for the `favoriteColor` property, the `favoriteColor` property in the component
|
1. Because the component template uses two-way data binding for the `favoriteColor` property, the `favoriteColor` property in the component
|
||||||
is updated to the value emitted by the `ngModelChange` event (*Blue*).
|
is updated to the value emitted by the `ngModelChange` event (*Blue*).
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/forms-overview/dataflow-td-forms-mtv.png" alt="Template-driven forms data flow - model to view" 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>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
The steps below outline the data flow from model to view when the `favoriteColor` changes from *Blue* to *Red*.
|
The steps below outline the data flow from model to view when the `favoriteColor` changes from *Blue* to *Red*.
|
||||||
|
|
||||||
|
@ -45,11 +45,9 @@ otherwise wrestle with yourself.
|
|||||||
|
|
||||||
You'll learn to build a template-driven form that looks like this:
|
You'll learn to build a template-driven form that looks like this:
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/forms/hero-form-1.png" alt="Clean Form">
|
<img src="generated/images/guide/forms/hero-form-1.png" alt="Clean Form">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
The *Hero Employment Agency* uses this form to maintain personal information about heroes.
|
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.
|
Every hero needs a job. It's the company mission to match the right hero with the right crisis.
|
||||||
@ -58,11 +56,9 @@ Two of the three fields on this form are required. Required fields have a green
|
|||||||
|
|
||||||
If you delete the hero name, the form displays a validation error in an attention-grabbing style:
|
If you delete the hero name, the form displays a validation error in an attention-grabbing style:
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/forms/hero-form-2.png" alt="Invalid, Name Required">
|
<img src="generated/images/guide/forms/hero-form-2.png" alt="Invalid, Name Required">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
Note that the *Submit* button is disabled, and the "required" bar to the left of the input control changes from green to red.
|
Note that the *Submit* button is disabled, and the "required" bar to the left of the input control changes from green to red.
|
||||||
|
|
||||||
@ -276,11 +272,9 @@ you display its name using the interpolation syntax.
|
|||||||
|
|
||||||
Running the app right now would be disappointing.
|
Running the app right now would be disappointing.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/forms/hero-form-3.png" alt="Early form with no binding">
|
<img src="generated/images/guide/forms/hero-form-3.png" alt="Early form with no binding">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
You don't see hero data because you're not binding to the `Hero` yet.
|
You don't see hero data because you're not binding to the `Hero` yet.
|
||||||
@ -341,11 +335,9 @@ adding and deleting characters, you'd see them appear and disappear
|
|||||||
from the interpolated text.
|
from the interpolated text.
|
||||||
At some point it might look like this:
|
At some point it might look like this:
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/forms/ng-model-in-action.png" alt="ngModel in action">
|
<img src="generated/images/guide/forms/ng-model-in-action.png" alt="ngModel in action">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
The diagnostic is evidence that values really are flowing from the input box to the model and
|
The diagnostic is evidence that values really are flowing from the input box to the model and
|
||||||
back again.
|
back again.
|
||||||
@ -391,11 +383,9 @@ After revision, the core of the form should look like this:
|
|||||||
|
|
||||||
If you run the app now and change every hero model property, the form might display like this:
|
If you run the app now and change every hero model property, the form might display like this:
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/forms/ng-model-in-action-2.png" alt="ngModel in action">
|
<img src="generated/images/guide/forms/ng-model-in-action-2.png" alt="ngModel in action">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
The diagnostic near the top of the form
|
The diagnostic near the top of the form
|
||||||
confirms that all of your changes are reflected in the model.
|
confirms that all of your changes are reflected in the model.
|
||||||
@ -493,19 +483,15 @@ Follow these steps *precisely*:
|
|||||||
|
|
||||||
The actions and effects are as follows:
|
The actions and effects are as follows:
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/forms/control-state-transitions-anim.gif" alt="Control State Transition">
|
<img src="generated/images/guide/forms/control-state-transitions-anim.gif" alt="Control State Transition">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
You should see the following transitions and class names:
|
You should see the following transitions and class names:
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/forms/ng-control-class-changes.png" alt="Control state transitions">
|
<img src="generated/images/guide/forms/ng-control-class-changes.png" alt="Control state transitions">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
The `ng-valid`/`ng-invalid` pair is the most interesting, because you want to send a
|
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.
|
strong visual signal when the values are invalid. You also want to mark required fields.
|
||||||
@ -518,11 +504,9 @@ To create such visual feedback, add definitions for the `ng-*` CSS classes.
|
|||||||
You can mark required fields and invalid data at the same time with a colored bar
|
You can mark required fields and invalid data at the same time with a colored bar
|
||||||
on the left of the input box:
|
on the left of the input box:
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/forms/validity-required-indicator.png" alt="Invalid Form">
|
<img src="generated/images/guide/forms/validity-required-indicator.png" alt="Invalid Form">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
You achieve this effect by adding these class definitions to a new `forms.css` file
|
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`:
|
that you add to the project as a sibling to `index.html`:
|
||||||
@ -541,11 +525,9 @@ Leverage the control's state to reveal a helpful message.
|
|||||||
|
|
||||||
When the user deletes the name, the form should look like this:
|
When the user deletes the name, the form should look like this:
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/forms/name-required-error.png" alt="Name required">
|
<img src="generated/images/guide/forms/name-required-error.png" alt="Name required">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
To achieve this effect, extend the `<input>` tag with the following:
|
To achieve this effect, extend the `<input>` tag with the following:
|
||||||
|
|
||||||
|
@ -111,11 +111,9 @@ directives in `CommonModule`; they don’t need to re-install app-wide providers
|
|||||||
If you do import `BrowserModule` into a lazy loaded feature module,
|
If you do import `BrowserModule` into a lazy loaded feature module,
|
||||||
Angular returns an error telling you to use `CommonModule` instead.
|
Angular returns an error telling you to use `CommonModule` instead.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/frequent-ngmodules/browser-module-error.gif" width=750 alt="BrowserModule error">
|
<img src="generated/images/guide/frequent-ngmodules/browser-module-error.gif" width=750 alt="BrowserModule error">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
|
@ -108,11 +108,9 @@ The following diagram represents the relationship between the
|
|||||||
`root` `ModuleInjector` and its parent injectors as the
|
`root` `ModuleInjector` and its parent injectors as the
|
||||||
previous paragraphs describe.
|
previous paragraphs describe.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/dependency-injection/injectors.svg" alt="NullInjector, ModuleInjector, root injector">
|
<img src="generated/images/guide/dependency-injection/injectors.svg" alt="NullInjector, ModuleInjector, root injector">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
While the name `root` is a special alias, other `ModuleInjector`s
|
While the name `root` is a special alias, other `ModuleInjector`s
|
||||||
don't have aliases. You have the option to create `ModuleInjector`s
|
don't have aliases. You have the option to create `ModuleInjector`s
|
||||||
@ -1098,12 +1096,9 @@ Each tax return component has the following characteristics:
|
|||||||
* Can change a tax return without affecting a return in another component.
|
* Can change a tax return without affecting a return in another component.
|
||||||
* Has the ability to save the changes to its tax return or cancel them.
|
* Has the ability to save the changes to its tax return or cancel them.
|
||||||
|
|
||||||
|
<div class="lightbox">
|
||||||
<figure class="lightbox">
|
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/dependency-injection/hid-heroes-anim.gif" alt="Heroes in action">
|
<img src="generated/images/guide/dependency-injection/hid-heroes-anim.gif" alt="Heroes in action">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
Suppose that the `HeroTaxReturnComponent` had logic to manage and restore changes.
|
Suppose that the `HeroTaxReturnComponent` had logic to manage and restore changes.
|
||||||
That would be a pretty easy task for a simple hero tax return.
|
That would be a pretty easy task for a simple hero tax return.
|
||||||
@ -1172,11 +1167,9 @@ that have special capabilities suitable for whatever is going on in component (B
|
|||||||
Component (B) is the parent of another component (C) that defines its own, even _more specialized_ provider for `CarService`.
|
Component (B) is the parent of another component (C) that defines its own, even _more specialized_ provider for `CarService`.
|
||||||
|
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/dependency-injection/car-components.png" alt="car components">
|
<img src="generated/images/guide/dependency-injection/car-components.png" alt="car components">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
Behind the scenes, each component sets up its own injector with zero, one, or more providers defined for that component itself.
|
Behind the scenes, each component sets up its own injector with zero, one, or more providers defined for that component itself.
|
||||||
|
|
||||||
@ -1185,11 +1178,9 @@ its injector produces an instance of `Car` resolved by injector (C) with an `Eng
|
|||||||
`Tires` resolved by the root injector (A).
|
`Tires` resolved by the root injector (A).
|
||||||
|
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/dependency-injection/injector-tree.png" alt="car injector tree">
|
<img src="generated/images/guide/dependency-injection/injector-tree.png" alt="car injector tree">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
@ -170,7 +170,7 @@ As you can see, the response object has a `body` property of the correct type.
|
|||||||
|
|
||||||
### Making a JSONP request
|
### Making a JSONP request
|
||||||
|
|
||||||
Apps can use the the `HttpClient` to make [JSONP](https://en.wikipedia.org/wiki/JSONP) requests across domains when the server doesn't support [CORS protocol](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS).
|
Apps can use the `HttpClient` to make [JSONP](https://en.wikipedia.org/wiki/JSONP) requests across domains when the server doesn't support [CORS protocol](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS).
|
||||||
|
|
||||||
Angular JSONP requests return an `Observable`.
|
Angular JSONP requests return an `Observable`.
|
||||||
Follow the pattern for subscribing to observables and use the RxJS `map` operator to transform the response before using the [async pipe](api/common/AsyncPipe) to manage the results.
|
Follow the pattern for subscribing to observables and use the RxJS `map` operator to transform the response before using the [async pipe](api/common/AsyncPipe) to manage the results.
|
||||||
@ -951,7 +951,7 @@ by returning an observable of simulated events.
|
|||||||
|
|
||||||
## Security: XSRF protection
|
## Security: XSRF protection
|
||||||
|
|
||||||
[Cross-Site Request Forgery (XSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery) is an attack technique by which the attacker can trick an authenticated user into unknowingly executing actions on your website.
|
[Cross-Site Request Forgery (XSRF or CSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery) is an attack technique by which the attacker can trick an authenticated user into unknowingly executing actions on your website.
|
||||||
`HttpClient` supports a [common mechanism](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Cookie-to-Header_Token) used to prevent XSRF attacks.
|
`HttpClient` supports a [common mechanism](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Cookie-to-Header_Token) used to prevent XSRF attacks.
|
||||||
When performing HTTP requests, an interceptor reads a token from a cookie, by default `XSRF-TOKEN`, and sets it as an HTTP header, `X-XSRF-TOKEN`.
|
When performing HTTP requests, an interceptor reads a token from a cookie, by default `XSRF-TOKEN`, and sets it as an HTTP header, `X-XSRF-TOKEN`.
|
||||||
Since only code that runs on your domain could read the cookie, the backend can be certain that the HTTP request came from your client application and not an attacker.
|
Since only code that runs on your domain could read the cookie, the backend can be certain that the HTTP request came from your client application and not an attacker.
|
||||||
|
@ -25,6 +25,16 @@ After you have set up your app to use i18n, the CLI can help you with the follow
|
|||||||
* Building and serving the app for a given locale, using the translated text.
|
* Building and serving the app for a given locale, using the translated text.
|
||||||
* Creating multiple language versions of your app.
|
* Creating multiple language versions of your app.
|
||||||
|
|
||||||
|
{@a setting-up-cli}
|
||||||
|
## Setting up localization with the Angular CLI
|
||||||
|
|
||||||
|
The first step to setting up localization when using the Angular CLI is to add the `@angular/localize` package to the project. This will install the package within your project as well as
|
||||||
|
initialize the project to take advantage of Angular's localization features.
|
||||||
|
|
||||||
|
<code-example language="sh" class="code-shell">
|
||||||
|
ng add @angular/localize
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
{@a setting-up-locale}
|
{@a setting-up-locale}
|
||||||
## Setting up the locale of your app
|
## Setting up the locale of your app
|
||||||
@ -76,12 +86,12 @@ time of writing:
|
|||||||
## i18n pipes
|
## i18n pipes
|
||||||
|
|
||||||
Angular pipes can help you with internationalization: the `DatePipe`, `CurrencyPipe`, `DecimalPipe`
|
Angular pipes can help you with internationalization: the `DatePipe`, `CurrencyPipe`, `DecimalPipe`
|
||||||
and `PercentPipe` use locale data to format data based on the `LOCALE_ID`.
|
and `PercentPipe` use locale data to format data based on the `LOCALE_ID` dependency injection token.
|
||||||
|
|
||||||
By default, Angular only contains locale data for `en-US`. If you set the value of
|
By default, Angular only contains locale data for `en-US`.
|
||||||
`LOCALE_ID` to another locale, you must import locale data for that new locale.
|
The CLI automatically includes the locale data and sets the `LOCALE_ID` value for you when you use the
|
||||||
The CLI imports the locale data for you when you use the parameter `--configuration` with `ng serve` and
|
parameter `--i18nLocale` or option `i18nLocale` with `ng serve` and `ng build`.
|
||||||
`ng build`.
|
However, if you manually set the value of `LOCALE_ID` to another locale, you must import locale data for that new locale.
|
||||||
|
|
||||||
If you want to import locale data for other languages, you can do it manually:
|
If you want to import locale data for other languages, you can do it manually:
|
||||||
|
|
||||||
@ -98,6 +108,7 @@ locale id "fr-FR" instead of "fr".
|
|||||||
The files in `@angular/common/locales` contain most of the locale data that you
|
The files in `@angular/common/locales` contain most of the locale data that you
|
||||||
need, but some advanced formatting options might only be available in the extra dataset that you can
|
need, but some advanced formatting options might only be available in the extra dataset that you can
|
||||||
import from `@angular/common/locales/extra`. An error message informs you when this is the case.
|
import from `@angular/common/locales/extra`. An error message informs you when this is the case.
|
||||||
|
Ivy will automatically include the extra locale data if the locale was configured via `i18nLocale`.
|
||||||
|
|
||||||
<code-example path="i18n/doc-files/app.locale_data_extra.ts" region="import-locale-extra" header="src/app/app.module.ts"></code-example>
|
<code-example path="i18n/doc-files/app.locale_data_extra.ts" region="import-locale-extra" header="src/app/app.module.ts"></code-example>
|
||||||
|
|
||||||
@ -126,10 +137,10 @@ The i18n template translation process has four phases:
|
|||||||
|
|
||||||
3. Edit the generated translation file: Translate the extracted text into the target language.
|
3. Edit the generated translation file: Translate the extracted text into the target language.
|
||||||
|
|
||||||
4. Merge the completed translation file into the app. To do this, use the Angular CLI `build` command to compile the app, choosing a [locale-specific configuration](#merge-aot), or specifying the following command options.
|
4. Merge the completed translation file into the app. To do this, use the Angular CLI `build` command to compile the app, choosing a [locale-specific configuration](#merge), or specifying the following command options.
|
||||||
|
|
||||||
* `--i18nFile`=*path to the translation file*
|
* `--i18nFile`=*path to the translation file*
|
||||||
* `--i18nFormat`=*format of the translation file*
|
* `--i18nFormat`=*format of the translation file (only required if using an earlier version of Angular, or if you [disable Ivy](guide/ivy#opting-out-of-ivy-in-version-9))*
|
||||||
* `--i18nLocale`= *locale id*
|
* `--i18nLocale`= *locale id*
|
||||||
|
|
||||||
The command replaces the original messages with translated text, and generates a new version of the app in the target language.
|
The command replaces the original messages with translated text, and generates a new version of the app in the target language.
|
||||||
@ -381,17 +392,6 @@ Open a terminal window at the root of the app project and run the CLI command `x
|
|||||||
|
|
||||||
By default, the command creates a file named `messages.xlf` in your project's root directory.
|
By default, the command creates a file named `messages.xlf` in your project's root directory.
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
|
|
||||||
If you don't use the CLI, you have two options:
|
|
||||||
* You can use the `ng-xi18n` tool directly from the `@angular/compiler-cli` package.
|
|
||||||
For more information, see the [`ng xi18n` command documentation](cli/xi18n).
|
|
||||||
* You can use the CLI Webpack plugin `AngularCompilerPlugin` from the `@ngtools/webpack` package.
|
|
||||||
Set the parameters `i18nOutFile` and `i18nOutFormat` to trigger the extraction.
|
|
||||||
For more information, see the [Angular Ahead-of-Time Webpack Plugin documentation](https://github.com/angular/angular-cli/tree/master/packages/ngtools/webpack).
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{@a other-formats}
|
{@a other-formats}
|
||||||
### Output options
|
### Output options
|
||||||
|
|
||||||
@ -412,13 +412,13 @@ The command can read and write files in three translation formats:
|
|||||||
* <a href="http://cldr.unicode.org/development/development-process/design-proposals/xmb" >XML Message
|
* <a href="http://cldr.unicode.org/development/development-process/design-proposals/xmb" >XML Message
|
||||||
Bundle (XMB)</a>
|
Bundle (XMB)</a>
|
||||||
|
|
||||||
You can specify the translation format explicitly with the `--i18nFormat` command option, as illustrated in
|
You can specify the translation format explicitly with the `--format` command option, as illustrated in
|
||||||
these example commands:
|
these example commands:
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
ng xi18n --i18n-format=xlf
|
ng xi18n --format=xlf
|
||||||
ng xi18n --i18n-format=xlf2
|
ng xi18n --format=xlf2
|
||||||
ng xi18n --i18n-format=xmb
|
ng xi18n --format=xmb
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
The sample in this guide uses the default XLIFF 1.2 format.
|
The sample in this guide uses the default XLIFF 1.2 format.
|
||||||
@ -454,8 +454,7 @@ file. This information is not used by Angular, but external translation tools ma
|
|||||||
{@a translate}
|
{@a translate}
|
||||||
## Translate the source text
|
## Translate the source text
|
||||||
|
|
||||||
The `ng xi18n` command generates a translation source file named `messages.xlf` in the project `src`
|
By default, the `ng xi18n` command generates a translation source file named `messages.xlf` in the project `src` folder.
|
||||||
folder.
|
|
||||||
The next step is to translate the display strings in this source file into language-specific
|
The next step is to translate the display strings in this source file into language-specific
|
||||||
translation files. The example in this guide creates a French translation file.
|
translation files. The example in this guide creates a French translation file.
|
||||||
|
|
||||||
@ -630,18 +629,17 @@ translation file.
|
|||||||
The compilation process is the same whether the translation file is in `.xlf` format or in another
|
The compilation process is the same whether the translation file is in `.xlf` format or in another
|
||||||
format that Angular understands, such as `.xtb`.
|
format that Angular understands, such as `.xtb`.
|
||||||
|
|
||||||
How you provide this information depends upon whether you compile with
|
|
||||||
the JIT compiler or the AOT compiler.
|
|
||||||
|
|
||||||
* With [AOT](guide/i18n#merge-aot), you pass the information as configuration settings.
|
|
||||||
* With [JIT](guide/i18n#merge-jit), you provide the information at bootstrap time.
|
|
||||||
|
|
||||||
|
|
||||||
{@a merge-aot}
|
{@a merge-aot}
|
||||||
### Merge with the AOT compiler
|
|
||||||
|
|
||||||
The [AOT compiler](guide/glossary#aot) is part of a build process that produces a small, fast,
|
The [AOT compiler](guide/glossary#aot) is part of a build process that produces a small, fast,
|
||||||
ready-to-run application package, typically for production.
|
ready-to-run application package, with Ivy it is now used for both production and development.
|
||||||
|
|
||||||
|
<div class="alert is-important">
|
||||||
|
|
||||||
|
Ivy does not support merging i18n translations when using JIT mode.
|
||||||
|
If you [disable Ivy](guide/ivy#opting-out-of-ivy-in-version-9) and are using JIT mode,
|
||||||
|
additional information regarding translation merging can be found [here](https://v8.angular.io/guide/i18n#merge-with-the-jit-compiler).
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
When you internationalize with the AOT compiler, you must pre-build a separate application
|
When you internationalize with the AOT compiler, you must pre-build a separate application
|
||||||
package for each language and serve the appropriate package based on either server-side language
|
package for each language and serve the appropriate package based on either server-side language
|
||||||
@ -650,7 +648,7 @@ detection or URL parameters.
|
|||||||
To instruct the AOT compiler to use your translation configuration, set the three "i18n" build configuration options in your CLI configuration file, `angular.json`.
|
To instruct the AOT compiler to use your translation configuration, set the three "i18n" build configuration options in your CLI configuration file, `angular.json`.
|
||||||
|
|
||||||
* `i18nFile`: the path to the translation file.
|
* `i18nFile`: the path to the translation file.
|
||||||
* `i18nFormat`: the format of the translation file.
|
* `i18nFormat`: the format of the translation file (only required if using an earlier version of Angular, or if you [disable Ivy](guide/ivy#opting-out-of-ivy-in-version-9)).
|
||||||
* `i18nLocale`: the locale id.
|
* `i18nLocale`: the locale id.
|
||||||
|
|
||||||
You should also direct the output to a locale-specific folder to keep it separate from other locale versions of your app, by setting the `outputPath` configuration option.
|
You should also direct the output to a locale-specific folder to keep it separate from other locale versions of your app, by setting the `outputPath` configuration option.
|
||||||
@ -689,8 +687,11 @@ sections of this guide:
|
|||||||
ng serve --configuration=fr
|
ng serve --configuration=fr
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
For production builds, you define a separate `production-fr` build configuration in
|
For production builds, you can use configuration composition to execute both configurations:
|
||||||
the CLI configuration file, `angular.json`.
|
|
||||||
|
<code-example language="sh" class="code-shell">
|
||||||
|
ng build --configuration=production,fr
|
||||||
|
</code-example>
|
||||||
|
|
||||||
```
|
```
|
||||||
...
|
...
|
||||||
@ -733,34 +734,6 @@ The same configuration options can also be provided through the CLI with your ex
|
|||||||
ng build --prod --i18n-file src/locale/messages.fr.xlf --i18n-format xlf --i18n-locale fr
|
ng build --prod --i18n-file src/locale/messages.fr.xlf --i18n-format xlf --i18n-locale fr
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
{@a merge-jit}
|
|
||||||
### Merge with the JIT compiler
|
|
||||||
|
|
||||||
The [JITcompiler](guide/glossary#jit) compiles your app in the browser as the app loads.
|
|
||||||
To support translation with the JIT compiler, you must do the following:
|
|
||||||
|
|
||||||
1. Import the appropriate language translation file as a string constant.
|
|
||||||
2. Create corresponding translation providers for the JIT compiler.
|
|
||||||
3. Bootstrap the app with those providers.
|
|
||||||
|
|
||||||
Three providers tell the JIT compiler how to translate the template texts for a particular language
|
|
||||||
while compiling the app:
|
|
||||||
|
|
||||||
* `TRANSLATIONS` is a string containing the content of the translation file.
|
|
||||||
* `TRANSLATIONS_FORMAT` is the format of the file: `xlf`, `xlf2`, or `xtb`.
|
|
||||||
* `LOCALE_ID` is the locale of the target language.
|
|
||||||
|
|
||||||
The Angular `bootstrapModule` method has a second `compilerOptions` parameter that can influence the
|
|
||||||
behavior of the compiler. You can use it to specify the translation providers:
|
|
||||||
|
|
||||||
<code-example path="i18n/doc-files/main.2.ts" header="src/main.ts">
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
Then provide the `LOCALE_ID` in the main module:
|
|
||||||
|
|
||||||
<code-example path="i18n/doc-files/app.module.ts" header="src/app/app.module.ts"></code-example>
|
|
||||||
|
|
||||||
|
|
||||||
{@a missing-translation}
|
{@a missing-translation}
|
||||||
### Report missing translations
|
### Report missing translations
|
||||||
|
|
||||||
@ -785,13 +758,6 @@ You specify the warning level in the `configurations` section of your Angular CL
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If you use the JIT compiler, specify the warning level in the compiler config at bootstrap by adding
|
|
||||||
the 'MissingTranslationStrategy' property. The example below shows how to set the warning level to
|
|
||||||
error.
|
|
||||||
|
|
||||||
<code-example path="i18n/doc-files/main.3.ts" header="src/main.ts">
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
### Build for multiple locales
|
### Build for multiple locales
|
||||||
|
|
||||||
When you use the CLI `build` or `serve` command to build your application for different locales, change the output path using the `--outputPath` command option (along with the i18n-specific command options), so that the translation files are saved to different locations.
|
When you use the CLI `build` or `serve` command to build your application for different locales, change the output path using the `--outputPath` command option (along with the i18n-specific command options), so that the translation files are saved to different locations.
|
||||||
|
@ -112,3 +112,105 @@ Option 2:
|
|||||||
<div #foo></div> <!-- matches in both old runtime and new runtime -->
|
<div #foo></div> <!-- matches in both old runtime and new runtime -->
|
||||||
</comp>
|
</comp>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
{@a undecorated-classes}
|
||||||
|
## All Classes That Use Angular DI Must Have An Angular Class-level Decorator
|
||||||
|
|
||||||
|
|
||||||
|
### Basic example of change:
|
||||||
|
|
||||||
|
In the previous rendering engine, the following would work:
|
||||||
|
|
||||||
|
```
|
||||||
|
export class DataService {
|
||||||
|
constructor(@Inject('CONFIG') public config: DataConfig) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AppService extends DataService {...}
|
||||||
|
```
|
||||||
|
|
||||||
|
In Ivy, it will throw an error because `DataService` is using Angular dependency injection, but is missing an `@Injectable` decorator.
|
||||||
|
|
||||||
|
The following would also work in the previous rendering engine, but in Ivy would require a `@Directive` decorator because it uses DI:
|
||||||
|
|
||||||
|
```
|
||||||
|
export class BaseMenu {
|
||||||
|
constructor(private vcr: ViewContainerRef) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Directive({selector: '[settingsMenu]'})
|
||||||
|
export class SettingsMenu extends BaseMenu {}
|
||||||
|
```
|
||||||
|
|
||||||
|
The same is true if your directive class extends a decorated directive, but does not have a decorator of its own.
|
||||||
|
|
||||||
|
If you're using the CLI, there are two automated migrations that should transition your code for you ([this one](guide/migration-injectable) and [this one](guide/migration-undecorated-classes)).
|
||||||
|
However, as you're adding new code in version 9, you may run into this difference.
|
||||||
|
|
||||||
|
### Background
|
||||||
|
|
||||||
|
When a class has an Angular decorator like `@Injectable` or `@Directive`, the Angular compiler generates extra code to support injecting dependencies into the constructor of your class.
|
||||||
|
When using inheritance, Ivy needs both the parent class and the child class to apply a decorator to generate the correct code.
|
||||||
|
Otherwise, when the decorator is missing from the parent class, the subclass will inherit a constructor from a class for which the compiler did not generate special constructor info, and Angular won't have the dependency info it needs to create it properly.
|
||||||
|
|
||||||
|
In the previous rendering engine, the compiler had global knowledge, so in some cases (such as AOT mode or the presence of certain injection flags), it could look up the missing data.
|
||||||
|
However, the Ivy compiler only processes each class in isolation.
|
||||||
|
This means that compilation has the potential to be faster (and opens the framework up for optimizations and features going forward), but the compiler can't automatically infer the same information as before.
|
||||||
|
|
||||||
|
Adding the proper decorator explicitly provides this information.
|
||||||
|
|
||||||
|
### Example of error
|
||||||
|
|
||||||
|
In JIT mode, the framework will throw the following error:
|
||||||
|
|
||||||
|
```
|
||||||
|
ERROR: This constructor is not compatible with Angular Dependency Injection because dependency at index 'X' is invalid.
|
||||||
|
This can happen if the dependency type is a primitive like a string or if an ancestor of this class is missing an Angular decorator.
|
||||||
|
|
||||||
|
Please check that 1) the type for dependency X is correct and 2) the correct Angular decorators are defined for this class and its ancestors.
|
||||||
|
```
|
||||||
|
|
||||||
|
In AOT mode, you'll see something like:
|
||||||
|
|
||||||
|
```
|
||||||
|
X inherits its constructor from Y, but the latter does not have an Angular decorator of its own.
|
||||||
|
Dependency injection will not be able to resolve the parameters of Y's constructor. Either add a
|
||||||
|
@Directive decorator to Y, or add an explicit constructor to X.
|
||||||
|
```
|
||||||
|
|
||||||
|
In some cases, the framework may not be able to detect the missing decorator.
|
||||||
|
In these cases, you'll generally see a runtime error thrown when there is a property access attempted on the missing dependency.
|
||||||
|
If dependency was `foo`, you'd see an error when accessing something like `foo.bar`:
|
||||||
|
|
||||||
|
```
|
||||||
|
Uncaught TypeError: Cannot read property 'bar' of undefined
|
||||||
|
```
|
||||||
|
|
||||||
|
If you see an error like this, and the `undefined` value refers to something that should have been injected, it may be this change.
|
||||||
|
|
||||||
|
### Recommended fix
|
||||||
|
|
||||||
|
- Add an `@Injectable` decorator to anything you plan to provide or inject.
|
||||||
|
|
||||||
|
```
|
||||||
|
@Injectable()
|
||||||
|
export class DataService {
|
||||||
|
constructor(@Inject('CONFIG') public config: DataConfig) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AppService extends DataService {...}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Add a [selectorless `@Directive` decorator](guide/migration-undecorated-classes#what-does-it-mean-to-have-a-directive-decorator-with-no-metadata-inside-of-it) to any class that extends a directive or any class from which a directive inherits.
|
||||||
|
|
||||||
|
```
|
||||||
|
@Directive() // selectorless, so it's not usable directly
|
||||||
|
export class BaseMenu {
|
||||||
|
constructor(private vcr: ViewContainerRef) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Directive({selector: '[settingsMenu]'})
|
||||||
|
export class SettingsMenu extends BaseMenu {}
|
||||||
|
```
|
@ -11,9 +11,9 @@ That said, some applications will likely need to apply some manual updates.
|
|||||||
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.
|
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.
|
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 in your `tsconfig.json`](guide/ivy#opting-out-of-angular-ivy) 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 9 guide](guide/updating-to-version-9).
|
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.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.
|
||||||
|
|
||||||
@ -21,40 +21,39 @@ If the errors are gone, switch back to Ivy by removing the changes to the `tscon
|
|||||||
{@a common-changes}
|
{@a common-changes}
|
||||||
### Changes You May See
|
### Changes You May See
|
||||||
|
|
||||||
- By default, `@ContentChildren` queries will only search direct child nodes in the DOM hierarchy (previously, they would search any nesting level in the DOM as long as another directive wasn't matched above it). ([details](guide/ivy-compatibility-examples#content-children-descendants))
|
* By default, `@ContentChildren` queries will only search direct child nodes in the DOM hierarchy (previously, they would search any nesting level in the DOM as long as another directive wasn't matched above it). [details](guide/ivy-compatibility-examples#content-children-descendants)
|
||||||
|
|
||||||
- All classes that use Angular DI must have an Angular decorator like `@Directive()` or `@Injectable` (previously, undecorated classes were allowed if an ancestor class or subclass had a decorator).
|
* All classes that use Angular DI must have an Angular decorator like `@Directive()` or `@Injectable` (previously, undecorated classes were allowed in AOT mode only or if injection flags were used). [details](guide/ivy-compatibility-examples#undecorated-classes)
|
||||||
|
|
||||||
- Unbound inputs for directives (e.g. name in `<my-comp name="">`) are now set upon creation of the view, before change detection runs (previously, all inputs were set during change detection).
|
|
||||||
|
|
||||||
|
* Unbound inputs for directives (e.g. name in `<my-comp name="">`) are now set upon creation of the view, before change detection runs (previously, all inputs were set during change detection).
|
||||||
|
|
||||||
{@a less-common-changes}
|
{@a less-common-changes}
|
||||||
### Less Common Changes
|
### Less Common Changes
|
||||||
|
|
||||||
- Properties like `host` inside `@Component` and `@Directive` decorators can be inherited (previously, only properties with explicit field decorators like `@HostBinding` would be inherited).
|
* Properties like `host` inside `@Component` and `@Directive` decorators can be inherited (previously, only properties with explicit field decorators like `@HostBinding` would be inherited).
|
||||||
|
|
||||||
- HammerJS support is opt-in through importing the `HammerModule` (previously, it was always included in production bundles regardless of whether the app used HammerJS).
|
* HammerJS support is opt-in through importing the `HammerModule` (previously, it was always included in production bundles regardless of whether the app used HammerJS).
|
||||||
|
|
||||||
- `@ContentChild` and `@ContentChildren` queries will no longer be able to match their directive's own host node (previously, these queries would match the host node in addition to its content children).
|
* `@ContentChild` and `@ContentChildren` queries will no longer be able to match their directive's own host node (previously, these queries would match the host node in addition to its content children).
|
||||||
|
|
||||||
- If a token is injected with the `@Host` or `@Self` flag, the module injector is not searched for that token (previously, tokens marked with these flags would still search at the module level).
|
* If a token is injected with the `@Host` or `@Self` flag, the module injector is not searched for that token (previously, tokens marked with these flags would still search at the module level).
|
||||||
|
|
||||||
- If a template is declared in one view but inserted into a different view, change detection will occur for that template only when its insertion point is checked (previously, change detection would also run when its declaration point was checked).
|
* When accessing multiple local refs with the same name in template bindings, the first is matched (previously, the last instance was matched).
|
||||||
|
|
||||||
- When accessing multiple local refs with the same name in template bindings, the first is matched (previously, the last instance was matched).
|
* Directives that are used in an exported module (but not exported themselves) are exported publicly (previously, the compiler would automatically write a private, aliased export that it could use its global knowledge to resolve downstream).
|
||||||
|
|
||||||
- Directives that are used in an exported module (but not exported themselves) are exported publicly (previously, the compiler would automatically write a private, aliased export that it could use its global knowledge to resolve downstream).
|
* 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).
|
||||||
|
|
||||||
- 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.
|
||||||
|
|
||||||
- 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).
|
||||||
|
|
||||||
- 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).
|
* It is now an error to assign values to template-only variables like `item` in `ngFor="let item of items"` (previously, the compiler would ignore these assignments).
|
||||||
|
|
||||||
- It is now an error to assign values to template-only variables like `item` in `ngFor="let item of items"` (previously, the compiler would ignore these assignments).
|
* It's no longer possible to overwrite lifecycle hooks with mocks on directive instances for testing (instead, modify the lifecycle hook on the directive type itself).
|
||||||
|
|
||||||
- It's no longer possible to overwrite lifecycle hooks with mocks on directive instances for testing (instead, modify the lifecycle hook on the directive type itself).
|
* Special injection tokens (such as `TemplateRef` or `ViewContainerRef`) return a new instance whenever they are requested (previously, instances of special tokens were shared if requested on the same node). This primarily affects tests that do identity comparison of these objects.
|
||||||
|
|
||||||
- Special injection tokens (e.g. `TemplateRef` or `ViewContainerRef`) return a new instance whenever they are requested (previously, instances of special tokens were shared if requested on the same node). This primarily affects tests that do identity comparison of these objects.
|
* ICU parsing happens at runtime, so only text, HTML tags and text bindings are allowed inside ICU cases (previously, directives were also permitted inside ICUs).
|
||||||
|
|
||||||
- ICU parsing happens at runtime, so only text, HTML tags and text bindings are allowed inside ICU cases (previously, directives were also permitted inside ICUs).
|
* Providers formatted as `{provide: X}` without a `useValue`, `useFactory`, `useExisting`, or `useClass` property are treated like `{provide: X, useClass: X}` (previously, it defaulted to `{provide: X, useValue: undefined}`).
|
@ -15,6 +15,7 @@ Learn more about the [Compiler](https://www.youtube.com/watch?v=anphffaCZrQ) and
|
|||||||
|
|
||||||
AOT compilation with Ivy is faster and should be used by default.
|
AOT compilation with Ivy is faster and should be used by default.
|
||||||
In the `angular.json` workspace configuration file, set the default build options for your project to always use AOT compilation.
|
In the `angular.json` workspace configuration file, set the default build options for your project to always use AOT compilation.
|
||||||
|
When using application internationalization (i18n) with Ivy, [translation merging](guide/i18n#merge) also requires the use of AOT compilation.
|
||||||
|
|
||||||
<code-example language="json" header="angular.json">
|
<code-example language="json" header="angular.json">
|
||||||
|
|
||||||
@ -38,7 +39,33 @@ In the `angular.json` workspace configuration file, set the default build option
|
|||||||
|
|
||||||
Ivy applications can be built with libraries that were created with the View Engine compiler.
|
Ivy applications can be built with libraries that were created with the View Engine compiler.
|
||||||
This compatibility is provided by a tool known as the Angular compatibility compiler (`ngcc`).
|
This compatibility is provided by a tool known as the Angular compatibility compiler (`ngcc`).
|
||||||
CLI commands run `ngcc` as needed, either after npm installation of dependencies or when performing an Angular build.
|
CLI commands run `ngcc` as needed performing an Angular build.
|
||||||
|
|
||||||
|
{@a speeding-up-ngcc-compilation}
|
||||||
|
### Speeding up ngcc compilation
|
||||||
|
|
||||||
|
The standalone `ngcc` program can run in parallel over your third party modules, making it more efficient than letting Angular CLI run it as needed.
|
||||||
|
|
||||||
|
You can run `ngcc` after each installation of node_modules by adding a `postinstall` [npm script](https://docs.npmjs.com/misc/scripts):
|
||||||
|
|
||||||
|
<code-example language="json" header="package.json">
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"postinstall": "ngcc --properties es2015 browser module main --first-only --create-ivy-entry-points"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
<div class="alert is-important">
|
||||||
|
|
||||||
|
The `postinstall` script will run on every installation of `node_modules`, including those performed by `ng update` and `ng add`.
|
||||||
|
|
||||||
|
If you perform multiple installs in a row, this can end up being slower than letting Angular CLI run `ngcc` on builds.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{@a maintaining-library-compatibility}
|
||||||
|
### Maintaining library compatibility
|
||||||
|
|
||||||
If you are a library author, you should keep using the View Engine compiler as of version 9.
|
If you are a library author, you should keep using the View Engine compiler as of version 9.
|
||||||
By having all libraries continue to use View Engine, you will maintain compatibility with default v9 applications that use Ivy, as well as with applications that have opted to continue using View Engine.
|
By having all libraries continue to use View Engine, you will maintain compatibility with default v9 applications that use Ivy, as well as with applications that have opted to continue using View Engine.
|
||||||
@ -61,6 +88,7 @@ Before disabling Ivy, check out the debugging recommendations in the [Ivy Compat
|
|||||||
To opt out of Ivy, change the `angularCompilerOptions` in your project's TypeScript configuration, most commonly located at `tsconfig.app.json` at the root of the workspace.
|
To opt out of Ivy, change the `angularCompilerOptions` in your project's TypeScript configuration, most commonly located at `tsconfig.app.json` at the root of the workspace.
|
||||||
|
|
||||||
The value of the `enableIvy` flag is set to `true` by default, as of version 9.
|
The value of the `enableIvy` flag is set to `true` by default, as of version 9.
|
||||||
|
|
||||||
The following example shows how to set the `enableIvy` option to `false` in order to opt out of Ivy.
|
The following example shows how to set the `enableIvy` option to `false` in order to opt out of Ivy.
|
||||||
|
|
||||||
<code-example language="json" header="tsconfig.app.json">
|
<code-example language="json" header="tsconfig.app.json">
|
||||||
@ -70,12 +98,12 @@ The following example shows how to set the `enableIvy` option to `false` in orde
|
|||||||
"outDir": "./out-tsc/app",
|
"outDir": "./out-tsc/app",
|
||||||
"types": []
|
"types": []
|
||||||
},
|
},
|
||||||
"include": [
|
"files": [
|
||||||
"src/**/*.ts"
|
"src/main.ts",
|
||||||
|
"src/polyfills.ts"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"include": [
|
||||||
"src/test.ts",
|
"src/**/*.d.ts"
|
||||||
"src/**/*.spec.ts"
|
|
||||||
],
|
],
|
||||||
"angularCompilerOptions": {
|
"angularCompilerOptions": {
|
||||||
"enableIvy": false
|
"enableIvy": false
|
||||||
@ -83,4 +111,92 @@ The following example shows how to set the `enableIvy` option to `false` in orde
|
|||||||
}
|
}
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
If you disable Ivy, you might also want to reconsider whether to make AOT compilation the default for your application development, as described [above](#aot-and-ivy). To revert the compiler default, set the build option `aot: false` in the `angular.json` configuration file.
|
<div class="alert is-important">
|
||||||
|
|
||||||
|
If you disable Ivy, you might also want to reconsider whether to make AOT compilation the default for your application development, as described [above](#aot-and-ivy).
|
||||||
|
|
||||||
|
To revert the compiler default, set the build option `aot: false` in the `angular.json` configuration file.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
If you disable Ivy and the project uses internationalization, you can also remove the `@angular/localize` runtime component from the project's polyfills file located be default at `src/polyfills.ts`.
|
||||||
|
|
||||||
|
To remove, delete the `import '@angular/localize/init';` line from the polyfills file.
|
||||||
|
|
||||||
|
<code-example language="typescript" header="polyfills.ts">
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Load `$localize` onto the global scope - used if i18n tags appear in Angular templates.
|
||||||
|
*/
|
||||||
|
import '@angular/localize/init';
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
{@a using-ssr-without-angular-ivy}
|
||||||
|
### Using SSR without Ivy
|
||||||
|
|
||||||
|
If you opt out of Ivy and your application uses [Angular Universal](guide/universal) to render Angular applications on the server, you must also change the way the server performs bootstrapping.
|
||||||
|
|
||||||
|
The following example shows how you modify the `server.ts` file to provide the `AppServerModuleNgFactory` as the bootstrap module.
|
||||||
|
|
||||||
|
* Import `AppServerModuleNgFactory` from the `app.server.module.ngfactory` virtual file.
|
||||||
|
* Set `bootstrap: AppServerModuleNgFactory` in the `ngExpressEngine` call.
|
||||||
|
|
||||||
|
<code-example language="typescript" header="server.ts">
|
||||||
|
import 'zone.js/dist/zone-node';
|
||||||
|
|
||||||
|
import { ngExpressEngine } from '@nguniversal/express-engine';
|
||||||
|
import * as express from 'express';
|
||||||
|
import { join } from 'path';
|
||||||
|
|
||||||
|
import { APP_BASE_HREF } from '@angular/common';
|
||||||
|
|
||||||
|
import { AppServerModuleNgFactory } from './src/app/app.server.module.ngfactory';
|
||||||
|
|
||||||
|
// The Express app is exported so that it can be used by serverless Functions.
|
||||||
|
export function app() {
|
||||||
|
const server = express();
|
||||||
|
const distFolder = join(process.cwd(), 'dist/ivy-test/browser');
|
||||||
|
|
||||||
|
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
|
||||||
|
server.engine('html', ngExpressEngine({
|
||||||
|
bootstrap: AppServerModuleNgFactory,
|
||||||
|
}));
|
||||||
|
|
||||||
|
server.set('view engine', 'html');
|
||||||
|
server.set('views', distFolder);
|
||||||
|
|
||||||
|
// Example Express Rest API endpoints
|
||||||
|
// app.get('/api/**', (req, res) => { });
|
||||||
|
// Serve static files from /browser
|
||||||
|
server.get('*.*', express.static(distFolder, {
|
||||||
|
maxAge: '1y'
|
||||||
|
}));
|
||||||
|
|
||||||
|
// All regular routes use the Universal engine
|
||||||
|
server.get('*', (req, res) => {
|
||||||
|
res.render('index', { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
|
||||||
|
});
|
||||||
|
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
function run() {
|
||||||
|
const port = process.env.PORT || 4000;
|
||||||
|
|
||||||
|
// Start up the Node server
|
||||||
|
const server = app();
|
||||||
|
server.listen(port, () => {
|
||||||
|
console.log(`Node Express server listening on http://localhost:${port}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Webpack will replace 'require' with '__webpack_require__'
|
||||||
|
// '__non_webpack_require__' is a proxy to Node 'require'
|
||||||
|
// The below code is to ensure that the server is run only when not requiring the bundle.
|
||||||
|
declare const __non_webpack_require__: NodeRequire;
|
||||||
|
const mainModule = __non_webpack_require__.main;
|
||||||
|
if (mainModule && mainModule.filename === __filename) {
|
||||||
|
run();
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from './src/main.server';
|
||||||
|
</code-example>
|
||||||
|
@ -25,11 +25,9 @@ contextual possibilities and hints as you type.
|
|||||||
This example shows autocomplete in an interpolation. As you type it out,
|
This example shows autocomplete in an interpolation. As you type it out,
|
||||||
you can hit tab to complete.
|
you can hit tab to complete.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/language-service/language-completion.gif" alt="autocompletion">
|
<img src="generated/images/guide/language-service/language-completion.gif" alt="autocompletion">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
There are also completions within elements. Any elements you have as a component selector will
|
There are also completions within elements. Any elements you have as a component selector will
|
||||||
show up in the completion list.
|
show up in the completion list.
|
||||||
@ -39,22 +37,18 @@ show up in the completion list.
|
|||||||
The Angular Language Service can forewarn you of mistakes in your code.
|
The Angular Language Service can forewarn you of mistakes in your code.
|
||||||
In this example, Angular doesn't know what `orders` is or where it comes from.
|
In this example, Angular doesn't know what `orders` is or where it comes from.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/language-service/language-error.gif" alt="error checking">
|
<img src="generated/images/guide/language-service/language-error.gif" alt="error checking">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
### Quick info and navigation
|
### Quick info and navigation
|
||||||
|
|
||||||
The quick-info feature allows you to hover to see where components, directives, modules, and so on come from.
|
The quick-info feature allows you to hover to see where components, directives, modules, and so on come from.
|
||||||
You can then click "Go to definition" or press F12 to go directly to the definition.
|
You can then click "Go to definition" or press F12 to go directly to the definition.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/language-service/language-navigation.gif" alt="navigation">
|
<img src="generated/images/guide/language-service/language-navigation.gif" alt="navigation">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
## Angular Language Service in your editor
|
## Angular Language Service in your editor
|
||||||
|
@ -29,6 +29,13 @@ generates a file called `app-routing.module.ts`, which is one of
|
|||||||
the files you need for setting up lazy loading for your feature module.
|
the files you need for setting up lazy loading for your feature module.
|
||||||
Navigate into the project by issuing the command `cd customer-app`.
|
Navigate into the project by issuing the command `cd customer-app`.
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
The `--routing` option requires Angular/CLI version 8.1 or higher.
|
||||||
|
See [Keeping Up to Date](guide/updating).
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
## Create a feature module with routing
|
## Create a feature module with routing
|
||||||
|
|
||||||
Next, you’ll need a feature module with a component to route to.
|
Next, you’ll need a feature module with a component to route to.
|
||||||
@ -91,11 +98,9 @@ ng serve
|
|||||||
|
|
||||||
Then go to `localhost:4200` where you should see “customer-app” and three buttons.
|
Then go to `localhost:4200` where you should see “customer-app” and three buttons.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/lazy-loading-ngmodules/three-buttons.png" width="300" alt="three buttons in the browser">
|
<img src="generated/images/guide/lazy-loading-ngmodules/three-buttons.png" width="300" alt="three buttons in the browser">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
These buttons work, because the CLI automatically added the routes to the feature modules to the `routes` array in `app.module.ts`.
|
These buttons work, because the CLI automatically added the routes to the feature modules to the `routes` array in `app.module.ts`.
|
||||||
|
|
||||||
@ -137,30 +142,24 @@ The other feature module's routing module is configured similarly.
|
|||||||
|
|
||||||
You can check to see that a module is indeed being lazy loaded with the Chrome developer tools. In Chrome, open the dev tools by pressing `Cmd+Option+i` on a Mac or `Ctrl+Shift+j` on a PC and go to the Network Tab.
|
You can check to see that a module is indeed being lazy loaded with the Chrome developer tools. In Chrome, open the dev tools by pressing `Cmd+Option+i` on a Mac or `Ctrl+Shift+j` on a PC and go to the Network Tab.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/lazy-loading-ngmodules/network-tab.png" width="600" alt="lazy loaded modules diagram">
|
<img src="generated/images/guide/lazy-loading-ngmodules/network-tab.png" width="600" alt="lazy loaded modules diagram">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
Click on the Orders or Customers button. If you see a chunk appear, everything is wired up properly and the feature module is being lazy loaded. A chunk should appear for Orders and for Customers but will only appear once for each.
|
Click on the Orders or Customers button. If you see a chunk appear, everything is wired up properly and the feature module is being lazy loaded. A chunk should appear for Orders and for Customers but will only appear once for each.
|
||||||
|
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/lazy-loading-ngmodules/chunk-arrow.png" width="600" alt="lazy loaded modules diagram">
|
<img src="generated/images/guide/lazy-loading-ngmodules/chunk-arrow.png" width="600" alt="lazy loaded modules diagram">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
To see it again, or to test after working in the project, clear everything out by clicking the circle with a line through it in the upper left of the Network Tab:
|
To see it again, or to test after working in the project, clear everything out by clicking the circle with a line through it in the upper left of the Network Tab:
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/lazy-loading-ngmodules/clear.gif" width="200" alt="lazy loaded modules diagram">
|
<img src="generated/images/guide/lazy-loading-ngmodules/clear.gif" width="200" alt="lazy loaded modules diagram">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
Then reload with `Cmd+r` or `Ctrl+r`, depending on your platform.
|
Then reload with `Cmd+r` or `Ctrl+r`, depending on your platform.
|
||||||
|
@ -291,11 +291,9 @@ The peek-a-boo exists to show how Angular calls the hooks in the expected order.
|
|||||||
|
|
||||||
This snapshot reflects the state of the log after the user clicked the *Create...* button and then the *Destroy...* button.
|
This snapshot reflects the state of the log after the user clicked the *Create...* button and then the *Destroy...* button.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/lifecycle-hooks/peek-a-boo.png" alt="Peek-a-boo">
|
<img src="generated/images/guide/lifecycle-hooks/peek-a-boo.png" alt="Peek-a-boo">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
The sequence of log messages follows the prescribed hook calling order:
|
The sequence of log messages follows the prescribed hook calling order:
|
||||||
`OnChanges`, `OnInit`, `DoCheck` (3x), `AfterContentInit`, `AfterContentChecked` (3x),
|
`OnChanges`, `OnInit`, `DoCheck` (3x), `AfterContentInit`, `AfterContentChecked` (3x),
|
||||||
@ -351,11 +349,9 @@ Here it is attached to the repeated hero `<div>`:
|
|||||||
Each spy's birth and death marks the birth and death of the attached hero `<div>`
|
Each spy's birth and death marks the birth and death of the attached hero `<div>`
|
||||||
with an entry in the *Hook Log* as seen here:
|
with an entry in the *Hook Log* as seen here:
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src='generated/images/guide/lifecycle-hooks/spy-directive.gif' alt="Spy Directive">
|
<img src='generated/images/guide/lifecycle-hooks/spy-directive.gif' alt="Spy Directive">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
Adding a hero results in a new hero `<div>`. The spy's `ngOnInit()` logs that event.
|
Adding a hero results in a new hero `<div>`. The spy's `ngOnInit()` logs that event.
|
||||||
|
|
||||||
@ -444,11 +440,9 @@ The host `OnChangesParentComponent` binds to them like this:
|
|||||||
|
|
||||||
Here's the sample in action as the user makes changes.
|
Here's the sample in action as the user makes changes.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src='generated/images/guide/lifecycle-hooks/on-changes-anim.gif' alt="OnChanges">
|
<img src='generated/images/guide/lifecycle-hooks/on-changes-anim.gif' alt="OnChanges">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
The log entries appear as the string value of the *power* property changes.
|
The log entries appear as the string value of the *power* property changes.
|
||||||
But the `ngOnChanges` does not catch changes to `hero.name`
|
But the `ngOnChanges` does not catch changes to `hero.name`
|
||||||
@ -479,11 +473,9 @@ This code inspects certain _values of interest_, capturing and comparing their c
|
|||||||
It writes a special message to the log when there are no substantive changes to the `hero` or the `power`
|
It writes a special message to the log when there are no substantive changes to the `hero` or the `power`
|
||||||
so you can see how often `DoCheck` is called. The results are illuminating:
|
so you can see how often `DoCheck` is called. The results are illuminating:
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src='generated/images/guide/lifecycle-hooks/do-check-anim.gif' alt="DoCheck">
|
<img src='generated/images/guide/lifecycle-hooks/do-check-anim.gif' alt="DoCheck">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
While the `ngDoCheck()` hook can detect when the hero's `name` has changed, it has a frightful cost.
|
While the `ngDoCheck()` hook can detect when the hero's `name` has changed, it has a frightful cost.
|
||||||
This hook is called with enormous frequency—after _every_
|
This hook is called with enormous frequency—after _every_
|
||||||
@ -535,11 +527,9 @@ for one turn of the browser's JavaScript cycle and that's just long enough.
|
|||||||
|
|
||||||
Here's *AfterView* in action:
|
Here's *AfterView* in action:
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src='generated/images/guide/lifecycle-hooks/after-view-anim.gif' alt="AfterView">
|
<img src='generated/images/guide/lifecycle-hooks/after-view-anim.gif' alt="AfterView">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
Notice that Angular frequently calls `AfterViewChecked()`, often when there are no changes of interest.
|
Notice that Angular frequently calls `AfterViewChecked()`, often when there are no changes of interest.
|
||||||
Write lean hook methods to avoid performance problems.
|
Write lean hook methods to avoid performance problems.
|
||||||
@ -582,11 +572,9 @@ The `<ng-content>` tag is a *placeholder* for the external content.
|
|||||||
It tells Angular where to insert that content.
|
It tells Angular where to insert that content.
|
||||||
In this case, the projected content is the `<app-child>` from the parent.
|
In this case, the projected content is the `<app-child>` from the parent.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src='generated/images/guide/lifecycle-hooks/projected-child-view.png' alt="Projected Content">
|
<img src='generated/images/guide/lifecycle-hooks/projected-child-view.png' alt="Projected Content">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
@ -1,64 +1,65 @@
|
|||||||
# Migration to Add Missing `@Injectable()` Decorators
|
# Migration to Add Missing `@Injectable()` Decorators
|
||||||
|
|
||||||
## What does this schematic do?
|
### What does this schematic do?
|
||||||
|
|
||||||
This schematic adds an `@Injectable()` decorator to a class
|
1. This schematic adds an `@Injectable()` decorator to classes which are provided in the
|
||||||
if the class has been added as a provider anywhere in the application.
|
application but are not decorated.
|
||||||
|
2. The schematic updates providers which follow the `{provide: SomeToken}` pattern
|
||||||
|
to explicitly specify `useValue: undefined`.
|
||||||
|
|
||||||
An example diff might look like the following:
|
**Example for missing `@Injectable()`**
|
||||||
|
|
||||||
**Before:**
|
_Before migration:_
|
||||||
|
```typescript
|
||||||
|
export class MyService {...}
|
||||||
|
export class MyOtherService {...}
|
||||||
|
export class MyThirdClass {...}
|
||||||
|
export class MyFourthClass {...}
|
||||||
|
export class MyFifthClass {...}
|
||||||
|
|
||||||
```ts
|
|
||||||
export class TypeCase {...}
|
|
||||||
```
|
|
||||||
|
|
||||||
**After:**
|
|
||||||
|
|
||||||
```ts
|
|
||||||
@Injectable()
|
|
||||||
export class TypeCase {...}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
There are a few cases where the decorator won't be added. For example:
|
|
||||||
|
|
||||||
- It already has another decorator such as `@Component()`, `@Directive()` or `@Pipe()`. These decorators already cause the compiler to generate the necessary information.
|
|
||||||
- The provider definition has `useValue`, `useFactory`, or `useExisting`. In
|
|
||||||
these cases, the framework doesn't need the `@Injectable()` decorator to create the class
|
|
||||||
because it can just use the value,
|
|
||||||
factory function, or existing instance that was provided.
|
|
||||||
|
|
||||||
For example, for the following module definition, the schematic will check
|
|
||||||
`TypeCase`, `ProvideCase`, `ExistingClass`, and `SomeClass` to ensure they
|
|
||||||
are marked with the `@Injectable()` decorator and add one if not.
|
|
||||||
|
|
||||||
|
|
||||||
```ts
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
providers: [
|
providers: [
|
||||||
// TypeCase needs @Injectable()
|
MyService,
|
||||||
TypeCase,
|
{provide: SOME_TOKEN, useClass: MyOtherService},
|
||||||
// ProvideCase needs @Injectable()
|
// The following classes do not need to be decorated because they
|
||||||
{provide: ProvideCase},
|
// are never instantiated and just serve as DI tokens.
|
||||||
// No @Injectable() needed because the value will be used
|
{provide: MyThirdClass, useValue: ...},
|
||||||
{provide: ValueCase, useValue: 0},
|
{provide: MyFourthClass, useFactory: ...},
|
||||||
// No @Injectable() needed because factory will be used
|
{provide: MyFifthClass, useExisting: ...},
|
||||||
{provide: FactoryCase, useFactory: ()=> null},
|
|
||||||
// ExistingClass needs @Injectable()
|
|
||||||
{provide: ExistingToken, useExisting: ExistingClass},
|
|
||||||
// SomeClass needs @Injectable()
|
|
||||||
{provide: ClassToken, useClass: SomeClass},
|
|
||||||
// No @Injectable() needed because it has a @Pipe() decorator
|
|
||||||
PipeCase,
|
|
||||||
|
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
```
|
||||||
|
_After migration:_
|
||||||
|
```ts
|
||||||
|
@Injectable()
|
||||||
|
export class MyService {...}
|
||||||
|
@Injectable()
|
||||||
|
export class MyOtherService {...}
|
||||||
|
export class MyThirdClass {...}
|
||||||
|
export class MyFourthClass {...}
|
||||||
|
export class MySixthClass {...}
|
||||||
|
|
||||||
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note that `MyThirdClass`, `MyFourthClass` and `MyFifthClass` do not need to be decorated
|
||||||
|
with `@Injectable()` because they are never instantiated, but just used as a [DI token][DI_TOKEN].
|
||||||
|
|
||||||
## Why is this migration necessary?
|
**Example for provider needing `useValue: undefined`**
|
||||||
|
|
||||||
|
This example shows a provider following the `{provide: X}` pattern. The provider needs to be
|
||||||
|
migrated to a more explicit definition where `useValue: undefined` is specified.
|
||||||
|
|
||||||
|
_Before migration_:
|
||||||
|
```typescript
|
||||||
|
{provide: MyToken}
|
||||||
|
```
|
||||||
|
_After migration_:
|
||||||
|
```typescript
|
||||||
|
{provide: MyToken, useValue: undefined}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Why is adding `@Injectable()` necessary?
|
||||||
|
|
||||||
In our docs, we've always recommended adding `@Injectable()`
|
In our docs, we've always recommended adding `@Injectable()`
|
||||||
decorators to any class that is provided or injected in your application.
|
decorators to any class that is provided or injected in your application.
|
||||||
@ -71,15 +72,39 @@ to strictly require the decorator because doing so enables further
|
|||||||
optimization of both the compiler and the runtime. This schematic
|
optimization of both the compiler and the runtime. This schematic
|
||||||
adds any `@Injectable()` decorators that may be missing to future-proof your app.
|
adds any `@Injectable()` decorators that may be missing to future-proof your app.
|
||||||
|
|
||||||
|
### Why is adding `useValue: undefined` necessary?
|
||||||
|
|
||||||
|
Consider the following pattern:
|
||||||
|
|
||||||
## When should I be adding `@Injectable()` decorators to classes?
|
```typescript
|
||||||
|
@NgModule({
|
||||||
|
providers: [{provide: MyService}]
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
Any class that is provided or injected somewhere must have an `@Injectable()` decorator. The decorator is necessary for the framework to properly create an instance of that class through DI.
|
Providers using this pattern will behave as if they provide `MyService` as [DI token][DI_TOKEN]
|
||||||
|
with the value of `undefined`. This is not the case in Ivy where such providers will be interpreted
|
||||||
|
as if `useClass: MyService` is specified. This means that these providers will behave differently
|
||||||
|
when updating to version 9 and above. To ensure that the provider behaves the same as before, the
|
||||||
|
DI value should be explicitly set to `undefined`.
|
||||||
|
|
||||||
However, as noted above, classes that already have another class decorator like `@Pipe` do not need both decorators. The existing class decorator will cause the compiler to generate the proper information.
|
### When should I be adding `@Injectable()` decorators to classes?
|
||||||
|
|
||||||
|
Any class that is provided must have an `@Injectable()` decorator. The decorator is necessary
|
||||||
|
for the framework to properly create an instance of that class through DI.
|
||||||
|
|
||||||
## Should I update my library?
|
However, classes which are already decorated with `@Pipe`, `@Component` or `@Directive` do not
|
||||||
|
need both decorators. The existing class decorator already instructs the compiler to generate the
|
||||||
|
needed information.
|
||||||
|
|
||||||
Yes, if your library has any tokens that are meant to be injected, they should be updated with the `@Injectable()` decorator. In a future version of Angular, a missing `@Injectable()` decorator will always throw an error.
|
### Should I update my library?
|
||||||
|
|
||||||
|
Yes, if your library has any classes that are meant to be injected, they should be updated with
|
||||||
|
the `@Injectable()` decorator. In a future version of Angular, a missing `@Injectable()` decorator
|
||||||
|
will always throw an error.
|
||||||
|
|
||||||
|
Additionally, providers in your library that follow the described `{provide: X}` pattern should be
|
||||||
|
updated to specify an explicit value. Without explicit value, these providers can behave
|
||||||
|
differently based on the Angular version in applications consuming your library.
|
||||||
|
|
||||||
|
[DI_TOKEN]: guide/glossary#di-token
|
@ -1,79 +0,0 @@
|
|||||||
# Migration to `ngcc` npm `postinstall` script
|
|
||||||
|
|
||||||
## What does this schematic do?
|
|
||||||
|
|
||||||
This schematic adds an [Angular compatibility compiler](guide/ngcc), or `ngcc`, invocation to npm/yarn's `postinstall` script in the `package.json` of an Angular CLI workspace.
|
|
||||||
This script is invoked after each execution of `npm install` and modifies `node_modules` by converting any found Angular libraries to a format that is compatible with Angular version 9.
|
|
||||||
|
|
||||||
An example diff might look like the following:
|
|
||||||
|
|
||||||
**Before:**
|
|
||||||
|
|
||||||
```json
|
|
||||||
"scripts": {
|
|
||||||
"ng": "ng",
|
|
||||||
"start": "ng serve",
|
|
||||||
"build": "ng build",
|
|
||||||
"test": "ng test",
|
|
||||||
"lint": "ng lint",
|
|
||||||
"e2e": "ng e2e"
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
**After:**
|
|
||||||
|
|
||||||
```json
|
|
||||||
"scripts": {
|
|
||||||
"ng": "ng",
|
|
||||||
"start": "ng serve",
|
|
||||||
"build": "ng build",
|
|
||||||
"test": "ng test",
|
|
||||||
"lint": "ng lint",
|
|
||||||
"e2e": "ng e2e",
|
|
||||||
"postinstall": "ngcc --properties es2015 browser module main --first-only --create-ivy-entry-points"
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
If the `package.json` already contains a `postinstall` script, then the `ngcc` invocation will be prepended to the current command:
|
|
||||||
|
|
||||||
**Before:**
|
|
||||||
```json
|
|
||||||
"scripts": {
|
|
||||||
...
|
|
||||||
"postinstall": "some-command"
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
**After:**
|
|
||||||
```json
|
|
||||||
"scripts": {
|
|
||||||
...
|
|
||||||
"postinstall": "ngcc --properties es2015 browser module main --first-only --create-ivy-entry-points && some-command"
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Why is this migration necessary?
|
|
||||||
|
|
||||||
This migration is a build performance optimization that enables `ngcc` to parallelize the compilation of npm libraries.
|
|
||||||
An application build performed via CLI's `ng build` should succeed regardless of this `postinstall` script being installed, because the CLI has `ngcc` built-in.
|
|
||||||
However, this built-in `ngcc` can't parallelize the compilation of multiple libraries, and therefore often takes considerably longer to run.
|
|
||||||
|
|
||||||
|
|
||||||
## Can I customize the `ngcc` options in the `postinstall` script?
|
|
||||||
|
|
||||||
By default the `postinstall` script invokes `ngcc` with options to compile only the most commonly needed library formats.
|
|
||||||
For some projects, especially those that depend on the CommonJS distribution of Angular (for example, Angular Universal apps), it might be beneficial to modify the `postinstall` script to also compile the CommonJS distribution of the library:
|
|
||||||
|
|
||||||
```json
|
|
||||||
"scripts": {
|
|
||||||
...
|
|
||||||
"postinstall": "ngcc --properties es2015 browser module main --first-only --create-ivy-entry-points && ngcc --properties main --create-ivy-entry-points"
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
For the full set of options run `npx ngcc --help` or `yarn ngcc --help`.
|
|
||||||
|
|
||||||
## Will libraries compiled with `ngcc` still be compatible with Angular version 8?
|
|
||||||
|
|
||||||
Yes, the migration causes `ngcc` to be invoked with the `--create-ivy-entry-points` flag, which ensures that the `ngcc` compilation is non-destructive, so the same `node_modules` can be used with Angular version 8 and version 9.
|
|
@ -86,11 +86,11 @@ The following table shows all methods that the migration maps from `Renderer` to
|
|||||||
|`createText(parentElement, value, debugInfo?)`|`appendChild(parentElement, createText(value))`|
|
|`createText(parentElement, value, debugInfo?)`|`appendChild(parentElement, createText(value))`|
|
||||||
|`createTemplateAnchor(parentElement)`|`appendChild(parentElement, createComment(''))`|
|
|`createTemplateAnchor(parentElement)`|`appendChild(parentElement, createComment(''))`|
|
||||||
|`setElementClass(renderElement, className, isAdd)`|`isAdd ? addClass(renderElement, className) : removeClass(renderElement, className)`|
|
|`setElementClass(renderElement, className, isAdd)`|`isAdd ? addClass(renderElement, className) : removeClass(renderElement, className)`|
|
||||||
|`projectNodes(parentElement, nodes)`|`for (let i = 0; i < nodes.length; i<ins></ins>) { appendChild(parentElement, nodes<i>); }`|
|
|`projectNodes(parentElement, nodes)`|`for (let i = 0; i < nodes.length; i++) { appendChild(parentElement, nodes[i]); }`|
|
||||||
|`attachViewAfter(node, viewRootNodes)`|`const parentElement = parentNode(node); const nextSibling = nextSibling(node); for (let i = 0; i < viewRootNodes.length; i<ins></ins>) { insertBefore(parentElement, viewRootNodes<i>, nextSibling);}`|
|
|`attachViewAfter(node, viewRootNodes)`|`const parentElement = parentNode(node); const nextSibling = nextSibling(node); for (let i = 0; i < viewRootNodes.length; i++) { insertBefore(parentElement, viewRootNodes[i], nextSibling);}`|
|
||||||
|`detachView(viewRootNodes)`|`for (let i = 0; i < viewRootNodes.length; i<ins></ins>) {const node = viewRootNodes<i>; const parentElement = parentNode(node); removeChild(parentElement, node);}`|
|
|`detachView(viewRootNodes)`|`for (let i = 0; i < viewRootNodes.length; i++) {const node = viewRootNodes[i]; const parentElement = parentNode(node); removeChild(parentElement, node);}`|
|
||||||
|`destroyView(hostElement, viewAllNodes)`|`for (let i = 0; i < viewAllNodes.length; i<ins></ins>) { destroyNode(viewAllNodes<i>); }`|
|
|`destroyView(hostElement, viewAllNodes)`|`for (let i = 0; i < viewAllNodes.length; i++) { destroyNode(viewAllNodes[i]); }`|
|
||||||
|`setBindingDebugInfo()`|This function is a noop in `Renderer2`.|
|
|`setBindingDebugInfo()`|This function is a noop in `Renderer2`.|
|
||||||
|`createViewRoot(hostElement)`|Should be replaced with a reference to `hostElement`|
|
|`createViewRoot(hostElement)`|Should be replaced with a reference to `hostElement`|
|
||||||
|`invokeElementMethod(renderElement, methodName, args?)`|`(renderElement as any)<methodName>.apply(renderElement, args);`|
|
|`invokeElementMethod(renderElement, methodName, args?)`|`(renderElement as any)[methodName].apply(renderElement, args);`|
|
||||||
|`animate(element, startingStyles, keyframes, duration, delay, easing, previousPlayers?)`|Throws an error (same behavior as `Renderer.animate()`)|
|
|`animate(element, startingStyles, keyframes, duration, delay, easing, previousPlayers?)`|Throws an error (same behavior as `Renderer.animate()`)|
|
||||||
|
@ -106,7 +106,7 @@ The packages listed in the `devDependencies` section of `package.json` help you
|
|||||||
To add a new `devDependency`, use either one of the following commands:
|
To add a new `devDependency`, use either one of the following commands:
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
npm install --dev <package-name>
|
npm install --save-dev <package-name>
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
|
@ -106,13 +106,9 @@ As you click the button, the displayed date alternates between
|
|||||||
"**<samp>04/15/1988</samp>**" and
|
"**<samp>04/15/1988</samp>**" and
|
||||||
"**<samp>Friday, April 15, 1988</samp>**".
|
"**<samp>Friday, April 15, 1988</samp>**".
|
||||||
|
|
||||||
|
<div class="lightbox">
|
||||||
<figure class="lightbox">
|
|
||||||
<div class="card">
|
|
||||||
<img src='generated/images/guide/pipes/date-format-toggle-anim.gif' alt="Date Format Toggle">
|
<img src='generated/images/guide/pipes/date-format-toggle-anim.gif' alt="Date Format Toggle">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
@ -188,11 +184,9 @@ Now you need a component to demonstrate the pipe.
|
|||||||
|
|
||||||
<code-example path="pipes/src/app/power-booster.component.ts" header="src/app/power-booster.component.ts"></code-example>
|
<code-example path="pipes/src/app/power-booster.component.ts" header="src/app/power-booster.component.ts"></code-example>
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src='generated/images/guide/pipes/power-booster.png' alt="Power Booster">
|
<img src='generated/images/guide/pipes/power-booster.png' alt="Power Booster">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -234,11 +228,9 @@ your pipe and two-way data binding with `ngModel`.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src='generated/images/guide/pipes/power-boost-calculator-anim.gif' alt="Power Boost Calculator">
|
<img src='generated/images/guide/pipes/power-boost-calculator-anim.gif' alt="Power Boost Calculator">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -313,11 +305,9 @@ The Flying Heroes application extends the
|
|||||||
code with checkbox switches and additional displays to help you experience these effects.
|
code with checkbox switches and additional displays to help you experience these effects.
|
||||||
|
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src='generated/images/guide/pipes/flying-heroes-anim.gif' alt="Flying Heroes">
|
<img src='generated/images/guide/pipes/flying-heroes-anim.gif' alt="Flying Heroes">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -494,11 +484,9 @@ both requesting the heroes from the `heroes.json` file.
|
|||||||
The component renders as the following:
|
The component renders as the following:
|
||||||
|
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src='generated/images/guide/pipes/hero-list.png' alt="Hero List">
|
<img src='generated/images/guide/pipes/hero-list.png' alt="Hero List">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ Though you can provide services by lazy loading modules, not all services can be
|
|||||||
|
|
||||||
Another way to limit provider scope is by adding the service you want to limit to the component’s
|
Another way to limit provider scope is by adding the service you want to limit to the component’s
|
||||||
`providers` array. Component providers and NgModule providers are independent of each other. This
|
`providers` array. Component providers and NgModule providers are independent of each other. This
|
||||||
method is helpful for when you want to eagerly load a module that needs a service all to itself.
|
method is helpful when you want to eagerly load a module that needs a service all to itself.
|
||||||
Providing a service in the component limits the service only to that component (other components in
|
Providing a service in the component limits the service only to that component (other components in
|
||||||
the same module can’t access it.)
|
the same module can’t access it.)
|
||||||
|
|
||||||
|
@ -64,11 +64,9 @@ The form control assigned to `name` is displayed when the component is added to
|
|||||||
|
|
||||||
<code-example path="reactive-forms/src/app/app.component.1.html" region="app-name-editor" header="src/app/app.component.html (name editor)"></code-example>
|
<code-example path="reactive-forms/src/app/app.component.1.html" region="app-name-editor" header="src/app/app.component.html (name editor)"></code-example>
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/reactive-forms/name-editor-1.png" alt="Name Editor">
|
<img src="generated/images/guide/reactive-forms/name-editor-1.png" alt="Name Editor">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
## Managing control values
|
## Managing control values
|
||||||
|
|
||||||
@ -110,11 +108,9 @@ Update the template with a button to simulate a name update. When you click the
|
|||||||
|
|
||||||
The form model is the source of truth for the control, so when you click the button, the value of the input is changed within the component class, overriding its current value.
|
The form model is the source of truth for the control, so when you click the button, the value of the input is changed within the component class, overriding its current value.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/reactive-forms/name-editor-2.png" alt="Name Editor Update">
|
<img src="generated/images/guide/reactive-forms/name-editor-2.png" alt="Name Editor Update">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
@ -192,11 +188,9 @@ To display the `ProfileEditor` component that contains the form, add it to a com
|
|||||||
|
|
||||||
`ProfileEditor` allows you to manage the form control instances for the `firstName` and `lastName` controls within the form group instance.
|
`ProfileEditor` allows you to manage the form control instances for the `firstName` and `lastName` controls within the form group instance.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/reactive-forms/profile-editor-1.png" alt="Profile Editor">
|
<img src="generated/images/guide/reactive-forms/profile-editor-1.png" alt="Profile Editor">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
## Creating nested form groups
|
## Creating nested form groups
|
||||||
|
|
||||||
@ -220,11 +214,9 @@ Add the `address` form group containing the `street`, `city`, `state`, and `zip`
|
|||||||
|
|
||||||
The `ProfileEditor` form is displayed as one group, but the model is broken down further to represent the logical grouping areas.
|
The `ProfileEditor` form is displayed as one group, but the model is broken down further to represent the logical grouping areas.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/reactive-forms/profile-editor-2.png" alt="Profile Editor Update">
|
<img src="generated/images/guide/reactive-forms/profile-editor-2.png" alt="Profile Editor Update">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
@ -354,11 +346,9 @@ Display the current status of `profileForm` using interpolation.
|
|||||||
|
|
||||||
<code-example path="reactive-forms/src/app/profile-editor/profile-editor.component.html" region="display-status" header="src/app/profile-editor/profile-editor.component.html (display status)"></code-example>
|
<code-example path="reactive-forms/src/app/profile-editor/profile-editor.component.html" region="display-status" header="src/app/profile-editor/profile-editor.component.html (display status)"></code-example>
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/reactive-forms/profile-editor-3.png" alt="Profile Editor Validation">
|
<img src="generated/images/guide/reactive-forms/profile-editor-3.png" alt="Profile Editor Validation">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
The **Submit** button is disabled because `profileForm` is invalid due to the required `firstName` form control. After you fill out the `firstName` input, the form becomes valid and the **Submit** button is enabled.
|
The **Submit** button is disabled because `profileForm` is invalid due to the required `firstName` form control. After you fill out the `firstName` input, the form becomes valid and the **Submit** button is enabled.
|
||||||
|
|
||||||
@ -422,11 +412,9 @@ Add the template HTML below after the `<div>` closing the `formGroupName` elemen
|
|||||||
|
|
||||||
The `*ngFor` directive iterates over each form control instance provided by the aliases form array instance. Because form array elements are unnamed, you assign the index to the `i` variable and pass it to each control to bind it to the `formControlName` input.
|
The `*ngFor` directive iterates over each form control instance provided by the aliases form array instance. Because form array elements are unnamed, you assign the index to the `i` variable and pass it to each control to bind it to the `formControlName` input.
|
||||||
|
|
||||||
<figure class="lightbox">
|
<div class="lightbox">
|
||||||
<div class="card">
|
|
||||||
<img src="generated/images/guide/reactive-forms/profile-editor-4.png" alt="Profile Editor Aliases">
|
<img src="generated/images/guide/reactive-forms/profile-editor-4.png" alt="Profile Editor Aliases">
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
|
|
||||||
Each time a new alias instance is added, the new form array instance is provided its control based on the index. This allows you to track each individual control when calculating the status and value of the root control.
|
Each time a new alias instance is added, the new form array instance is provided its control based on the index. This allows you to track each individual control when calculating the status and value of the root control.
|
||||||
|
|
||||||
|
@ -122,12 +122,8 @@ Version | Status | Released | Active Ends | LTS Ends
|
|||||||
------- | ------ | ------------ | ------------ | ------------
|
------- | ------ | ------------ | ------------ | ------------
|
||||||
^8.0.0 | Active | May 28, 2019 | Nov 28, 2019 | Nov 28, 2020
|
^8.0.0 | Active | May 28, 2019 | Nov 28, 2019 | Nov 28, 2020
|
||||||
^7.0.0 | LTS | Oct 18, 2018 | Apr 18, 2019 | Apr 18, 2020
|
^7.0.0 | LTS | Oct 18, 2018 | Apr 18, 2019 | Apr 18, 2020
|
||||||
^6.0.0 | LTS | May 3, 2018 | Nov 3, 2018 | Nov 3, 2019
|
|
||||||
|
|
||||||
Angular versions ^4.0.0 and ^5.0.0 are no longer under support.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Angular versions ^4.0.0, ^5.0.0 and ^6.0.0 are no longer under support.
|
||||||
|
|
||||||
{@a deprecation}
|
{@a deprecation}
|
||||||
## Deprecation practices
|
## Deprecation practices
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user