Compare commits
246 Commits
Author | SHA1 | Date | |
---|---|---|---|
bbeac0727b | |||
03b3a3881a | |||
2c74996b7c | |||
28406707e0 | |||
b43ae44d84 | |||
2174827fe5 | |||
8bce694c2f | |||
38e9959cf0 | |||
1fc778644a | |||
a08b1816d5 | |||
f97c464a9e | |||
ac4353ce8a | |||
26a6db208c | |||
e0428fe83c | |||
82df950c65 | |||
663aba5775 | |||
2d465ee37b | |||
70238f7d7d | |||
704e3543dc | |||
98e71d31db | |||
7478d0cf4d | |||
ef5c0dae7d | |||
57c3a238ea | |||
bb284066ca | |||
fc147289a9 | |||
3f3e1bfce9 | |||
2b02e87f4a | |||
88869a2965 | |||
958aba9391 | |||
d9581bd6a4 | |||
19ada81a08 | |||
3d60f2cefc | |||
f13e40db1b | |||
fab6ea0109 | |||
05a1cebceb | |||
1281bef896 | |||
37cbcfaa71 | |||
ef0b8f4a87 | |||
8bc2f0647b | |||
b71ccc2954 | |||
2daa838a04 | |||
a2716acf4c | |||
7a0cc534df | |||
5f52e63857 | |||
9409dce93c | |||
2fa788c9e6 | |||
73e667f61f | |||
a7d5d33f0a | |||
7e511e78cd | |||
9e76a38073 | |||
242981963e | |||
970df9ebaf | |||
4c7e7fbd09 | |||
5f78456170 | |||
36fd063737 | |||
c1b7f0370e | |||
882a9e3856 | |||
362b3e4d03 | |||
2952ea57a5 | |||
3541e590f4 | |||
8ef0ae3561 | |||
c3ff66c1ba | |||
a1d9848456 | |||
a3482f7076 | |||
006af0b985 | |||
9dc4815e39 | |||
4263d9ea0d | |||
30253a7df3 | |||
16b83e8e2f | |||
e0c10632ea | |||
686b62129c | |||
dd2587d9e5 | |||
2742649a52 | |||
eb0461d2d4 | |||
e24393c35b | |||
8237e958a6 | |||
9ba898d588 | |||
cd1b0c1b1f | |||
06072e0062 | |||
288e0ef7b6 | |||
88ad5052bf | |||
7e6644a25a | |||
d533d15001 | |||
d0abf1bc54 | |||
56ac18ea8c | |||
11d3b19b32 | |||
d96167fc54 | |||
68fed2fc28 | |||
57457fb7c7 | |||
a2fc5774a7 | |||
c6041b985e | |||
b45d2e0fb1 | |||
42f7419522 | |||
32f5241598 | |||
06e72721ca | |||
3a80069f65 | |||
0818e2c799 | |||
7b8b2d4622 | |||
f6526a0872 | |||
0984022192 | |||
bb7603104f | |||
bdea243fed | |||
2397144e01 | |||
466c754cc8 | |||
45fee069d7 | |||
432f7ce2a0 | |||
e8c34c47af | |||
e81fc14da1 | |||
d5c210a2e1 | |||
7dbde6f570 | |||
78de6211e3 | |||
104c786b90 | |||
9680f4c991 | |||
e63390daf8 | |||
af99f9e98e | |||
8398f9d54c | |||
da5d91b97b | |||
ba1ef6b1a5 | |||
acebf6464e | |||
e367aa2ca5 | |||
0ee2b755e2 | |||
f213c7a643 | |||
947c076ff2 | |||
6600bea815 | |||
6cd61aeb1c | |||
581b991432 | |||
4014aab300 | |||
b523844966 | |||
8d322c89b7 | |||
08a7c6f0b5 | |||
31f06ee3f9 | |||
1c5b157f10 | |||
38fe47316c | |||
9488da0d0a | |||
5a8c560373 | |||
d8675c7e72 | |||
bf29bd95a6 | |||
1775498b40 | |||
1eea575dfc | |||
0c624b2ca7 | |||
8659451d13 | |||
2565f67956 | |||
38f4dcd5e1 | |||
6e380cff82 | |||
76a84706b6 | |||
39302ba923 | |||
1c71db846f | |||
48e4b0eb7f | |||
9fd63c3ef6 | |||
aaea3878d9 | |||
8838a1b54c | |||
e742edca78 | |||
8304343e94 | |||
2ec91443e9 | |||
be30f25da6 | |||
c426a2595f | |||
896a8a441e | |||
b1e7f4c952 | |||
d3ee9e3926 | |||
2b7116a4f3 | |||
8be20f3a3e | |||
5112669d29 | |||
3d453fe6df | |||
32a6972cdc | |||
2cd5d4c64b | |||
3248fe865f | |||
b3ea6981cd | |||
f698a6bd73 | |||
97d2673eae | |||
4e93c4f87a | |||
b5f85638f7 | |||
efd13d31fc | |||
3a45bef0e7 | |||
5b105544fc | |||
4c5cfecc56 | |||
9d2348b9af | |||
e7bca0751c | |||
45c909a237 | |||
5b76b939af | |||
261593aab1 | |||
c9ce735675 | |||
b7f95bec04 | |||
d02573d05f | |||
8ff6ed6aa3 | |||
6aaf4eac89 | |||
1d0c93622d | |||
acd6c195a0 | |||
53a9a28ec0 | |||
aa8dd74176 | |||
ed6dcce13b | |||
d170e45784 | |||
7033e7eb22 | |||
893123936b | |||
31fcb9e036 | |||
c303d44df6 | |||
73dd43170b | |||
514271ba9c | |||
8d18b49899 | |||
6b0b7d01bf | |||
079773f54e | |||
b5cb120db0 | |||
0fb78d6c94 | |||
a80a8636ba | |||
0878d67757 | |||
5e0890b3af | |||
43bac21301 | |||
4df415060b | |||
039d70efec | |||
2a71496791 | |||
617a329c24 | |||
a00eae0b62 | |||
e54dd741ef | |||
7b4c1cdbe4 | |||
5e4babeaa9 | |||
f661f460bb | |||
44f233c02c | |||
31e8a52722 | |||
e3c9f9d794 | |||
e7c4e94c9a | |||
26dc826821 | |||
287247ef05 | |||
af170d2ae9 | |||
a01ed0d7b4 | |||
a7b94783b5 | |||
789dd6a0da | |||
e5b18e810c | |||
b8f86ad7d5 | |||
6f2e8afaed | |||
699c705a8d | |||
adc869ff88 | |||
46f2dcc470 | |||
2d9c4c1d82 | |||
0757702d63 | |||
174777443d | |||
baf2d9ddbc | |||
da444984a8 | |||
84a3daf609 | |||
c88cdea9ac | |||
7b3bd219f7 | |||
dc76c14e31 | |||
0ffc1d0d21 | |||
3d1b82be67 | |||
dec7e5286f | |||
2f812f31d5 | |||
18bac15ddd | |||
a1fe52b41c |
59
.bazelrc
59
.bazelrc
@ -18,10 +18,6 @@ test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test
|
|||||||
# See https://github.com/bazelbuild/bazel/issues/4603
|
# See https://github.com/bazelbuild/bazel/issues/4603
|
||||||
build --symlink_prefix=dist/
|
build --symlink_prefix=dist/
|
||||||
|
|
||||||
# Disable watchfs as it causes tests to be flaky on Windows
|
|
||||||
# https://github.com/angular/angular/issues/29541
|
|
||||||
build --nowatchfs
|
|
||||||
|
|
||||||
# Turn off legacy external runfiles
|
# Turn off legacy external runfiles
|
||||||
run --nolegacy_external_runfiles
|
run --nolegacy_external_runfiles
|
||||||
test --nolegacy_external_runfiles
|
test --nolegacy_external_runfiles
|
||||||
@ -36,22 +32,6 @@ build --incompatible_strict_action_env
|
|||||||
run --incompatible_strict_action_env
|
run --incompatible_strict_action_env
|
||||||
test --incompatible_strict_action_env
|
test --incompatible_strict_action_env
|
||||||
|
|
||||||
###############################
|
|
||||||
# Saucelabs support #
|
|
||||||
# Turn on these settings with #
|
|
||||||
# --config=saucelabs #
|
|
||||||
###############################
|
|
||||||
|
|
||||||
# Expose SauceLabs environment to actions
|
|
||||||
# These environment variables are needed by
|
|
||||||
# web_test_karma to run on Saucelabs
|
|
||||||
test:saucelabs --action_env=SAUCE_USERNAME
|
|
||||||
test:saucelabs --action_env=SAUCE_ACCESS_KEY
|
|
||||||
test:saucelabs --action_env=SAUCE_READY_FILE
|
|
||||||
test:saucelabs --action_env=SAUCE_PID_FILE
|
|
||||||
test:saucelabs --action_env=SAUCE_TUNNEL_IDENTIFIER
|
|
||||||
test:saucelabs --define=KARMA_WEB_TEST_MODE=SL_REQUIRED
|
|
||||||
|
|
||||||
###############################
|
###############################
|
||||||
# Release support #
|
# Release support #
|
||||||
# Turn on these settings with #
|
# Turn on these settings with #
|
||||||
@ -87,11 +67,26 @@ test --test_output=errors
|
|||||||
# any bazel target. This is a temporary flag until codebase is permanently switched to Ivy.
|
# any bazel target. This is a temporary flag until codebase is permanently switched to Ivy.
|
||||||
build --define=compile=legacy
|
build --define=compile=legacy
|
||||||
|
|
||||||
###############################
|
#######################
|
||||||
# Remote Build Execution support
|
# Remote HTTP Caching #
|
||||||
# Turn on these settings with
|
#######################
|
||||||
# --config=remote
|
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 #
|
||||||
|
# Turn on these settings with #
|
||||||
|
# --config=remote #
|
||||||
|
##################################
|
||||||
|
|
||||||
# Load default settings for Remote Build Execution.
|
# Load default settings for Remote Build Execution.
|
||||||
import %workspace%/third_party/github.com/bazelbuild/bazel-toolchains/bazelrc/.bazelrc.notoolchain
|
import %workspace%/third_party/github.com/bazelbuild/bazel-toolchains/bazelrc/.bazelrc.notoolchain
|
||||||
@ -99,6 +94,7 @@ import %workspace%/third_party/github.com/bazelbuild/bazel-toolchains/bazelrc/.b
|
|||||||
# Increase the default number of jobs by 50% because our build has lots of
|
# Increase the default number of jobs by 50% because our build has lots of
|
||||||
# parallelism
|
# parallelism
|
||||||
build:remote --jobs=150
|
build:remote --jobs=150
|
||||||
|
build:remote --google_default_credentials
|
||||||
|
|
||||||
# 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
|
||||||
@ -112,21 +108,10 @@ build:remote --extra_execution_platforms=//tools:rbe_ubuntu1604-angular
|
|||||||
build:remote --host_platform=//tools:rbe_ubuntu1604-angular
|
build:remote --host_platform=//tools:rbe_ubuntu1604-angular
|
||||||
build:remote --platforms=//tools:rbe_ubuntu1604-angular
|
build:remote --platforms=//tools:rbe_ubuntu1604-angular
|
||||||
|
|
||||||
# Remote instance.
|
# Remote instance and caching
|
||||||
build:remote --remote_instance_name=projects/internal-200822/instances/default_instance
|
build:remote --remote_instance_name=projects/internal-200822/instances/default_instance
|
||||||
build:remote --project_id=internal-200822
|
build:remote --project_id=internal-200822
|
||||||
|
|
||||||
# Remote caching
|
|
||||||
build:remote --remote_cache=remotebuildexecution.googleapis.com
|
build:remote --remote_cache=remotebuildexecution.googleapis.com
|
||||||
# By default, do not accept remote cache, to be set to true for CI based on environment
|
|
||||||
build:remote --remote_accept_cached=false
|
|
||||||
# By default, do not upload local results to cache, to be set to true for CI based on environment
|
|
||||||
build:remote --remote_upload_local_results=false
|
|
||||||
|
|
||||||
# Build Event Service Configuration
|
|
||||||
build:remote --bes_backend=buildeventservice.googleapis.com
|
|
||||||
build:remote --bes_timeout=30s
|
|
||||||
build:remote --bes_results_url="https://source.cloud.google.com/results/invocations/"
|
|
||||||
|
|
||||||
###############################
|
###############################
|
||||||
# NodeJS rules settings
|
# NodeJS rules settings
|
||||||
|
@ -28,14 +28,3 @@ test --flaky_test_attempts=2
|
|||||||
|
|
||||||
# More details on failures
|
# More details on failures
|
||||||
build --verbose_failures=true
|
build --verbose_failures=true
|
||||||
|
|
||||||
# We have seen some flakiness in using TS workers on CircleCI
|
|
||||||
# https://angular-team.slack.com/archives/C07DT5M6V/p1562693245183400
|
|
||||||
# > failures like `ERROR: /home/circleci/ng/packages/core/test/BUILD.bazel:5:1:
|
|
||||||
# > Compiling TypeScript (devmode) //packages/core/test:test_lib failed: Worker process did not return a WorkResponse:`
|
|
||||||
# > I saw that issue a couple times today.
|
|
||||||
# > Example job: https://circleci.com/gh/angular/angular/385517
|
|
||||||
# We expect that TypeScript compilations will parallelize wider than the number of local cores anyway
|
|
||||||
# so we should saturate remote workers with TS compilations
|
|
||||||
build --strategy=TypeScriptCompile=standalone
|
|
||||||
build --strategy=AngularTemplateCompile=standalone
|
|
||||||
|
@ -7,156 +7,162 @@
|
|||||||
# To validate changes, use an online parser, eg.
|
# To validate changes, use an online parser, eg.
|
||||||
# http://yaml-online-parser.appspot.com/
|
# http://yaml-online-parser.appspot.com/
|
||||||
|
|
||||||
# Note that the browser docker image comes with Chrome and Firefox preinstalled. This is just
|
# CircleCI configuration version
|
||||||
# needed for jobs that run tests without Bazel. Bazel runs tests with browsers that will be
|
# Version 2.1 allows for extra config reuse features
|
||||||
# fetched by the Webtesting rules. Therefore for jobs that run tests with Bazel, we don't need a
|
# https://circleci.com/docs/2.0/reusing-config/#getting-started-with-config-reuse
|
||||||
# docker image with browsers pre-installed.
|
version: 2.1
|
||||||
# **NOTE 1**: If you change the version of the `*-browsers` docker image, make sure the
|
|
||||||
# `CI_CHROMEDRIVER_VERSION_ARG` env var (in `.circleci/env.sh`) points to a ChromeDriver
|
|
||||||
# version that is compatible with the Chrome version in the image.
|
|
||||||
# **NOTE 2**: If you change the version of the docker images, also change the `cache_key` suffix.
|
|
||||||
var_1: &default_docker_image circleci/node:10.16
|
|
||||||
var_2: &browsers_docker_image circleci/node:10.16-browsers
|
|
||||||
# We don't want to include the current branch name in the cache key because that would prevent
|
# We don't want to include the current branch name in the cache key because that would prevent
|
||||||
# PRs from being able to restore the cache since the branch names are always different for PRs.
|
# PRs from being able to restore the cache since the branch names are always different for PRs.
|
||||||
# The cache key should only consist of dynamic values that change whenever something in the
|
# The cache key should only consist of dynamic values that change whenever something in the
|
||||||
# cache changes. For example:
|
# cache changes. For example:
|
||||||
# 1) yarn lock file changes --> cached "node_modules" are different.
|
# 1) yarn lock file changes --> cached "node_modules" are different.
|
||||||
# 2) bazel repository definitions change --> cached bazel repositories are different.
|
# 2) bazel repository definitions change --> cached bazel repositories are different.
|
||||||
# **NOTE 1 **: If you change the cache key prefix, also sync the restore_cache fallback to match.
|
# **NOTE 1 **: If you change the cache key prefix, also sync the cache_key_fallback to match.
|
||||||
# **NOTE 2 **: Keep the static part of the cache key as prefix to enable correct fallbacks.
|
# **NOTE 2 **: Keep the static part of the cache key as prefix to enable correct fallbacks.
|
||||||
# See https://circleci.com/docs/2.0/caching/#restoring-cache for how prefixes work in CircleCI.
|
# See https://circleci.com/docs/2.0/caching/#restoring-cache for how prefixes work in CircleCI.
|
||||||
var_3: &cache_key v3-angular-node-10.16-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
var_3: &cache_key v3-angular-node-10.16-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
||||||
|
var_4: &cache_key_fallback v3-angular-node-10.16-
|
||||||
# Initializes the CI environment by setting up common environment variables.
|
|
||||||
var_4: &init_environment
|
|
||||||
run:
|
|
||||||
name: Initializing environment (setting up variables, overwriting Yarn)
|
|
||||||
# Overwrite the yarn installed in the docker container with our own version.
|
|
||||||
command: |
|
|
||||||
./.circleci/env.sh
|
|
||||||
ourYarn=$(realpath ./third_party/github.com/yarnpkg/yarn/releases/download/v1.13.0/bin/yarn.js)
|
|
||||||
sudo chmod a+x $ourYarn
|
|
||||||
sudo ln -fs $ourYarn /usr/local/bin/yarn
|
|
||||||
echo "Yarn version: $(yarn --version)"
|
|
||||||
|
|
||||||
# Add GitHub to known hosts.
|
|
||||||
mkdir -p ~/.ssh
|
|
||||||
echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==' >> ~/.ssh/known_hosts
|
|
||||||
|
|
||||||
# use git+ssh instead of https
|
|
||||||
git config --global url."ssh://git@github.com".insteadOf "https://github.com" || true
|
|
||||||
git config --global gc.auto 0 || true
|
|
||||||
|
|
||||||
|
|
||||||
var_5: &setup_bazel_remote_execution
|
|
||||||
run:
|
|
||||||
name: "Setup bazel RBE remote execution"
|
|
||||||
command: |
|
|
||||||
# We need ensure that the same default digest is used for encoding and decoding
|
|
||||||
# with openssl. Openssl versions might have different default digests which can
|
|
||||||
# cause decryption failures based on the openssl version. https://stackoverflow.com/a/39641378/4317734
|
|
||||||
openssl aes-256-cbc -d -in .circleci/gcp_token -md md5 -k "$CI_REPO_NAME" -out /home/circleci/.gcp_credentials
|
|
||||||
echo "export GOOGLE_APPLICATION_CREDENTIALS=/home/circleci/.gcp_credentials" >> $BASH_ENV
|
|
||||||
./.circleci/setup-rbe.sh .bazelrc.user
|
|
||||||
|
|
||||||
# Settings common to each job
|
|
||||||
var_6: &job_defaults
|
|
||||||
working_directory: ~/ng
|
|
||||||
docker:
|
|
||||||
- image: *default_docker_image
|
|
||||||
|
|
||||||
# After checkout, rebase on top of target branch.
|
|
||||||
var_7: &post_checkout
|
|
||||||
run:
|
|
||||||
name: Rebase PR on target branch
|
|
||||||
command: >
|
|
||||||
if [[ -n "${CIRCLE_PR_NUMBER}" ]]; then
|
|
||||||
# User is required for rebase.
|
|
||||||
git config user.name "angular-ci"
|
|
||||||
git config user.email "angular-ci"
|
|
||||||
# Rebase PR on top of target branch.
|
|
||||||
node tools/rebase-pr.js angular/angular ${CIRCLE_PR_NUMBER}
|
|
||||||
else
|
|
||||||
echo "This build is not over a PR, nothing to do."
|
|
||||||
fi
|
|
||||||
|
|
||||||
var_8: &yarn_install
|
|
||||||
run:
|
|
||||||
name: Running Yarn install
|
|
||||||
command: |
|
|
||||||
# Yarn's requests sometimes take more than 10mins to complete.
|
|
||||||
# Print something to stdout, to prevent CircleCI from failing due to not output.
|
|
||||||
while true; do sleep 60; echo "[`date`] Keeping alive..."; done &
|
|
||||||
KEEP_ALIVE_PID=$!
|
|
||||||
yarn install --frozen-lockfile --non-interactive
|
|
||||||
kill $KEEP_ALIVE_PID
|
|
||||||
|
|
||||||
var_9: &setup_circleci_bazel_config
|
|
||||||
run:
|
|
||||||
name: Setting up CircleCI bazel configuration
|
|
||||||
command: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
|
||||||
|
|
||||||
var_10: &restore_cache
|
|
||||||
restore_cache:
|
|
||||||
keys:
|
|
||||||
- *cache_key
|
|
||||||
# This fallback should be the cache_key without variables.
|
|
||||||
- v3-angular-node-10.16-
|
|
||||||
|
|
||||||
# Branch filter that can be specified for jobs that should only run on publish branches
|
|
||||||
# (e.g. master or the patch branch)
|
|
||||||
var_11: &publish_branches_filter
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
# e.g. 7.0.x, 7.1.x, etc.
|
|
||||||
- /\d+\.\d+\.x/
|
|
||||||
|
|
||||||
# Workspace initially persisted by the `install` job, and then enhanced by `test_aio` and
|
|
||||||
# `build-npm-packages`.
|
|
||||||
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
|
|
||||||
# https://circleci.com/blog/deep-diving-into-circleci-workspaces/
|
|
||||||
var_12: &attach_workspace
|
|
||||||
attach_workspace:
|
|
||||||
at: ~/
|
|
||||||
|
|
||||||
var_13: ¬ify_caretaker_on_fail
|
|
||||||
run:
|
|
||||||
when: on_fail
|
|
||||||
name: Notify caretaker about failure
|
|
||||||
# `$SLACK_CARETAKER_WEBHOOK_URL` is a secret env var defined in CircleCI project settings.
|
|
||||||
# The URL comes from https://angular-team.slack.com/apps/A0F7VRE7N-circleci.
|
|
||||||
command: |
|
|
||||||
notificationJson="{\"text\":\":x: \`$CIRCLE_JOB\` job for $CIRCLE_BRANCH branch failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}"
|
|
||||||
curl --request POST --header "Content-Type: application/json" --data "$notificationJson" $SLACK_CARETAKER_WEBHOOK_URL
|
|
||||||
|
|
||||||
var_14: ¬ify_dev_infra_on_fail
|
|
||||||
run:
|
|
||||||
when: on_fail
|
|
||||||
name: Notify dev-infra about failure
|
|
||||||
# `$SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL` is a secret env var defined in CircleCI project settings.
|
|
||||||
# The URL comes from https://angular-team.slack.com/apps/A0F7VRE7N-circleci.
|
|
||||||
command: |
|
|
||||||
notificationJson="{\"text\":\":x: \`$CIRCLE_JOB\` job for $CIRCLE_BRANCH branch failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}"
|
|
||||||
curl --request POST --header "Content-Type: application/json" --data "$notificationJson" $SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
|
||||||
|
|
||||||
# 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_15: &material_unit_tests_cache_key v4-angular-material-701302dc482d7e4b77990b24e3b5ab330bbf1aa5
|
var_5: &material_unit_tests_cache_key v4-angular-material-18b9ef3f5529f0fa8f034944681486447af7b879
|
||||||
var_16: &material_unit_tests_cache_key_short v4-angular-material
|
var_6: &material_unit_tests_cache_key_fallback v4-angular-material-
|
||||||
|
|
||||||
version: 2
|
|
||||||
|
# Workspace initially persisted by the `setup` job, and then enhanced by `build-npm-packages` and
|
||||||
|
# `build-ivy-npm-packages`.
|
||||||
|
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
|
||||||
|
# https://circleci.com/blog/deep-diving-into-circleci-workspaces/
|
||||||
|
var_7: &workspace_location ~/
|
||||||
|
|
||||||
|
# Executor Definitions
|
||||||
|
# https://circleci.com/docs/2.0/reusing-config/#authoring-reusable-executors
|
||||||
|
# **NOTE 1**: Pin to exact images using an ID (SHA). See https://circleci.com/docs/2.0/circleci-images/#using-a-docker-image-id-to-pin-an-image-to-a-fixed-version.
|
||||||
|
# (Using the tag in not necessary when pinning by ID, but include it anyway for documentation purposes.)
|
||||||
|
# **NOTE 2**: If you change the version of the docker images, also change the `cache_key` suffix.
|
||||||
|
# **NOTE 3**: If you change the version of the `*-browsers` docker image, make sure the
|
||||||
|
# `CI_CHROMEDRIVER_VERSION_ARG` env var (in `.circleci/env.sh`) points to a ChromeDriver
|
||||||
|
# version that is compatible with the Chrome version in the image.
|
||||||
|
executors:
|
||||||
|
default-executor:
|
||||||
|
parameters:
|
||||||
|
resource_class:
|
||||||
|
type: string
|
||||||
|
default: medium
|
||||||
|
docker:
|
||||||
|
- image: circleci/node:10.16@sha256:75c05084fff4afa3683a03c5a04a4a3ad95c536ff2439d8fe14e7e1f5c58b09a
|
||||||
|
resource_class: << parameters.resource_class >>
|
||||||
|
working_directory: ~/ng
|
||||||
|
|
||||||
|
browsers-executor:
|
||||||
|
parameters:
|
||||||
|
resource_class:
|
||||||
|
type: string
|
||||||
|
default: medium
|
||||||
|
docker:
|
||||||
|
# The browser docker image comes with Chrome and Firefox preinstalled. This is just
|
||||||
|
# needed for jobs that run tests without Bazel. Bazel runs tests with browsers that will be
|
||||||
|
# fetched by the Webtesting rules. Therefore for jobs that run tests with Bazel, we don't need a
|
||||||
|
# docker image with browsers pre-installed.
|
||||||
|
- image: circleci/node:10.16-browsers@sha256:d2a96fe1cbef51257ee626b5f645e64dade3e886f00ba9cb7e8ea65b4efe8db1
|
||||||
|
resource_class: << parameters.resource_class >>
|
||||||
|
working_directory: ~/ng
|
||||||
|
|
||||||
|
# Command Definitions
|
||||||
|
# https://circleci.com/docs/2.0/reusing-config/#authoring-reusable-commands
|
||||||
|
commands:
|
||||||
|
custom_attach_workspace:
|
||||||
|
description: Attach workspace at a predefined location
|
||||||
|
steps:
|
||||||
|
- attach_workspace:
|
||||||
|
at: *workspace_location
|
||||||
|
|
||||||
|
# Initializes the CI environment by setting up common environment variables.
|
||||||
|
init_environment:
|
||||||
|
description: Initializing environment (setting up variables, overwriting Yarn)
|
||||||
|
steps:
|
||||||
|
- run: ./.circleci/env.sh
|
||||||
|
- run:
|
||||||
|
# Overwrite the yarn installed in the docker container with our own version.
|
||||||
|
name: Overwrite yarn with our own version
|
||||||
|
command: |
|
||||||
|
ourYarn=$(realpath ./third_party/github.com/yarnpkg/yarn/releases/download/v1.17.3/bin/yarn.js)
|
||||||
|
sudo chmod a+x $ourYarn
|
||||||
|
sudo ln -fs $ourYarn /usr/local/bin/yarn
|
||||||
|
- run: echo "Yarn version $(yarn --version)"
|
||||||
|
- run:
|
||||||
|
# Configure git as the CircleCI `checkout` command does.
|
||||||
|
# This is needed because we only checkout on the setup job.
|
||||||
|
# Add GitHub to known hosts
|
||||||
|
name: Configure git
|
||||||
|
command: |
|
||||||
|
mkdir -p ~/.ssh
|
||||||
|
echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==' >> ~/.ssh/known_hosts
|
||||||
|
git config --global url."ssh://git@github.com".insteadOf "https://github.com" || true
|
||||||
|
git config --global gc.auto 0 || true
|
||||||
|
|
||||||
|
setup_circleci_bazel_config:
|
||||||
|
description: Set up CircleCI bazel configuration
|
||||||
|
steps:
|
||||||
|
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||||
|
|
||||||
|
setup_bazel_rbe:
|
||||||
|
description: Setup bazel RBE remote execution
|
||||||
|
steps:
|
||||||
|
# We need ensure that the same default digest is used for encoding and decoding
|
||||||
|
# with openssl. Openssl versions might have different default digests which can
|
||||||
|
# cause decryption failures based on the openssl version. https://stackoverflow.com/a/39641378/4317734
|
||||||
|
- run: openssl aes-256-cbc -d -in .circleci/gcp_token -md md5 -k "$CI_REPO_NAME" -out /home/circleci/.gcp_credentials
|
||||||
|
- run: echo "export GOOGLE_APPLICATION_CREDENTIALS=/home/circleci/.gcp_credentials" >> $BASH_ENV
|
||||||
|
- run: ./.circleci/setup-rbe.sh .bazelrc.user
|
||||||
|
|
||||||
|
notify_webhook_on_fail:
|
||||||
|
description: Notify a webhook about failure
|
||||||
|
parameters:
|
||||||
|
# `webhook_url_env_var` are secret env vars defined in CircleCI project settings.
|
||||||
|
# The URLs come from https://angular-team.slack.com/apps/A0F7VRE7N-circleci.
|
||||||
|
webhook_url_env_var:
|
||||||
|
type: env_var_name
|
||||||
|
steps:
|
||||||
|
- run:
|
||||||
|
when: on_fail
|
||||||
|
command: |
|
||||||
|
notificationJson="{\"text\":\":x: \`$CIRCLE_JOB\` job for $CIRCLE_BRANCH branch failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}"
|
||||||
|
curl --request POST --header "Content-Type: application/json" --data "$notificationJson" ${<< parameters.webhook_url_env_var >>}
|
||||||
|
|
||||||
|
# Job definitions
|
||||||
|
# Jobs can include parameters that are passed in the workflow job invocation.
|
||||||
|
# https://circleci.com/docs/2.0/reusing-config/#authoring-parameterized-jobs
|
||||||
jobs:
|
jobs:
|
||||||
setup:
|
setup:
|
||||||
<<: *job_defaults
|
executor: default-executor
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- *post_checkout
|
- run:
|
||||||
|
name: Rebase PR on target branch
|
||||||
|
# After checkout, rebase on top of target branch.
|
||||||
|
command: >
|
||||||
|
if [[ -n "${CIRCLE_PR_NUMBER}" ]]; then
|
||||||
|
# User is required for rebase.
|
||||||
|
git config user.name "angular-ci"
|
||||||
|
git config user.email "angular-ci"
|
||||||
|
# Rebase PR on top of target branch.
|
||||||
|
node tools/rebase-pr.js angular/angular ${CIRCLE_PR_NUMBER}
|
||||||
|
else
|
||||||
|
echo "This build is not over a PR, nothing to do."
|
||||||
|
fi
|
||||||
# This cache is saved in the build-npm-packages so that Bazel cache is also included.
|
# This cache is saved in the build-npm-packages so that Bazel cache is also included.
|
||||||
- *restore_cache
|
- restore_cache:
|
||||||
- *init_environment
|
keys:
|
||||||
- *yarn_install
|
- *cache_key
|
||||||
|
- *cache_key_fallback
|
||||||
|
- init_environment
|
||||||
|
- run:
|
||||||
|
name: Running Yarn install
|
||||||
|
command: yarn install --frozen-lockfile --non-interactive
|
||||||
|
# Yarn's requests sometimes take more than 10mins to complete.
|
||||||
|
no_output_timeout: 45m
|
||||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||||
# Make the bazel directories and add a file to them if they don't exist already so that
|
# Make the bazel directories and add a file to them if they don't exist already so that
|
||||||
# persist_to_workspace does not fail.
|
# persist_to_workspace does not fail.
|
||||||
@ -166,19 +172,18 @@ jobs:
|
|||||||
touch ~/bazel_repository_cache/MARKER
|
touch ~/bazel_repository_cache/MARKER
|
||||||
fi
|
fi
|
||||||
# Persist any changes at this point to be reused by further jobs.
|
# Persist any changes at this point to be reused by further jobs.
|
||||||
# **NOTE 1 **: Folders persisted here should be kept in sync with `var_13: &attach_workspace`.
|
# **NOTE**: To add new content to the workspace, always persist on the same root.
|
||||||
# **NOTE 2 **: To add new content to the workspace, always persist on the same root.
|
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
root: ~/
|
root: *workspace_location
|
||||||
paths:
|
paths:
|
||||||
- ./ng
|
- ./ng
|
||||||
- ./bazel_repository_cache
|
- ./bazel_repository_cache
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
<<: *job_defaults
|
executor: default-executor
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
|
|
||||||
- run: 'yarn bazel:format -mode=check ||
|
- run: 'yarn bazel:format -mode=check ||
|
||||||
(echo "BUILD files not formatted. Please run ''yarn bazel:format''" ; exit 1)'
|
(echo "BUILD files not formatted. Please run ''yarn bazel:format''" ; exit 1)'
|
||||||
@ -187,34 +192,32 @@ jobs:
|
|||||||
(echo -e "\n.bzl files have lint errors. Please run ''yarn bazel:lint-fix''"; exit 1)'
|
(echo -e "\n.bzl files have lint errors. Please run ''yarn bazel:lint-fix''"; exit 1)'
|
||||||
|
|
||||||
- run: yarn gulp lint
|
- run: yarn gulp lint
|
||||||
|
- run: node tools/verify-codeownership
|
||||||
|
|
||||||
test:
|
test:
|
||||||
<<: *job_defaults
|
executor:
|
||||||
resource_class: xlarge
|
name: default-executor
|
||||||
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
- *setup_circleci_bazel_config
|
- setup_circleci_bazel_config
|
||||||
# Setup remote execution and run RBE-compatible tests.
|
# Setup remote execution and run RBE-compatible tests.
|
||||||
- *setup_bazel_remote_execution
|
- setup_bazel_rbe
|
||||||
- run: yarn bazel test //... --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only
|
- run:
|
||||||
- run: mkdir ~/testlogs
|
command: yarn bazel test //... --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only
|
||||||
- run: cp -Lr dist/testlogs/* ~/testlogs
|
no_output_timeout: 20m
|
||||||
- store_test_results:
|
|
||||||
# Bazel always writes test.xml files under this directory
|
|
||||||
path: ~/testlogs
|
|
||||||
- store_artifacts:
|
|
||||||
path: ~/testlogs
|
|
||||||
|
|
||||||
# Temporary job to test what will happen when we flip the Ivy flag to true
|
# Temporary job to test what will happen when we flip the Ivy flag to true
|
||||||
test_ivy_aot:
|
test_ivy_aot:
|
||||||
<<: *job_defaults
|
executor:
|
||||||
resource_class: xlarge
|
name: default-executor
|
||||||
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
- *setup_circleci_bazel_config
|
- setup_circleci_bazel_config
|
||||||
- *setup_bazel_remote_execution
|
- setup_bazel_rbe
|
||||||
|
|
||||||
# We need to explicitly specify the --symlink_prefix option because otherwise we would
|
# We need to explicitly specify the --symlink_prefix option because otherwise we would
|
||||||
# not be able to easily find the output bin directory when uploading artifacts for size
|
# not be able to easily find the output bin directory when uploading artifacts for size
|
||||||
@ -246,43 +249,41 @@ jobs:
|
|||||||
#
|
#
|
||||||
# NOTE: This is currently limited to master builds only. See the `default_workflow` configuration.
|
# NOTE: This is currently limited to master builds only. See the `default_workflow` configuration.
|
||||||
test_saucelabs_bazel:
|
test_saucelabs_bazel:
|
||||||
<<: *job_defaults
|
executor:
|
||||||
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
name: default-executor
|
||||||
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
||||||
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
||||||
resource_class: xlarge
|
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
||||||
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
- *setup_circleci_bazel_config
|
- setup_circleci_bazel_config
|
||||||
|
- setup_bazel_rbe
|
||||||
- run:
|
- run:
|
||||||
name: Preparing environment for running tests on Saucelabs.
|
name: Run Bazel tests in saucelabs
|
||||||
command: setSecretVar SAUCE_ACCESS_KEY $(echo $SAUCE_ACCESS_KEY | rev)
|
# All web tests are contained within a single //:test_web_all target for Saucelabs
|
||||||
- run:
|
# as running each set of tests as a separate target will attempt to acquire too
|
||||||
name: Starting Saucelabs tunnel
|
# many browsers on Saucelabs (7 per target currently) and some tests will always
|
||||||
command: ./scripts/saucelabs/start-tunnel.sh
|
# fail to acquire browsers. For example:
|
||||||
background: true
|
# 14 02 2019 19:52:33.170:WARN [launcher]: chrome beta on SauceLabs have not captured in 180000 ms, killing.
|
||||||
# Waits for the Saucelabs tunnel to be ready. This ensures that we don't run tests
|
# //packages/forms/test:web_test_sauce TIMEOUT in 315.0s
|
||||||
# too early without Saucelabs not being ready.
|
command: |
|
||||||
- run: ./scripts/saucelabs/wait-for-tunnel.sh
|
./scripts/saucelabs/run-bazel-via-tunnel.sh \
|
||||||
# All web tests are contained within a single //:test_web_all target for Saucelabs
|
--tunnel-id angular-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_INDEX} \
|
||||||
# as running each set of tests as a separate target will attempt to acquire too
|
--username $SAUCE_USERNAME \
|
||||||
# many browsers on Saucelabs (7 per target currently) and some tests will always
|
--key $(echo $SAUCE_ACCESS_KEY | rev) \
|
||||||
# fail to acquire browsers. For example:
|
yarn bazel test //:test_web_all
|
||||||
# 14 02 2019 19:52:33.170:WARN [launcher]: chrome beta on SauceLabs have not captured in 180000 ms, killing.
|
no_output_timeout: 20m
|
||||||
# //packages/forms/test:web_test_sauce TIMEOUT in 315.0s
|
- notify_webhook_on_fail:
|
||||||
- run: yarn bazel test --config=saucelabs //:test_web_all
|
webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
||||||
- run: ./scripts/saucelabs/stop-tunnel.sh
|
|
||||||
- *notify_dev_infra_on_fail
|
|
||||||
|
|
||||||
test_aio:
|
test_aio:
|
||||||
<<: *job_defaults
|
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
||||||
docker:
|
executor: browsers-executor
|
||||||
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
|
||||||
- image: *browsers_docker_image
|
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
# Build aio
|
# Build aio
|
||||||
- run: yarn --cwd aio build --progress=false
|
- run: yarn --cwd aio build --progress=false
|
||||||
# Lint the code
|
# Lint the code
|
||||||
@ -301,27 +302,27 @@ jobs:
|
|||||||
- run: yarn --cwd aio redirects-test
|
- run: yarn --cwd aio redirects-test
|
||||||
|
|
||||||
deploy_aio:
|
deploy_aio:
|
||||||
<<: *job_defaults
|
|
||||||
docker:
|
|
||||||
# Needed because before deploying the deploy-production script runs the PWA score tests.
|
# Needed because before deploying the deploy-production script runs the PWA score tests.
|
||||||
- image: *browsers_docker_image
|
executor: browsers-executor
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
# Deploy angular.io to production (if necessary)
|
# Deploy angular.io to production (if necessary)
|
||||||
- run: setPublicVar_CI_STABLE_BRANCH
|
- run: setPublicVar_CI_STABLE_BRANCH
|
||||||
- run: yarn --cwd aio deploy-production
|
- run: yarn --cwd aio deploy-production
|
||||||
|
|
||||||
test_aio_local:
|
test_aio_local:
|
||||||
<<: *job_defaults
|
parameters:
|
||||||
docker:
|
ivy:
|
||||||
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
type: boolean
|
||||||
- image: *browsers_docker_image
|
default: false
|
||||||
|
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
||||||
|
executor: browsers-executor
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
# Build aio (with local Angular packages)
|
# Build aio (with local Angular packages)
|
||||||
- run: yarn --cwd aio build-local-ci
|
- run: yarn --cwd aio build-local<<# parameters.ivy >>-with-ivy<</ parameters.ivy >>-ci
|
||||||
# Run unit tests
|
# Run unit tests
|
||||||
- run: yarn --cwd aio test --progress=false --watch=false
|
- run: yarn --cwd aio test --progress=false --watch=false
|
||||||
# Run e2e tests
|
# Run e2e tests
|
||||||
@ -329,32 +330,13 @@ jobs:
|
|||||||
# Run PWA-score tests
|
# Run PWA-score tests
|
||||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||||
# Check the bundle sizes.
|
# Check the bundle sizes.
|
||||||
- run: yarn --cwd aio payload-size aio-local
|
- run: yarn --cwd aio payload-size aio-local<<# parameters.ivy >>-ivy<</ parameters.ivy >>
|
||||||
|
|
||||||
test_aio_local_ivy:
|
|
||||||
<<: *job_defaults
|
|
||||||
docker:
|
|
||||||
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
|
||||||
- image: *browsers_docker_image
|
|
||||||
steps:
|
|
||||||
- *attach_workspace
|
|
||||||
- *init_environment
|
|
||||||
# Build aio with Ivy (using local Angular packages)
|
|
||||||
- run: yarn --cwd aio build-with-ivy-ci
|
|
||||||
# Run unit tests
|
|
||||||
- run: yarn --cwd aio test --progress=false --watch=false
|
|
||||||
# Run e2e tests
|
|
||||||
- run: yarn --cwd aio e2e --configuration=ci
|
|
||||||
# Run PWA-score tests
|
|
||||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
|
||||||
# Check the bundle sizes.
|
|
||||||
- run: yarn --cwd aio payload-size aio-local-ivy
|
|
||||||
|
|
||||||
test_aio_tools:
|
test_aio_tools:
|
||||||
<<: *job_defaults
|
executor: default-executor
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
# Install
|
# Install
|
||||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||||
- run: yarn --cwd aio extract-cli-command-docs
|
- run: yarn --cwd aio extract-cli-command-docs
|
||||||
@ -363,56 +345,42 @@ jobs:
|
|||||||
- run: ./aio/aio-builds-setup/scripts/test.sh
|
- run: ./aio/aio-builds-setup/scripts/test.sh
|
||||||
|
|
||||||
test_docs_examples:
|
test_docs_examples:
|
||||||
<<: *job_defaults
|
parameters:
|
||||||
docker:
|
ivy:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
executor:
|
||||||
# Needed because the example e2e tests depend on Chrome.
|
# Needed because the example e2e tests depend on Chrome.
|
||||||
- image: *browsers_docker_image
|
name: browsers-executor
|
||||||
parallelism: 4
|
resource_class: xlarge
|
||||||
resource_class: xlarge
|
|
||||||
steps:
|
|
||||||
- *attach_workspace
|
|
||||||
- *init_environment
|
|
||||||
# Install aio
|
|
||||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
|
||||||
# Run examples tests. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
|
||||||
# Since the parallelism is set to "3", there will be three parallel CircleCI containers
|
|
||||||
# with either "0", "1" or "2" as node index. This can be passed to the "--shard" argument.
|
|
||||||
- run: yarn --cwd aio example-e2e --setup --local --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL}
|
|
||||||
|
|
||||||
test_docs_examples_ivy:
|
|
||||||
<<: *job_defaults
|
|
||||||
docker:
|
|
||||||
# Needed because the example e2e tests depend on Chrome.
|
|
||||||
- image: *browsers_docker_image
|
|
||||||
resource_class: xlarge
|
|
||||||
# We increase the parallelism here to five while the "test_docs_examples" job runs with
|
|
||||||
# a parallelism of four. This is necessary because this job also need to run NGCC which
|
|
||||||
# takes up more time and we don't want these jobs to impact the overall CI turnaround.
|
|
||||||
parallelism: 5
|
parallelism: 5
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
# Install aio
|
# Install aio
|
||||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||||
# Rename the Ivy packages dist folder to "dist/packages-dist" as the AIO
|
- when:
|
||||||
# package installer picks up the locally built packages from that location.
|
condition: << parameters.ivy >>
|
||||||
# *Note*: We could also adjust the packages installer, but given we won't have
|
steps:
|
||||||
# two different folders of Angular distributions in the future, we should keep
|
# Rename the Ivy packages dist folder to "dist/packages-dist" as the AIO
|
||||||
# the packages installer unchanged.
|
# package installer picks up the locally built packages from that location.
|
||||||
- run: mv dist/packages-dist-ivy-aot dist/packages-dist
|
# *Note*: We could also adjust the packages installer, but given we won't have
|
||||||
# Run examples tests with ivy. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
# two different folders of Angular distributions in the future, we should keep
|
||||||
# Since the parallelism is set to "3", there will be three parallel CircleCI containers
|
# the packages installer unchanged.
|
||||||
# with either "0", "1" or "2" as node index. This can be passed to the "--shard" argument.
|
- run: mv dist/packages-dist-ivy-aot dist/packages-dist
|
||||||
- run: yarn --cwd aio example-e2e --setup --local --ivy --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL}
|
# Run examples tests. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
||||||
|
# Since the parallelism is set to "5", there will be five parallel CircleCI containers.
|
||||||
|
# with either "0", "1", etc as node index. This can be passed to the "--shard" argument.
|
||||||
|
- run: yarn --cwd aio example-e2e --setup --local <<# parameters.ivy >>--ivy<</ parameters.ivy >> --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL} --retry 2
|
||||||
|
|
||||||
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
||||||
aio_preview:
|
aio_preview:
|
||||||
<<: *job_defaults
|
executor: default-executor
|
||||||
environment:
|
environment:
|
||||||
AIO_SNAPSHOT_ARTIFACT_PATH: &aio_preview_artifact_path 'aio/tmp/snapshot.tgz'
|
AIO_SNAPSHOT_ARTIFACT_PATH: &aio_preview_artifact_path 'aio/tmp/snapshot.tgz'
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
- run: ./aio/scripts/build-artifacts.sh $AIO_SNAPSHOT_ARTIFACT_PATH $CI_PULL_REQUEST $CI_COMMIT
|
- run: ./aio/scripts/build-artifacts.sh $AIO_SNAPSHOT_ARTIFACT_PATH $CI_PULL_REQUEST $CI_COMMIT
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: *aio_preview_artifact_path
|
path: *aio_preview_artifact_path
|
||||||
@ -423,13 +391,11 @@ jobs:
|
|||||||
|
|
||||||
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
||||||
test_aio_preview:
|
test_aio_preview:
|
||||||
<<: *job_defaults
|
# Needed because the test-preview script runs e2e tests and the PWA score test with Chrome.
|
||||||
docker:
|
executor: browsers-executor
|
||||||
# Needed because the test-preview script runs e2e tests and the PWA score test with Chrome.
|
|
||||||
- image: *browsers_docker_image
|
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||||
- run:
|
- run:
|
||||||
name: Wait for preview and run tests
|
name: Wait for preview and run tests
|
||||||
@ -445,19 +411,20 @@ jobs:
|
|||||||
|
|
||||||
# Build the view engine npm packages. No new jobs should depend on this.
|
# Build the view engine npm packages. No new jobs should depend on this.
|
||||||
build-npm-packages:
|
build-npm-packages:
|
||||||
<<: *job_defaults
|
executor:
|
||||||
resource_class: xlarge
|
name: default-executor
|
||||||
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
- *setup_circleci_bazel_config
|
- setup_circleci_bazel_config
|
||||||
- *setup_bazel_remote_execution
|
- setup_bazel_rbe
|
||||||
|
|
||||||
- run: scripts/build-packages-dist.sh
|
- run: scripts/build-packages-dist.sh
|
||||||
|
|
||||||
# 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: ~/
|
root: *workspace_location
|
||||||
paths:
|
paths:
|
||||||
- ng/dist/packages-dist
|
- ng/dist/packages-dist
|
||||||
|
|
||||||
@ -471,19 +438,20 @@ jobs:
|
|||||||
|
|
||||||
# Build the ivy npm packages.
|
# Build the ivy npm packages.
|
||||||
build-ivy-npm-packages:
|
build-ivy-npm-packages:
|
||||||
<<: *job_defaults
|
executor:
|
||||||
resource_class: xlarge
|
name: default-executor
|
||||||
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
- *setup_circleci_bazel_config
|
- setup_circleci_bazel_config
|
||||||
- *setup_bazel_remote_execution
|
- setup_bazel_rbe
|
||||||
|
|
||||||
- run: scripts/build-ivy-npm-packages.sh
|
- run: scripts/build-ivy-npm-packages.sh
|
||||||
|
|
||||||
# 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: ~/
|
root: *workspace_location
|
||||||
paths:
|
paths:
|
||||||
- ng/dist/packages-dist-ivy-aot
|
- ng/dist/packages-dist-ivy-aot
|
||||||
|
|
||||||
@ -494,18 +462,17 @@ jobs:
|
|||||||
# need to re-run manually should be alleviated.
|
# need to re-run manually should be alleviated.
|
||||||
# See comments inside the integration/run_tests.sh script.
|
# See comments inside the integration/run_tests.sh script.
|
||||||
integration_test:
|
integration_test:
|
||||||
<<: *job_defaults
|
executor:
|
||||||
parallelism: 4
|
|
||||||
docker:
|
|
||||||
# Needed because the integration tests expect Chrome to be installed (e.g cli-hello-world)
|
# Needed because the integration tests expect Chrome to be installed (e.g cli-hello-world)
|
||||||
- image: *browsers_docker_image
|
name: browsers-executor
|
||||||
# Note: we run Bazel in one of the integration tests, and it can consume >2G
|
# Note: we run Bazel in one of the integration tests, and it can consume >2G
|
||||||
# of memory. Together with the system under test, this can exhaust the RAM
|
# of memory. Together with the system under test, this can exhaust the RAM
|
||||||
# on a 4G worker so we use a larger machine here too.
|
# on a 4G worker so we use a larger machine here too.
|
||||||
resource_class: xlarge
|
resource_class: xlarge
|
||||||
|
parallelism: 4
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
# Runs the integration tests in parallel across multiple CircleCI container instances. The
|
# Runs the integration tests in parallel across multiple CircleCI container instances. The
|
||||||
# amount of container nodes for this job is controlled by the "parallelism" option.
|
# amount of container nodes for this job is controlled by the "parallelism" option.
|
||||||
- run: ./integration/run_tests.sh ${CIRCLE_NODE_INDEX} ${CIRCLE_NODE_TOTAL}
|
- run: ./integration/run_tests.sh ${CIRCLE_NODE_INDEX} ${CIRCLE_NODE_TOTAL}
|
||||||
@ -513,7 +480,7 @@ jobs:
|
|||||||
# 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.
|
||||||
publish_snapshot:
|
publish_snapshot:
|
||||||
<<: *job_defaults
|
executor: default-executor
|
||||||
steps:
|
steps:
|
||||||
# See below - ideally this job should not trigger for non-upstream builds.
|
# See below - ideally this job should not trigger for non-upstream builds.
|
||||||
# But since it does, we have to check this condition.
|
# But since it does, we have to check this condition.
|
||||||
@ -527,8 +494,8 @@ jobs:
|
|||||||
[[ "$CIRCLE_PROJECT_REPONAME" != "angular" ]]; then
|
[[ "$CIRCLE_PROJECT_REPONAME" != "angular" ]]; then
|
||||||
circleci step halt
|
circleci step halt
|
||||||
fi
|
fi
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
# CircleCI has a config setting to force SSH for all github connections
|
# CircleCI has a config setting to force SSH for all github connections
|
||||||
# This is not compatible with our mechanism of using a Personal Access Token
|
# This is not compatible with our mechanism of using a Personal Access Token
|
||||||
# Clear the global setting
|
# Clear the global setting
|
||||||
@ -542,14 +509,12 @@ jobs:
|
|||||||
- run: ./scripts/ci/publish-build-artifacts.sh
|
- run: ./scripts/ci/publish-build-artifacts.sh
|
||||||
|
|
||||||
aio_monitoring_stable:
|
aio_monitoring_stable:
|
||||||
<<: *job_defaults
|
# This job needs Chrome to be globally installed because the tests run with Protractor
|
||||||
docker:
|
# which does not load the browser through the Bazel webtesting rules.
|
||||||
# This job needs Chrome to be globally installed because the tests run with Protractor
|
executor: browsers-executor
|
||||||
# which does not load the browser through the Bazel webtesting rules.
|
|
||||||
- image: *browsers_docker_image
|
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
- run: setPublicVar_CI_STABLE_BRANCH
|
- run: setPublicVar_CI_STABLE_BRANCH
|
||||||
- run:
|
- run:
|
||||||
name: Check out `aio/` from the stable branch
|
name: Check out `aio/` from the stable branch
|
||||||
@ -559,33 +524,36 @@ jobs:
|
|||||||
- run:
|
- run:
|
||||||
name: Run tests against https://angular.io/
|
name: Run tests against https://angular.io/
|
||||||
command: ./aio/scripts/test-production.sh https://angular.io/ $CI_AIO_MIN_PWA_SCORE
|
command: ./aio/scripts/test-production.sh https://angular.io/ $CI_AIO_MIN_PWA_SCORE
|
||||||
- *notify_caretaker_on_fail
|
- notify_webhook_on_fail:
|
||||||
- *notify_dev_infra_on_fail
|
webhook_url_env_var: SLACK_CARETAKER_WEBHOOK_URL
|
||||||
|
- notify_webhook_on_fail:
|
||||||
|
webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
||||||
|
|
||||||
aio_monitoring_next:
|
aio_monitoring_next:
|
||||||
<<: *job_defaults
|
# This job needs Chrome to be globally installed because the tests run with Protractor
|
||||||
docker:
|
# which does not load the browser through the Bazel webtesting rules.
|
||||||
# This job needs Chrome to be globally installed because the tests run with Protractor
|
executor: browsers-executor
|
||||||
# which does not load the browser through the Bazel webtesting rules.
|
|
||||||
- image: *browsers_docker_image
|
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
- run:
|
- run:
|
||||||
name: Run tests against https://next.angular.io/
|
name: Run tests against https://next.angular.io/
|
||||||
command: ./aio/scripts/test-production.sh https://next.angular.io/ $CI_AIO_MIN_PWA_SCORE
|
command: ./aio/scripts/test-production.sh https://next.angular.io/ $CI_AIO_MIN_PWA_SCORE
|
||||||
- *notify_caretaker_on_fail
|
- notify_webhook_on_fail:
|
||||||
- *notify_dev_infra_on_fail
|
webhook_url_env_var: SLACK_CARETAKER_WEBHOOK_URL
|
||||||
|
- notify_webhook_on_fail:
|
||||||
|
webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
||||||
|
|
||||||
legacy-unit-tests-saucelabs:
|
legacy-unit-tests-saucelabs:
|
||||||
<<: *job_defaults
|
executor:
|
||||||
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
name: default-executor
|
||||||
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
||||||
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
||||||
resource_class: xlarge
|
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
||||||
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
- run:
|
- run:
|
||||||
name: Preparing environment for running tests on Saucelabs.
|
name: Preparing environment for running tests on Saucelabs.
|
||||||
command: |
|
command: |
|
||||||
@ -604,10 +572,10 @@ jobs:
|
|||||||
- run: ./scripts/saucelabs/stop-tunnel.sh
|
- run: ./scripts/saucelabs/stop-tunnel.sh
|
||||||
|
|
||||||
legacy-misc-tests:
|
legacy-misc-tests:
|
||||||
<<: *job_defaults
|
executor: default-executor
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
- run: yarn gulp check-cycle
|
- run: yarn gulp check-cycle
|
||||||
# TODO: disabled because the Bazel packages-dist does not seem to have map files for
|
# TODO: disabled because the Bazel packages-dist does not seem to have map files for
|
||||||
# the ESM5/ES2015 output. See: https://github.com/angular/angular/issues/27966
|
# the ESM5/ES2015 output. See: https://github.com/angular/angular/issues/27966
|
||||||
@ -616,23 +584,22 @@ jobs:
|
|||||||
# Job to run unit tests from angular/material2. Needs a browser since all
|
# Job to run unit tests from angular/material2. Needs a browser since all
|
||||||
# component unit tests assume they're running in the browser environment.
|
# component unit tests assume they're running in the browser environment.
|
||||||
material-unit-tests:
|
material-unit-tests:
|
||||||
<<: *job_defaults
|
executor:
|
||||||
resource_class: xlarge
|
name: browsers-executor
|
||||||
docker:
|
resource_class: xlarge
|
||||||
- image: *browsers_docker_image
|
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
# Although RBE is configured below for the Material repo, also setup RBE in the Angular repo
|
# Although RBE is configured below for the Material repo, also setup RBE in the Angular repo
|
||||||
# to provision Angular's GCP token into the environment variables.
|
# to provision Angular's GCP token into the environment variables.
|
||||||
- *setup_bazel_remote_execution
|
- setup_bazel_rbe
|
||||||
# Restore the cache before cloning the repository because the clone script re-uses
|
# Restore the cache before cloning the repository because the clone script re-uses
|
||||||
# the restored repository if present. This reduces the amount of times the components
|
# the restored repository if present. This reduces the amount of times the components
|
||||||
# repository needs to be cloned (this is slow and increases based on commits in the repo).
|
# repository needs to be cloned (this is slow and increases based on commits in the repo).
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- *material_unit_tests_cache_key
|
- *material_unit_tests_cache_key
|
||||||
- *material_unit_tests_cache_key_short
|
- *material_unit_tests_cache_key_fallback
|
||||||
- run:
|
- run:
|
||||||
name: "Fetching Material repository"
|
name: "Fetching Material repository"
|
||||||
command: ./scripts/ci/clone_angular_material_repo.sh
|
command: ./scripts/ci/clone_angular_material_repo.sh
|
||||||
@ -655,10 +622,14 @@ jobs:
|
|||||||
command: ./scripts/ci/run_angular_material_unit_tests.sh
|
command: ./scripts/ci/run_angular_material_unit_tests.sh
|
||||||
|
|
||||||
test_zonejs:
|
test_zonejs:
|
||||||
<<: *job_defaults
|
executor:
|
||||||
|
name: default-executor
|
||||||
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- custom_attach_workspace
|
||||||
- *init_environment
|
- init_environment
|
||||||
|
- setup_circleci_bazel_config
|
||||||
|
- setup_bazel_rbe
|
||||||
# Install
|
# Install
|
||||||
- run: yarn --cwd packages/zone.js install --frozen-lockfile --non-interactive
|
- run: yarn --cwd packages/zone.js install --frozen-lockfile --non-interactive
|
||||||
# Run zone.js tools tests
|
# Run zone.js tools tests
|
||||||
@ -673,7 +644,10 @@ workflows:
|
|||||||
version: 2
|
version: 2
|
||||||
default_workflow:
|
default_workflow:
|
||||||
jobs:
|
jobs:
|
||||||
- setup
|
- setup:
|
||||||
|
filters:
|
||||||
|
branches:
|
||||||
|
ignore: g3
|
||||||
- lint:
|
- lint:
|
||||||
requires:
|
requires:
|
||||||
- setup
|
- setup
|
||||||
@ -714,7 +688,9 @@ workflows:
|
|||||||
- test_aio_local:
|
- test_aio_local:
|
||||||
requires:
|
requires:
|
||||||
- build-npm-packages
|
- build-npm-packages
|
||||||
- test_aio_local_ivy:
|
- test_aio_local:
|
||||||
|
name: test_aio_local_ivy
|
||||||
|
ivy: true
|
||||||
requires:
|
requires:
|
||||||
- build-npm-packages
|
- build-npm-packages
|
||||||
- test_aio_tools:
|
- test_aio_tools:
|
||||||
@ -723,7 +699,9 @@ workflows:
|
|||||||
- test_docs_examples:
|
- test_docs_examples:
|
||||||
requires:
|
requires:
|
||||||
- build-npm-packages
|
- build-npm-packages
|
||||||
- test_docs_examples_ivy:
|
- test_docs_examples:
|
||||||
|
name: test_docs_examples_ivy
|
||||||
|
ivy: true
|
||||||
requires:
|
requires:
|
||||||
- build-ivy-npm-packages
|
- build-ivy-npm-packages
|
||||||
- aio_preview:
|
- aio_preview:
|
||||||
@ -784,9 +762,3 @@ workflows:
|
|||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
|
|
||||||
# TODO:
|
|
||||||
# - don't build the g3 branch
|
|
||||||
# - verify that we are bootstrapping with the right yarn version coming from the docker image
|
|
||||||
# - check local chrome version pulled from docker image
|
|
||||||
# - remove /tools/ngcontainer
|
|
||||||
|
@ -19,16 +19,20 @@ setPublicVar PROJECT_ROOT "$projectDir";
|
|||||||
setPublicVar CI_AIO_MIN_PWA_SCORE "95";
|
setPublicVar CI_AIO_MIN_PWA_SCORE "95";
|
||||||
# This is the branch being built; e.g. `pull/12345` for PR builds.
|
# This is the branch being built; e.g. `pull/12345` for PR builds.
|
||||||
setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
|
setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
|
||||||
|
setPublicVar CI_BUILD_URL "$CIRCLE_BUILD_URL";
|
||||||
# ChromeDriver version compatible with the Chrome version included in the docker image used in
|
# ChromeDriver version compatible with the Chrome version included in the docker image used in
|
||||||
# `.circleci/config.yml`. See http://chromedriver.chromium.org/downloads for a list of versions.
|
# `.circleci/config.yml`. See http://chromedriver.chromium.org/downloads for a list of versions.
|
||||||
# This variable is intended to be passed as an arg to the `webdriver-manager update` command (e.g.
|
# This variable is intended to be passed as an arg to the `webdriver-manager update` command (e.g.
|
||||||
# `"postinstall": "webdriver-manager update $CI_CHROMEDRIVER_VERSION_ARG"`).
|
# `"postinstall": "webdriver-manager update $CI_CHROMEDRIVER_VERSION_ARG"`).
|
||||||
setPublicVar CI_CHROMEDRIVER_VERSION_ARG "--versions.chrome 75.0.3770.90";
|
setPublicVar CI_CHROMEDRIVER_VERSION_ARG "--versions.chrome 75.0.3770.90";
|
||||||
setPublicVar CI_COMMIT "$CIRCLE_SHA1";
|
setPublicVar CI_COMMIT "$CIRCLE_SHA1";
|
||||||
# `CI_COMMIT_RANGE` will only be available when `CIRCLE_COMPARE_URL` is also available (or can be
|
# `CI_COMMIT_RANGE` is only used on push builds (a.k.a. non-PR, non-scheduled builds and rerun
|
||||||
# retrieved via `get-compare-url.js`), i.e. on push builds (a.k.a. non-PR, non-scheduled builds and
|
# workflows of such builds).
|
||||||
# rerun workflows of such builds). That is fine, since we only need it in push builds.
|
# NOTE: With [CircleCI Pipelines](https://circleci.com/docs/2.0/build-processing) enabled,
|
||||||
setPublicVar CI_COMMIT_RANGE "`[[ ${CIRCLE_PR_NUMBER:-false} != false ]] && echo "" || node $getCommitRangePath "$CIRCLE_BUILD_NUM" "$CIRCLE_COMPARE_URL"`";
|
# `CIRCLE_COMPARE_URL` is no longer available and the commit range cannot be reliably
|
||||||
|
# detected. Fall back to only considering the last commit (which is accurate in the majority
|
||||||
|
# of cases for push builds).
|
||||||
|
setPublicVar CI_COMMIT_RANGE "`[[ ${CIRCLE_PR_NUMBER:-false} != false ]] && echo "" || echo "$CIRCLE_SHA1~1...$CIRCLE_SHA1"`";
|
||||||
setPublicVar CI_PULL_REQUEST "${CIRCLE_PR_NUMBER:-false}";
|
setPublicVar CI_PULL_REQUEST "${CIRCLE_PR_NUMBER:-false}";
|
||||||
setPublicVar CI_REPO_NAME "$CIRCLE_PROJECT_REPONAME";
|
setPublicVar CI_REPO_NAME "$CIRCLE_PROJECT_REPONAME";
|
||||||
setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
|
setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
|
||||||
@ -61,6 +65,7 @@ else
|
|||||||
setPublicVar SAUCE_USERNAME "angular-ci";
|
setPublicVar SAUCE_USERNAME "angular-ci";
|
||||||
setSecretVar SAUCE_ACCESS_KEY "9b988f434ff8-fbca-8aa4-4ae3-35442987";
|
setSecretVar SAUCE_ACCESS_KEY "9b988f434ff8-fbca-8aa4-4ae3-35442987";
|
||||||
fi
|
fi
|
||||||
|
# TODO(josephperrott): Remove environment variables once all saucelabs tests are via bazel method.
|
||||||
setPublicVar SAUCE_LOG_FILE /tmp/angular/sauce-connect.log
|
setPublicVar SAUCE_LOG_FILE /tmp/angular/sauce-connect.log
|
||||||
setPublicVar SAUCE_READY_FILE /tmp/angular/sauce-connect-ready-file.lock
|
setPublicVar SAUCE_READY_FILE /tmp/angular/sauce-connect-ready-file.lock
|
||||||
setPublicVar SAUCE_PID_FILE /tmp/angular/sauce-connect-pid-file.lock
|
setPublicVar SAUCE_PID_FILE /tmp/angular/sauce-connect-pid-file.lock
|
||||||
@ -79,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 "701302dc482d7e4b77990b24e3b5ab330bbf1aa5"
|
setPublicVar MATERIAL_REPO_COMMIT "18b9ef3f5529f0fa8f034944681486447af7b879"
|
||||||
|
|
||||||
# Source `$BASH_ENV` to make the variables available immediately.
|
# Source `$BASH_ENV` to make the variables available immediately.
|
||||||
source $BASH_ENV;
|
source $BASH_ENV;
|
||||||
|
@ -10,6 +10,13 @@
|
|||||||
* format of the `CIRCLE_COMPARE_URL` environment variable, or by retrieving the equivalent of
|
* format of the `CIRCLE_COMPARE_URL` environment variable, or by retrieving the equivalent of
|
||||||
* `CIRCLE_COMPARE_URL` for jobs that are part of a rerun workflow and extracting it from there.
|
* `CIRCLE_COMPARE_URL` for jobs that are part of a rerun workflow and extracting it from there.
|
||||||
*
|
*
|
||||||
|
* > !!! WARNING !!!
|
||||||
|
* > !!
|
||||||
|
* > !! When [CircleCI Pipelines](https://circleci.com/docs/2.0/build-processing) is enabled, the
|
||||||
|
* > !! `CIRCLE_COMPARE_URL` environment variable is not available at all and this script does not
|
||||||
|
* > !! work.
|
||||||
|
* > !!!!!!!!!!!!!!!
|
||||||
|
*
|
||||||
* **Context:**
|
* **Context:**
|
||||||
* CircleCI sets the `CIRCLE_COMPARE_URL` environment variable (from which we can extract the commit
|
* CircleCI sets the `CIRCLE_COMPARE_URL` environment variable (from which we can extract the commit
|
||||||
* range) on push builds (a.k.a. non-PR, non-scheduled builds). Yet, when a workflow is rerun
|
* range) on push builds (a.k.a. non-PR, non-scheduled builds). Yet, when a workflow is rerun
|
||||||
@ -21,7 +28,7 @@
|
|||||||
* (undocumented) fact that the workspace ID happens to be the same as the workflow ID that first
|
* (undocumented) fact that the workspace ID happens to be the same as the workflow ID that first
|
||||||
* created it.
|
* created it.
|
||||||
*
|
*
|
||||||
* For example, for a job on push build workflow, the CircleCI API will return data that look like:
|
* For example, for a job on push build workflows, the CircleCI API will return data that look like:
|
||||||
* ```js
|
* ```js
|
||||||
* {
|
* {
|
||||||
* compare: 'THE_COMPARE_URL_WE_ARE_LOOKING_FOR',
|
* compare: 'THE_COMPARE_URL_WE_ARE_LOOKING_FOR',
|
||||||
|
165
.github/CODEOWNERS
vendored
165
.github/CODEOWNERS
vendored
@ -44,23 +44,19 @@
|
|||||||
# alxhub - Alex Rickabaugh
|
# alxhub - Alex Rickabaugh
|
||||||
# AndrewKushnir - Andrew Kushnir
|
# AndrewKushnir - Andrew Kushnir
|
||||||
# andrewseguin - Andrew Seguin
|
# andrewseguin - Andrew Seguin
|
||||||
# benlesh - Ben Lesh
|
# atscott - Andrew Scott
|
||||||
# brandonroberts - Brandon Roberts
|
|
||||||
# devversion - Paul Gschwendtner
|
# devversion - Paul Gschwendtner
|
||||||
# filipesilva - Filipe Silva
|
# filipesilva - Filipe Silva
|
||||||
# gkalpak - George Kalpakas
|
# gkalpak - George Kalpakas
|
||||||
# hansl - Hans Larsen
|
|
||||||
# IgorMinar - Igor Minar
|
# IgorMinar - Igor Minar
|
||||||
# jasonaden - Jason Aden
|
|
||||||
# jenniferfell - Jennifer Fell
|
|
||||||
# JiaLiPassion - Jia Li
|
# JiaLiPassion - Jia Li
|
||||||
# josephperrott - Joey Perrott
|
# josephperrott - Joey Perrott
|
||||||
|
# kapunahelewong - Kapunahele Wong
|
||||||
# kara - Kara Erickson
|
# kara - Kara Erickson
|
||||||
# kyliau - Keen Yee Liau
|
# kyliau - Keen Yee Liau
|
||||||
# matsko - Matias Niemelä
|
# matsko - Matias Niemelä
|
||||||
# mgechev - Minko Gechev
|
# mgechev - Minko Gechev
|
||||||
# mhevery - Misko Hevery
|
# mhevery - Misko Hevery
|
||||||
# ocombe - Olivier Combe
|
|
||||||
# petebacondarwin - Pete Bacon Darwin
|
# petebacondarwin - Pete Bacon Darwin
|
||||||
# pkozlowski-opensource - Pawel Kozlowski
|
# pkozlowski-opensource - Pawel Kozlowski
|
||||||
# robwormald - Rob Wormald
|
# robwormald - Rob Wormald
|
||||||
@ -88,9 +84,9 @@
|
|||||||
# (secret team to avoid review requests, it also doesn't inherit from @angular/framework because nested teams can't be secret)
|
# (secret team to avoid review requests, it also doesn't inherit from @angular/framework because nested teams can't be secret)
|
||||||
#
|
#
|
||||||
# - IgorMinar
|
# - IgorMinar
|
||||||
|
# - josephperrott
|
||||||
# - kara
|
# - kara
|
||||||
# - mhevery
|
# - mhevery
|
||||||
# - alexeagle
|
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -99,9 +95,8 @@
|
|||||||
# Used for approving minor documentation-only changes that don't require engineering review.
|
# Used for approving minor documentation-only changes that don't require engineering review.
|
||||||
# (secret team to avoid review requests, it also doesn't inherit from @angular/framework because nested teams can't be secret)
|
# (secret team to avoid review requests, it also doesn't inherit from @angular/framework because nested teams can't be secret)
|
||||||
#
|
#
|
||||||
# - brandonroberts
|
|
||||||
# - gkalpak
|
# - gkalpak
|
||||||
# - jenniferfell
|
# - kapunahelewong
|
||||||
# - petebacondarwin
|
# - petebacondarwin
|
||||||
|
|
||||||
|
|
||||||
@ -126,10 +121,9 @@
|
|||||||
# @angular/tools-cli
|
# @angular/tools-cli
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
#
|
#
|
||||||
# - alexeagle
|
|
||||||
# - filipesilva
|
# - filipesilva
|
||||||
# - hansl
|
|
||||||
# - mgechev
|
# - mgechev
|
||||||
|
# - vikerman
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -180,8 +174,7 @@
|
|||||||
# @angular/fw-forms
|
# @angular/fw-forms
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
#
|
#
|
||||||
# - kara
|
# - AndrewKushnir
|
||||||
# - jasonaden
|
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -203,7 +196,7 @@
|
|||||||
# @angular/fw-router
|
# @angular/fw-router
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
#
|
#
|
||||||
# - jasonaden
|
# - atscott
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -221,7 +214,6 @@
|
|||||||
#
|
#
|
||||||
# - gkalpak
|
# - gkalpak
|
||||||
# - petebacondarwin
|
# - petebacondarwin
|
||||||
# - jasonaden
|
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -237,7 +229,7 @@
|
|||||||
#
|
#
|
||||||
# - AndrewKushnir
|
# - AndrewKushnir
|
||||||
# - mhevery
|
# - mhevery
|
||||||
# - ocombe
|
# - petebacondarwin
|
||||||
# - vikerman
|
# - vikerman
|
||||||
|
|
||||||
|
|
||||||
@ -269,8 +261,8 @@
|
|||||||
# @angular/fw-integration
|
# @angular/fw-integration
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
#
|
#
|
||||||
# - alexeagle
|
|
||||||
# - IgorMinar
|
# - IgorMinar
|
||||||
|
# - josephperrott
|
||||||
# - mhevery
|
# - mhevery
|
||||||
|
|
||||||
|
|
||||||
@ -278,7 +270,6 @@
|
|||||||
# @angular/docs-infra
|
# @angular/docs-infra
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
#
|
#
|
||||||
# - brandonroberts
|
|
||||||
# - gkalpak
|
# - gkalpak
|
||||||
# - IgorMinar
|
# - IgorMinar
|
||||||
# - petebacondarwin
|
# - petebacondarwin
|
||||||
@ -288,8 +279,6 @@
|
|||||||
# @angular/fw-docs-intro
|
# @angular/fw-docs-intro
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
#
|
#
|
||||||
# - jenniferfell
|
|
||||||
# - brandonroberts
|
|
||||||
# - IgorMinar
|
# - IgorMinar
|
||||||
# - stephenfluin
|
# - stephenfluin
|
||||||
|
|
||||||
@ -298,16 +287,15 @@
|
|||||||
# @angular/fw-docs-observables
|
# @angular/fw-docs-observables
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
#
|
#
|
||||||
# - benlesh
|
# - alxhub
|
||||||
# - jasonaden
|
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
# @angular/fw-docs-packaging
|
# @angular/fw-docs-packaging
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
#
|
#
|
||||||
# - alexeagle
|
|
||||||
# - IgorMinar
|
# - IgorMinar
|
||||||
|
# - vikerman
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -315,10 +303,9 @@
|
|||||||
# ===========================================================
|
# ===========================================================
|
||||||
#
|
#
|
||||||
# - alan-agius4
|
# - alan-agius4
|
||||||
# - alexeagle
|
|
||||||
# - hansl
|
|
||||||
# - IgorMinar
|
# - IgorMinar
|
||||||
# - mgechev
|
# - mgechev
|
||||||
|
# - vikerman
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -326,11 +313,9 @@
|
|||||||
# ===========================================================
|
# ===========================================================
|
||||||
#
|
#
|
||||||
# - alan-agius4
|
# - alan-agius4
|
||||||
# - alexeagle
|
|
||||||
# - hansl
|
|
||||||
# - IgorMinar
|
# - IgorMinar
|
||||||
# - mgechev
|
# - mgechev
|
||||||
|
# - vikerman
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -349,10 +334,9 @@
|
|||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
# @angular/fw-dev-infra
|
# @angular/dev-infra-framework
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
#
|
#
|
||||||
# - alexeagle
|
|
||||||
# - devversion
|
# - devversion
|
||||||
# - filipesilva
|
# - filipesilva
|
||||||
# - gkalpak
|
# - gkalpak
|
||||||
@ -383,6 +367,43 @@
|
|||||||
* @IgorMinar @angular/framework-global-approvers
|
* @IgorMinar @angular/framework-global-approvers
|
||||||
|
|
||||||
|
|
||||||
|
# ================================================
|
||||||
|
# Build, CI & Dev-infra Owners
|
||||||
|
# ================================================
|
||||||
|
|
||||||
|
/* @angular/dev-infra-framework
|
||||||
|
/.buildkite/** @angular/dev-infra-framework
|
||||||
|
/.circleci/** @angular/dev-infra-framework
|
||||||
|
/.devcontainer/** @angular/dev-infra-framework
|
||||||
|
/.github/** @angular/dev-infra-framework
|
||||||
|
/.vscode/** @angular/dev-infra-framework
|
||||||
|
/docs/BAZEL.md @angular/dev-infra-framework
|
||||||
|
/packages/* @angular/dev-infra-framework
|
||||||
|
/packages/examples/test-utils/** @angular/dev-infra-framework
|
||||||
|
/packages/private/** @angular/dev-infra-framework
|
||||||
|
/scripts/** @angular/dev-infra-framework
|
||||||
|
/third_party/** @angular/dev-infra-framework
|
||||||
|
/tools/build/** @angular/dev-infra-framework
|
||||||
|
/tools/cjs-jasmine/** @angular/dev-infra-framework
|
||||||
|
/tools/gulp-tasks/** @angular/dev-infra-framework
|
||||||
|
/tools/ngcontainer/** @angular/dev-infra-framework
|
||||||
|
/tools/npm/** @angular/dev-infra-framework
|
||||||
|
/tools/npm_workspace/** @angular/dev-infra-framework
|
||||||
|
/tools/public_api_guard/** @angular/dev-infra-framework
|
||||||
|
/tools/rxjs/** @angular/dev-infra-framework
|
||||||
|
/tools/size-tracking/** @angular/dev-infra-framework
|
||||||
|
/tools/source-map-test/** @angular/dev-infra-framework
|
||||||
|
/tools/symbol-extractor/** @angular/dev-infra-framework
|
||||||
|
/tools/testing/** @angular/dev-infra-framework
|
||||||
|
/tools/ts-api-guardian/** @angular/dev-infra-framework
|
||||||
|
/tools/tslint/** @angular/dev-infra-framework
|
||||||
|
/tools/validate-commit-message/** @angular/dev-infra-framework
|
||||||
|
/tools/yarn/** @angular/dev-infra-framework
|
||||||
|
/tools/* @angular/dev-infra-framework
|
||||||
|
*.BAZEL @angular/dev-infra-framework
|
||||||
|
*.bzl @angular/dev-infra-framework
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
# @angular/animations
|
# @angular/animations
|
||||||
@ -410,6 +431,7 @@
|
|||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/packages/bazel/** @angular/tools-bazel @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/bazel/** @angular/tools-bazel @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/guide/bazel.md @angular/tools-bazel @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -419,8 +441,11 @@
|
|||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/packages/compiler/** @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/compiler/** @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/packages/examples/compiler/** @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/packages/compiler-cli/** @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/compiler-cli/** @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/guide/angular-compiler-options.md @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/aot-compiler.md @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/aot-compiler.md @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/guide/aot-metadata-errors.md @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -439,6 +464,7 @@
|
|||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/packages/compiler-cli/src/ngtools/** @angular/tools-cli @angular/framework-global-approvers
|
/packages/compiler-cli/src/ngtools/** @angular/tools-cli @angular/framework-global-approvers
|
||||||
|
/aio/content/guide/cli-builder.md @angular/tools-cli @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/ivy.md @angular/tools-cli @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/ivy.md @angular/tools-cli @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/web-worker.md @angular/tools-cli @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/web-worker.md @angular/tools-cli @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
@ -454,12 +480,18 @@
|
|||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/packages/core/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/core/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/packages/examples/core/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/packages/common/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/common/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/packages/platform-browser/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/platform-browser/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/packages/examples/platform-browser/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/packages/platform-browser-dynamic/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/platform-browser-dynamic/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/packages/platform-webworker/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/platform-webworker/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/packages/platform-webworker-dynamic/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/platform-webworker-dynamic/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/packages/examples/common/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/examples/common/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/packages/docs/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
/aio/content/guide/accessibility.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/accessibility/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
/aio/content/guide/architecture-components.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/architecture-components.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/architecture-modules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/architecture-modules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -516,6 +548,8 @@
|
|||||||
|
|
||||||
/aio/content/guide/hierarchical-dependency-injection.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/hierarchical-dependency-injection.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/hierarchical-dependency-injection/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/hierarchical-dependency-injection/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/providers-viewproviders/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/resolution-modifiers/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
/aio/content/guide/lazy-loading-ngmodules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/lazy-loading-ngmodules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/lazy-loading-ngmodules/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/lazy-loading-ngmodules/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -550,11 +584,12 @@
|
|||||||
/aio/content/examples/attribute-binding/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/attribute-binding/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/two-way-binding/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/two-way-binding/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/built-in-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/built-in-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/images/guide/built-in-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/template-reference-variables/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/template-reference-variables/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/inputs-outputs/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/inputs-outputs/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/images/guide/inputs-outputs/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/template-expression-operators/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/template-expression-operators/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
/aio/content/guide/pipes.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/pipes.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/pipes/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/pipes/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/pipes/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/pipes/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -587,6 +622,7 @@
|
|||||||
|
|
||||||
/packages/common/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/common/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/packages/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/packages/examples/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/http.md @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/http.md @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -609,6 +645,7 @@
|
|||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/packages/forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/packages/examples/forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/forms.md @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/forms.md @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -652,6 +689,7 @@
|
|||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/packages/router/** @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/router/** @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/packages/examples/router/** @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/router.md @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/router.md @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/router/** @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/router/** @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/router/** @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/router/** @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -663,6 +701,7 @@
|
|||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/packages/service-worker/** @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/service-worker/** @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/packages/examples/service-worker/** @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/service-worker-getting-started.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/service-worker-getting-started.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/service-worker-getting-started/** @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/service-worker-getting-started/** @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/app-shell.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/app-shell.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -689,6 +728,7 @@
|
|||||||
/aio/content/examples/upgrade-phonecat-2-hybrid/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/upgrade-phonecat-2-hybrid/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/upgrade-phonecat-3-final/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/upgrade-phonecat-3-final/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/upgrade-performance.md @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/upgrade-performance.md @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/guide/upgrade-setup.md @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/ajs-quick-reference.md @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/ajs-quick-reference.md @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/ajs-quick-reference/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/ajs-quick-reference/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
@ -726,7 +766,6 @@ testing/** @angular/fw-test
|
|||||||
/aio/content/examples/i18n/** @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/i18n/** @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
# @angular security
|
# @angular security
|
||||||
# ================================================
|
# ================================================
|
||||||
@ -777,7 +816,6 @@ testing/** @angular/fw-test
|
|||||||
/aio/tools/** @angular/docs-infra @angular/framework-global-approvers
|
/aio/tools/** @angular/docs-infra @angular/framework-global-approvers
|
||||||
|
|
||||||
# Hidden docs
|
# Hidden docs
|
||||||
/aio/content/guide/change-log.md @angular/docs-infra @angular/framework-global-approvers
|
|
||||||
/aio/content/guide/docs-style-guide.md @angular/docs-infra @angular/framework-global-approvers
|
/aio/content/guide/docs-style-guide.md @angular/docs-infra @angular/framework-global-approvers
|
||||||
/aio/content/examples/docs-style-guide/** @angular/docs-infra @angular/framework-global-approvers
|
/aio/content/examples/docs-style-guide/** @angular/docs-infra @angular/framework-global-approvers
|
||||||
/aio/content/images/guide/docs-style-guide/** @angular/docs-infra @angular/framework-global-approvers
|
/aio/content/images/guide/docs-style-guide/** @angular/docs-infra @angular/framework-global-approvers
|
||||||
@ -790,9 +828,8 @@ testing/** @angular/fw-test
|
|||||||
# Docs: getting started & tutorial
|
# Docs: getting started & tutorial
|
||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/aio/content/guide/quickstart.md @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/setup-local.md @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/cli-quickstart/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/setup-local/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/cli-quickstart/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/tutorial/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/tutorial/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/toh/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/toh/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/toh-pt0/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/toh-pt0/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -804,8 +841,8 @@ testing/** @angular/fw-test
|
|||||||
/aio/content/examples/toh-pt6/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/toh-pt6/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/getting-started-v0/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/getting-started-v0/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/getting-started/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/getting-started/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/getting-started/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/start/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/getting-started/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/start/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
@ -831,11 +868,11 @@ testing/** @angular/fw-test
|
|||||||
/aio/content/guide/npm-packages.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/npm-packages.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/browser-support.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/browser-support.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/typescript-configuration.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/typescript-configuration.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/setup.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/setup/** @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/setup/** @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/build.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/build.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/build/** @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/build/** @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/deployment.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/deployment.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/images/guide/deployment/** @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/file-structure.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/file-structure.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/releases.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/releases.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/updating.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/updating.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -877,48 +914,6 @@ testing/** @angular/fw-test
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
|
||||||
# Build & CI Owners
|
|
||||||
# ================================================
|
|
||||||
|
|
||||||
/* @angular/fw-dev-infra
|
|
||||||
/.buildkite/** @angular/fw-dev-infra
|
|
||||||
/.circleci/** @angular/fw-dev-infra
|
|
||||||
/.devcontainer/** @angular/fw-dev-infra
|
|
||||||
/.github/** @angular/fw-dev-infra
|
|
||||||
/.vscode/** @angular/fw-dev-infra
|
|
||||||
/docs/BAZEL.md @angular/fw-dev-infra
|
|
||||||
/packages/* @angular/fw-dev-infra
|
|
||||||
/scripts/** @angular/fw-dev-infra
|
|
||||||
/third_party/** @angular/fw-dev-infra
|
|
||||||
/tools/build/** @angular/fw-dev-infra
|
|
||||||
/tools/cjs-jasmine/** @angular/fw-dev-infra
|
|
||||||
/tools/gulp-tasks/** @angular/fw-dev-infra
|
|
||||||
/tools/ngcontainer/** @angular/fw-dev-infra
|
|
||||||
/tools/npm/** @angular/fw-dev-infra
|
|
||||||
/tools/npm_workspace/** @angular/fw-dev-infra
|
|
||||||
/tools/public_api_guard/** @angular/fw-dev-infra
|
|
||||||
/tools/rxjs/** @angular/fw-dev-infra
|
|
||||||
/tools/source-map-test/** @angular/fw-dev-infra
|
|
||||||
/tools/symbol-extractor/** @angular/fw-dev-infra
|
|
||||||
/tools/testing/** @angular/fw-dev-infra
|
|
||||||
/tools/ts-api-guardian/** @angular/fw-dev-infra
|
|
||||||
/tools/tslint/** @angular/fw-dev-infra
|
|
||||||
/tools/validate-commit-message/** @angular/fw-dev-infra
|
|
||||||
/tools/yarn/** @angular/fw-dev-infra
|
|
||||||
/tools/*
|
|
||||||
*.bzl @angular/fw-dev-infra
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
|
||||||
# Material CI
|
|
||||||
# ================================================
|
|
||||||
|
|
||||||
/tools/material-ci/** @angular/fw-core @angular/framework-global-approvers
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
# Public API
|
# Public API
|
||||||
# ================================================
|
# ================================================
|
||||||
@ -931,6 +926,14 @@ testing/** @angular/fw-test
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ================================================
|
||||||
|
# Special cases
|
||||||
|
# ================================================
|
||||||
|
|
||||||
|
/aio/content/guide/static-query-migration.md @kara @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
# CODEOWNERS Owners owners ...
|
# CODEOWNERS Owners owners ...
|
||||||
# ================================================
|
# ================================================
|
||||||
|
111
CHANGELOG.md
111
CHANGELOG.md
@ -1,3 +1,114 @@
|
|||||||
|
<a name="8.2.14"></a>
|
||||||
|
## [8.2.14](https://github.com/angular/angular/compare/8.2.13...8.2.14) (2019-11-13)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** exclude [@angular](https://github.com/angular)/cli from metadata build ([b43ae44](https://github.com/angular/angular/commit/b43ae44)), closes [#33502](https://github.com/angular/angular/issues/33502)
|
||||||
|
* **service-worker:** ensure initialization before handling messages ([#32525](https://github.com/angular/angular/issues/32525)) ([2840670](https://github.com/angular/angular/commit/2840670)), closes [#25611](https://github.com/angular/angular/issues/25611)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.2.13"></a>
|
||||||
|
## [8.2.13](https://github.com/angular/angular/compare/8.2.12...8.2.13) (2019-10-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **compiler:** i18n - ignore `alt-trans` tags in XLIFF 1.2 ([#33464](https://github.com/angular/angular/issues/33464)) ([f97c464](https://github.com/angular/angular/commit/f97c464)), closes [#33161](https://github.com/angular/angular/issues/33161)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.2.12"></a>
|
||||||
|
## [8.2.12](https://github.com/angular/angular/compare/8.2.11...8.2.12) (2019-10-23)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **upgrade:** remove unused version export ([#33180](https://github.com/angular/angular/issues/33180)) ([37cbcfa](https://github.com/angular/angular/commit/37cbcfa))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.2.11"></a>
|
||||||
|
## [8.2.11](https://github.com/angular/angular/compare/8.2.10...8.2.11) (2019-10-15)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **service-worker:** continue serving api requests on cache failure ([#33165](https://github.com/angular/angular/issues/33165)) ([a2716ac](https://github.com/angular/angular/commit/a2716ac)), closes [#32996](https://github.com/angular/angular/issues/32996) [#21412](https://github.com/angular/angular/issues/21412)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.2.10"></a>
|
||||||
|
## [8.2.10](https://github.com/angular/angular/compare/8.2.9...8.2.10) (2019-10-09)
|
||||||
|
|
||||||
|
This release contains various API docs improvements.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.2.9"></a>
|
||||||
|
## [8.2.9](https://github.com/angular/angular/compare/8.2.8...8.2.9) (2019-10-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **upgrade:** fix AngularJsUrlCodec to support Safari ([#32959](https://github.com/angular/angular/issues/32959)) ([57457fb](https://github.com/angular/angular/commit/57457fb))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.2.8"></a>
|
||||||
|
## [8.2.8](https://github.com/angular/angular/compare/8.2.7...8.2.8) (2019-09-25)
|
||||||
|
|
||||||
|
This release contains various API docs improvements.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.2.7"></a>
|
||||||
|
## [8.2.7](https://github.com/angular/angular/compare/8.2.6...8.2.7) (2019-09-18)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** ng_package(data) should support non-text files ([#32721](https://github.com/angular/angular/issues/32721)) ([ba1ef6b](https://github.com/angular/angular/commit/ba1ef6b))
|
||||||
|
* **compiler-cli:** fix typo in diagnostic template info. ([#32684](https://github.com/angular/angular/issues/32684)) ([947c076](https://github.com/angular/angular/commit/947c076)), closes [#32662](https://github.com/angular/angular/issues/32662)
|
||||||
|
* **language-service:** cache module resolution ([#32483](https://github.com/angular/angular/issues/32483)) ([1c5b157](https://github.com/angular/angular/commit/1c5b157))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.2.6"></a>
|
||||||
|
## [8.2.6](https://github.com/angular/angular/compare/8.2.5...8.2.6) (2019-09-11)
|
||||||
|
|
||||||
|
This release contains various API docs improvements.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.2.5"></a>
|
||||||
|
## [8.2.5](https://github.com/angular/angular/compare/8.2.4...8.2.5) (2019-09-04)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **common:** HttpParams fromObject accepts ReadonlyArray<string> ([#31072](https://github.com/angular/angular/issues/31072)) ([b3ea698](https://github.com/angular/angular/commit/b3ea698)), closes [#28452](https://github.com/angular/angular/issues/28452)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.2.4"></a>
|
||||||
|
## [8.2.4](https://github.com/angular/angular/compare/8.2.3...8.2.4) (2019-08-28)
|
||||||
|
|
||||||
|
This release contains various API docs improvements.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.2.3"></a>
|
||||||
|
## [8.2.3](https://github.com/angular/angular/compare/8.2.2...8.2.3) (2019-08-21)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** pin `[@microsoft](https://github.com/microsoft)/api-extractor` ([#32187](https://github.com/angular/angular/issues/32187)) ([a7b9478](https://github.com/angular/angular/commit/a7b9478))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="8.2.2"></a>
|
<a name="8.2.2"></a>
|
||||||
## [8.2.2](https://github.com/angular/angular/compare/8.2.1...8.2.2) (2019-08-12)
|
## [8.2.2](https://github.com/angular/angular/compare/8.2.1...8.2.2) (2019-08-12)
|
||||||
|
|
||||||
|
@ -201,7 +201,7 @@ Must be one of the following:
|
|||||||
* **test**: Adding missing tests or correcting existing tests
|
* **test**: Adding missing tests or correcting existing tests
|
||||||
|
|
||||||
### Scope
|
### Scope
|
||||||
The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages.
|
The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages).
|
||||||
|
|
||||||
The following is the list of supported scopes:
|
The following is the list of supported scopes:
|
||||||
|
|
||||||
@ -233,6 +233,7 @@ There are currently a few exceptions to the "use package name" rule:
|
|||||||
* **docs-infra**: used for docs-app (angular.io) related changes within the /aio directory of the
|
* **docs-infra**: used for docs-app (angular.io) related changes within the /aio directory of the
|
||||||
repo
|
repo
|
||||||
* **ivy**: used for changes to the [Ivy renderer](https://github.com/angular/angular/issues/21706).
|
* **ivy**: used for changes to the [Ivy renderer](https://github.com/angular/angular/issues/21706).
|
||||||
|
* **ngcc**: used for changes to the [Angular Compatibility Compiler](./packages/compiler-cli/ngcc/README.md)
|
||||||
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all
|
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all
|
||||||
packages (e.g. `style: add missing semicolons`) and for docs changes that are not related to a
|
packages (e.g. `style: add missing semicolons`) and for docs changes that are not related to a
|
||||||
specific package (e.g. `docs: fix typo in tutorial`).
|
specific package (e.g. `docs: fix typo in tutorial`).
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
# Angular
|
# Angular
|
||||||
|
|
||||||
Angular is a development platform for building mobile and desktop web applications using Typescript/JavaScript and other languages.
|
Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages.
|
||||||
|
|
||||||
## Quickstart
|
## Quickstart
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ Angular is a development platform for building mobile and desktop web applicatio
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
[Learn about the latest improvements][changelog].
|
[Learn about the latest improvements][changelog].
|
||||||
|
|
||||||
## Want to help?
|
## Want to help?
|
||||||
|
|
||||||
|
@ -65,6 +65,9 @@ node_repositories(
|
|||||||
},
|
},
|
||||||
node_version = "10.16.0",
|
node_version = "10.16.0",
|
||||||
package_json = ["//:package.json"],
|
package_json = ["//:package.json"],
|
||||||
|
yarn_repositories = {
|
||||||
|
"1.17.3": ("yarn-v1.17.3.tar.gz", "yarn-v1.17.3", "e3835194409f1b3afa1c62ca82f561f1c29d26580c9e220c36866317e043c6f3"),
|
||||||
|
},
|
||||||
# yarn 1.13.0 under Bazel has a regression on Windows that causes build errors on rebuilds:
|
# yarn 1.13.0 under Bazel has a regression on Windows that causes build errors on rebuilds:
|
||||||
# ```
|
# ```
|
||||||
# ERROR: Source forest creation failed: C:/.../fyuc5c3n/execroot/angular/external (Directory not empty)
|
# ERROR: Source forest creation failed: C:/.../fyuc5c3n/execroot/angular/external (Directory not empty)
|
||||||
@ -73,7 +76,7 @@ node_repositories(
|
|||||||
# It possible that versions of yarn past 1.13.0 do not have this issue, however, before
|
# It possible that versions of yarn past 1.13.0 do not have this issue, however, before
|
||||||
# advancing this version we need to test manually on Windows that the above error does not
|
# advancing this version we need to test manually on Windows that the above error does not
|
||||||
# happen as the issue is not caught by CI.
|
# happen as the issue is not caught by CI.
|
||||||
yarn_version = "1.12.1",
|
yarn_version = "1.17.3",
|
||||||
)
|
)
|
||||||
|
|
||||||
yarn_install(
|
yarn_install(
|
||||||
|
@ -18,7 +18,7 @@ Here are the most important tasks you might need to use:
|
|||||||
|
|
||||||
* `yarn build` - create a production build of the application (after installing dependencies, boilerplate, etc).
|
* `yarn build` - create a production build of the application (after installing dependencies, boilerplate, etc).
|
||||||
* `yarn build-local` - same as `build`, but use `setup-local` instead of `setup`.
|
* `yarn build-local` - same as `build`, but use `setup-local` instead of `setup`.
|
||||||
* `yarn build-with-ivy` - same as `build-local`, but in addition also turns on `ivy` mode in aio.
|
* `yarn build-local-with-ivy` - same as `build-local`, but in addition also turns on `ivy` mode in aio.
|
||||||
(Note: To turn on `ivy` mode in examples, see `yarn boilerplate:add` below.)
|
(Note: To turn on `ivy` mode in examples, see `yarn boilerplate:add` below.)
|
||||||
|
|
||||||
* `yarn start` - run a development web server that watches the files; then builds the doc-viewer and reloads the page, as necessary.
|
* `yarn start` - run a development web server that watches the files; then builds the doc-viewer and reloads the page, as necessary.
|
||||||
@ -34,18 +34,28 @@ Here are the most important tasks you might need to use:
|
|||||||
* `yarn docs-test` - run the unit tests for the doc generation code.
|
* `yarn docs-test` - run the unit tests for the doc generation code.
|
||||||
|
|
||||||
* `yarn boilerplate:add` - generate all the boilerplate code for the examples, so that they can be run locally.
|
* `yarn boilerplate:add` - generate all the boilerplate code for the examples, so that they can be run locally.
|
||||||
- Add the option `--local` to use your local version of Angular contained in the "dist" folder.
|
* `yarn boilerplate:add:ivy` - same as `boilerplate:add` but also turns on `ivy` mode.
|
||||||
- Add the option `--ivy` to turn on `ivy` mode.
|
|
||||||
|
|
||||||
* `yarn boilerplate:remove` - remove all the boilerplate code that was added via `yarn boilerplate:add`.
|
* `yarn boilerplate:remove` - remove all the boilerplate code that was added via `yarn boilerplate:add`.
|
||||||
* `yarn generate-stackblitz` - generate the stackblitz files that are used by the `live-example` tags in the docs.
|
* `yarn generate-stackblitz` - generate the stackblitz files that are used by the `live-example` tags in the docs.
|
||||||
* `yarn generate-zips` - generate the zip files from the examples. Zip available via the `live-example` tags in the docs.
|
* `yarn generate-zips` - generate the zip files from the examples. Zip available via the `live-example` tags in the docs.
|
||||||
|
|
||||||
* `yarn example-e2e` - run all e2e tests for examples
|
* `yarn example-e2e` - run all e2e tests for examples. Available options:
|
||||||
- `yarn example-e2e --setup` - force webdriver update & other setup, then run tests
|
- `--setup`: generate boilerplate, force webdriver update & other setup, then run tests.
|
||||||
- `yarn example-e2e --filter=foo` - limit e2e tests to those containing the word "foo"
|
- `--local`: run e2e tests with the local version of Angular contained in the "dist" folder.
|
||||||
- `yarn example-e2e --setup --local` - run e2e tests with the local version of Angular contained in the "dist" folder
|
_Requires `--setup` in order to take effect._
|
||||||
|
- `--ivy`: run e2e tests in `ivy` mode.
|
||||||
|
- `--filter=foo`: limit e2e tests to those containing the word "foo".
|
||||||
|
|
||||||
|
> **Note for Windows users**
|
||||||
|
>
|
||||||
|
> Setting up the examples involves creating some [symbolic links](https://en.wikipedia.org/wiki/Symbolic_link) (see [here](./tools/examples/README.md#symlinked-node_modules) for details). On Windows, this requires to either have [Developer Mode enabled](https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10) (supported on Windows 10 or newer) or run the setup commands as administrator.
|
||||||
|
>
|
||||||
|
> The affected commands are:
|
||||||
|
> - `yarn setup` / `yarn setup-*`
|
||||||
|
> - `yarn build` / `yarn build-*`
|
||||||
|
> - `yarn boilerplate:add`
|
||||||
|
> - `yarn example-e2e --setup`
|
||||||
|
|
||||||
## Using ServiceWorker locally
|
## Using ServiceWorker locally
|
||||||
|
|
||||||
|
21
aio/content/examples/accessibility/e2e/src/app.e2e-spec.ts
Normal file
21
aio/content/examples/accessibility/e2e/src/app.e2e-spec.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
|
describe('Accessibility example e2e tests', () => {
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display Accessibility Example', function () {
|
||||||
|
expect(element(by.css('h1')).getText()).toEqual('Accessibility Example');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should take a number and change progressbar width', function () {
|
||||||
|
element(by.css('input')).sendKeys('16');
|
||||||
|
expect(element(by.css('input')).getAttribute('value')).toEqual('016');
|
||||||
|
expect(element(by.css('app-example-progressbar div')).getCssValue('width')).toBe('48px');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
0
aio/content/examples/accessibility/src/app/app.component.css
Executable file
0
aio/content/examples/accessibility/src/app/app.component.css
Executable file
13
aio/content/examples/accessibility/src/app/app.component.html
Executable file
13
aio/content/examples/accessibility/src/app/app.component.html
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
<h1>Accessibility Example</h1>
|
||||||
|
<!-- #docregion template -->
|
||||||
|
<label>
|
||||||
|
Enter an example progress value
|
||||||
|
<input type="number" min="0" max="100"
|
||||||
|
[value]="progress" (input)="progress = $event.target.value">
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<!-- The user of the progressbar sets an aria-label to communicate what the progress means. -->
|
||||||
|
<app-example-progressbar [value]="progress" aria-label="Example of a progress bar">
|
||||||
|
</app-example-progressbar>
|
||||||
|
<!-- #enddocregion template -->
|
||||||
|
|
10
aio/content/examples/accessibility/src/app/app.component.ts
Executable file
10
aio/content/examples/accessibility/src/app/app.component.ts
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styleUrls: [ './app.component.css' ]
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
progress = 0;
|
||||||
|
}
|
12
aio/content/examples/accessibility/src/app/app.module.ts
Executable file
12
aio/content/examples/accessibility/src/app/app.module.ts
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
import { ExampleProgressbarComponent } from './progress-bar.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [ BrowserModule ],
|
||||||
|
declarations: [ AppComponent, ExampleProgressbarComponent ],
|
||||||
|
bootstrap: [ AppComponent ]
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
12
aio/content/examples/accessibility/src/app/progress-bar.component.css
Executable file
12
aio/content/examples/accessibility/src/app/progress-bar.component.css
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
width: 300px;
|
||||||
|
height: 25px;
|
||||||
|
border: 1px solid black;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bar {
|
||||||
|
background: blue;
|
||||||
|
height: 100%;
|
||||||
|
}
|
28
aio/content/examples/accessibility/src/app/progress-bar.component.ts
Executable file
28
aio/content/examples/accessibility/src/app/progress-bar.component.ts
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
// #docregion progressbar-component
|
||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example progressbar component.
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'app-example-progressbar',
|
||||||
|
template: `<div class="bar" [style.width.%]="value"></div>`,
|
||||||
|
styleUrls: ['./progress-bar.component.css'],
|
||||||
|
host: {
|
||||||
|
// Sets the role for this component to "progressbar"
|
||||||
|
role: 'progressbar',
|
||||||
|
|
||||||
|
// Sets the minimum and maximum values for the progressbar role.
|
||||||
|
'aria-valuemin': '0',
|
||||||
|
'aria-valuemax': '100',
|
||||||
|
|
||||||
|
// Binding that updates the current value of the progressbar.
|
||||||
|
'[attr.aria-valuenow]': 'value',
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export class ExampleProgressbarComponent {
|
||||||
|
/** Current value of the progressbar. */
|
||||||
|
@Input() value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #enddocregion progressbar-component
|
14
aio/content/examples/accessibility/src/index.html
Normal file
14
aio/content/examples/accessibility/src/index.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Accessibility Example</title>
|
||||||
|
<base href="/">
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<app-root>Loading...</app-root>
|
||||||
|
</body>
|
||||||
|
</html>
|
11
aio/content/examples/accessibility/src/main.ts
Normal file
11
aio/content/examples/accessibility/src/main.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { enableProdMode } from '@angular/core';
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
|
||||||
|
import { AppModule } from './app/app.module';
|
||||||
|
import { environment } from './environments/environment';
|
||||||
|
|
||||||
|
if (environment.production) {
|
||||||
|
enableProdMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
platformBrowserDynamic().bootstrapModule(AppModule);
|
10
aio/content/examples/accessibility/stackblitz.json
Normal file
10
aio/content/examples/accessibility/stackblitz.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"description": "Accessibility",
|
||||||
|
"files": [
|
||||||
|
"!**/*.d.ts",
|
||||||
|
"!**/*.js",
|
||||||
|
"!**/*.[1,2].*"
|
||||||
|
],
|
||||||
|
"file": "src/app/app.component.ts",
|
||||||
|
"tags": ["Accessibility"]
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion imports
|
// #docregion imports
|
||||||
import { Component } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { CartService } from '../cart.service';
|
import { CartService } from '../cart.service';
|
||||||
// #enddocregion imports
|
// #enddocregion imports
|
||||||
|
|
||||||
@ -10,12 +10,14 @@ import { CartService } from '../cart.service';
|
|||||||
styleUrls: ['./cart.component.css']
|
styleUrls: ['./cart.component.css']
|
||||||
})
|
})
|
||||||
// #docregion props-services, submit
|
// #docregion props-services, submit
|
||||||
export class CartComponent {
|
export class CartComponent implements OnInit {
|
||||||
items;
|
items;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private cartService: CartService
|
private cartService: CartService
|
||||||
) {
|
) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
this.items = this.cartService.getItems();
|
this.items = this.cartService.getItems();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion imports
|
// #docregion imports
|
||||||
import { Component } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
import { CartService } from '../cart.service';
|
import { CartService } from '../cart.service';
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
@ -11,7 +11,7 @@ import { CartService } from '../cart.service';
|
|||||||
styleUrls: ['./shipping.component.css']
|
styleUrls: ['./shipping.component.css']
|
||||||
})
|
})
|
||||||
// #docregion props, ctor
|
// #docregion props, ctor
|
||||||
export class ShippingComponent {
|
export class ShippingComponent implements OnInit {
|
||||||
shippingCosts;
|
shippingCosts;
|
||||||
// #enddocregion props
|
// #enddocregion props
|
||||||
|
|
||||||
@ -19,10 +19,12 @@ export class ShippingComponent {
|
|||||||
constructor(
|
constructor(
|
||||||
private cartService: CartService
|
private cartService: CartService
|
||||||
) {
|
) {
|
||||||
// #enddocregion inject-cart-service
|
|
||||||
this.shippingCosts = this.cartService.getShippingPrices();
|
|
||||||
// #docregion inject-cart-service
|
|
||||||
}
|
}
|
||||||
// #enddocregion inject-cart-service
|
// #enddocregion inject-cart-service
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.shippingCosts = this.cartService.getShippingPrices();
|
||||||
|
}
|
||||||
|
|
||||||
// #docregion props
|
// #docregion props
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<h1>HTTP Sample</h1>
|
<h1>HTTP Sample</h1>
|
||||||
<div>
|
<div>
|
||||||
<input type="checkbox" id="heroes" [checked]="toggleHeroes" (click)="toggleHeroes()">
|
<input type="checkbox" id="heroes" [checked]="showHeroes" (click)="toggleHeroes()">
|
||||||
<label for="heroes">Heroes</label>
|
<label for="heroes">Heroes</label>
|
||||||
|
|
||||||
<input type="checkbox" id="config" [checked]="showConfig" (click)="toggleConfig()">
|
<input type="checkbox" id="config" [checked]="showConfig" (click)="toggleConfig()">
|
||||||
|
@ -12,7 +12,7 @@ if (environment.production) {
|
|||||||
// use the require method provided by webpack
|
// use the require method provided by webpack
|
||||||
declare const require;
|
declare const require;
|
||||||
// we use the webpack raw-loader to return the content as a string
|
// we use the webpack raw-loader to return the content as a string
|
||||||
const translations = require(`raw-loader!./locale/messages.fr.xlf`);
|
const translations = require('raw-loader!./locale/messages.fr.xlf').default;
|
||||||
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule, {
|
platformBrowserDynamic().bootstrapModule(AppModule, {
|
||||||
providers: [
|
providers: [
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
import { browser, element, by } from 'protractor';
|
||||||
|
import { logging } from 'selenium-webdriver';
|
||||||
|
|
||||||
|
describe('Providers and ViewProviders', function () {
|
||||||
|
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows basic flower emoji', function() {
|
||||||
|
expect(element.all(by.css('p')).get(0).getText()).toContain('🌺');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows whale emoji', function() {
|
||||||
|
expect(element.all(by.css('p')).get(1).getText()).toContain('🐳');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows sunflower from FlowerService', function() {
|
||||||
|
expect(element.all(by.css('p')).get(8).getText()).toContain('🌻');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
10
aio/content/examples/providers-viewproviders/src/app/animal.service.ts
Executable file
10
aio/content/examples/providers-viewproviders/src/app/animal.service.ts
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
// #docregion animal-service
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class AnimalService {
|
||||||
|
emoji = '🐳';
|
||||||
|
}
|
||||||
|
// #enddocregion animal-service
|
@ -0,0 +1,15 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { FlowerService } from './flower.service';
|
||||||
|
import { AnimalService } from './animal.service';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styleUrls: [ './app.component.css' ]
|
||||||
|
})
|
||||||
|
// #docregion injection
|
||||||
|
export class AppComponent {
|
||||||
|
constructor(public flower: FlowerService) {}
|
||||||
|
}
|
||||||
|
// #enddocregion injection
|
15
aio/content/examples/providers-viewproviders/src/app/app.component.html
Executable file
15
aio/content/examples/providers-viewproviders/src/app/app.component.html
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
<h2>From AppComponent:</h2>
|
||||||
|
<!-- #docregion binding-flower -->
|
||||||
|
<p>Emoji from FlowerService: {{flower.emoji}}</p>
|
||||||
|
<!-- #enddocregion binding-flower -->
|
||||||
|
<!-- #docregion binding-animal -->
|
||||||
|
<p>Emoji from AnimalService: {{animal.emoji}}</p>
|
||||||
|
<!-- #enddocregion binding-animal -->
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<h2>From ChildComponent:</h2>
|
||||||
|
<!-- #docregion content-projection -->
|
||||||
|
<app-child><app-inspector></app-inspector></app-child>
|
||||||
|
<!-- #enddocregion content-projection -->
|
31
aio/content/examples/providers-viewproviders/src/app/app.component.ts
Executable file
31
aio/content/examples/providers-viewproviders/src/app/app.component.ts
Executable file
@ -0,0 +1,31 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { FlowerService } from './flower.service';
|
||||||
|
import { AnimalService } from './animal.service';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styleUrls: [ './app.component.css' ]
|
||||||
|
})
|
||||||
|
// #docregion inject-animal-service
|
||||||
|
export class AppComponent {
|
||||||
|
constructor(public flower: FlowerService, public animal: AnimalService) {}
|
||||||
|
}
|
||||||
|
// #enddocregion inject-animal-service
|
||||||
|
|
||||||
|
// When using @Host() together with @SkipSelf() in
|
||||||
|
// child.component.ts for the AnimalService, add the
|
||||||
|
// following viewProviders array to the @Component metadata:
|
||||||
|
|
||||||
|
// viewProviders: [{ provide: AnimalService, useValue: { emoji: '🦔' } }]
|
||||||
|
|
||||||
|
// So, the entire @ChildComponent() decorator and its
|
||||||
|
// metadata should be as follows:
|
||||||
|
|
||||||
|
// @Component({
|
||||||
|
// selector: 'app-root',
|
||||||
|
// templateUrl: './app.component.html',
|
||||||
|
// styleUrls: [ './app.component.css' ],
|
||||||
|
// viewProviders: [{ provide: AnimalService, useValue: { emoji: '🦔' } }]
|
||||||
|
// })
|
17
aio/content/examples/providers-viewproviders/src/app/app.module.ts
Executable file
17
aio/content/examples/providers-viewproviders/src/app/app.module.ts
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
import { ChildComponent } from './child/child.component';
|
||||||
|
import { InspectorComponent } from './inspector/inspector.component';
|
||||||
|
|
||||||
|
// #docregion appmodule
|
||||||
|
@NgModule({
|
||||||
|
imports: [ BrowserModule, FormsModule ],
|
||||||
|
declarations: [ AppComponent, ChildComponent, InspectorComponent ],
|
||||||
|
bootstrap: [ AppComponent ],
|
||||||
|
providers: []
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
||||||
|
// #enddocregion appmodule
|
@ -0,0 +1,19 @@
|
|||||||
|
import { Component, OnInit, Host, SkipSelf, Optional } from '@angular/core';
|
||||||
|
import { FlowerService } from '../flower.service';
|
||||||
|
|
||||||
|
// #docregion flowerservice
|
||||||
|
@Component({
|
||||||
|
selector: 'app-child',
|
||||||
|
templateUrl: './child.component.html',
|
||||||
|
styleUrls: ['./child.component.css'],
|
||||||
|
// use the providers array to provide a service
|
||||||
|
providers: [{ provide: FlowerService, useValue: { emoji: '🌻' } }]
|
||||||
|
})
|
||||||
|
|
||||||
|
export class ChildComponent {
|
||||||
|
// inject the service
|
||||||
|
constructor( public flower: FlowerService) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
// #enddocregion flowerservice
|
||||||
|
|
@ -0,0 +1,4 @@
|
|||||||
|
.container {
|
||||||
|
border: 1px solid darkblue;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
<!-- #docplaster -->
|
||||||
|
<!-- #docregion child-component -->
|
||||||
|
<!-- #docregion flower-binding -->
|
||||||
|
<p>Emoji from FlowerService: {{flower.emoji}}</p>
|
||||||
|
<!-- #enddocregion flower-binding -->
|
||||||
|
<!-- #docregion animal-binding -->
|
||||||
|
<p>Emoji from AnimalService: {{animal.emoji}}</p>
|
||||||
|
<!-- #enddocregion animal-binding -->
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h3>Content projection</h3>
|
||||||
|
<!-- #enddocregion child-component -->
|
||||||
|
<p>The following is coming from content. It doesn't get to see the puppy because the puppy is declared inside the view only.</p>
|
||||||
|
<!-- #docregion child-component -->
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>Inside the view</h3>
|
||||||
|
<!-- #enddocregion child-component -->
|
||||||
|
<p>The following is inside the view so it does see the puppy.</p>
|
||||||
|
<!-- #docregion child-component -->
|
||||||
|
<app-inspector></app-inspector>
|
||||||
|
<!-- #enddocregion child-component -->
|
||||||
|
|
@ -0,0 +1,44 @@
|
|||||||
|
// #docplaster
|
||||||
|
import { Component, OnInit, Host, SkipSelf, Optional } from '@angular/core';
|
||||||
|
import { FlowerService } from '../flower.service';
|
||||||
|
import { AnimalService } from '../animal.service';
|
||||||
|
|
||||||
|
// #docregion provide-animal-service
|
||||||
|
@Component({
|
||||||
|
selector: 'app-child',
|
||||||
|
templateUrl: './child.component.html',
|
||||||
|
styleUrls: ['./child.component.css'],
|
||||||
|
// provide services
|
||||||
|
providers: [{ provide: FlowerService, useValue: { emoji: '🌻' } }],
|
||||||
|
viewProviders: [{ provide: AnimalService, useValue: { emoji: '🐶' } }]
|
||||||
|
})
|
||||||
|
|
||||||
|
export class ChildComponent {
|
||||||
|
// inject service
|
||||||
|
constructor( public flower: FlowerService, public animal: AnimalService) { }
|
||||||
|
// #enddocregion provide-animal-service
|
||||||
|
|
||||||
|
// viewProviders ensures that only the view gets to see this.
|
||||||
|
// With the AnimalService in the viewProviders, the
|
||||||
|
// InspectorComponent doesn't get to see it because the
|
||||||
|
// inspector is in the content.
|
||||||
|
|
||||||
|
|
||||||
|
// constructor( public flower: FlowerService, @Optional() @Host() public animal: AnimalService) { }
|
||||||
|
|
||||||
|
// Comment out the above constructor and alternately
|
||||||
|
// uncomment the two following constructors to see the
|
||||||
|
// effects of @Host() and @Host() + @SkipSelf().
|
||||||
|
|
||||||
|
// constructor(
|
||||||
|
// @Host() public animal : AnimalService,
|
||||||
|
// @Host() @Optional() public flower : FlowerService) { }
|
||||||
|
|
||||||
|
// constructor(
|
||||||
|
// @SkipSelf() @Host() public animal : AnimalService,
|
||||||
|
// @SkipSelf() @Host() @Optional() public flower : FlowerService) { }
|
||||||
|
|
||||||
|
// #docregion provide-animal-service
|
||||||
|
}
|
||||||
|
// #enddocregion provide-animal-service
|
||||||
|
|
11
aio/content/examples/providers-viewproviders/src/app/flower.service.ts
Executable file
11
aio/content/examples/providers-viewproviders/src/app/flower.service.ts
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion flowerservice
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class FlowerService {
|
||||||
|
emoji = '🌺';
|
||||||
|
}
|
||||||
|
// #enddocregion flowerservice
|
||||||
|
|
@ -0,0 +1,4 @@
|
|||||||
|
<!-- #docregion binding -->
|
||||||
|
<p>Emoji from FlowerService: {{flower.emoji}}</p>
|
||||||
|
<p>Emoji from AnimalService: {{animal.emoji}}</p>
|
||||||
|
<!-- #enddocregion binding -->
|
@ -0,0 +1,14 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { FlowerService } from '../flower.service';
|
||||||
|
import { AnimalService } from '../animal.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-inspector',
|
||||||
|
templateUrl: './inspector.component.html',
|
||||||
|
styleUrls: ['./inspector.component.css']
|
||||||
|
})
|
||||||
|
// #docregion injection
|
||||||
|
export class InspectorComponent {
|
||||||
|
constructor(public flower: FlowerService, public animal: AnimalService) { }
|
||||||
|
}
|
||||||
|
// #enddocregion injection
|
14
aio/content/examples/providers-viewproviders/src/index.html
Normal file
14
aio/content/examples/providers-viewproviders/src/index.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>providers vs. viewProviders</title>
|
||||||
|
<base href="/">
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<app-root></app-root>
|
||||||
|
</body>
|
||||||
|
</html>
|
12
aio/content/examples/providers-viewproviders/src/main.ts
Normal file
12
aio/content/examples/providers-viewproviders/src/main.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { enableProdMode } from '@angular/core';
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
|
||||||
|
import { AppModule } from './app/app.module';
|
||||||
|
import { environment } from './environments/environment';
|
||||||
|
|
||||||
|
if (environment.production) {
|
||||||
|
enableProdMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
platformBrowserDynamic().bootstrapModule(AppModule)
|
||||||
|
.catch(err => console.log(err));
|
10
aio/content/examples/providers-viewproviders/stackblitz.json
Normal file
10
aio/content/examples/providers-viewproviders/stackblitz.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"description": "Inputs and Outputs",
|
||||||
|
"files": [
|
||||||
|
"!**/*.d.ts",
|
||||||
|
"!**/*.js",
|
||||||
|
"!**/*.[1,2].*"
|
||||||
|
],
|
||||||
|
"file": "src/app/app.component.ts",
|
||||||
|
"tags": ["Inputs and Outputs"]
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
|
describe('Resolution-modifiers-example', function () {
|
||||||
|
|
||||||
|
beforeAll(function () {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows basic flower emoji', function() {
|
||||||
|
expect(element.all(by.css('p')).get(0).getText()).toContain('🌸');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows basic leaf emoji', function() {
|
||||||
|
expect(element.all(by.css('p')).get(1).getText()).toContain('🌿');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows yellow flower in host child', function() {
|
||||||
|
expect(element.all(by.css('p')).get(9).getText()).toContain('🌼');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
0
aio/content/examples/resolution-modifiers/src/app/app.component.css
Executable file
0
aio/content/examples/resolution-modifiers/src/app/app.component.css
Executable file
14
aio/content/examples/resolution-modifiers/src/app/app.component.html
Executable file
14
aio/content/examples/resolution-modifiers/src/app/app.component.html
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
<h1>DI resolution modifiers</h1>
|
||||||
|
|
||||||
|
<p>Basic flower service: {{flower.emoji}}</p>
|
||||||
|
<p>Basic leaf service: {{leaf.emoji}}</p>
|
||||||
|
|
||||||
|
<app-optional></app-optional>
|
||||||
|
|
||||||
|
<app-self></app-self>
|
||||||
|
|
||||||
|
<app-self-no-data></app-self-no-data>
|
||||||
|
|
||||||
|
<app-skipself></app-skipself>
|
||||||
|
|
||||||
|
<app-host-parent></app-host-parent>
|
13
aio/content/examples/resolution-modifiers/src/app/app.component.ts
Executable file
13
aio/content/examples/resolution-modifiers/src/app/app.component.ts
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { LeafService } from './leaf.service';
|
||||||
|
import { FlowerService } from './flower.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styleUrls: [ './app.component.css' ]
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
name = 'Angular';
|
||||||
|
constructor(public flower: FlowerService, public leaf: LeafService) {}
|
||||||
|
}
|
33
aio/content/examples/resolution-modifiers/src/app/app.module.ts
Executable file
33
aio/content/examples/resolution-modifiers/src/app/app.module.ts
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
;
|
||||||
|
import { OptionalComponent } from './optional/optional.component';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
import { SelfNoDataComponent } from './self-no-data/self-no-data.component';
|
||||||
|
import { HostComponent } from './host/host.component';
|
||||||
|
import { SelfComponent } from './self/self.component';
|
||||||
|
import { SkipselfComponent } from './skipself/skipself.component';
|
||||||
|
import { HostParentComponent } from './host-parent/host-parent.component';
|
||||||
|
import { HostChildComponent } from './host-child/host-child.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
BrowserModule,
|
||||||
|
FormsModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
AppComponent,
|
||||||
|
OptionalComponent,
|
||||||
|
SelfComponent,
|
||||||
|
SelfNoDataComponent,
|
||||||
|
HostComponent,
|
||||||
|
SkipselfComponent,
|
||||||
|
HostParentComponent,
|
||||||
|
HostChildComponent
|
||||||
|
],
|
||||||
|
bootstrap: [AppComponent],
|
||||||
|
providers: []
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
9
aio/content/examples/resolution-modifiers/src/app/flower.service.ts
Executable file
9
aio/content/examples/resolution-modifiers/src/app/flower.service.ts
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root' // provide this service in the root ModuleInjector
|
||||||
|
|
||||||
|
})
|
||||||
|
export class FlowerService {
|
||||||
|
emoji = '🌸';
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
.section {
|
||||||
|
border: 2px solid #369;
|
||||||
|
padding: 1rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
<div class="section">
|
||||||
|
<h2>Child of @Host() Component</h2>
|
||||||
|
<p>Flower emoji: {{flower.emoji}}</p>
|
||||||
|
</div>
|
@ -0,0 +1,11 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { FlowerService } from '../flower.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-host-child',
|
||||||
|
templateUrl: './host-child.component.html',
|
||||||
|
styleUrls: ['./host-child.component.css']
|
||||||
|
})
|
||||||
|
export class HostChildComponent {
|
||||||
|
constructor(public flower: FlowerService) { }
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
.section {
|
||||||
|
border: 2px solid #369;
|
||||||
|
padding: 1rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
<div class="section">
|
||||||
|
<h2>Parent of @Host() Component</h2>
|
||||||
|
<p>Flower emoji: {{flower.emoji}}</p>
|
||||||
|
<app-host></app-host>
|
||||||
|
</div>
|
@ -0,0 +1,16 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { FlowerService } from '../flower.service';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-host-parent',
|
||||||
|
templateUrl: './host-parent.component.html',
|
||||||
|
styleUrls: ['./host-parent.component.css'],
|
||||||
|
providers: [{ provide: FlowerService, useValue: { emoji: '🌺' } }]
|
||||||
|
|
||||||
|
})
|
||||||
|
export class HostParentComponent {
|
||||||
|
|
||||||
|
constructor(public flower: FlowerService) { }
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
.section {
|
||||||
|
border: 2px solid #369;
|
||||||
|
padding: 1rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
<div class="section">
|
||||||
|
<h2>@Host() Component</h2>
|
||||||
|
<p>Flower emoji: {{flower.emoji}}</p>
|
||||||
|
<p><i>(@Host() stops it here)</i></p>
|
||||||
|
<app-host-child></app-host-child>
|
||||||
|
</div>
|
21
aio/content/examples/resolution-modifiers/src/app/host/host.component.ts
Executable file
21
aio/content/examples/resolution-modifiers/src/app/host/host.component.ts
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
import { Component, Host, Optional } from '@angular/core';
|
||||||
|
import { FlowerService } from '../flower.service';
|
||||||
|
|
||||||
|
// #docregion host-component
|
||||||
|
@Component({
|
||||||
|
selector: 'app-host',
|
||||||
|
templateUrl: './host.component.html',
|
||||||
|
styleUrls: ['./host.component.css'],
|
||||||
|
// provide the service
|
||||||
|
providers: [{ provide: FlowerService, useValue: { emoji: '🌼' } }]
|
||||||
|
})
|
||||||
|
export class HostComponent {
|
||||||
|
// use @Host() in the constructor when injecting the service
|
||||||
|
constructor(@Host() @Optional() public flower: FlowerService) { }
|
||||||
|
|
||||||
|
}
|
||||||
|
// #enddocregion host-component
|
||||||
|
|
||||||
|
// if you take out @Host() and the providers array, flower will be red hibiscus
|
||||||
|
|
||||||
|
|
11
aio/content/examples/resolution-modifiers/src/app/leaf.service.ts
Executable file
11
aio/content/examples/resolution-modifiers/src/app/leaf.service.ts
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
// #docregion leafservice
|
||||||
|
export class LeafService {
|
||||||
|
emoji = '🌿';
|
||||||
|
}
|
||||||
|
// #enddocregion leafservice
|
||||||
|
|
7
aio/content/examples/resolution-modifiers/src/app/optional.service.ts
Executable file
7
aio/content/examples/resolution-modifiers/src/app/optional.service.ts
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class OptionalService {
|
||||||
|
}
|
||||||
|
|
||||||
|
// This service isn't provided anywhere.
|
@ -0,0 +1,5 @@
|
|||||||
|
.section {
|
||||||
|
border: 2px solid #369;
|
||||||
|
padding: 1rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
<div class="section">
|
||||||
|
<h2>@Optional() Component</h2>
|
||||||
|
<p>This component still works even though the OptionalService (notice @Optional() in the consturctor isn't provided or configured anywhere. Angular goes through tree and visibilty rules, and if it doesn't find the requested service, returns null.</p>
|
||||||
|
</div>
|
@ -0,0 +1,21 @@
|
|||||||
|
import { Component, Optional } from '@angular/core';
|
||||||
|
import { OptionalService } from '../optional.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-optional',
|
||||||
|
templateUrl: './optional.component.html',
|
||||||
|
styleUrls: ['./optional.component.css']
|
||||||
|
})
|
||||||
|
|
||||||
|
// #docregion optional-component
|
||||||
|
export class OptionalComponent {
|
||||||
|
constructor(@Optional() public optional: OptionalService) {}
|
||||||
|
}
|
||||||
|
// #enddocregion optional-component
|
||||||
|
|
||||||
|
// The OptionalService isn't provided here, in the @Injectable()
|
||||||
|
// providers array, or in the NgModule. If you remove @Optional()
|
||||||
|
// from the constructor, you'll get an error.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
|||||||
|
.section {
|
||||||
|
border: 2px solid #369;
|
||||||
|
padding: 1rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
<div class="section">
|
||||||
|
<h2>@Self() Component (without a provider)</h2>
|
||||||
|
<p>Leaf emoji: {{leaf?.emoji}}</p>
|
||||||
|
</div>
|
@ -0,0 +1,18 @@
|
|||||||
|
import { Component, Self, Optional } from '@angular/core';
|
||||||
|
import { LeafService } from '../leaf.service';
|
||||||
|
|
||||||
|
// #docregion self-no-data-component
|
||||||
|
@Component({
|
||||||
|
selector: 'app-self-no-data',
|
||||||
|
templateUrl: './self-no-data.component.html',
|
||||||
|
styleUrls: ['./self-no-data.component.css']
|
||||||
|
})
|
||||||
|
export class SelfNoDataComponent {
|
||||||
|
constructor(@Self() @Optional() public leaf: LeafService) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
// #enddocregion self-no-data-component
|
||||||
|
|
||||||
|
// The app doesn't break because the value being available at self is optional.
|
||||||
|
// If you remove @Optional(), the app breaks.
|
||||||
|
|
@ -0,0 +1,5 @@
|
|||||||
|
.section {
|
||||||
|
border: 2px solid #369;
|
||||||
|
padding: 1rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
<div class="section">
|
||||||
|
<h2>@Self() Component</h2>
|
||||||
|
<p>Flower emoji: {{flower?.emoji}}</p>
|
||||||
|
</div>
|
19
aio/content/examples/resolution-modifiers/src/app/self/self.component.ts
Executable file
19
aio/content/examples/resolution-modifiers/src/app/self/self.component.ts
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
import { Component, Self } from '@angular/core';
|
||||||
|
import { FlowerService } from '../flower.service';
|
||||||
|
|
||||||
|
// #docregion self-component
|
||||||
|
@Component({
|
||||||
|
selector: 'app-self',
|
||||||
|
templateUrl: './self.component.html',
|
||||||
|
styleUrls: ['./self.component.css'],
|
||||||
|
providers: [{ provide: FlowerService, useValue: { emoji: '🌼' } }]
|
||||||
|
|
||||||
|
})
|
||||||
|
export class SelfComponent {
|
||||||
|
constructor(@Self() public flower: FlowerService) {}
|
||||||
|
}
|
||||||
|
// #enddocregion self-component
|
||||||
|
|
||||||
|
// This component provides the FlowerService so the injector
|
||||||
|
// doesn't have to look further up the injector tree
|
||||||
|
|
@ -0,0 +1,5 @@
|
|||||||
|
.section {
|
||||||
|
border: 2px solid #369;
|
||||||
|
padding: 1rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
<div class="section">
|
||||||
|
<h2>@SkipSelf() Component</h2>
|
||||||
|
<p>Leaf emoji: {{leaf.emoji}}</p>
|
||||||
|
</div>
|
@ -0,0 +1,18 @@
|
|||||||
|
import { Component, SkipSelf } from '@angular/core';
|
||||||
|
import { LeafService } from '../leaf.service';
|
||||||
|
|
||||||
|
// #docregion skipself-component
|
||||||
|
@Component({
|
||||||
|
selector: 'app-skipself',
|
||||||
|
templateUrl: './skipself.component.html',
|
||||||
|
styleUrls: ['./skipself.component.css'],
|
||||||
|
// Angular would ignore this LeafService instance
|
||||||
|
providers: [{ provide: LeafService, useValue: { emoji: '🍁' } }]
|
||||||
|
})
|
||||||
|
export class SkipselfComponent {
|
||||||
|
// Use @SkipSelf() in the constructor
|
||||||
|
constructor(@SkipSelf() public leaf: LeafService) { }
|
||||||
|
}
|
||||||
|
// #enddocregion skipself-component
|
||||||
|
|
||||||
|
// @SkipSelf(): Specifies that the dependency resolution should start from the parent injector, not here.
|
14
aio/content/examples/resolution-modifiers/src/index.html
Normal file
14
aio/content/examples/resolution-modifiers/src/index.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>DI Resolution Modifiers Example</title>
|
||||||
|
<base href="/">
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<app-root>Loading...</app-root>
|
||||||
|
</body>
|
||||||
|
</html>
|
11
aio/content/examples/resolution-modifiers/src/main.ts
Normal file
11
aio/content/examples/resolution-modifiers/src/main.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { enableProdMode } from '@angular/core';
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
|
||||||
|
import { AppModule } from './app/app.module';
|
||||||
|
import { environment } from './environments/environment';
|
||||||
|
|
||||||
|
if (environment.production) {
|
||||||
|
enableProdMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
platformBrowserDynamic().bootstrapModule(AppModule);
|
10
aio/content/examples/resolution-modifiers/stackblitz.json
Normal file
10
aio/content/examples/resolution-modifiers/stackblitz.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"description": "NgModules",
|
||||||
|
"files": [
|
||||||
|
"!**/*.d.ts",
|
||||||
|
"!**/*.js",
|
||||||
|
"!**/*.[1,2].*"
|
||||||
|
],
|
||||||
|
"file": "src/app/app.component.ts",
|
||||||
|
"tags": ["NgModules"]
|
||||||
|
}
|
@ -12,7 +12,7 @@ import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
|
|||||||
* then the templated elements are removed removed from the DOM,
|
* then the templated elements are removed removed from the DOM,
|
||||||
* the templated elements are (re)inserted into the DOM.
|
* the templated elements are (re)inserted into the DOM.
|
||||||
*
|
*
|
||||||
* <div *ngUnless="errorCount" class="success">
|
* <div *appUnless="errorCount" class="success">
|
||||||
* Congrats! Everything is great!
|
* Congrats! Everything is great!
|
||||||
* </div>
|
* </div>
|
||||||
*
|
*
|
||||||
|
@ -206,6 +206,7 @@ function heroModuleSetup() {
|
|||||||
nameInput.value = 'quick BROWN fOx';
|
nameInput.value = 'quick BROWN fOx';
|
||||||
|
|
||||||
// dispatch a DOM event so that Angular learns of input value change.
|
// dispatch a DOM event so that Angular learns of input value change.
|
||||||
|
// use newEvent utility function (not provided by Angular) for better browser compatibility
|
||||||
nameInput.dispatchEvent(newEvent('input'));
|
nameInput.dispatchEvent(newEvent('input'));
|
||||||
|
|
||||||
// Tell Angular to update the display binding through the title pipe
|
// Tell Angular to update the display binding through the title pipe
|
||||||
|
@ -28,7 +28,7 @@ export class KeyUpComponent_v1 {
|
|||||||
// #docregion key-up-component-1-class
|
// #docregion key-up-component-1-class
|
||||||
|
|
||||||
onKey(event: KeyboardEvent) { // with type info
|
onKey(event: KeyboardEvent) { // with type info
|
||||||
this.values += (<HTMLInputElement>event.target).value + ' | ';
|
this.values += (event.target as HTMLInputElement).value + ' | ';
|
||||||
}
|
}
|
||||||
// #docregion key-up-component-1-class-no-type
|
// #docregion key-up-component-1-class-no-type
|
||||||
}
|
}
|
||||||
|
@ -84,48 +84,15 @@ The following example shows how to make a simple progress bar accessible by usin
|
|||||||
|
|
||||||
* The component defines an accessibility-enabled element with both the standard HTML attribute `role`, and ARIA attributes. The ARIA attribute `aria-valuenow` is bound to the user's input.
|
* The component defines an accessibility-enabled element with both the standard HTML attribute `role`, and ARIA attributes. The ARIA attribute `aria-valuenow` is bound to the user's input.
|
||||||
|
|
||||||
```ts
|
<code-example path="accessibility/src/app/progress-bar.component.ts" header="src/app/progress-bar.component.ts" region="progressbar-component"></code-example>
|
||||||
import { Component, Input } from '@angular/core';
|
|
||||||
/**
|
|
||||||
* Example progressbar component.
|
|
||||||
*/
|
|
||||||
@Component({
|
|
||||||
selector: 'example-progressbar',
|
|
||||||
template: `<div class="bar" [style.width.%]="value"></div>`,
|
|
||||||
styleUrls: ['./progress-bar.css'],
|
|
||||||
host: {
|
|
||||||
// Sets the role for this component to "progressbar"
|
|
||||||
role: 'progressbar',
|
|
||||||
|
|
||||||
// Sets the minimum and maximum values for the progressbar role.
|
|
||||||
'aria-valuemin': '0',
|
|
||||||
'aria-valuemax': '0',
|
|
||||||
|
|
||||||
// Binding that updates the current value of the progressbar.
|
|
||||||
'[attr.aria-valuenow]': 'value',
|
|
||||||
}
|
|
||||||
})
|
|
||||||
export class ExampleProgressbar {
|
|
||||||
/** Current value of the progressbar. */
|
|
||||||
@Input() value: number = 0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
* In the template, the `aria-label` attribute ensures that the control is accessible to screen readers.
|
* In the template, the `aria-label` attribute ensures that the control is accessible to screen readers.
|
||||||
|
|
||||||
```html
|
<code-example path="accessibility/src/app/app.component.html" header="src/app/app.component.html" region="template"></code-example>
|
||||||
<label>
|
|
||||||
Enter an example progress value
|
|
||||||
<input type="number" min="0" max="100"
|
|
||||||
[value]="progress" (input)="progress = $event.target.value">
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<!-- The user of the progressbar sets an aria-label to communicate what the progress means. -->
|
|
||||||
<example-progressbar [value]="progress" aria-label="Example of a progress bar">
|
|
||||||
</example-progressbar>
|
|
||||||
```
|
|
||||||
|
|
||||||
[See the full example in StackBlitz](https://stackblitz.com/edit/angular-kn5jdi?file=src%2Fapp%2Fapp.component.html).
|
To see the progress bar in a working example app, refer to the <live-example></live-example>.
|
||||||
|
|
||||||
## Routing and focus management
|
## Routing and focus management
|
||||||
|
|
||||||
|
@ -1148,9 +1148,7 @@ The Angular code is shown using TypeScript.
|
|||||||
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.ts" region="class"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.ts" region="class"></code-example>
|
||||||
|
|
||||||
|
|
||||||
In Angular, you create a component class.
|
In Angular, you create a component class to contain the data model and control methods. Use the TypeScript <code>export</code> keyword to export the class so that the functionality can be imported into NgModules.
|
||||||
|
|
||||||
NOTE: If you are using TypeScript with AngularJS, you must use the `export` keyword to export the component class.
|
|
||||||
|
|
||||||
For more information, see the [Components](guide/architecture#components)
|
For more information, see the [Components](guide/architecture#components)
|
||||||
section of the [Architecture Overview](guide/architecture) page.
|
section of the [Architecture Overview](guide/architecture) page.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Angular compiler options
|
# Angular compiler options
|
||||||
|
|
||||||
When you use [AOT compilation](guide/aot-compiler), you can control how your application is compiled by specifying *template* compiler options in the `tsconfig.json` [TypeScript configuration file](guide/typescript-configuration).
|
When you use [AoT compilation](guide/aot-compiler), you can control how your application is compiled by specifying *template* compiler options in the `tsconfig.json` [TypeScript configuration file](guide/typescript-configuration).
|
||||||
|
|
||||||
The template options object, `angularCompilerOptions`, is a sibling to the `compilerOptions` object that supplies standard options to the TypeScript compiler.
|
The template options object, `angularCompilerOptions`, is a sibling to the `compilerOptions` object that supplies standard options to the TypeScript compiler.
|
||||||
|
|
||||||
@ -17,7 +17,38 @@ The template options object, `angularCompilerOptions`, is a sibling to the `comp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
This page describes the available Angular template compiler options.
|
|
||||||
|
{@a tsconfig-extends}
|
||||||
|
## Configuration inheritance with extends
|
||||||
|
|
||||||
|
Like the TypeScript compiler, The Angular AoT compiler also supports `extends` in the `angularCompilerOptions` section of the TypeScript configuration file, `tsconfig.json`.
|
||||||
|
The `extends` property is at the top level, parallel to `compilerOptions` and `angularCompilerOptions`.
|
||||||
|
|
||||||
|
A TypeScript configuration can inherit settings from another file using the `extends` property.
|
||||||
|
The configuration options from the base file are loaded first, then overridden by those in the inheriting `tsconfig` file.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"extends": "../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
...
|
||||||
|
},
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"fullTemplateTypeCheck": true,
|
||||||
|
"preserveWhitespaces": true,
|
||||||
|
...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For more information, see the [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html).
|
||||||
|
|
||||||
|
## Template options
|
||||||
|
|
||||||
|
The following options are available for configuring the AoT template compiler.
|
||||||
|
|
||||||
### `allowEmptyCodegenFiles`
|
### `allowEmptyCodegenFiles`
|
||||||
|
|
||||||
@ -29,7 +60,7 @@ Modifies how Angular-specific annotations are emitted to improve tree-shaking. N
|
|||||||
|
|
||||||
* By default, the compiler replaces decorators with a static field in the class, which allows advanced tree-shakers like [Closure compiler](https://github.com/google/closure-compiler) to remove unused classes.
|
* By default, the compiler replaces decorators with a static field in the class, which allows advanced tree-shakers like [Closure compiler](https://github.com/google/closure-compiler) to remove unused classes.
|
||||||
|
|
||||||
* The `decorators` value leaves the decorators in place, which makes compilation faster. TypeScript emits calls to the` __decorate` helper. Use `--emitDecoratorMetadata` for runtime reflection (but note taht the resulting code will not properly tree-shake.
|
* The `decorators` value leaves the decorators in place, which makes compilation faster. TypeScript emits calls to the` __decorate` helper. Use `--emitDecoratorMetadata` for runtime reflection (but note that the resulting code will not properly tree-shake.
|
||||||
|
|
||||||
### `annotateForClosureCompiler`
|
### `annotateForClosureCompiler`
|
||||||
|
|
||||||
@ -57,7 +88,7 @@ When enabled, the `.js` output of `ngc` does not include any lazy-loaded templat
|
|||||||
|
|
||||||
### `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`
|
||||||
|
|
||||||
|
@ -69,8 +69,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/animations/open-closed.png" alt="open and closed states">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/animations/open-closed.png" alt="open and closed states">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
### Animation state and styles
|
### Animation state and styles
|
||||||
@ -93,7 +95,7 @@ In the `closed` state, shown below, the button has a height of 100 pixels, an op
|
|||||||
|
|
||||||
In Angular, you can set multiple styles without any animation. However, without further refinement, the button instantly transforms with no fade, no shrinkage, or other visible indicator that a change is occurring.
|
In Angular, you can set multiple styles without any animation. However, without further refinement, the button instantly transforms with no fade, no shrinkage, or other visible indicator that a change is occurring.
|
||||||
|
|
||||||
To make the change less abrupt, we need to define an animation *transition* to specify the changes that occur between one state and another over a period of time. The `transition()` function accepts two arguments: the first argument accepts an expression that defines the direction between two transition states, and the second argument accepts an `animate()` function.
|
To make the change less abrupt, we need to define an animation *transition* to specify the changes that occur between one state and another over a period of time. The `transition()` function accepts two arguments: the first argument accepts an expression that defines the direction between two transition states, and the second argument accepts one or a series of `animate()` steps.
|
||||||
|
|
||||||
|
|
||||||
Use the `animate()` function to define the length, delay, and easing of a transition, and to designate the style function for defining styles while transitions are taking place. You can also use the `animate()` function to define the `keyframes()` function for multi-step animations. These definitions are placed in the second argument of the `animate()` function.
|
Use the `animate()` function to define the length, delay, and easing of a transition, and to designate the style function for defining styles while transitions are taking place. You can also use the `animate()` function to define the `keyframes()` function for multi-step animations. These definitions are placed in the second argument of the `animate()` function.
|
||||||
@ -166,8 +168,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/animations/triggering-the-animation.png" alt="triggering the animation">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/animations/triggering-the-animation.png" alt="triggering the animation">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
@ -260,7 +264,7 @@ What it does
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>state()</code></td>
|
<td><code><a href="api/animations/state" class="code-anchor">state()</a></code></td>
|
||||||
<td>Creates a named set of CSS styles that should be applied on successful transition to a given state. The state can then be referenced by name within other animation functions.</td>
|
<td>Creates a named set of CSS styles that should be applied on successful transition to a given state. The state can then be referenced by name within other animation functions.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
@ -280,7 +284,7 @@ What it does
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>group()</code></td>
|
<td><code><a href="api/animations/group" class="code-anchor">group()</a></code></td>
|
||||||
<td>Specifies a group of animation steps (<em>inner animations</em>) to be run in parallel. Animation continues only after all inner animation steps have completed. Used within <code>sequence()</code> or <code>transition().</code></td>
|
<td>Specifies a group of animation steps (<em>inner animations</em>) to be run in parallel. Animation continues only after all inner animation steps have completed. Used within <code>sequence()</code> or <code>transition().</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
540
aio/content/guide/aot-metadata-errors.md
Normal file
540
aio/content/guide/aot-metadata-errors.md
Normal file
@ -0,0 +1,540 @@
|
|||||||
|
# AoT metadata errors
|
||||||
|
|
||||||
|
The following are metadata errors you may encounter, with explanations and suggested corrections.
|
||||||
|
|
||||||
|
[Expression form not supported](#expression-form-not-supported)<br>
|
||||||
|
[Reference to a local (non-exported) symbol](#reference-to-a-local-symbol)<br>
|
||||||
|
[Only initialized variables and constants](#only-initialized-variables)<br>
|
||||||
|
[Reference to a non-exported class](#reference-to-a-non-exported-class)<br>
|
||||||
|
[Reference to a non-exported function](#reference-to-a-non-exported-function)<br>
|
||||||
|
[Function calls are not supported](#function-calls-not-supported)<br>
|
||||||
|
[Destructured variable or constant not supported](#destructured-variable-not-supported)<br>
|
||||||
|
[Could not resolve type](#could-not-resolve-type)<br>
|
||||||
|
[Name expected](#name-expected)<br>
|
||||||
|
[Unsupported enum member name](#unsupported-enum-member-name)<br>
|
||||||
|
[Tagged template expressions are not supported](#tagged-template-expressions-not-supported)<br>
|
||||||
|
[Symbol reference expected](#symbol-reference-expected)<br>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
{@a expression-form-not-supported}
|
||||||
|
## Expression form not supported
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
*The compiler encountered an expression it didn't understand while evaluating Angular metadata.*
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Language features outside of the compiler's [restricted expression syntax](guide/aot-compiler#expression-syntax)
|
||||||
|
can produce this error, as seen in the following example:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// ERROR
|
||||||
|
export class Fooish { ... }
|
||||||
|
...
|
||||||
|
const prop = typeof Fooish; // typeof is not valid in metadata
|
||||||
|
...
|
||||||
|
// bracket notation is not valid in metadata
|
||||||
|
{ provide: 'token', useValue: { [prop]: 'value' } };
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
You can use `typeof` and bracket notation in normal application code.
|
||||||
|
You just can't use those features within expressions that define Angular metadata.
|
||||||
|
|
||||||
|
Avoid this error by sticking to the compiler's [restricted expression syntax](guide/aot-compiler#expression-syntax)
|
||||||
|
when writing Angular metadata
|
||||||
|
and be wary of new or unusual TypeScript features.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
{@a reference-to-a-local-symbol}
|
||||||
|
## Reference to a local (non-exported) symbol
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
_Reference to a local (non-exported) symbol 'symbol name'. Consider exporting the symbol._
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
The compiler encountered a referenced to a locally defined symbol that either wasn't exported or wasn't initialized.
|
||||||
|
|
||||||
|
Here's a `provider` example of the problem.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// ERROR
|
||||||
|
let foo: number; // neither exported nor initialized
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-component',
|
||||||
|
template: ... ,
|
||||||
|
providers: [
|
||||||
|
{ provide: Foo, useValue: foo }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class MyComponent {}
|
||||||
|
```
|
||||||
|
The compiler generates the component factory, which includes the `useValue` provider code, in a separate module. _That_ factory module can't reach back to _this_ source module to access the local (non-exported) `foo` variable.
|
||||||
|
|
||||||
|
You could fix the problem by initializing `foo`.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
let foo = 42; // initialized
|
||||||
|
```
|
||||||
|
|
||||||
|
The compiler will [fold](guide/aot-compiler#code-folding) the expression into the provider as if you had written this.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
providers: [
|
||||||
|
{ provide: Foo, useValue: 42 }
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, you can fix it by exporting `foo` with the expectation that `foo` will be assigned at runtime when you actually know its value.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// CORRECTED
|
||||||
|
export let foo: number; // exported
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-component',
|
||||||
|
template: ... ,
|
||||||
|
providers: [
|
||||||
|
{ provide: Foo, useValue: foo }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class MyComponent {}
|
||||||
|
```
|
||||||
|
|
||||||
|
Adding `export` often works for variables referenced in metadata such as `providers` and `animations` because the compiler can generate _references_ to the exported variables in these expressions. It doesn't need the _values_ of those variables.
|
||||||
|
|
||||||
|
Adding `export` doesn't work when the compiler needs the _actual value_
|
||||||
|
in order to generate code.
|
||||||
|
For example, it doesn't work for the `template` property.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// ERROR
|
||||||
|
export let someTemplate: string; // exported but not initialized
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-component',
|
||||||
|
template: someTemplate
|
||||||
|
})
|
||||||
|
export class MyComponent {}
|
||||||
|
```
|
||||||
|
|
||||||
|
The compiler needs the value of the `template` property _right now_ to generate the component factory.
|
||||||
|
The variable reference alone is insufficient.
|
||||||
|
Prefixing the declaration with `export` merely produces a new error, "[`Only initialized variables and constants can be referenced`](#only-initialized-variables)".
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
{@a only-initialized-variables}
|
||||||
|
## Only initialized variables and constants
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
_Only initialized variables and constants can be referenced because the value of this variable is needed by the template compiler._
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
The compiler found a reference to an exported variable or static field that wasn't initialized.
|
||||||
|
It needs the value of that variable to generate code.
|
||||||
|
|
||||||
|
The following example tries to set the component's `template` property to the value of
|
||||||
|
the exported `someTemplate` variable which is declared but _unassigned_.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// ERROR
|
||||||
|
export let someTemplate: string;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-component',
|
||||||
|
template: someTemplate
|
||||||
|
})
|
||||||
|
export class MyComponent {}
|
||||||
|
```
|
||||||
|
|
||||||
|
You'd also get this error if you imported `someTemplate` from some other module and neglected to initialize it there.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// ERROR - not initialized there either
|
||||||
|
import { someTemplate } from './config';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-component',
|
||||||
|
template: someTemplate
|
||||||
|
})
|
||||||
|
export class MyComponent {}
|
||||||
|
```
|
||||||
|
|
||||||
|
The compiler cannot wait until runtime to get the template information.
|
||||||
|
It must statically derive the value of the `someTemplate` variable from the source code
|
||||||
|
so that it can generate the component factory, which includes
|
||||||
|
instructions for building the element based on the template.
|
||||||
|
|
||||||
|
To correct this error, provide the initial value of the variable in an initializer clause _on the same line_.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// CORRECTED
|
||||||
|
export let someTemplate = '<h1>Greetings from Angular</h1>';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-component',
|
||||||
|
template: someTemplate
|
||||||
|
})
|
||||||
|
export class MyComponent {}
|
||||||
|
```
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
{@a reference-to-a-non-exported-class}
|
||||||
|
## Reference to a non-exported class
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
_Reference to a non-exported class <class name>. Consider exporting the class._
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Metadata referenced a class that wasn't exported.
|
||||||
|
|
||||||
|
For example, you may have defined a class and used it as an injection token in a providers array
|
||||||
|
but neglected to export that class.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// ERROR
|
||||||
|
abstract class MyStrategy { }
|
||||||
|
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
{ provide: MyStrategy, useValue: ... }
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Angular generates a class factory in a separate module and that
|
||||||
|
factory [can only access exported classes](guide/aot-compiler#exported-symbols).
|
||||||
|
To correct this error, export the referenced class.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// CORRECTED
|
||||||
|
export abstract class MyStrategy { }
|
||||||
|
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
{ provide: MyStrategy, useValue: ... }
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
{@a reference-to-a-non-exported-function}
|
||||||
|
## Reference to a non-exported function
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
*Metadata referenced a function that wasn't exported.*
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
For example, you may have set a providers `useFactory` property to a locally defined function that you neglected to export.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// ERROR
|
||||||
|
function myStrategy() { ... }
|
||||||
|
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
{ provide: MyStrategy, useFactory: myStrategy }
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Angular generates a class factory in a separate module and that
|
||||||
|
factory [can only access exported functions](guide/aot-compiler#exported-symbols).
|
||||||
|
To correct this error, export the function.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// CORRECTED
|
||||||
|
export function myStrategy() { ... }
|
||||||
|
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
{ provide: MyStrategy, useFactory: myStrategy }
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
{@a function-calls-not-supported}
|
||||||
|
## Function calls are not supported
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
_Function calls are not supported. Consider replacing the function or lambda with a reference to an exported function._
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
The compiler does not currently support [function expressions or lambda functions](guide/aot-compiler#function-expression).
|
||||||
|
For example, you cannot set a provider's `useFactory` to an anonymous function or arrow function like this.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// ERROR
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
{ provide: MyStrategy, useFactory: function() { ... } },
|
||||||
|
{ provide: OtherStrategy, useFactory: () => { ... } }
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
You also get this error if you call a function or method in a provider's `useValue`.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// ERROR
|
||||||
|
import { calculateValue } from './utilities';
|
||||||
|
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
{ provide: SomeValue, useValue: calculateValue() }
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
To correct this error, export a function from the module and refer to the function in a `useFactory` provider instead.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// CORRECTED
|
||||||
|
import { calculateValue } from './utilities';
|
||||||
|
|
||||||
|
export function myStrategy() { ... }
|
||||||
|
export function otherStrategy() { ... }
|
||||||
|
export function someValueFactory() {
|
||||||
|
return calculateValue();
|
||||||
|
}
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
{ provide: MyStrategy, useFactory: myStrategy },
|
||||||
|
{ provide: OtherStrategy, useFactory: otherStrategy },
|
||||||
|
{ provide: SomeValue, useFactory: someValueFactory }
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
{@a destructured-variable-not-supported}
|
||||||
|
## Destructured variable or constant not supported
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
_Referencing an exported destructured variable or constant is not supported by the template compiler. Consider simplifying this to avoid destructuring._
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
The compiler does not support references to variables assigned by [destructuring](https://www.typescriptlang.org/docs/handbook/variable-declarations.html#destructuring).
|
||||||
|
|
||||||
|
For example, you cannot write something like this:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// ERROR
|
||||||
|
import { configuration } from './configuration';
|
||||||
|
|
||||||
|
// destructured assignment to foo and bar
|
||||||
|
const {foo, bar} = configuration;
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
{provide: Foo, useValue: foo},
|
||||||
|
{provide: Bar, useValue: bar},
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
To correct this error, refer to non-destructured values.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// CORRECTED
|
||||||
|
import { configuration } from './configuration';
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
{provide: Foo, useValue: configuration.foo},
|
||||||
|
{provide: Bar, useValue: configuration.bar},
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
{@a could-not-resolve-type}
|
||||||
|
## Could not resolve type
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
*The compiler encountered a type and can't determine which module exports that type.*
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
This can happen if you refer to an ambient type.
|
||||||
|
For example, the `Window` type is an ambient type declared in the global `.d.ts` file.
|
||||||
|
|
||||||
|
You'll get an error if you reference it in the component constructor,
|
||||||
|
which the compiler must statically analyze.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// ERROR
|
||||||
|
@Component({ })
|
||||||
|
export class MyComponent {
|
||||||
|
constructor (private win: Window) { ... }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
TypeScript understands ambient types so you don't import them.
|
||||||
|
The Angular compiler does not understand a type that you neglect to export or import.
|
||||||
|
|
||||||
|
In this case, the compiler doesn't understand how to inject something with the `Window` token.
|
||||||
|
|
||||||
|
Do not refer to ambient types in metadata expressions.
|
||||||
|
|
||||||
|
If you must inject an instance of an ambient type,
|
||||||
|
you can finesse the problem in four steps:
|
||||||
|
|
||||||
|
1. Create an injection token for an instance of the ambient type.
|
||||||
|
1. Create a factory function that returns that instance.
|
||||||
|
1. Add a `useFactory` provider with that factory function.
|
||||||
|
1. Use `@Inject` to inject the instance.
|
||||||
|
|
||||||
|
Here's an illustrative example.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// CORRECTED
|
||||||
|
import { Inject } from '@angular/core';
|
||||||
|
|
||||||
|
export const WINDOW = new InjectionToken('Window');
|
||||||
|
export function _window() { return window; }
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
{ provide: WINDOW, useFactory: _window }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class MyComponent {
|
||||||
|
constructor (@Inject(WINDOW) private win: Window) { ... }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `Window` type in the constructor is no longer a problem for the compiler because it
|
||||||
|
uses the `@Inject(WINDOW)` to generate the injection code.
|
||||||
|
|
||||||
|
Angular does something similar with the `DOCUMENT` token so you can inject the browser's `document` object (or an abstraction of it, depending upon the platform in which the application runs).
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { Inject } from '@angular/core';
|
||||||
|
import { DOCUMENT } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
@Component({ ... })
|
||||||
|
export class MyComponent {
|
||||||
|
constructor (@Inject(DOCUMENT) private doc: Document) { ... }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
{@a name-expected}
|
||||||
|
## Name expected
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
*The compiler expected a name in an expression it was evaluating.*
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
This can happen if you use a number as a property name as in the following example.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// ERROR
|
||||||
|
provider: [{ provide: Foo, useValue: { 0: 'test' } }]
|
||||||
|
```
|
||||||
|
|
||||||
|
Change the name of the property to something non-numeric.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// CORRECTED
|
||||||
|
provider: [{ provide: Foo, useValue: { '0': 'test' } }]
|
||||||
|
```
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
{@a unsupported-enum-member-name}
|
||||||
|
## Unsupported enum member name
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
*Angular couldn't determine the value of the [enum member](https://www.typescriptlang.org/docs/handbook/enums.html) that you referenced in metadata.*
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
The compiler can understand simple enum values but not complex values such as those derived from computed properties.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// ERROR
|
||||||
|
enum Colors {
|
||||||
|
Red = 1,
|
||||||
|
White,
|
||||||
|
Blue = "Blue".length // computed
|
||||||
|
}
|
||||||
|
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
{ provide: BaseColor, useValue: Colors.White } // ok
|
||||||
|
{ provide: DangerColor, useValue: Colors.Red } // ok
|
||||||
|
{ provide: StrongColor, useValue: Colors.Blue } // bad
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Avoid referring to enums with complicated initializers or computed properties.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
{@a tagged-template-expressions-not-supported}
|
||||||
|
## Tagged template expressions are not supported
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
_Tagged template expressions are not supported in metadata._
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
The compiler encountered a JavaScript ES2015 [tagged template expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_template_literals) such as the following.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// ERROR
|
||||||
|
const expression = 'funky';
|
||||||
|
const raw = String.raw`A tagged template ${expression} string`;
|
||||||
|
...
|
||||||
|
template: '<div>' + raw + '</div>'
|
||||||
|
...
|
||||||
|
```
|
||||||
|
[`String.raw()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/raw)
|
||||||
|
is a _tag function_ native to JavaScript ES2015.
|
||||||
|
|
||||||
|
The AoT compiler does not support tagged template expressions; avoid them in metadata expressions.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
{@a symbol-reference-expected}
|
||||||
|
## Symbol reference expected
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
*The compiler expected a reference to a symbol at the location specified in the error message.*
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
This error can occur if you use an expression in the `extends` clause of a class.
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Chuck: After reviewing your PR comment I'm still at a loss. See [comment there](https://github.com/angular/angular/pull/17712#discussion_r132025495).
|
||||||
|
|
||||||
|
-->
|
@ -44,6 +44,12 @@ After running this command you will notice that the `angular.json` configuration
|
|||||||
"browserTarget": "my-app:build",
|
"browserTarget": "my-app:build",
|
||||||
"serverTarget": "my-app:server",
|
"serverTarget": "my-app:server",
|
||||||
"route": "shell"
|
"route": "shell"
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"browserTarget": "my-app:build:production",
|
||||||
|
"serverTarget": "my-app:server:production"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -56,4 +62,12 @@ Use the CLI to build the `app-shell` target.
|
|||||||
ng run my-app:app-shell
|
ng run my-app:app-shell
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
Or to use the production configuration.
|
||||||
|
|
||||||
|
<code-example language="bash">
|
||||||
|
ng run my-app:app-shell:production
|
||||||
|
</code-example>
|
||||||
|
|
||||||
To verify the build output, open `dist/my-app/index.html`. Look for default text `app-shell works!` to show that the app shell route was rendered as part of the output.
|
To verify the build output, open `dist/my-app/index.html`. Look for default text `app-shell works!` to show that the app shell route was rendered as part of the output.
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ Here's an example of basic metadata for `HeroListComponent`.
|
|||||||
|
|
||||||
This example shows some of the most useful `@Component` configuration options:
|
This example shows some of the most useful `@Component` configuration options:
|
||||||
|
|
||||||
* `selector`: A CSS selector that tells Angular to create and insert an instance of this component wherever it finds the corresponding tag in template HTML. For example, if an app's HTML contains `<app-hero-list></app-hero-list>`, then
|
* `selector`: A CSS selector that tells Angular to create and insert an instance of this component wherever it finds the corresponding tag in template HTML. For example, if an app's HTML contains `<app-hero-list></app-hero-list>`, then
|
||||||
Angular inserts an instance of the `HeroListComponent` view between those tags.
|
Angular inserts an instance of the `HeroListComponent` view between those tags.
|
||||||
|
|
||||||
* `templateUrl`: The module-relative address of this component's HTML template. Alternatively, you can provide the HTML template inline, as the value of the `template` property. This template defines the component's *host view*.
|
* `templateUrl`: The module-relative address of this component's HTML template. Alternatively, you can provide the HTML template inline, as the value of the `template` property. This template defines the component's *host view*.
|
||||||
@ -51,8 +51,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/architecture/component-tree.png" alt="Component tree" class="left">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/architecture/component-tree.png" alt="Component tree" class="left">
|
||||||
|
</div>
|
||||||
</figure>
|
</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.
|
||||||
@ -81,8 +83,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/architecture/databinding.png" alt="Data Binding" class="left">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/architecture/databinding.png" alt="Data Binding" class="left">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
This example from the `HeroListComponent` template uses three of these forms.
|
This example from the `HeroListComponent` template uses three of these forms.
|
||||||
@ -110,14 +114,18 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/architecture/component-databinding.png" alt="Data Binding" class="left">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/architecture/component-databinding.png" alt="Data Binding" class="left">
|
||||||
|
</div>
|
||||||
</figure>
|
</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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/architecture/parent-child-binding.png" alt="Parent/Child binding" class="left">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/architecture/parent-child-binding.png" alt="Parent/Child binding" class="left">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
### Pipes
|
### Pipes
|
||||||
|
@ -35,20 +35,20 @@ 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>
|
<figure 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>
|
||||||
</figure>
|
</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>
|
<figure 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>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
@ -70,8 +70,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/architecture/injector-injects.png" alt="Service" class="left">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/architecture/injector-injects.png" alt="Service" class="left">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
### Providing services
|
### Providing services
|
||||||
@ -82,7 +84,7 @@ or you can register providers with specific modules or components.
|
|||||||
You register providers in the metadata of the service (in the `@Injectable()` decorator),
|
You register providers in the metadata of the service (in the `@Injectable()` decorator),
|
||||||
or in the `@NgModule()` or `@Component()` metadata
|
or in the `@NgModule()` or `@Component()` metadata
|
||||||
|
|
||||||
* By default, the Angular CLI command [`ng generate service`](cli/generate) registers a provider with the root injector for your service by including provider metadata in the `@Injectable()` decorator. The tutorial uses this method to register the provider of HeroService class definition.
|
* By default, the Angular CLI command [`ng generate service`](cli/generate) registers a provider with the root injector for your service by including provider metadata in the `@Injectable()` decorator. The tutorial uses this method to register the provider of HeroService class definition.
|
||||||
|
|
||||||
```
|
```
|
||||||
@Injectable({
|
@Injectable({
|
||||||
|
@ -113,8 +113,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/architecture/overview2.png" alt="overview">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/architecture/overview2.png" alt="overview">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
* Together, a component and template define an Angular view.
|
* Together, a component and template define an Angular view.
|
||||||
|
@ -142,7 +142,7 @@ Begin by adding `HostListener` to the list of imported symbols.
|
|||||||
|
|
||||||
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts (imports)" region="imports"></code-example>
|
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts (imports)" region="imports"></code-example>
|
||||||
|
|
||||||
Then add two eventhandlers that respond when the mouse enters or leaves,
|
Then add two event handlers that respond when the mouse enters or leaves,
|
||||||
each adorned by the `HostListener` decorator.
|
each adorned by the `HostListener` decorator.
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts (mouse-methods)" region="mouse-methods"></code-example>
|
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts (mouse-methods)" region="mouse-methods"></code-example>
|
||||||
@ -175,8 +175,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/attribute-directives/highlight-directive-anim.gif" alt="Second Highlight">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/attribute-directives/highlight-directive-anim.gif" alt="Second Highlight">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
{@a bindings}
|
{@a bindings}
|
||||||
@ -247,7 +249,7 @@ You get the best of both worlds: the property name you want and the binding synt
|
|||||||
<code-example path="attribute-directives/src/app/app.component.html" header="src/app/app.component.html (color)" region="color"></code-example>
|
<code-example path="attribute-directives/src/app/app.component.html" header="src/app/app.component.html (color)" region="color"></code-example>
|
||||||
|
|
||||||
Now that you're binding via the alias to the `highlightColor`, modify the `onMouseEnter()` method to use that property.
|
Now that you're binding via the alias to the `highlightColor`, modify the `onMouseEnter()` method to use that property.
|
||||||
If someone neglects to bind to `appHighlightColor`, highlight the host element in red:
|
If someone neglects to bind to `appHighlight`, highlight the host element in red:
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/highlight.directive.3.ts" header="src/app/highlight.directive.ts (mouse enter)" region="mouse-enter"></code-example>
|
<code-example path="attribute-directives/src/app/highlight.directive.3.ts" header="src/app/highlight.directive.ts (mouse enter)" region="mouse-enter"></code-example>
|
||||||
|
|
||||||
@ -271,8 +273,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/attribute-directives/highlight-directive-v2-anim.gif" alt="Highlight v.2">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/attribute-directives/highlight-directive-v2-anim.gif" alt="Highlight v.2">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
{@a second-property}
|
{@a second-property}
|
||||||
@ -307,8 +311,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/attribute-directives/highlight-directive-final-anim.gif" alt="Final Highlight">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/attribute-directives/highlight-directive-final-anim.gif" alt="Final Highlight">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
@ -8,13 +8,7 @@ This page discusses build-specific configuration options for Angular projects.
|
|||||||
|
|
||||||
You can define different named build configurations for your project, such as *stage* and *production*, with different defaults.
|
You can define different named build configurations for your project, such as *stage* and *production*, with different defaults.
|
||||||
|
|
||||||
Each named build configuration can have defaults for any of the options that apply to the various build targets, such as `build`, `serve`, and `test`. The [Angular CLI](cli) `build`, `serve`, and `test` commands can then replace files with appropriate versions for your intended target environment.
|
Each named configuration can have defaults for any of the options that apply to the various [builder targets](guide/glossary#target), such as `build`, `serve`, and `test`. The [Angular CLI](cli) `build`, `serve`, and `test` commands can then replace files with appropriate versions for your intended target environment.
|
||||||
|
|
||||||
The following figure shows how a project has multiple build targets, which can be executed using the named configurations that you define.
|
|
||||||
|
|
||||||
<figure>
|
|
||||||
<img src="generated/images/guide/build/build-config-targets.gif" alt="build configurations and targets">
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
### Configure environment-specific defaults
|
### Configure environment-specific defaults
|
||||||
|
|
||||||
@ -170,8 +164,9 @@ You can also configure the `serve` command to use the targeted build configurati
|
|||||||
```
|
```
|
||||||
|
|
||||||
{@a size-budgets}
|
{@a size-budgets}
|
||||||
|
{@a configure-size-budgets}
|
||||||
|
|
||||||
## Configure size budgets
|
## Configuring size budgets
|
||||||
|
|
||||||
As applications grow in functionality, they also grow in size.
|
As applications grow in functionality, they also grow in size.
|
||||||
The CLI allows you to set size thresholds in your configuration to ensure that parts of your application stay within size boundaries that you define.
|
The CLI allows you to set size thresholds in your configuration to ensure that parts of your application stay within size boundaries that you define.
|
||||||
@ -296,10 +291,9 @@ Autoprefixer looks for the `browserslist` configuration when it prefixes your CS
|
|||||||
|
|
||||||
See the [browserslist repo](https://github.com/browserslist/browserslist) for more examples of how to target specific browsers and versions.
|
See the [browserslist repo](https://github.com/browserslist/browserslist) for more examples of how to target specific browsers and versions.
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
### Backward compatibility with Lighthouse
|
||||||
Backward compatibility
|
|
||||||
|
|
||||||
If you want to produce a progressive web app and are using [Lighthouse](https://developers.google.com/web/tools/lighthouse/) to grade the project, add the following browserslist entry to your `package.json` file, in order to eliminate the [old flexbox](https://developers.google.com/web/tools/lighthouse/audits/old-flexbox) prefixes:
|
If you want to produce a progressive web app and are using [Lighthouse](https://developers.google.com/web/tools/lighthouse/) to grade the project, add the following `browserslist` entry to your `package.json` file, in order to eliminate the [old flexbox](https://developers.google.com/web/tools/lighthouse/audits/old-flexbox) prefixes:
|
||||||
|
|
||||||
```
|
```
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
@ -309,7 +303,23 @@ If you want to produce a progressive web app and are using [Lighthouse](https://
|
|||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
### Backward compatibility with CSS grid
|
||||||
|
|
||||||
|
CSS grid layout support in Autoprefixer, which was previously on by default, is off by default in Angular 8 and higher.
|
||||||
|
|
||||||
|
To use CSS grid with IE10/11, you must explicitly enable it using the `autoplace` option.
|
||||||
|
To do this, add the following to the top of the global styles file (or within a specific css selector scope):
|
||||||
|
|
||||||
|
```
|
||||||
|
/* autoprefixer grid: autoplace /
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```
|
||||||
|
/ autoprefixer grid: no-autoplace */
|
||||||
|
```
|
||||||
|
|
||||||
|
For more information, see [Autoprefixer documentation](https://autoprefixer.github.io/).
|
||||||
|
|
||||||
|
|
||||||
{@a proxy}
|
{@a proxy}
|
||||||
|
|
||||||
@ -318,7 +328,7 @@ If you want to produce a progressive web app and are using [Lighthouse](https://
|
|||||||
You can use the [proxying support](https://webpack.js.org/configuration/dev-server/#devserver-proxy) in the `webpack` dev server to divert certain URLs to a backend server, by passing a file to the `--proxy-config` build option.
|
You can use the [proxying support](https://webpack.js.org/configuration/dev-server/#devserver-proxy) in the `webpack` dev server to divert certain URLs to a backend server, by passing a file to the `--proxy-config` build option.
|
||||||
For example, to divert all calls for `http://localhost:4200/api` to a server running on `http://localhost:3000/api`, take the following steps.
|
For example, to divert all calls for `http://localhost:4200/api` to a server running on `http://localhost:3000/api`, take the following steps.
|
||||||
|
|
||||||
1. Create a file `proxy.conf.json` in the projects `src/` folder, in the same directory as `package.json`.
|
1. Create a file `proxy.conf.json` in your project's `src/` folder.
|
||||||
|
|
||||||
1. Add the following content to the new proxy file:
|
1. Add the following content to the new proxy file:
|
||||||
```
|
```
|
||||||
@ -401,7 +411,7 @@ Proxy log levels are `info` (the default), `debug`, `warn`, `error`, and `silent
|
|||||||
|
|
||||||
### Proxy multiple entries
|
### Proxy multiple entries
|
||||||
|
|
||||||
You can proxy multiple entries to the same target by defining the configuration in JavaScript.
|
You can proxy multiple entries to the same target by defining the configuration in JavaScript.
|
||||||
|
|
||||||
Set the proxy configuration file to `proxy.conf.js` (instead of `proxy.conf.json`), and specify configuration files as in the following example.
|
Set the proxy configuration file to `proxy.conf.js` (instead of `proxy.conf.json`), and specify configuration files as in the following example.
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ This object contains a Boolean `success` field and an optional `error` field tha
|
|||||||
|
|
||||||
Angular provides some builders that are used by the CLI for commands such as `ng build`, `ng test`, and `ng lint`.
|
Angular provides some builders that are used by the CLI for commands such as `ng build`, `ng test`, and `ng lint`.
|
||||||
Default target configurations for these and other built-in CLI builders can be found (and customized) in the "architect" section of the [workspace configuration file](guide/workspace-config), `angular.json`.
|
Default target configurations for these and other built-in CLI builders can be found (and customized) in the "architect" section of the [workspace configuration file](guide/workspace-config), `angular.json`.
|
||||||
You can also extend and customize Angular by creating your own builders, which you can run using the [`ng run` CLI command](cli/run).
|
You can also extend and customize Angular by creating your own builders, which you can run using the [`ng run` CLI command](cli/run).
|
||||||
|
|
||||||
### Builder project structure
|
### Builder project structure
|
||||||
|
|
||||||
@ -59,8 +59,7 @@ npm install @example/my-builder
|
|||||||
As an example, let’s create a builder that executes a shell command.
|
As an example, let’s create a builder that executes a shell command.
|
||||||
To create a builder, use the `createBuilder()` CLI Builder function, and return a `BuilderOutput` object.
|
To create a builder, use the `createBuilder()` CLI Builder function, and return a `BuilderOutput` object.
|
||||||
|
|
||||||
```
|
<code-example language="typescript" header="/command/index.ts">
|
||||||
|
|
||||||
import { BuilderOutput, createBuilder } from '@angular-devkit/architect';
|
import { BuilderOutput, createBuilder } from '@angular-devkit/architect';
|
||||||
|
|
||||||
export default createBuilder(_commandBuilder);
|
export default createBuilder(_commandBuilder);
|
||||||
@ -72,13 +71,13 @@ function _commandBuilder(
|
|||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
</code-example>
|
||||||
|
|
||||||
Now let’s add some logic to it.
|
Now let’s add some logic to it.
|
||||||
The following code retrieves the command and arguments from the user options, spawns the new process, and waits for the process to finish.
|
The following code retrieves the command and arguments from the user options, spawns the new process, and waits for the process to finish.
|
||||||
If the process is successful (returns a code of 0), it resolves the return value.
|
If the process is successful (returns a code of 0), it resolves the return value.
|
||||||
|
|
||||||
```
|
<code-example language="typescript" header="/command/index.ts">
|
||||||
import { BuilderOutput, createBuilder } from '@angular-devkit/architect';
|
import { BuilderOutput, createBuilder } from '@angular-devkit/architect';
|
||||||
import * as childProcess from 'child_process';
|
import * as childProcess from 'child_process';
|
||||||
|
|
||||||
@ -95,7 +94,8 @@ function _commandBuilder(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
</code-example>
|
||||||
|
|
||||||
### Handling output
|
### Handling output
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ This also allows the builder itself to be executed in a separate process, even i
|
|||||||
|
|
||||||
We can retrieve a Logger instance from the context.
|
We can retrieve a Logger instance from the context.
|
||||||
|
|
||||||
```
|
<code-example language="typescript" header="/command/index.ts">
|
||||||
import { BuilderOutput, createBuilder, BuilderContext } from '@angular-devkit/architect';
|
import { BuilderOutput, createBuilder, BuilderContext } from '@angular-devkit/architect';
|
||||||
import * as childProcess from 'child_process';
|
import * as childProcess from 'child_process';
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ function _commandBuilder(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
</code-example>
|
||||||
|
|
||||||
### Progress and status reporting
|
### Progress and status reporting
|
||||||
|
|
||||||
@ -144,10 +144,10 @@ You can see an [example](https://github.com/angular/angular-cli/blob/ba21c855c0c
|
|||||||
|
|
||||||
In our example, the shell command either finishes or is still executing, so there’s no need for a progress report, but we can report status so that a parent builder that called our builder would know what’s going on.
|
In our example, the shell command either finishes or is still executing, so there’s no need for a progress report, but we can report status so that a parent builder that called our builder would know what’s going on.
|
||||||
Use the `BuilderContext.reportStatus()` method to generate a status string of any length.
|
Use the `BuilderContext.reportStatus()` method to generate a status string of any length.
|
||||||
(Note that there’s no guarantee that a long string will be shown entirely; it could be cut to fit the UI that displays it.)
|
(Note that there’s no guarantee that a long string will be shown entirely; it could be cut to fit the UI that displays it.)
|
||||||
Pass an empty string to remove the status.
|
Pass an empty string to remove the status.
|
||||||
|
|
||||||
```
|
<code-example language="typescript" header="/command/index.ts">
|
||||||
import { BuilderOutput, createBuilder, BuilderContext } from '@angular-devkit/architect';
|
import { BuilderOutput, createBuilder, BuilderContext } from '@angular-devkit/architect';
|
||||||
import * as childProcess from 'child_process';
|
import * as childProcess from 'child_process';
|
||||||
|
|
||||||
@ -174,7 +174,8 @@ function _commandBuilder(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
</code-example>
|
||||||
|
|
||||||
## Builder input
|
## Builder input
|
||||||
|
|
||||||
@ -191,8 +192,7 @@ For our example builder, we expect the `options` value to be a `JsonObject` with
|
|||||||
|
|
||||||
We can provide the following schema for type validation of these values.
|
We can provide the following schema for type validation of these values.
|
||||||
|
|
||||||
<code-example language="json">
|
<code-example language="json" header="command/schema.json">
|
||||||
|
|
||||||
{
|
{
|
||||||
"$schema": "http://json-schema.org/schema",
|
"$schema": "http://json-schema.org/schema",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -222,7 +222,7 @@ To link our builder implementation with its schema and name, we need to create a
|
|||||||
|
|
||||||
Create a file named `builders.json` file that looks like this.
|
Create a file named `builders.json` file that looks like this.
|
||||||
|
|
||||||
<code-example language="json">
|
<code-example language="json" header="builders.json">
|
||||||
|
|
||||||
{
|
{
|
||||||
"builders": {
|
"builders": {
|
||||||
@ -238,7 +238,7 @@ Create a file named `builders.json` file that looks like this.
|
|||||||
|
|
||||||
In the `package.json` file, add a `builders` key that tells the Architect tool where to find our builder definition file.
|
In the `package.json` file, add a `builders` key that tells the Architect tool where to find our builder definition file.
|
||||||
|
|
||||||
<code-example language="json">
|
<code-example language="json" header="package.json">
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": "@example/command-runner",
|
"name": "@example/command-runner",
|
||||||
@ -253,11 +253,11 @@ In the `package.json` file, add a `builders` key that tells the Architect tool w
|
|||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
The official name of our builder is now ` @example/command-runner:command`.
|
The official name of our builder is now ` @example/command-runner:command`.
|
||||||
The first part of this is the package name (resolved using node resolution), and the second part is the builder name (resolved using the `builders.json` file).
|
The first part of this is the package name (resolved using node resolution), and the second part is the builder name (resolved using the `builders.json` file).
|
||||||
|
|
||||||
Using one of our `options` is very straightforward, we did this in the previous section when we accessed `options.command`.
|
Using one of our `options` is very straightforward, we did this in the previous section when we accessed `options.command`.
|
||||||
|
|
||||||
<code-example language="typescript">
|
<code-example language="typescript" header="/command/index.ts">
|
||||||
context.reportStatus(`Executing "${options.command}"...`);
|
context.reportStatus(`Executing "${options.command}"...`);
|
||||||
const child = childProcess.spawn(options.command, options.args, { stdio: 'pipe' });
|
const child = childProcess.spawn(options.command, options.args, { stdio: 'pipe' });
|
||||||
|
|
||||||
@ -267,14 +267,14 @@ Using one of our `options` is very straightforward, we did this in the previous
|
|||||||
|
|
||||||
A builder must have a defined target that associates it with a specific input configuration and [project](guide/glossary#project).
|
A builder must have a defined target that associates it with a specific input configuration and [project](guide/glossary#project).
|
||||||
|
|
||||||
Targets are defined in the `angular.json` [workspace configuration file](guide/workspace-config).
|
Targets are defined in the `angular.json` [CLI configuration file](guide/workspace-config).
|
||||||
A target specifies the builder to use, its default options configuration, and named alternative configurations.
|
A target specifies the builder to use, its default options configuration, and named alternative configurations.
|
||||||
The Architect tool uses the target definition to resolve input options for a given run.
|
The Architect tool uses the target definition to resolve input options for a given run.
|
||||||
|
|
||||||
The `angular.json` file has a section for each project, and the "architect" section of each project configures targets for builders used by CLI commands such as 'build', 'test', and 'lint'.
|
The `angular.json` file has a section for each project, and the "architect" section of each project configures targets for builders used by CLI commands such as 'build', 'test', and 'lint'.
|
||||||
By default, for example, the `build` command runs the builder `@angular-devkit/build-angular:browser` to perform the build task, and passes in default option values as specified for the `build` target in `angular.json`.
|
By default, for example, the `build` command runs the builder `@angular-devkit/build-angular:browser` to perform the build task, and passes in default option values as specified for the `build` target in `angular.json`.
|
||||||
|
|
||||||
<code-example language="json">
|
<code-example language="json" header="angular.json">
|
||||||
{
|
{
|
||||||
"myApp": {
|
"myApp": {
|
||||||
...
|
...
|
||||||
@ -311,7 +311,7 @@ You might also add more alternative configurations to the `build` target, to def
|
|||||||
|
|
||||||
#### Target strings
|
#### Target strings
|
||||||
|
|
||||||
The generic `ng run` CLI command takes as its first argument a target string of the form *project:target[:configuration]*.
|
The generic `ng run` CLI command takes as its first argument a target string of the form *project:target[:configuration]*.
|
||||||
|
|
||||||
* *project*: The name of the Angular CLI project that the target is associated with.
|
* *project*: The name of the Angular CLI project that the target is associated with.
|
||||||
|
|
||||||
@ -361,7 +361,7 @@ npm install @example/command-runner
|
|||||||
|
|
||||||
If we create a new project with `ng new builder-test`, the generated `angular.json` file looks something like this, with only default builder configurations.
|
If we create a new project with `ng new builder-test`, the generated `angular.json` file looks something like this, with only default builder configurations.
|
||||||
|
|
||||||
<code-example language="json">
|
<code-example language="json" header="angular.json">
|
||||||
|
|
||||||
{
|
{
|
||||||
// ...
|
// ...
|
||||||
@ -413,7 +413,7 @@ We need to update the `angular.json` file to add a target for this builder to th
|
|||||||
|
|
||||||
* The configurations key is optional, we'll leave it out for now.
|
* The configurations key is optional, we'll leave it out for now.
|
||||||
|
|
||||||
<code-example language="json">
|
<code-example language="json" header="angular.json">
|
||||||
|
|
||||||
{
|
{
|
||||||
"projects": {
|
"projects": {
|
||||||
@ -493,7 +493,7 @@ Use integration testing for your builder, so that you can use the Architect sche
|
|||||||
Here’s an example of a test that runs the command builder.
|
Here’s an example of a test that runs the command builder.
|
||||||
The test uses the builder to run the `ls` command, then validates that it ran successfully and listed the proper files.
|
The test uses the builder to run the `ls` command, then validates that it ran successfully and listed the proper files.
|
||||||
|
|
||||||
<code-example language="typescript">
|
<code-example language="typescript" header="command/index_spec.ts">
|
||||||
|
|
||||||
import { Architect } from '@angular-devkit/architect';
|
import { Architect } from '@angular-devkit/architect';
|
||||||
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
|
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
|
||||||
|
@ -26,8 +26,8 @@ Observables are often compared to promises. Here are some key differences:
|
|||||||
new Observable((observer) => { subscriber_fn });
|
new Observable((observer) => { subscriber_fn });
|
||||||
// initiate execution
|
// initiate execution
|
||||||
observable.subscribe(() => {
|
observable.subscribe(() => {
|
||||||
// observer handles notifications
|
// observer handles notifications
|
||||||
});
|
});
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
* Promises execute immediately, and just once. The computation of the result is initiated when the promise is created. There is no way to restart work. All `then` clauses (subscriptions) share the same computation.
|
* Promises execute immediately, and just once. The computation of the result is initiated when the promise is created. There is no way to restart work. All `then` clauses (subscriptions) share the same computation.
|
||||||
@ -37,8 +37,8 @@ observable.subscribe(() => {
|
|||||||
new Promise((resolve, reject) => { executer_fn });
|
new Promise((resolve, reject) => { executer_fn });
|
||||||
// handle return value
|
// handle return value
|
||||||
promise.then((value) => {
|
promise.then((value) => {
|
||||||
// handle result here
|
// handle result here
|
||||||
});
|
});
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
### Chaining
|
### Chaining
|
||||||
@ -80,7 +80,7 @@ obs.subscribe(() => {
|
|||||||
|
|
||||||
<code-example hideCopy>
|
<code-example hideCopy>
|
||||||
promise.then(() => {
|
promise.then(() => {
|
||||||
throw Error('my error');
|
throw Error('my error');
|
||||||
});
|
});
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
@ -314,6 +314,3 @@ An observable produces values over time. An array is created as a static set of
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#### Prerequisites
|
#### Prerequisites
|
||||||
|
|
||||||
A basic understanding of the following concepts:
|
A basic understanding of the following concepts:
|
||||||
|
|
||||||
* [Introduction to Angular animations](guide/animations)
|
* [Introduction to Angular animations](guide/animations)
|
||||||
* [Transition and triggers](guide/transition-and-triggers)
|
* [Transition and triggers](guide/transition-and-triggers)
|
||||||
@ -30,7 +30,7 @@ The Filter/Stagger tab in the live example shows a list of heroes with an introd
|
|||||||
|
|
||||||
The following example demonstrates how to use `query()` and `stagger()` functions on the entry of an animated element.
|
The following example demonstrates how to use `query()` and `stagger()` functions on the entry of an animated element.
|
||||||
|
|
||||||
* Use `query()` to look for any element entering or leaving the page. The query specifies elements meeting certain CSS class criteria.
|
* Use `query()` to look for an element entering the page that meets certain criteria.
|
||||||
|
|
||||||
* For each of these elements, use `style()` to set the same initial style for the element. Make it invisible and use `transform` to move it out of position so that it can slide into place.
|
* For each of these elements, use `style()` to set the same initial style for the element. Make it invisible and use `transform` to move it out of position so that it can slide into place.
|
||||||
|
|
||||||
|
@ -50,8 +50,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/component-interaction/parent-to-child.png" alt="Parent-to-child">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/component-interaction/parent-to-child.png" alt="Parent-to-child">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
|
||||||
@ -94,8 +96,10 @@ Here's the `NameParentComponent` demonstrating name variations including a name
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<figure>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/component-interaction/setter.png" alt="Parent-to-child-setter">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/component-interaction/setter.png" alt="Parent-to-child-setter">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
|
||||||
@ -125,7 +129,7 @@ Detect and act upon changes to input property values with the `ngOnChanges()` me
|
|||||||
|
|
||||||
You may prefer this approach to the property setter when watching multiple, interacting input properties.
|
You may prefer this approach to the property setter when watching multiple, interacting input properties.
|
||||||
|
|
||||||
Learn about `ngOnChanges()` in the [LifeCycle Hooks](guide/lifecycle-hooks) chapter.
|
Learn about `ngOnChanges()` in the [Lifecycle Hooks](guide/lifecycle-hooks) chapter.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -152,8 +156,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/component-interaction/parent-to-child-on-changes.gif" alt="Parent-to-child-onchanges">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/component-interaction/parent-to-child-on-changes.gif" alt="Parent-to-child-onchanges">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
|
||||||
@ -206,8 +212,10 @@ The framework passes the event argument—represented by `$event`—to t
|
|||||||
and the method processes it:
|
and the method processes it:
|
||||||
|
|
||||||
|
|
||||||
<figure>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/component-interaction/child-to-parent.gif" alt="Child-to-parent">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/component-interaction/child-to-parent.gif" alt="Child-to-parent">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
|
||||||
@ -268,8 +276,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/component-interaction/countdown-timer-anim.gif" alt="countdown timer">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/component-interaction/countdown-timer-anim.gif" alt="countdown timer">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
|
||||||
@ -421,8 +431,10 @@ the parent `MissionControlComponent` and the `AstronautComponent` children,
|
|||||||
facilitated by the service:
|
facilitated by the service:
|
||||||
|
|
||||||
|
|
||||||
<figure>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/component-interaction/bidirectional-service.gif" alt="bidirectional-service">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/component-interaction/bidirectional-service.gif" alt="bidirectional-service">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Creating Libraries
|
# Creating Libraries
|
||||||
|
|
||||||
You can create and publish new libraries to extend Angular functionality. If you find that you need to solve the same problem in more than one app (or want to share your solution with other developers), you have a candidate for a library.
|
You can create and publish new libraries to extend Angular functionality. If you find that you need to solve the same problem in more than one app (or want to share your solution with other developers), you have a candidate for a library.
|
||||||
|
|
||||||
@ -13,9 +13,15 @@ A simple example might be a button that sends users to your company website, tha
|
|||||||
Use the Angular CLI to generate a new library skeleton with the following command:
|
Use the Angular CLI to generate a new library skeleton with the following command:
|
||||||
|
|
||||||
<code-example language="bash">
|
<code-example language="bash">
|
||||||
|
ng new my-workspace --create-application=false
|
||||||
|
cd my-workspace
|
||||||
ng generate library my-lib
|
ng generate library my-lib
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
<p>You can use the monorepo model to use the same workspace for multiple projects. See <a href="guide/file-structure#multiple-projects">Setting up for a multi-project workspace</a>.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
This creates the `projects/my-lib` folder in your workspace, which contains a component and a service inside an NgModule.
|
This creates the `projects/my-lib` folder in your workspace, which contains a component and a service inside an NgModule.
|
||||||
The workspace configuration file, `angular.json`, is updated with a project of type 'library'.
|
The workspace configuration file, `angular.json`, is updated with a project of type 'library'.
|
||||||
|
|
||||||
@ -41,7 +47,7 @@ You can build, test, and lint the project with CLI commands:
|
|||||||
ng lint my-lib
|
ng lint my-lib
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Notice that the configured builder for the project is different from the default builder for app projects.
|
Notice that the configured builder for the project is different from the default builder for app projects.
|
||||||
This builder, among other things, ensures that the library is always built with the [AoT compiler](guide/aot-compiler), without the need to specify the `--prod` flag.
|
This builder, among other things, ensures that the library is always built with the [AoT compiler](guide/aot-compiler), without the need to specify the `--prod` flag.
|
||||||
|
|
||||||
To make library code reusable you must define a public API for it. This "user layer" defines what is available to consumers of your library. A user of your library should be able to access public functionality (such as NgModules, service providers and general utility functions) through a single import path.
|
To make library code reusable you must define a public API for it. This "user layer" defines what is available to consumers of your library. A user of your library should be able to access public functionality (such as NgModules, service providers and general utility functions) through a single import path.
|
||||||
@ -175,7 +181,7 @@ For instance, if you clone your git repository and run `npm install`, your edito
|
|||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
When you import something from a library in an Angular app, Angular looks for a mapping between the library name and a location on disk.
|
When you import something from a library in an Angular app, Angular looks for a mapping between the library name and a location on disk.
|
||||||
When you install a library package, the mapping is in the `node_modules` folder. When you build your own library, it has to find the mapping in your `tsconfig` paths.
|
When you install a library package, the mapping is in the `node_modules` folder. When you build your own library, it has to find the mapping in your `tsconfig` paths.
|
||||||
|
|
||||||
Generating a library with the Angular CLI automatically adds its path to the `tsconfig` file.
|
Generating a library with the Angular CLI automatically adds its path to the `tsconfig` file.
|
||||||
The Angular CLI uses the `tsconfig` paths to tell the build system where to find the library.
|
The Angular CLI uses the `tsconfig` paths to tell the build system where to find the library.
|
||||||
@ -188,8 +194,23 @@ You can rebuild your library whenever you make changes to it, but this extra ste
|
|||||||
*Incremental builds* functionality improves the library-development experience.
|
*Incremental builds* functionality improves the library-development experience.
|
||||||
Every time a file is changed a partial build is performed that emits the amended files.
|
Every time a file is changed a partial build is performed that emits the amended files.
|
||||||
|
|
||||||
Incremental builds can be run as a backround process in your dev environment. To take advantage of this feature add the `--watch` flag to the build command:
|
Incremental builds can be run as a background process in your dev environment. To take advantage of this feature add the `--watch` flag to the build command:
|
||||||
|
|
||||||
<code-example language="bash">
|
<code-example language="bash">
|
||||||
ng build my-lib --watch
|
ng build my-lib --watch
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
<div class="alert is-important">
|
||||||
|
|
||||||
|
The CLI `build` command uses a different builder and invokes a different build tool for libraries than it does for applications.
|
||||||
|
|
||||||
|
* The build system for apps, `@angular-devkit/build-angular`, is based on `webpack`, and is included in all new Angular CLI projects.
|
||||||
|
* The build system for libraries is based on `ng-packagr`. It is only added to your dependencies when you add a library using `ng generate library my-lib`.
|
||||||
|
|
||||||
|
The two build systems support different things, and even where they support the same things, they do those things differently.
|
||||||
|
This means that the TypeScript source can result in different JavaScript code in a built library than it would in a built application.
|
||||||
|
|
||||||
|
For this reason, an app that depends on a library should only use TypeScript path mappings that point to the *built library*.
|
||||||
|
TypeScript path mappings should *not* point to the library source `.ts` files.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@ -40,8 +40,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/logged-in-user.png" alt="Logged In User">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/dependency-injection-in-action/logged-in-user.png" alt="Logged In User">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
{@a service-scope}
|
{@a service-scope}
|
||||||
@ -131,8 +133,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/hero-bios.png" alt="Bios">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/dependency-injection-in-action/hero-bios.png" alt="Bios">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
{@a qualify-dependency-lookup}
|
{@a qualify-dependency-lookup}
|
||||||
@ -191,8 +195,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/hero-bio-and-content.png" alt="bio and contact">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/dependency-injection-in-action/hero-bio-and-content.png" alt="bio and contact">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
|
||||||
@ -221,8 +227,10 @@ When the property is marked as optional, Angular sets `loggerService` to null an
|
|||||||
|
|
||||||
Here's `HeroBiosAndContactsComponent` in action.
|
Here's `HeroBiosAndContactsComponent` in action.
|
||||||
|
|
||||||
<figure>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/hero-bios-and-contacts.png" alt="Bios with contact into">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/dependency-injection-in-action/hero-bios-and-contacts.png" alt="Bios with contact into">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
|
||||||
@ -232,8 +240,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/hero-bio-contact-no-host.png" alt="Without @Host">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/dependency-injection-in-action/hero-bio-contact-no-host.png" alt="Without @Host">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
|
||||||
@ -262,7 +272,7 @@ Providers can also be scoped by injector through constructor parameter decorator
|
|||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Using the `@Self` decorator, the injector only looks at the component's injector for its providers. The `@SkipSelf` decorator allows you to skip the local injector and look up in the hierarchy to find a provider that satisfies this dependency. The `sessionStorageService` instance interacts with the `BrowserStorageService` using the `sessionStorage` browser API, while the `localStorageService` skips the local injector and uses the root `BrowserStorageService` that uses the `localStorage` browswer API.
|
Using the `@Self` decorator, the injector only looks at the component's injector for its providers. The `@SkipSelf` decorator allows you to skip the local injector and look up in the hierarchy to find a provider that satisfies this dependency. The `sessionStorageService` instance interacts with the `BrowserStorageService` using the `sessionStorage` browser API, while the `localStorageService` skips the local injector and uses the root `BrowserStorageService` that uses the `localStorage` browser API.
|
||||||
|
|
||||||
{@a component-element}
|
{@a component-element}
|
||||||
|
|
||||||
@ -294,8 +304,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/highlight.png" alt="Highlighted bios">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/dependency-injection-in-action/highlight.png" alt="Highlighted bios">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
{@a providers}
|
{@a providers}
|
||||||
@ -347,8 +359,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/hero-of-month.png" alt="Hero of the month">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/dependency-injection-in-action/hero-of-month.png" alt="Hero of the month">
|
||||||
|
</div>
|
||||||
</figure>
|
</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.
|
||||||
@ -460,8 +474,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/minimal-logger-intellisense.png" alt="MinimalLogger restricted API">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/dependency-injection-in-action/minimal-logger-intellisense.png" alt="MinimalLogger restricted API">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
|
||||||
@ -472,8 +488,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/date-logger-entry.png" alt="DateLoggerService entry">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/dependency-injection-in-action/date-logger-entry.png" alt="DateLoggerService entry">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -556,7 +574,7 @@ as the token for a provider of `LoggerService`.
|
|||||||
|
|
||||||
An abstract class is usually a base class that you can extend.
|
An abstract class is usually a base class that you can extend.
|
||||||
In this app, however there is no class that inherits from `MinimalLogger`.
|
In this app, however there is no class that inherits from `MinimalLogger`.
|
||||||
The `LoggerService` and the `DateLoggerService`could have inherited from `MinimalLogger`,
|
The `LoggerService` and the `DateLoggerService` could have inherited from `MinimalLogger`,
|
||||||
or they could have implemented it instead, in the manner of an interface.
|
or they could have implemented it instead, in the manner of an interface.
|
||||||
But they did neither.
|
But they did neither.
|
||||||
`MinimalLogger` is used only as a dependency injection token.
|
`MinimalLogger` is used only as a dependency injection token.
|
||||||
@ -568,7 +586,7 @@ an interface is not a valid DI token because it is a TypeScript artifact that do
|
|||||||
Use this abstract class interface to get the strong typing of an interface,
|
Use this abstract class interface to get the strong typing of an interface,
|
||||||
and also use it as a provider token in the way you would a normal class.
|
and also use it as a provider token in the way you would a normal class.
|
||||||
|
|
||||||
A class interface should define *only* the members that its consumers are allowed to call.
|
A class interface should define *only* the members that its consumers are allowed to call.
|
||||||
Such a narrowing interface helps decouple the concrete class from its consumers.
|
Such a narrowing interface helps decouple the concrete class from its consumers.
|
||||||
|
|
||||||
|
|
||||||
@ -627,8 +645,10 @@ 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>
|
<figure class="lightbox">
|
||||||
<img src="generated/images/guide/dependency-injection-in-action/sorted-heroes.png" alt="Sorted Heroes">
|
<div class="card">
|
||||||
|
<img src="generated/images/guide/dependency-injection-in-action/sorted-heroes.png" alt="Sorted Heroes">
|
||||||
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
The `HeroesBaseComponent` can stand on its own.
|
The `HeroesBaseComponent` can stand on its own.
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user