Compare commits
281 Commits
Author | SHA1 | Date | |
---|---|---|---|
a2ba4448da | |||
ac6b2b4dc3 | |||
b6dffa9763 | |||
54b57def58 | |||
e2b3cc8118 | |||
5e701a2c88 | |||
27a3df146d | |||
8cce7efbb2 | |||
d225c3a6e3 | |||
b23582d57e | |||
d3c6e512a3 | |||
a873fab10c | |||
ecef0dd65e | |||
1cc74eaece | |||
e2b3be87cb | |||
3ca6c928f9 | |||
5933d16f3e | |||
0f839bcfd0 | |||
edda94edfa | |||
b5e36eaa3e | |||
08a1f51704 | |||
9690e36f78 | |||
68e741227b | |||
50a2327520 | |||
b07346c8e3 | |||
8e95849751 | |||
cd143f67af | |||
dd85351162 | |||
c1c68889de | |||
866f4be782 | |||
80e4019c83 | |||
d9f3316021 | |||
424a3b95aa | |||
7e883c2319 | |||
6a7fd70ddf | |||
73f9db53c2 | |||
2bf526bbfb | |||
8bd7d5befc | |||
aa163bea93 | |||
2f73c554c9 | |||
fb2d15fda1 | |||
018507fa02 | |||
95bb72d322 | |||
ce6e6c3f81 | |||
e4b1bdbfa0 | |||
6477c9e04a | |||
3f380b3b78 | |||
c4c0e9dbc5 | |||
4ddf57c58d | |||
624f01c311 | |||
6a713521e3 | |||
57a5ba3438 | |||
1b6fb5bc19 | |||
bd9da268c1 | |||
1e58a2194f | |||
da81c9cb54 | |||
ef6d26d4fa | |||
13bc1cd853 | |||
1fa1379318 | |||
d9efacc07e | |||
47f5b5f2d4 | |||
019fe77f64 | |||
a0e3a8e0f7 | |||
8908156eae | |||
2ee265fb1f | |||
116512b06d | |||
1d841973eb | |||
3694e1a38c | |||
88d8813ccc | |||
49bfb63442 | |||
48848c9ca4 | |||
a1f1ea993d | |||
be8a403bc9 | |||
c378402af4 | |||
91ce8c17ff | |||
786be967fd | |||
e88d5e0df2 | |||
f39f01e00b | |||
ce750e6f5b | |||
beba944843 | |||
50981cbb1f | |||
76e40eed35 | |||
d491a20f3b | |||
74c202a5cd | |||
483e8d28ec | |||
a6fd118f79 | |||
fe6e76c1e7 | |||
de560019f2 | |||
52ed53d071 | |||
5b72d4d676 | |||
c1aa1bf872 | |||
dad1bc7ca3 | |||
2109c30afe | |||
874919a25b | |||
c64e666755 | |||
1da403d8f3 | |||
60c5ebd46a | |||
b71d1987cd | |||
e6325eb9ef | |||
114519ab6a | |||
a9a095d44a | |||
5f9d574d4d | |||
baeb446392 | |||
0d1bfdc505 | |||
fa130e9445 | |||
194710fc1d | |||
6ae5e2b32a | |||
d85d396c26 | |||
1a25144297 | |||
449da8c18e | |||
0f37ed1060 | |||
5c85b4f1e9 | |||
22bc6ef22a | |||
bf928d1c9e | |||
d11c2f915b | |||
98c99e5073 | |||
2c63108faa | |||
0ff48a1266 | |||
ea2a3f8335 | |||
cbed4851a3 | |||
7c157780a9 | |||
cc1b2a5373 | |||
5076185fc8 | |||
65375f4c21 | |||
068a6070dc | |||
47e9761a01 | |||
bef52d20b5 | |||
fe50710021 | |||
71b66fb862 | |||
8db05b408e | |||
351610ca8d | |||
ef78e33560 | |||
12b8a6e351 | |||
260ac20e92 | |||
aed48e00d2 | |||
a9d46e4952 | |||
2f19ad9b46 | |||
81678e62db | |||
cf82fbceba | |||
1d67cb0ce1 | |||
318bd83a6e | |||
f767c22b31 | |||
8346a6dca2 | |||
6397885e74 | |||
8cee56e8c5 | |||
a1b9995731 | |||
35f7ff047a | |||
4ad691a33d | |||
c5af3f8617 | |||
bc1032866c | |||
63e6d1a896 | |||
cb9fd9b4d7 | |||
d5dca0764c | |||
bcd1a09dec | |||
898c0134e7 | |||
763d2150cc | |||
beacbfcb8e | |||
f72319cf6e | |||
5877b3f702 | |||
cf310ba1fa | |||
c2d2953ee4 | |||
5c5fe34241 | |||
32737a6bf7 | |||
7642308c14 | |||
f1c08d83b0 | |||
617412f9c3 | |||
cf716684a9 | |||
54565ed389 | |||
ab08385336 | |||
eb8ccf65d1 | |||
cb93027f32 | |||
607fd8e970 | |||
f4ac96d0ff | |||
1c7d156abd | |||
4c00059260 | |||
93d78c9c51 | |||
49bee4c0d8 | |||
d8c75f1bb0 | |||
6d40ef2d6b | |||
4ea6c27dcf | |||
a4d9192fbc | |||
7b772e93a3 | |||
05168395b0 | |||
03293c4fec | |||
479019f457 | |||
68515818b9 | |||
8bc369f828 | |||
3d1a4d5cc3 | |||
5c56b778e0 | |||
585e871c96 | |||
6ae7aee2c3 | |||
701270d039 | |||
02a852a34a | |||
531f940212 | |||
de80f1b6dd | |||
ca3965afe0 | |||
f269e433a7 | |||
8750b09fca | |||
ea2eef737b | |||
0ceab97a03 | |||
fbbdaaacc0 | |||
080de58a88 | |||
5390948360 | |||
0d860051af | |||
edbba24b60 | |||
6ae8d7691d | |||
af3cf36ce9 | |||
1be2f11965 | |||
495ce325b2 | |||
92411043d1 | |||
aa3f75b3c9 | |||
d64aadf57a | |||
51f7f081a3 | |||
b9fd62413f | |||
c5664bf245 | |||
c66a076614 | |||
28d34b699d | |||
47840bee71 | |||
305331f634 | |||
5e6c24cb01 | |||
0ec4e1372a | |||
84c1bad3a1 | |||
1640832f56 | |||
8ab036262d | |||
76e8c0ac7b | |||
0e81e418fb | |||
60255b68c0 | |||
ae7b3c8d45 | |||
9556ba7bca | |||
80994b25b9 | |||
2f154b980f | |||
342d352a00 | |||
f240ae5084 | |||
e4fc8bad35 | |||
5c680d4aa8 | |||
f05c5f82c8 | |||
2e0c58ec3e | |||
21093b9090 | |||
a6153accf0 | |||
dee789c204 | |||
12dd552fcd | |||
079bcffe07 | |||
30256e8fe8 | |||
8ee69831fc | |||
c3d8e2888d | |||
bea677136b | |||
11728bbbd9 | |||
1da4b03940 | |||
54ba0f021f | |||
836a5c72a0 | |||
f589933440 | |||
ef3ec34aa3 | |||
37a6d2d033 | |||
354f3639bb | |||
c4b06868b1 | |||
e3853e842e | |||
aee5cbd057 | |||
e9614eff1a | |||
80f9f7e8ef | |||
7d2589556f | |||
468fcab59d | |||
f720e972d4 | |||
b51ae7e59a | |||
eedb06936f | |||
ee5a094424 | |||
9773b5a173 | |||
eed171839e | |||
1057b52def | |||
302506e940 | |||
cc35feb445 | |||
21b875d4d0 | |||
dac9c09235 | |||
5cba438eb5 | |||
2b001cb2b1 | |||
0be8487f09 | |||
e1e69ca828 | |||
f376c46d78 | |||
fad4145f48 | |||
6b394f62be | |||
16aad8b2d8 | |||
25bbcbcbe5 |
@ -2,3 +2,4 @@ node_modules
|
||||
dist
|
||||
aio/node_modules
|
||||
aio/tools/examples/shared/node_modules
|
||||
integration/bazel
|
||||
|
20
.bazelrc
20
.bazelrc
@ -22,8 +22,14 @@ test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test
|
||||
# Filesystem interactions #
|
||||
###############################
|
||||
|
||||
# Don't create symlinks like bazel-out in the project.
|
||||
# These cause VSCode to traverse a massive tree, opening file handles and
|
||||
# Create symlinks in the project:
|
||||
# - dist/bin for outputs
|
||||
# - dist/testlogs, dist/genfiles
|
||||
# - bazel-out
|
||||
# NB: bazel-out should be excluded from the editor configuration.
|
||||
# The checked-in /.vscode/settings.json does this for VSCode.
|
||||
# Other editors may require manual config to ignore this directory.
|
||||
# In the past, we say a problem where VSCode traversed a massive tree, opening file handles and
|
||||
# eventually a surprising failure with auto-discovery of the C++ toolchain in
|
||||
# MacOS High Sierra.
|
||||
# See https://github.com/bazelbuild/bazel/issues/4603
|
||||
@ -36,6 +42,16 @@ build --watchfs
|
||||
run --nolegacy_external_runfiles
|
||||
test --nolegacy_external_runfiles
|
||||
|
||||
# Turn on --incompatible_strict_action_env which was on by default
|
||||
# in Bazel 0.21.0 but turned off again in 0.22.0. Follow
|
||||
# https://github.com/bazelbuild/bazel/issues/7026 for more details.
|
||||
# This flag is needed to so that the bazel cache is not invalidated
|
||||
# when running bazel via `yarn bazel`.
|
||||
# See https://github.com/angular/angular/issues/27514.
|
||||
build --incompatible_strict_action_env
|
||||
run --incompatible_strict_action_env
|
||||
test --incompatible_strict_action_env
|
||||
|
||||
###############################
|
||||
# Release support #
|
||||
# Turn on these settings with #
|
||||
|
@ -2,6 +2,10 @@
|
||||
# We do this by copying this file to /etc/bazel.bazelrc at the start of the build.
|
||||
# See documentation in /docs/BAZEL.md
|
||||
|
||||
# Save downloaded repositories in a location that can be cached by CircleCI. This helps us
|
||||
# speeding up the analysis time significantly with Bazel managed node dependencies on the CI.
|
||||
build --repository_cache=/home/circleci/bazel_repository_cache
|
||||
|
||||
# Don't be spammy in the logs
|
||||
# TODO(gmagolan): Hide progress again once build performance improves
|
||||
# Presently, CircleCI can timeout during bazel test ... with the following
|
||||
|
@ -11,10 +11,22 @@
|
||||
# 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.
|
||||
# **NOTE**: If you change the version of the docker images, also change the `cache_key` suffix.
|
||||
# **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.12
|
||||
var_2: &browsers_docker_image circleci/node:10.12-browsers
|
||||
var_3: &cache_key v2-angular-{{ .Branch }}-{{ checksum "yarn.lock" }}-node-10.12
|
||||
# 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.
|
||||
# The cache key should only consist of dynamic values that change whenever something in the
|
||||
# cache changes. For example:
|
||||
# 1) yarn lock file changes --> cached "node_modules" 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 2 **: Keep the static part of the cache key as prefix to enable correct fallbacks.
|
||||
# See https://circleci.com/docs/2.0/caching/#restoring-cache for how prefixes work in CircleCI.
|
||||
var_3: &cache_key v2-angular-node-10.12-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}
|
||||
|
||||
# Define common ENV vars
|
||||
var_4: &define_env_vars
|
||||
@ -45,13 +57,35 @@ var_7: &post_checkout
|
||||
var_8: &yarn_install
|
||||
run:
|
||||
name: Running Yarn install
|
||||
command: yarn install --frozen-lockfile --non-interactive
|
||||
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
|
||||
|
||||
# Sets up Yarn by downloading it and installing it globally. We don't use Yarn from the
|
||||
# docker image because this means that we can only use the Yarn version that comes with
|
||||
# a specific version of NodeJS. We want to be able to update Yarn without having to
|
||||
# update the docker image that comes with NodeJS.
|
||||
var_10: &download_yarn
|
||||
run:
|
||||
name: Downloading Yarn
|
||||
command: curl -o- -L https://yarnpkg.com/install.sh | PROFILE=$BASH_ENV bash -s -- --version "$CI_YARN_VERSION"
|
||||
|
||||
var_11: &restore_cache
|
||||
restore_cache:
|
||||
keys:
|
||||
- *cache_key
|
||||
# This fallback should be the cache_key without variables.
|
||||
- v2-angular-node-10.12-
|
||||
|
||||
version: 2
|
||||
jobs:
|
||||
lint:
|
||||
@ -59,9 +93,9 @@ jobs:
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *restore_cache
|
||||
- *define_env_vars
|
||||
- *download_yarn
|
||||
- *yarn_install
|
||||
|
||||
- run: 'yarn bazel:format -mode=check ||
|
||||
@ -78,11 +112,11 @@ jobs:
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *restore_cache
|
||||
- *define_env_vars
|
||||
- *setup_circleci_bazel_config
|
||||
- *download_yarn
|
||||
- *yarn_install
|
||||
- *setup_circleci_bazel_config
|
||||
|
||||
# Setup remote execution and run RBE-compatible tests.
|
||||
- *setup_bazel_remote_execution
|
||||
@ -91,12 +125,6 @@ jobs:
|
||||
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||
- run: yarn bazel test //... --build_tag_filters=-ivy-only,local --test_tag_filters=-ivy-only,local
|
||||
|
||||
- save_cache:
|
||||
key: *cache_key
|
||||
paths:
|
||||
- "node_modules"
|
||||
- "~/bazel_repository_cache"
|
||||
|
||||
# Temporary job to test what will happen when we flip the Ivy flag to true
|
||||
test_ivy_aot:
|
||||
<<: *job_defaults
|
||||
@ -104,11 +132,11 @@ jobs:
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *restore_cache
|
||||
- *define_env_vars
|
||||
- *setup_circleci_bazel_config
|
||||
- *download_yarn
|
||||
- *yarn_install
|
||||
- *setup_circleci_bazel_config
|
||||
- *setup_bazel_remote_execution
|
||||
|
||||
# We need to explicitly specify the --symlink_prefix option because otherwise we would
|
||||
@ -143,9 +171,9 @@ jobs:
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *restore_cache
|
||||
- *define_env_vars
|
||||
- *download_yarn
|
||||
# Build aio
|
||||
- run: yarn --cwd aio build --progress=false
|
||||
# Lint the code
|
||||
@ -157,9 +185,9 @@ jobs:
|
||||
# (Run before unit and e2e tests, which destroy the `dist/` directory.)
|
||||
- run: yarn --cwd aio payload-size
|
||||
# Run unit tests
|
||||
- run: yarn --cwd aio test --watch=false
|
||||
- run: yarn --cwd aio test --progress=false --watch=false
|
||||
# Run e2e tests
|
||||
- run: yarn --cwd aio e2e
|
||||
- run: yarn --cwd aio e2e --configuration=ci
|
||||
# Run unit tests for Firebase redirects
|
||||
- run: yarn --cwd aio redirects-test
|
||||
|
||||
@ -171,9 +199,9 @@ jobs:
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *restore_cache
|
||||
- *define_env_vars
|
||||
- *download_yarn
|
||||
# Deploy angular.io to production (if necessary)
|
||||
- run: setPublicVar CI_STABLE_BRANCH "$(npm info @angular/core dist-tags.latest | sed -r 's/^\s*([0-9]+\.[0-9]+)\.[0-9]+.*$/\1.x/')"
|
||||
- run: yarn --cwd aio deploy-production
|
||||
@ -186,31 +214,44 @@ jobs:
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *restore_cache
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
- *download_yarn
|
||||
# Build aio (with local Angular packages)
|
||||
- run: yarn --cwd aio build-local --progress=false
|
||||
# Run PWA-score tests
|
||||
# (Run before unit and e2e tests, which destroy the `dist/` directory.)
|
||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||
# Run unit tests
|
||||
- run: yarn --cwd aio test --watch=false
|
||||
- run: yarn --cwd aio test --progress=false --watch=false
|
||||
# Run e2e tests
|
||||
- run: yarn --cwd aio e2e
|
||||
- run: yarn --cwd aio e2e --configuration=ci
|
||||
|
||||
test_aio_local_ivy:
|
||||
<<: *job_defaults
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- *restore_cache
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
- *download_yarn
|
||||
# Build aio with Ivy (using local Angular packages)
|
||||
- run: yarn --cwd aio build-with-ivy --progress=false
|
||||
|
||||
test_aio_tools:
|
||||
<<: *job_defaults
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *restore_cache
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
- *download_yarn
|
||||
# Install
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
- run: yarn --cwd aio extract-cli-command-docs
|
||||
@ -218,45 +259,47 @@ jobs:
|
||||
- run: yarn --cwd aio tools-test
|
||||
- run: ./aio/aio-builds-setup/scripts/test.sh
|
||||
|
||||
test_docs_examples_0:
|
||||
test_docs_examples:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because the example e2e tests depend on Chrome.
|
||||
- image: *browsers_docker_image
|
||||
parallelism: 3
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *restore_cache
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
# Install root
|
||||
- *yarn_install
|
||||
- *download_yarn
|
||||
# Install aio
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
# Run examples tests
|
||||
- run: yarn --cwd aio example-e2e --setup --local --shard=0/2
|
||||
# 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 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL}
|
||||
|
||||
test_docs_examples_1:
|
||||
test_docs_examples_ivy:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because the example e2e tests depend on Chrome.
|
||||
- image: *browsers_docker_image
|
||||
parallelism: 3
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *restore_cache
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
# Install root
|
||||
- *yarn_install
|
||||
- *download_yarn
|
||||
# Install aio
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
# Run examples tests
|
||||
- run: yarn --cwd aio example-e2e --setup --local --shard=1/2
|
||||
# Run examples tests with ivy. 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 --ivy --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL}
|
||||
|
||||
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
||||
aio_preview:
|
||||
@ -266,10 +309,9 @@ jobs:
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *restore_cache
|
||||
- *define_env_vars
|
||||
- *yarn_install
|
||||
- *download_yarn
|
||||
- run: ./aio/scripts/build-artifacts.sh $AIO_SNAPSHOT_ARTIFACT_PATH $CI_PULL_REQUEST $CI_COMMIT
|
||||
- store_artifacts:
|
||||
path: *aio_preview_artifact_path
|
||||
@ -287,32 +329,34 @@ jobs:
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *restore_cache
|
||||
- *define_env_vars
|
||||
- run: yarn install --cwd aio --frozen-lockfile --non-interactive
|
||||
- *download_yarn
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
- run:
|
||||
name: Wait for preview and run tests
|
||||
command: node aio/scripts/test-preview.js $CI_PULL_REQUEST $CI_COMMIT $CI_AIO_MIN_PWA_SCORE
|
||||
|
||||
# This job exists only for backwards-compatibility with old scripts and tests
|
||||
# that rely on the pre-Bazel dist/packages-dist layout.
|
||||
# It duplicates some work with the job above: we build the bazel packages
|
||||
# twice. Even though we have a remote cache, these jobs will typically run in
|
||||
# parallel so up-to-date outputs will not be available at the time the build
|
||||
|
||||
# The `build-npm-packages` tasks exist for backwards-compatibility with old scripts and
|
||||
# tests that rely on the pre-Bazel `dist/packages-dist` output structure (build.sh).
|
||||
# Having multiple jobs that independently build in this manner duplicates some work; we build
|
||||
# the bazel packages more than once. Even though we have a remote cache, these jobs will
|
||||
# typically run in parallel so up-to-date outputs will not be available at the time the build
|
||||
# starts.
|
||||
# No new jobs should depend on this one.
|
||||
build-packages-dist:
|
||||
|
||||
# Build the view engine npm packages. No new jobs should depend on this.
|
||||
build-npm-packages:
|
||||
<<: *job_defaults
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *restore_cache
|
||||
- *define_env_vars
|
||||
- *setup_circleci_bazel_config
|
||||
- *download_yarn
|
||||
- *yarn_install
|
||||
- *setup_circleci_bazel_config
|
||||
- *setup_bazel_remote_execution
|
||||
|
||||
- run: scripts/build-packages-dist.sh
|
||||
@ -323,6 +367,35 @@ jobs:
|
||||
root: dist
|
||||
paths:
|
||||
- packages-dist
|
||||
|
||||
- save_cache:
|
||||
key: *cache_key
|
||||
paths:
|
||||
- "node_modules"
|
||||
- "~/bazel_repository_cache"
|
||||
|
||||
|
||||
# Build the ivy npm packages.
|
||||
build-ivy-npm-packages:
|
||||
<<: *job_defaults
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- *restore_cache
|
||||
- *define_env_vars
|
||||
- *download_yarn
|
||||
- *yarn_install
|
||||
- *setup_circleci_bazel_config
|
||||
- *setup_bazel_remote_execution
|
||||
|
||||
- run: scripts/build-ivy-npm-packages.sh
|
||||
|
||||
# Save the npm packages from //packages/... for other workflow jobs to read
|
||||
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
|
||||
- persist_to_workspace:
|
||||
root: dist
|
||||
paths:
|
||||
- packages-dist-ivy-aot
|
||||
|
||||
# We run the integration tests outside of Bazel for now.
|
||||
@ -333,6 +406,7 @@ jobs:
|
||||
# See comments inside the integration/run_tests.sh script.
|
||||
integration_test:
|
||||
<<: *job_defaults
|
||||
parallelism: 4
|
||||
docker:
|
||||
# Needed because the integration tests expect Chrome to be installed (e.g cli-hello-world)
|
||||
- image: *browsers_docker_image
|
||||
@ -343,12 +417,16 @@ jobs:
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *restore_cache
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
- run: ./integration/run_tests.sh
|
||||
- *download_yarn
|
||||
# Some integration tests get their dependencies from the root `node_modules/`.
|
||||
- *yarn_install
|
||||
# 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.
|
||||
- run: ./integration/run_tests.sh ${CIRCLE_NODE_INDEX} ${CIRCLE_NODE_TOTAL}
|
||||
|
||||
# This job updates the content of repos like github.com/angular/core-builds
|
||||
# for every green build on angular/angular.
|
||||
@ -388,17 +466,80 @@ jobs:
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *restore_cache
|
||||
- *define_env_vars
|
||||
- *download_yarn
|
||||
- run:
|
||||
name: Run tests against the deployed apps
|
||||
command: ./aio/scripts/test-production.sh $CI_AIO_MIN_PWA_SCORE
|
||||
- run:
|
||||
name: Notify caretaker about failure
|
||||
command: 'curl --request POST --header "Content-Type: application/json" --data "{\"text\":\":x: \`$CIRCLE_JOB\` job failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}" $CI_SECRET_SLACK_CARETAKER_WEBHOOK_URL'
|
||||
# `$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: 'curl --request POST --header "Content-Type: application/json" --data "{\"text\":\":x: \`$CIRCLE_JOB\` job failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}" $SLACK_CARETAKER_WEBHOOK_URL'
|
||||
when: on_fail
|
||||
|
||||
legacy-unit-tests-local:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
- image: *browsers_docker_image
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- *restore_cache
|
||||
- *define_env_vars
|
||||
- *download_yarn
|
||||
- *yarn_install
|
||||
- run: yarn tsc -p packages
|
||||
- run: yarn tsc -p modules
|
||||
- run: yarn karma start ./karma-js.conf.js --single-run --browsers=ChromeNoSandbox
|
||||
|
||||
legacy-unit-tests-saucelabs:
|
||||
<<: *job_defaults
|
||||
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
||||
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
||||
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- *restore_cache
|
||||
- *define_env_vars
|
||||
- *download_yarn
|
||||
- *yarn_install
|
||||
- run:
|
||||
name: Preparing environment for running tests on Saucelabs.
|
||||
command: |
|
||||
setPublicVar KARMA_JS_BROWSERS $(node -e 'console.log(require("./browser-providers.conf").sauceAliases.CI_REQUIRED.join(","))')
|
||||
setSecretVar SAUCE_ACCESS_KEY $(echo $SAUCE_ACCESS_KEY | rev)
|
||||
- run:
|
||||
name: Starting Saucelabs tunnel
|
||||
command: ./scripts/saucelabs/start-tunnel.sh
|
||||
background: true
|
||||
- run: yarn tsc -p packages
|
||||
- run: yarn tsc -p modules
|
||||
# Waits for the Saucelabs tunnel to be ready. This ensures that we don't run tests
|
||||
# too early without Saucelabs not being ready.
|
||||
- run: ./scripts/saucelabs/wait-for-tunnel.sh
|
||||
- run: yarn karma start ./karma-js.conf.js --single-run --browsers=${KARMA_JS_BROWSERS}
|
||||
- run: ./scripts/saucelabs/stop-tunnel.sh
|
||||
|
||||
legacy-misc-tests:
|
||||
<<: *job_defaults
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- *restore_cache
|
||||
- *define_env_vars
|
||||
- *download_yarn
|
||||
- *yarn_install
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- run: yarn gulp check-cycle
|
||||
# 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
|
||||
# - run: yarn gulp source-map-test
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
default_workflow:
|
||||
@ -406,23 +547,31 @@ workflows:
|
||||
- lint
|
||||
- test
|
||||
- test_ivy_aot
|
||||
- build-packages-dist
|
||||
- build-npm-packages
|
||||
- test_aio
|
||||
- legacy-unit-tests-local
|
||||
- legacy-unit-tests-saucelabs
|
||||
- deploy_aio:
|
||||
requires:
|
||||
- test_aio
|
||||
- legacy-misc-tests:
|
||||
requires:
|
||||
- build-npm-packages
|
||||
- test_aio_local:
|
||||
requires:
|
||||
- build-packages-dist
|
||||
- build-npm-packages
|
||||
# - test_aio_local_ivy:
|
||||
# requires:
|
||||
# - build-npm-packages
|
||||
- test_aio_tools:
|
||||
requires:
|
||||
- build-packages-dist
|
||||
- test_docs_examples_0:
|
||||
- build-npm-packages
|
||||
- test_docs_examples:
|
||||
requires:
|
||||
- build-packages-dist
|
||||
- test_docs_examples_1:
|
||||
requires:
|
||||
- build-packages-dist
|
||||
- build-npm-packages
|
||||
# - test_docs_examples_ivy:
|
||||
# requires:
|
||||
# - build-npm-packages
|
||||
- aio_preview:
|
||||
# Only run on PR builds. (There can be no previews for non-PR builds.)
|
||||
filters:
|
||||
@ -433,7 +582,7 @@ workflows:
|
||||
- aio_preview
|
||||
- integration_test:
|
||||
requires:
|
||||
- build-packages-dist
|
||||
- build-npm-packages
|
||||
- publish_snapshot:
|
||||
# Note: no filters on this job because we want it to run for all upstream branches
|
||||
# We'd really like to filter out pull requests here, but not yet available:
|
||||
@ -446,11 +595,16 @@ workflows:
|
||||
- integration_test
|
||||
# Only publish if `aio`/`docs` tests using the locally built Angular packages pass
|
||||
- test_aio_local
|
||||
- test_docs_examples_0
|
||||
- test_docs_examples_1
|
||||
# - test_aio_local_ivy
|
||||
- test_docs_examples
|
||||
# - test_docs_examples_ivy
|
||||
# Get the artifacts to publish from the build-packages-dist job
|
||||
# since the publishing script expects the legacy outputs layout.
|
||||
- build-packages-dist
|
||||
- build-npm-packages
|
||||
- legacy-misc-tests
|
||||
- legacy-unit-tests-local
|
||||
- legacy-unit-tests-saucelabs
|
||||
|
||||
|
||||
aio_monitoring:
|
||||
jobs:
|
||||
@ -462,3 +616,9 @@ workflows:
|
||||
branches:
|
||||
only:
|
||||
- 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
|
||||
|
@ -15,7 +15,7 @@
|
||||
#
|
||||
# Usage: `setPublicVar <name> <value>`
|
||||
function setPublicVar() {
|
||||
setSecretVar $1 $2;
|
||||
setSecretVar $1 "$2";
|
||||
echo "$1=$2";
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Load helpers and make them available everywhere (through `$BASH_ENV`).
|
||||
# Variables
|
||||
readonly envHelpersPath="`dirname $0`/env-helpers.inc.sh";
|
||||
readonly getCommitRangePath="`dirname $0`/get-commit-range.js";
|
||||
|
||||
# Load helpers and make them available everywhere (through `$BASH_ENV`).
|
||||
source $envHelpersPath;
|
||||
echo "source $envHelpersPath;" >> $BASH_ENV;
|
||||
|
||||
@ -9,17 +12,26 @@ echo "source $envHelpersPath;" >> $BASH_ENV;
|
||||
####################################################################################################
|
||||
# Define PUBLIC environment variables for CircleCI.
|
||||
####################################################################################################
|
||||
# See https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables for more info.
|
||||
####################################################################################################
|
||||
setPublicVar PROJECT_ROOT "$(pwd)";
|
||||
setPublicVar CI_AIO_MIN_PWA_SCORE "95";
|
||||
# This is the branch being built; e.g. `pull/12345` for PR builds.
|
||||
setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
|
||||
# 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.
|
||||
# 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"`).
|
||||
setPublicVar CI_CHROMEDRIVER_VERSION_ARG "--versions.chrome 2.45";
|
||||
setPublicVar CI_COMMIT "$CIRCLE_SHA1";
|
||||
# `CI_COMMIT_RANGE` will only be available when `CIRCLE_COMPARE_URL` is also available,
|
||||
# i.e. on push builds (a.k.a. non-PR builds). That is fine, since we only need it in push builds.
|
||||
setPublicVar CI_COMMIT_RANGE "$(sed -r 's|^.*/([0-9a-f]+\.\.\.[0-9a-f]+)$|\1|i' <<< ${CIRCLE_COMPARE_URL:-})";
|
||||
# `CI_COMMIT_RANGE` will only be available when `CIRCLE_COMPARE_URL` is also available (or can be
|
||||
# retrieved via `get-compare-url.js`), i.e. on push builds (a.k.a. non-PR, non-scheduled builds and
|
||||
# rerun workflows of such builds). That is fine, since we only need it in push builds.
|
||||
setPublicVar CI_COMMIT_RANGE "`[[ ${CIRCLE_PR_NUMBER:-false} != false ]] && echo "" || node $getCommitRangePath "$CIRCLE_BUILD_NUM" "$CIRCLE_COMPARE_URL"`";
|
||||
setPublicVar CI_PULL_REQUEST "${CIRCLE_PR_NUMBER:-false}";
|
||||
setPublicVar CI_REPO_NAME "$CIRCLE_PROJECT_REPONAME";
|
||||
setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
|
||||
setPublicVar CI_YARN_VERSION "1.13.0";
|
||||
|
||||
|
||||
####################################################################################################
|
||||
@ -27,8 +39,27 @@ setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
|
||||
####################################################################################################
|
||||
setSecretVar CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN "$AIO_DEPLOY_TOKEN";
|
||||
setSecretVar CI_SECRET_PAYLOAD_FIREBASE_TOKEN "$ANGULAR_PAYLOAD_TOKEN";
|
||||
# Defined in https://angular-team.slack.com/apps/A0F7VRE7N-circleci.
|
||||
setSecretVar CI_SECRET_SLACK_CARETAKER_WEBHOOK_URL "$SLACK_CARETAKER_WEBHOOK_URL";
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Define SauceLabs environment variables for CircleCI.
|
||||
####################################################################################################
|
||||
# In order to have a meaningful SauceLabs badge on the repo page,
|
||||
# the angular2-ci account is used only when pushing commits to master;
|
||||
# in all other cases, the regular angular-ci account is used.
|
||||
if [ "${CI_PULL_REQUEST}" = "false" ] && [ "${CI_REPO_OWNER}" = "angular" ] && [ "${CI_BRANCH}" = "master" ]; then
|
||||
setPublicVar SAUCE_USERNAME "angular2-ci";
|
||||
setSecretVar SAUCE_ACCESS_KEY "693ebc16208a-0b5b-1614-8d66-a2662f4e";
|
||||
else
|
||||
setPublicVar SAUCE_USERNAME "angular-ci";
|
||||
setSecretVar SAUCE_ACCESS_KEY "9b988f434ff8-fbca-8aa4-4ae3-35442987";
|
||||
fi
|
||||
setPublicVar SAUCE_READY_FILE /tmp/angular/sauce-connect-ready-file.lock
|
||||
setPublicVar SAUCE_PID_FILE /tmp/angular/sauce-connect-pid-file.lock
|
||||
setPublicVar SAUCE_TUNNEL_IDENTIFIER "angular-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_INDEX}"
|
||||
# Amount of seconds we wait for sauceconnect to establish a tunnel instance. In order to not
|
||||
# acquire CircleCI instances for too long if sauceconnect failed, we need a connect timeout.
|
||||
setPublicVar SAUCE_READY_FILE_TIMEOUT 120
|
||||
|
||||
|
||||
# Source `$BASH_ENV` to make the variables available immediately.
|
||||
|
159
.circleci/get-commit-range.js
Normal file
159
.circleci/get-commit-range.js
Normal file
@ -0,0 +1,159 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* **Usage:**
|
||||
* ```
|
||||
* node get-commit-range <build-number> [<compare-url> [<circle-token>]]
|
||||
* ```
|
||||
*
|
||||
* Returns the value of the `CIRCLE_COMPARE_URL` environment variable (if defined) or, if this is
|
||||
* not a PR build (i.e. `CIRCLE_PR_NUMBER` is not defined), retrieves the equivalent of
|
||||
* `CIRCLE_COMPARE_URL` for jobs that are part of a rerun workflow.
|
||||
*
|
||||
* **Context:**
|
||||
* 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
|
||||
* (either from the beginning or from failed jobs) - e.g. when a job flakes - CircleCI does not set
|
||||
* the `CIRCLE_COMPARE_URL`.
|
||||
*
|
||||
* **Implementation details:**
|
||||
* This script relies on the fact that all rerun workflows share the same CircleCI workspace and the
|
||||
* (undocumented) fact that the workspace ID happens to be the same as the workflow ID that first
|
||||
* created it.
|
||||
*
|
||||
* For example, for a job on push build workflow, the CircleCI API will return data that look like:
|
||||
* ```js
|
||||
* {
|
||||
* compare: 'THE_COMPARE_URL_WE_ARE_LOOKING_FOR',
|
||||
* //...
|
||||
* previous: {
|
||||
* // ...
|
||||
* build_num: 12345,
|
||||
* },
|
||||
* //...
|
||||
* workflows: {
|
||||
* //...
|
||||
* workflow_id: 'SOME_ID_A',
|
||||
* workspace_id: 'SOME_ID_A', // Same as `workflow_id`.
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* If the workflow is rerun, the data for jobs on the new workflow will look like:
|
||||
* ```js
|
||||
* {
|
||||
* compare: null, // ¯\_(ツ)_/¯
|
||||
* //...
|
||||
* previous: {
|
||||
* // ...
|
||||
* build_num: 23456,
|
||||
* },
|
||||
* //...
|
||||
* workflows: {
|
||||
* //...
|
||||
* workflow_id: 'SOME_ID_B',
|
||||
* workspace_id: 'SOME_ID_A', // Different from current `workflow_id`.
|
||||
* // Same as original `workflow_id`. \o/
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* This script uses the `previous.build_num` (which points to the previous build number on the same
|
||||
* branch) to traverse the jobs backwards, until it finds a job from the original workflow. Such a
|
||||
* job (if found) should also contain the compare URL.
|
||||
*
|
||||
* **NOTE 1:**
|
||||
* This is only useful on workflows which are created by rerunning a workflow for which
|
||||
* `CIRCLE_COMPARE_URL` was defined.
|
||||
*
|
||||
* **NOTE 2:**
|
||||
* The `circleToken` will be used for CircleCI API requests if provided, but it is not needed for
|
||||
* accessing the read-only endpoints that we need (as long as the current project is FOSS and the
|
||||
* corresponding setting is turned on in "Advanced Settings" in the project dashboard).
|
||||
*
|
||||
* ---
|
||||
* Inspired by https://circleci.com/orbs/registry/orb/iynere/compare-url
|
||||
* (source code: https://github.com/iynere/compare-url-orb).
|
||||
*
|
||||
* We are not using the `compare-url` orb for the following reasons:
|
||||
* 1. (By looking at the code) it would only work if the rerun workflow is the latest workflow on
|
||||
* the branch (which is not guaranteed to be true).
|
||||
* 2. It is less efficient (e.g. makes unnecessary CircleCI API requests for builds on different
|
||||
* branches, installs extra dependencies, persists files to the workspace (as a means of passing
|
||||
* the result to the calling job), etc.).
|
||||
* 3. It is slightly more complicated to setup and consume than our own script.
|
||||
* 4. Its implementation is more complicated than needed for our usecase (e.g. handles different git
|
||||
* providers, handles newly created branches, etc.).
|
||||
*/
|
||||
|
||||
// Imports
|
||||
const {get: httpsGet} = require('https');
|
||||
|
||||
// Constants
|
||||
const API_URL_BASE = 'https://circleci.com/api/v1.1/project/github/angular/angular';
|
||||
const COMPARE_URL_RE = /^.*\/([0-9a-f]+\.\.\.[0-9a-f]+)$/i;
|
||||
|
||||
// Run
|
||||
_main(process.argv.slice(2));
|
||||
|
||||
// Helpers
|
||||
async function _main([buildNumber, compareUrl = '', circleToken = '']) {
|
||||
try {
|
||||
if (!buildNumber || isNaN(buildNumber)) {
|
||||
throw new Error(
|
||||
'Missing or invalid arguments.\n' +
|
||||
'Expected: buildNumber (number), compareUrl? (string), circleToken? (string)');
|
||||
}
|
||||
|
||||
if (!compareUrl) {
|
||||
compareUrl = await getCompareUrl(buildNumber, circleToken);
|
||||
}
|
||||
|
||||
const commitRangeMatch = COMPARE_URL_RE.exec(compareUrl)
|
||||
const commitRange = commitRangeMatch ? commitRangeMatch[1] : '';
|
||||
|
||||
console.log(commitRange);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
function getBuildInfo(buildNumber, circleToken) {
|
||||
console.error(`BUILD ${buildNumber}`);
|
||||
const url = `${API_URL_BASE}/${buildNumber}?circle-token=${circleToken}`;
|
||||
return getJson(url);
|
||||
}
|
||||
|
||||
async function getCompareUrl(buildNumber, circleToken) {
|
||||
let info = await getBuildInfo(buildNumber, circleToken);
|
||||
const targetWorkflowId = info.workflows.workspace_id;
|
||||
|
||||
while (info.workflows.workflow_id !== targetWorkflowId) {
|
||||
info = await getBuildInfo(info.previous.build_num, circleToken);
|
||||
}
|
||||
|
||||
return info.compare || '';
|
||||
}
|
||||
|
||||
function getJson(url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const opts = {headers: {Accept: 'application/json'}};
|
||||
const onResponse = res => {
|
||||
const statusCode = res.statusCode || -1;
|
||||
const isSuccess = (200 <= statusCode) && (statusCode <= 400);
|
||||
let responseText = '';
|
||||
|
||||
res.
|
||||
on('error', reject).
|
||||
on('data', d => responseText += d).
|
||||
on('end', () => isSuccess ?
|
||||
resolve(JSON.parse(responseText)) :
|
||||
reject(`Error getting '${url}' (status ${statusCode}):\n${responseText}`));
|
||||
};
|
||||
|
||||
httpsGet(url, opts, onResponse).
|
||||
on('error', reject).
|
||||
end();
|
||||
});
|
||||
}
|
21
.github/CODEOWNERS
vendored
21
.github/CODEOWNERS
vendored
@ -54,6 +54,7 @@
|
||||
# kara - Kara Erickson
|
||||
# kyliau - Keen Yee Liau
|
||||
# matsko - Matias Niemelä
|
||||
# mgechev - Minko Gechev
|
||||
# mhevery - Misko Hevery
|
||||
# ocombe - Olivier Combe
|
||||
# petebacondarwin - Pete Bacon Darwin
|
||||
@ -93,6 +94,7 @@
|
||||
# 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)
|
||||
#
|
||||
# - brandonroberts
|
||||
# - gkalpak
|
||||
# - jenniferfell
|
||||
# - petebacondarwin
|
||||
@ -112,6 +114,7 @@
|
||||
# - alexeagle
|
||||
# - kyliau
|
||||
# - IgorMinar
|
||||
# - mgechev
|
||||
|
||||
|
||||
# ===========================================================
|
||||
@ -121,6 +124,7 @@
|
||||
# - alexeagle
|
||||
# - filipesilva
|
||||
# - hansl
|
||||
# - mgechev
|
||||
|
||||
|
||||
# ===========================================================
|
||||
@ -258,6 +262,7 @@
|
||||
# @angular/docs-infra
|
||||
# ===========================================================
|
||||
#
|
||||
# - brandonroberts
|
||||
# - gkalpak
|
||||
# - IgorMinar
|
||||
# - petebacondarwin
|
||||
@ -730,14 +735,6 @@ testing/** @angular/fw-test
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# Public API
|
||||
# ================================================
|
||||
|
||||
/tools/public_api_guard/** @angular/fw-public-api
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# Build & CI Owners
|
||||
# ================================================
|
||||
@ -754,6 +751,14 @@ testing/** @angular/fw-test
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# Public API
|
||||
# ================================================
|
||||
|
||||
/tools/public_api_guard/** @angular/fw-public-api
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# CODEOWNERS Owners owners ...
|
||||
# ================================================
|
||||
|
7
.github/angular-robot.yml
vendored
7
.github/angular-robot.yml
vendored
@ -58,7 +58,6 @@ merge:
|
||||
- "**/package.json"
|
||||
- "**/tsconfig-build.json"
|
||||
- "**/tsconfig.json"
|
||||
- "**/rollup.config.js"
|
||||
- "**/BUILD.bazel"
|
||||
- "**/*.md"
|
||||
- "packages/**/integrationtest/**"
|
||||
@ -101,9 +100,13 @@ merge:
|
||||
|
||||
# list of PR statuses that need to be successful
|
||||
requiredStatuses:
|
||||
- "continuous-integration/travis-ci/pr"
|
||||
- "ci/circleci: build"
|
||||
- "ci/circleci: lint"
|
||||
- "ci/circleci: publish_snapshot"
|
||||
- "ci/angular: size"
|
||||
- "cla/google"
|
||||
- "google3"
|
||||
|
||||
|
||||
# the comment that will be added when the merge label is added despite failing checks, leave empty or set to false to disable
|
||||
# {{MERGE_LABEL}} will be replaced by the value of the mergeLabel option
|
||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,7 +1,7 @@
|
||||
.DS_STORE
|
||||
|
||||
/dist/
|
||||
/bazel-*
|
||||
/bazel-out/
|
||||
/integration/bazel/bazel-*
|
||||
e2e_test.*
|
||||
node_modules
|
||||
@ -13,9 +13,9 @@ pubspec.lock
|
||||
.c9
|
||||
.idea/
|
||||
.settings/
|
||||
.vscode/launch.json
|
||||
*.swo
|
||||
modules/.settings
|
||||
.vscode
|
||||
modules/.vscode
|
||||
|
||||
# Don't check in secret files
|
||||
|
66
.travis.yml
66
.travis.yml
@ -1,66 +0,0 @@
|
||||
language: node_js
|
||||
sudo: false
|
||||
dist: trusty
|
||||
node_js:
|
||||
- '10.9.0'
|
||||
|
||||
addons:
|
||||
# firefox: "38.0"
|
||||
apt:
|
||||
sources:
|
||||
# needed to install g++ that is used by npms's native modules
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
# needed to install g++ that is used by npms's native modules
|
||||
- g++-4.8
|
||||
|
||||
branches:
|
||||
except:
|
||||
- g3
|
||||
|
||||
cache:
|
||||
yarn: true
|
||||
directories:
|
||||
- ./node_modules
|
||||
- ./.chrome/chromium
|
||||
- ./aio/node_modules
|
||||
|
||||
env:
|
||||
global:
|
||||
# GITHUB_TOKEN_ANGULAR=<github token, a personal access token of the angular-builds account, account access in valentine>
|
||||
# This is needed for the e2e Travis matrix task to publish packages to github for continuous packages delivery.
|
||||
- secure: "aCdHveZuY8AT4Jr1JoJB4LxZsnGWRe/KseZh1YXYe5UtufFCtTVHvUcLn0j2aLBF0KpdyS+hWf0i4np9jthKu2xPKriefoPgCMpisYeC0MFkwbmv+XlgkUbgkgVZMGiVyX7DCYXVahxIoOUjVMEDCbNiHTIrfEuyq24U3ok2tHc="
|
||||
matrix:
|
||||
# Order: a slower build first, so that we don't occupy an idle travis worker waiting for others to complete.
|
||||
- CI_MODE=e2e
|
||||
- CI_MODE=js
|
||||
- CI_MODE=saucelabs_required
|
||||
# deactivated, see #19768
|
||||
# - CI_MODE=browserstack_required
|
||||
|
||||
# We disable these optional jobs because those acquire tunnel and browser instances which
|
||||
# could lead to rate limit excess while those are failing most of the time and nobody pays
|
||||
# attention anyway.
|
||||
# - CI_MODE=saucelabs_optional
|
||||
# - CI_MODE=browserstack_optional
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- env: "CI_MODE=saucelabs_optional"
|
||||
- env: "CI_MODE=browserstack_optional"
|
||||
|
||||
before_install:
|
||||
# source the env.sh script so that the exported variables are available to other scripts later on
|
||||
- source ./scripts/ci/env.sh print
|
||||
|
||||
install:
|
||||
- ./scripts/ci/install.sh
|
||||
|
||||
script:
|
||||
- ./scripts/ci/build.sh
|
||||
- ./scripts/ci/test.sh
|
||||
- ./scripts/ci/angular.sh
|
||||
# all the scripts under this line will not quickly abort in case ${TRAVIS_TEST_RESULT} is 1 (job failure)
|
||||
- ./scripts/ci/cleanup.sh
|
||||
- ./scripts/ci/print-logs.sh
|
15
.vscode/settings.json
vendored
Normal file
15
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"files.watcherExclude": {
|
||||
"**/.git/objects/**": true,
|
||||
"**/.git/subtree-cache/**": true,
|
||||
"**/node_modules/**": true,
|
||||
"**/bazel-out/**": true,
|
||||
"**/dist/**": true,
|
||||
},
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
"**/bower_components": true,
|
||||
"**/bazel-out": true,
|
||||
"**/dist": true,
|
||||
},
|
||||
}
|
190
CHANGELOG.md
190
CHANGELOG.md
@ -1,39 +1,145 @@
|
||||
<a name="7.2.0"></a>
|
||||
# [7.2.0](https://github.com/angular/angular/compare/7.2.0-rc.0...7.2.0) (2019-01-07)
|
||||
<a name="7.2.5"></a>
|
||||
## [7.2.5](https://github.com/angular/angular/compare/7.2.4...7.2.5) (2019-02-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** unable to launch protractor test on windows ([#27850](https://github.com/angular/angular/issues/27850)) ([1e6c9be](https://github.com/angular/angular/commit/1e6c9be))
|
||||
* **compiler-cli:** diagnostics should respect "newLine" compiler option ([#28550](https://github.com/angular/angular/issues/28550)) ([ce750e6](https://github.com/angular/angular/commit/ce750e6))
|
||||
* **router:** redirect to root url when returned as UrlTree from guard ([#28271](https://github.com/angular/angular/issues/28271)) ([1e58a21](https://github.com/angular/angular/commit/1e58a21)), closes [#27845](https://github.com/angular/angular/issues/27845)
|
||||
* **router:** set href when routerLink is used on an 'area' element ([#28441](https://github.com/angular/angular/issues/28441)) ([d491a20](https://github.com/angular/angular/commit/d491a20)), closes [#28401](https://github.com/angular/angular/issues/28401)
|
||||
|
||||
|
||||
|
||||
<a name="7.2.4"></a>
|
||||
## [7.2.4](https://github.com/angular/angular/compare/7.2.3...7.2.4) (2019-02-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** Bazel builder resolves with require.resolve() ([#28478](https://github.com/angular/angular/issues/28478)) ([d85d396](https://github.com/angular/angular/commit/d85d396))
|
||||
* **bazel:** fix integration test for bazel-schematics ([#28460](https://github.com/angular/angular/issues/28460)) ([449da8c](https://github.com/angular/angular/commit/449da8c))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* pngcrush all pngs ([#28479](https://github.com/angular/angular/issues/28479)) ([1a25144](https://github.com/angular/angular/commit/1a25144)), closes [#18243](https://github.com/angular/angular/issues/18243)
|
||||
|
||||
|
||||
|
||||
<a name="7.2.3"></a>
|
||||
## [7.2.3](https://github.com/angular/angular/compare/7.2.2...7.2.3) (2019-01-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** add [@npm](https://github.com/npm)//tslib dep to e2e ts_library target in bazel-workspace schematic ([#28358](https://github.com/angular/angular/issues/28358)) ([8cee56e](https://github.com/angular/angular/commit/8cee56e))
|
||||
* **bazel:** Bazel-workspace schematics should run in ScopedTree ([#28349](https://github.com/angular/angular/issues/28349)) ([260ac20](https://github.com/angular/angular/commit/260ac20))
|
||||
* **bazel:** Builder should invoke local bazel/iblaze ([#28303](https://github.com/angular/angular/issues/28303)) ([12b8a6e](https://github.com/angular/angular/commit/12b8a6e))
|
||||
* **bazel:** ng-new should run yarn install ([#28381](https://github.com/angular/angular/issues/28381)) ([a9d46e4](https://github.com/angular/angular/commit/a9d46e4))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* yarn version upgrade ([#28360](https://github.com/angular/angular/issues/28360)) ([cc1b2a5](https://github.com/angular/angular/commit/cc1b2a5))
|
||||
|
||||
|
||||
|
||||
<a name="7.2.2"></a>
|
||||
## [7.2.2](https://github.com/angular/angular/compare/7.2.1...7.2.2) (2019-01-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** Fix integration test after v8 bump ([#28194](https://github.com/angular/angular/issues/28194)) ([7b772e9](https://github.com/angular/angular/commit/7b772e9)), closes [#28142](https://github.com/angular/angular/issues/28142)
|
||||
* **router:** `skipLocationChange` with named outlets ([#28301](https://github.com/angular/angular/issues/28301)) ([32737a6](https://github.com/angular/angular/commit/32737a6)), closes [#27680](https://github.com/angular/angular/issues/27680) [#28200](https://github.com/angular/angular/issues/28200)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **bazel:** Add support for SASS ([#28167](https://github.com/angular/angular/issues/28167)) ([a4d9192](https://github.com/angular/angular/commit/a4d9192))
|
||||
* **compiler-cli:** resolve generated Sass/Less files to .css inputs ([#28166](https://github.com/angular/angular/issues/28166)) ([4c00059](https://github.com/angular/angular/commit/4c00059))
|
||||
|
||||
|
||||
|
||||
<a name="7.2.1"></a>
|
||||
## [7.2.1](https://github.com/angular/angular/compare/7.2.0...7.2.1) (2019-01-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** Add [@bazel](https://github.com/bazel)/bazel to dev deps ([#28032](https://github.com/angular/angular/issues/28032)) ([21093b9](https://github.com/angular/angular/commit/21093b9))
|
||||
* **bazel:** Add /bazel-out to .gitignore ([#27874](https://github.com/angular/angular/issues/27874)) ([e4fc8ba](https://github.com/angular/angular/commit/e4fc8ba))
|
||||
* **bazel:** Add ibazel to deps of Bazel project ([#28090](https://github.com/angular/angular/issues/28090)) ([28d34b6](https://github.com/angular/angular/commit/28d34b6))
|
||||
* **bazel:** Bazel schematics should add router package ([#28141](https://github.com/angular/angular/issues/28141)) ([02a852a](https://github.com/angular/angular/commit/02a852a))
|
||||
* **bazel:** flat module misses AMD module name on windows ([#27839](https://github.com/angular/angular/issues/27839)) ([c3d8e28](https://github.com/angular/angular/commit/c3d8e28))
|
||||
* **bazel:** incorrectly always uses ngc-wrapped from "npm" workspace ([#28137](https://github.com/angular/angular/issues/28137)) ([ca3965a](https://github.com/angular/angular/commit/ca3965a))
|
||||
* **bazel:** ng_package creates invalid typings reexport on windows ([#27829](https://github.com/angular/angular/issues/27829)) ([6b394f6](https://github.com/angular/angular/commit/6b394f6))
|
||||
* **bazel:** packager not properly removing amd directives on windows ([#27829](https://github.com/angular/angular/issues/27829)) ([fad4145](https://github.com/angular/angular/commit/fad4145))
|
||||
* **bazel:** protractor rule does not run spec files with underscore ([#28022](https://github.com/angular/angular/issues/28022)) ([f05c5f8](https://github.com/angular/angular/commit/f05c5f8))
|
||||
* **bazel:** protractor utils cannot start server on windows ([#27915](https://github.com/angular/angular/issues/27915)) ([0be8487](https://github.com/angular/angular/commit/0be8487))
|
||||
* **bazel:** replay compilation uses wrong compiler for building esm5 ([#28053](https://github.com/angular/angular/issues/28053)) ([fbbdaaa](https://github.com/angular/angular/commit/fbbdaaa))
|
||||
* **router:** ensure URL is updated after second redirect with UrlUpdateStrategy="eager" ([#27680](https://github.com/angular/angular/issues/27680)) ([6ae7aee](https://github.com/angular/angular/commit/6ae7aee)), closes [#27116](https://github.com/angular/angular/issues/27116)
|
||||
* **service-worker:** navigation urls backwards compatibility ([#27244](https://github.com/angular/angular/issues/27244)) ([585e871](https://github.com/angular/angular/commit/585e871))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **platform-server:** use shared `DomElementSchemaRegistry` instance ([#28150](https://github.com/angular/angular/issues/28150)) ([#28151](https://github.com/angular/angular/issues/28151)) ([6851581](https://github.com/angular/angular/commit/6851581))
|
||||
|
||||
|
||||
|
||||
<a name="7.2.0"></a>
|
||||
# [7.2.0](https://github.com/angular/angular/compare/7.1.4...7.2.0) (2019-01-07)
|
||||
|
||||
7.2.0 release also contains all the fixes released in 7.1.4.
|
||||
|
||||
### Features
|
||||
|
||||
* add support for typescript 3.2 ([#27536](https://github.com/angular/angular/issues/27536)) ([17e702b](https://github.com/angular/angular/commit/17e702b))
|
||||
* **bazel:** ng-new schematics with Bazel ([#27277](https://github.com/angular/angular/issues/27277)) ([06d4a0c](https://github.com/angular/angular/commit/06d4a0c))
|
||||
* **forms:** match getError and hasError to get method signature ([#20211](https://github.com/angular/angular/issues/20211)) ([1b0b36d](https://github.com/angular/angular/commit/1b0b36d))
|
||||
* **upgrade:** allow nesting components from different downgraded modules ([#27217](https://github.com/angular/angular/issues/27217)) ([bc0ee01](https://github.com/angular/angular/commit/bc0ee01))
|
||||
* **upgrade:** correctly handle nested downgraded components with `downgradeModule()` ([#27217](https://github.com/angular/angular/issues/27217)) ([326b464](https://github.com/angular/angular/commit/326b464)), closes [#22581](https://github.com/angular/angular/issues/22581) [#22869](https://github.com/angular/angular/issues/22869) [#27083](https://github.com/angular/angular/issues/27083)
|
||||
|
||||
|
||||
<a name="7.2.0-rc.0"></a>
|
||||
# [7.2.0-rc.0](https://github.com/angular/angular/compare/7.2.0-beta.2...7.2.0-rc.0) (2018-12-18)
|
||||
* **router:** add predicate function mode for runGuardsAndResolvers ([#27682](https://github.com/angular/angular/issues/27682)) ([12c3176](https://github.com/angular/angular/commit/12c3176)), closes [#26861](https://github.com/angular/angular/issues/26861) [#18253](https://github.com/angular/angular/issues/18253) [#27464](https://github.com/angular/angular/issues/27464)
|
||||
* **router:** add a Navigation type available during navigation ([#27198](https://github.com/angular/angular/issues/27198)) ([d40af0c](https://github.com/angular/angular/commit/d40af0c))
|
||||
* **router:** add pathParamsOrQueryParamsChange mode for runGuardsAndResolvers ([#27464](https://github.com/angular/angular/issues/27464)) ([d70a7f3](https://github.com/angular/angular/commit/d70a7f3)), closes [#26861](https://github.com/angular/angular/issues/26861) [#18253](https://github.com/angular/angular/issues/18253)
|
||||
* **router:** allow passing `state` to routerLink directives ([#27198](https://github.com/angular/angular/issues/27198)) ([73f6ed9](https://github.com/angular/angular/commit/73f6ed9)), closes [#24617](https://github.com/angular/angular/issues/24617)
|
||||
* **router:** allow passing state to `NavigationExtras` ([#27198](https://github.com/angular/angular/issues/27198)) ([67f4a5d](https://github.com/angular/angular/commit/67f4a5d))
|
||||
* **router:** restore whole object when navigating back to a page managed by Angular router ([#27198](https://github.com/angular/angular/issues/27198)) ([2684249](https://github.com/angular/angular/commit/2684249))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **animations:** do not truncate decimals for delay ([#24455](https://github.com/angular/angular/issues/24455)) ([f1c9d6a](https://github.com/angular/angular/commit/f1c9d6a))
|
||||
* **animations:** mark actual descendant node as disabled ([#26180](https://github.com/angular/angular/issues/26180)) ([df123e0](https://github.com/angular/angular/commit/df123e0))
|
||||
* **bazel:** unable to launch protractor test on windows ([#27850](https://github.com/angular/angular/issues/27850)) ([1e6c9be](https://github.com/angular/angular/commit/1e6c9be))
|
||||
* **bazel:** devserver entry_module should have underscore name ([#27719](https://github.com/angular/angular/issues/27719)) ([f57916c](https://github.com/angular/angular/commit/f57916c))
|
||||
* **bazel:** emit full node stack traces when Angular compilation crashes ([#27678](https://github.com/angular/angular/issues/27678)) ([522919a](https://github.com/angular/angular/commit/522919a))
|
||||
* **bazel:** fix major/minor semver check between [@angular](https://github.com/angular)/bazel npm packager version and angular bazel repo version ([#27635](https://github.com/angular/angular/issues/27635)) ([1cc08b4](https://github.com/angular/angular/commit/1cc08b4))
|
||||
* **bazel:** Load http_archive and rules_nodejs dependencies ([#27609](https://github.com/angular/angular/issues/27609)) ([8313ffc](https://github.com/angular/angular/commit/8313ffc))
|
||||
* **bazel:** ng_package writes unrelevant definitions to bazel out ([#27519](https://github.com/angular/angular/issues/27519)) ([44dfa60](https://github.com/angular/angular/commit/44dfa60)), closes [/github.com/angular/angular/blob/4f9374951d67c75f67a31c110bd61ab72563db7d/packages/bazel/src/ng_package/packager.ts#L105-L124](https://github.com//github.com/angular/angular/blob/4f9374951d67c75f67a31c110bd61ab72563db7d/packages/bazel/src/ng_package/packager.ts/issues/L105-L124)
|
||||
* **bazel:** Set module_name and enable ng test ([#27715](https://github.com/angular/angular/issues/27715)) ([85866de](https://github.com/angular/angular/commit/85866de))
|
||||
* **bazel:** fix TS errors in the `schematics/bazel-workspace` files ([#27600](https://github.com/angular/angular/issues/27600)) ([3290fc3](https://github.com/angular/angular/commit/3290fc3))
|
||||
* **bazel:** Read latest versions from latest-versions.ts & use semver check ([#27526](https://github.com/angular/angular/issues/27526)) ([30a3b49](https://github.com/angular/angular/commit/30a3b49))
|
||||
* **bazel:** tsickle dependency not working with typescript 3.1.x ([#27402](https://github.com/angular/angular/issues/27402)) ([f034114](https://github.com/angular/angular/commit/f034114))
|
||||
* **bazel:** do not throw error when writing tsickle externs ([#27200](https://github.com/angular/angular/issues/27200)) ([20a2bae](https://github.com/angular/angular/commit/20a2bae))
|
||||
* **bazel:** do not throw if ts compile action does not create esm5 outputs ([#27401](https://github.com/angular/angular/issues/27401)) ([c61a8b7](https://github.com/angular/angular/commit/c61a8b7))
|
||||
* **bazel:** ng_package cannot be run multiple times without clean ([#27200](https://github.com/angular/angular/issues/27200)) ([4f93749](https://github.com/angular/angular/commit/4f93749))
|
||||
* **bazel:** ng_package not generating UMD bundles on windows ([#27200](https://github.com/angular/angular/issues/27200)) ([7d59880](https://github.com/angular/angular/commit/7d59880))
|
||||
* **bazel:** ng_package should correctly map to source maps in secondary entry-points ([#27313](https://github.com/angular/angular/issues/27313)) ([eb17502](https://github.com/angular/angular/commit/eb17502)), closes [#25510](https://github.com/angular/angular/issues/25510)
|
||||
* **bazel:** Respect existing angular installation ([#27495](https://github.com/angular/angular/issues/27495)) ([4da739a](https://github.com/angular/angular/commit/4da739a))
|
||||
* **common:** KeyValuePipe should return empty array for empty objects ([#27258](https://github.com/angular/angular/issues/27258)) ([b39efdd](https://github.com/angular/angular/commit/b39efdd))
|
||||
* **common:** expose request url in network error ([#27143](https://github.com/angular/angular/issues/27143)) ([1db53da](https://github.com/angular/angular/commit/1db53da)), closes [#27029](https://github.com/angular/angular/issues/27029)
|
||||
* **compiler-cli:** create LiteralLikeNode for String and Number literal ([#27536](https://github.com/angular/angular/issues/27536)) ([2c9b6c0](https://github.com/angular/angular/commit/2c9b6c0))
|
||||
* **compiler-cli:** flatModuleIndex files not generated on windows with multiple input files ([#27200](https://github.com/angular/angular/issues/27200)) ([d3c08e7](https://github.com/angular/angular/commit/d3c08e7))
|
||||
* **core:** export a value for InjectFlags ([#27279](https://github.com/angular/angular/issues/27279)) ([23b06af](https://github.com/angular/angular/commit/23b06af)), closes [#27251](https://github.com/angular/angular/issues/27251)
|
||||
* **core:** More precise return type for `InjectableDecorator` ([#27360](https://github.com/angular/angular/issues/27360)) ([4b9948c](https://github.com/angular/angular/commit/4b9948c)), closes [#26942](https://github.com/angular/angular/issues/26942)
|
||||
* **forms:** typed argument for FormBuilder group ([#26985](https://github.com/angular/angular/issues/26985)) ([b0c7561](https://github.com/angular/angular/commit/b0c7561))
|
||||
* **platform-server:** add [@angular](https://github.com/angular)/http to the list of peerDependencies ([#27307](https://github.com/angular/angular/issues/27307)) ([32c5be9](https://github.com/angular/angular/commit/32c5be9)), closes [#26154](https://github.com/angular/angular/issues/26154)
|
||||
* **router:** ensure URL is updated after second redirect with UrlUpdateStrategy="eager" ([#27523](https://github.com/angular/angular/issues/27523)) ([ad26cd6](https://github.com/angular/angular/commit/ad26cd6)), closes [#27116](https://github.com/angular/angular/issues/27116)
|
||||
* **router:** update URL after redirects when urlHandlingStrategy='eager' ([#27356](https://github.com/angular/angular/issues/27356)) ([11a8bd8](https://github.com/angular/angular/commit/11a8bd8)), closes [#27076](https://github.com/angular/angular/issues/27076)
|
||||
* **upgrade:** allow nesting components from different downgraded modules ([#27217](https://github.com/angular/angular/issues/27217)) ([bc0ee01](https://github.com/angular/angular/commit/bc0ee01))
|
||||
* **upgrade:** correctly handle nested downgraded components with `downgradeModule()` ([#27217](https://github.com/angular/angular/issues/27217)) ([326b464](https://github.com/angular/angular/commit/326b464)), closes [#22581](https://github.com/angular/angular/issues/22581) [#22869](https://github.com/angular/angular/issues/22869) [#27083](https://github.com/angular/angular/issues/27083)
|
||||
* **upgrade:** upgrade Directive facade should not return different instance from constructor ([#27660](https://github.com/angular/angular/issues/27660)) ([c986d3d](https://github.com/angular/angular/commit/c986d3d))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add support for typescript 3.2 ([#27536](https://github.com/angular/angular/issues/27536)) ([17e702b](https://github.com/angular/angular/commit/17e702b))
|
||||
* **router:** add predicate function mode for runGuardsAndResolvers ([#27682](https://github.com/angular/angular/issues/27682)) ([12c3176](https://github.com/angular/angular/commit/12c3176)), closes [#26861](https://github.com/angular/angular/issues/26861) [#18253](https://github.com/angular/angular/issues/18253) [#27464](https://github.com/angular/angular/issues/27464)
|
||||
* **upgrade:** don't rely upon the runtime to resolve forward refs ([#27132](https://github.com/angular/angular/issues/27132)) ([a4462c2](https://github.com/angular/angular/commit/a4462c2))
|
||||
|
||||
|
||||
|
||||
@ -56,19 +162,6 @@
|
||||
|
||||
|
||||
|
||||
<a name="7.2.0-beta.2"></a>
|
||||
# [7.2.0-beta.2](https://github.com/angular/angular/compare/7.2.0-beta.1...7.2.0-beta.2) (2018-12-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** fix TS errors in the `schematics/bazel-workspace` files ([#27600](https://github.com/angular/angular/issues/27600)) ([3290fc3](https://github.com/angular/angular/commit/3290fc3))
|
||||
* **bazel:** Read latest versions from latest-versions.ts & use semver check ([#27526](https://github.com/angular/angular/issues/27526)) ([30a3b49](https://github.com/angular/angular/commit/30a3b49))
|
||||
* **bazel:** tsickle dependency not working with typescript 3.1.x ([#27402](https://github.com/angular/angular/issues/27402)) ([f034114](https://github.com/angular/angular/commit/f034114))
|
||||
* **forms:** typed argument for FormBuilder group ([#26985](https://github.com/angular/angular/issues/26985)) ([b0c7561](https://github.com/angular/angular/commit/b0c7561))
|
||||
|
||||
|
||||
|
||||
<a name="7.1.3"></a>
|
||||
## [7.1.3](https://github.com/angular/angular/compare/7.1.2...7.1.3) (2018-12-11)
|
||||
|
||||
@ -95,47 +188,6 @@
|
||||
* **platform-server:** add [@angular](https://github.com/angular)/http to the list of peerDependencies ([#27307](https://github.com/angular/angular/issues/27307)) ([236ac06](https://github.com/angular/angular/commit/236ac06)), closes [#26154](https://github.com/angular/angular/issues/26154)
|
||||
|
||||
|
||||
<a name="7.2.0-beta.1"></a>
|
||||
# [7.2.0-beta.1](https://github.com/angular/angular/compare/7.1.0...7.2.0-beta.1) (2018-12-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** do not throw error when writing tsickle externs ([#27200](https://github.com/angular/angular/issues/27200)) ([20a2bae](https://github.com/angular/angular/commit/20a2bae))
|
||||
* **bazel:** do not throw if ts compile action does not create esm5 outputs ([#27401](https://github.com/angular/angular/issues/27401)) ([c61a8b7](https://github.com/angular/angular/commit/c61a8b7))
|
||||
* **bazel:** ng_package cannot be run multiple times without clean ([#27200](https://github.com/angular/angular/issues/27200)) ([4f93749](https://github.com/angular/angular/commit/4f93749))
|
||||
* **bazel:** ng_package not generating UMD bundles on windows ([#27200](https://github.com/angular/angular/issues/27200)) ([7d59880](https://github.com/angular/angular/commit/7d59880))
|
||||
* **bazel:** ng_package should correctly map to source maps in secondary entry-points ([#27313](https://github.com/angular/angular/issues/27313)) ([eb17502](https://github.com/angular/angular/commit/eb17502)), closes [#25510](https://github.com/angular/angular/issues/25510)
|
||||
* **bazel:** Respect existing angular installation ([#27495](https://github.com/angular/angular/issues/27495)) ([4da739a](https://github.com/angular/angular/commit/4da739a))
|
||||
* **common:** expose request url in network error ([#27143](https://github.com/angular/angular/issues/27143)) ([1db53da](https://github.com/angular/angular/commit/1db53da)), closes [#27029](https://github.com/angular/angular/issues/27029)
|
||||
* **compiler-cli:** flatModuleIndex files not generated on windows with multiple input files ([#27200](https://github.com/angular/angular/issues/27200)) ([d3c08e7](https://github.com/angular/angular/commit/d3c08e7))
|
||||
* **core:** export a value for InjectFlags ([#27279](https://github.com/angular/angular/issues/27279)) ([23b06af](https://github.com/angular/angular/commit/23b06af)), closes [#27251](https://github.com/angular/angular/issues/27251)
|
||||
* **core:** More precise return type for `InjectableDecorator` ([#27360](https://github.com/angular/angular/issues/27360)) ([4b9948c](https://github.com/angular/angular/commit/4b9948c)), closes [#26942](https://github.com/angular/angular/issues/26942)
|
||||
* **forms:** apply unicode flag to pattern attribute when supported ([#20819](https://github.com/angular/angular/issues/20819)) ([3c34b8b](https://github.com/angular/angular/commit/3c34b8b))
|
||||
* **platform-server:** add [@angular](https://github.com/angular)/http to the list of peerDependencies ([#27307](https://github.com/angular/angular/issues/27307)) ([32c5be9](https://github.com/angular/angular/commit/32c5be9)), closes [#26154](https://github.com/angular/angular/issues/26154)
|
||||
* **router:** update URL after redirects when urlHandlingStrategy='eager' ([#27356](https://github.com/angular/angular/issues/27356)) ([11a8bd8](https://github.com/angular/angular/commit/11a8bd8)), closes [#27076](https://github.com/angular/angular/issues/27076)
|
||||
* **upgrade:** don't rely upon the runtime to resolve forward refs ([#27132](https://github.com/angular/angular/issues/27132)) ([a4462c2](https://github.com/angular/angular/commit/a4462c2))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **bazel:** ng-new schematics with Bazel ([#27277](https://github.com/angular/angular/issues/27277)) ([06d4a0c](https://github.com/angular/angular/commit/06d4a0c))
|
||||
* **router:** add a Navigation type available during navigation ([#27198](https://github.com/angular/angular/issues/27198)) ([d40af0c](https://github.com/angular/angular/commit/d40af0c))
|
||||
* **router:** add pathParamsOrQueryParamsChange mode for runGuardsAndResolvers ([#27464](https://github.com/angular/angular/issues/27464)) ([d70a7f3](https://github.com/angular/angular/commit/d70a7f3)), closes [#26861](https://github.com/angular/angular/issues/26861) [#18253](https://github.com/angular/angular/issues/18253)
|
||||
* **router:** allow passing `state` to routerLink directives ([#27198](https://github.com/angular/angular/issues/27198)) ([73f6ed9](https://github.com/angular/angular/commit/73f6ed9)), closes [#24617](https://github.com/angular/angular/issues/24617)
|
||||
* **router:** allow passing state to `NavigationExtras` ([#27198](https://github.com/angular/angular/issues/27198)) ([67f4a5d](https://github.com/angular/angular/commit/67f4a5d))
|
||||
* **router:** restore whole object when navigating back to a page managed by Angular router ([#27198](https://github.com/angular/angular/issues/27198)) ([2684249](https://github.com/angular/angular/commit/2684249))
|
||||
|
||||
<a name="7.2.0-beta.0"></a>
|
||||
# [7.2.0-beta.0](https://github.com/angular/angular/compare/7.1.0...7.2.0-beta.0) (2018-11-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **common:** expose request url in network error ([#27143](https://github.com/angular/angular/issues/27143)) ([1db53da](https://github.com/angular/angular/commit/1db53da)), closes [#27029](https://github.com/angular/angular/issues/27029)
|
||||
* **upgrade:** don't rely upon the runtime to resolve forward refs ([#27132](https://github.com/angular/angular/issues/27132)) ([a4462c2](https://github.com/angular/angular/commit/a4462c2))
|
||||
|
||||
|
||||
|
||||
<a name="7.1.1"></a>
|
||||
## [7.1.1](https://github.com/angular/angular/compare/7.1.0...7.1.1) (2018-11-28)
|
||||
|
@ -191,7 +191,7 @@ If the commit reverts a previous commit, it should begin with `revert: `, follow
|
||||
Must be one of the following:
|
||||
|
||||
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
|
||||
* **ci**: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
|
||||
* **ci**: Changes to our CI configuration files and scripts (example scopes: Circle, BrowserStack, SauceLabs)
|
||||
* **docs**: Documentation only changes
|
||||
* **feat**: A new feature
|
||||
* **fix**: A bug fix
|
||||
|
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2014-2018 Google, Inc. http://angular.io
|
||||
Copyright (c) 2010-2019 Google LLC. http://angular.io/license
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -1,4 +1,3 @@
|
||||
[](https://travis-ci.org/angular/angular)
|
||||
[](https://circleci.com/gh/angular/angular/tree/master)
|
||||
[](https://www.browserstack.com/automate/public-build/LzF3RzBVVGt6VWE2S0hHaC9uYllOZz09LS1BVjNTclBKV0x4eVRlcjA4QVY1M0N3PT0=--eb4ce8c8dc2c1c5b2b5352d473ee12a73ac20e06)
|
||||
[](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
104
WORKSPACE
104
WORKSPACE
@ -1,17 +1,6 @@
|
||||
workspace(name = "angular")
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
load(
|
||||
"//packages/bazel:package.bzl",
|
||||
"rules_angular_dependencies",
|
||||
"rules_angular_dev_dependencies",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "io_bazel_rules_go",
|
||||
sha256 = "b7a62250a3a73277ade0ce306d22f122365b513f5402222403e507f2f997d421",
|
||||
url = "https://github.com/bazelbuild/rules_go/releases/download/0.16.3/rules_go-0.16.3.tar.gz",
|
||||
)
|
||||
|
||||
# Uncomment for local bazel rules development
|
||||
#local_repository(
|
||||
@ -23,25 +12,15 @@ http_archive(
|
||||
# path = "../rules_typescript",
|
||||
#)
|
||||
|
||||
# Angular Bazel users will call this function
|
||||
rules_angular_dependencies()
|
||||
# Fetch rules_nodejs so we can install our npm dependencies
|
||||
http_archive(
|
||||
name = "build_bazel_rules_nodejs",
|
||||
sha256 = "1416d03823fed624b49a0abbd9979f7c63bbedfd37890ddecedd2fe25cccebc6",
|
||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.18.6/rules_nodejs-0.18.6.tar.gz"],
|
||||
)
|
||||
|
||||
# Install transitive deps of rules_nodejs
|
||||
load("@build_bazel_rules_nodejs//:package.bzl", "rules_nodejs_dependencies")
|
||||
|
||||
rules_nodejs_dependencies()
|
||||
|
||||
# These are the dependencies only for us
|
||||
rules_angular_dev_dependencies()
|
||||
|
||||
# Install transitive deps of rules_typescript
|
||||
load("@build_bazel_rules_typescript//:package.bzl", "rules_typescript_dependencies")
|
||||
|
||||
rules_typescript_dependencies()
|
||||
|
||||
#
|
||||
# Point Bazel to WORKSPACEs that live in subdirectories
|
||||
#
|
||||
# Fetch the rxjs repository since we build rxjs from source
|
||||
# TODO(gregmagolan): use rxjs bundles in the bazel build
|
||||
http_archive(
|
||||
name = "rxjs",
|
||||
sha256 = "72b0b4e517f43358f554c125e40e39f67688cd2738a8998b4a266981ed32f403",
|
||||
@ -49,21 +28,22 @@ http_archive(
|
||||
url = "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz",
|
||||
)
|
||||
|
||||
# Point to the integration test workspace just so that Bazel doesn't descend into it
|
||||
# when expanding the //... pattern
|
||||
# Use a mock @npm repository while we are building angular from source
|
||||
# downstream. Angular will get its npm dependencies with in @ngdeps which
|
||||
# is setup in ng_setup_workspace().
|
||||
# TODO(gregmagolan): remove @ngdeps once angular is no longer build from source
|
||||
# downstream and have build use @npm for npm dependencies
|
||||
local_repository(
|
||||
name = "bazel_integration_test",
|
||||
path = "integration/bazel",
|
||||
name = "npm",
|
||||
path = "tools/npm_workspace",
|
||||
)
|
||||
|
||||
#
|
||||
# Load and install our dependencies downloaded above.
|
||||
#
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories", "yarn_install")
|
||||
# Check the bazel version and download npm dependencies
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories")
|
||||
|
||||
# Bazel version must be at least v0.21.0 because:
|
||||
# - 0.21.0 --experimental_strict_action_env flag turned on by default which fixes cache when
|
||||
# running `yarn bazel` (see https://github.com/angular/angular/issues/27514#issuecomment-451438271)
|
||||
# - 0.21.0 Using --incompatible_strict_action_env flag fixes cache when running `yarn bazel`
|
||||
# (see https://github.com/angular/angular/issues/27514#issuecomment-451438271)
|
||||
check_bazel_version("0.21.0", """
|
||||
You no longer need to install Bazel on your machine.
|
||||
Angular has a dependency on the @bazel/bazel package which supplies it.
|
||||
@ -72,6 +52,7 @@ Try running `yarn bazel` instead.
|
||||
|
||||
""")
|
||||
|
||||
# Setup the Node.js toolchain
|
||||
node_repositories(
|
||||
node_version = "10.9.0",
|
||||
package_json = ["//:package.json"],
|
||||
@ -79,41 +60,48 @@ node_repositories(
|
||||
yarn_version = "1.12.1",
|
||||
)
|
||||
|
||||
local_repository(
|
||||
name = "npm",
|
||||
path = "tools/npm_workspace",
|
||||
)
|
||||
# Setup the angular toolchain which installs npm dependencies into @ngdeps
|
||||
load("//tools:ng_setup_workspace.bzl", "ng_setup_workspace")
|
||||
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_register_toolchains", "go_rules_dependencies")
|
||||
ng_setup_workspace()
|
||||
|
||||
go_rules_dependencies()
|
||||
# Install all bazel dependencies of the @ngdeps npm packages
|
||||
load("@ngdeps//:install_bazel_dependencies.bzl", "install_bazel_dependencies")
|
||||
|
||||
go_register_toolchains()
|
||||
install_bazel_dependencies()
|
||||
|
||||
load("@io_bazel_rules_webtesting//web:repositories.bzl", "browser_repositories", "web_test_repositories")
|
||||
# Load angular dependencies
|
||||
load("//packages/bazel:package.bzl", "rules_angular_dev_dependencies")
|
||||
|
||||
rules_angular_dev_dependencies()
|
||||
|
||||
# Load karma dependencies
|
||||
load("@build_bazel_rules_karma//:package.bzl", "rules_karma_dependencies")
|
||||
|
||||
rules_karma_dependencies()
|
||||
|
||||
# Setup the rules_webtesting toolchain
|
||||
load("@io_bazel_rules_webtesting//web:repositories.bzl", "web_test_repositories")
|
||||
|
||||
web_test_repositories()
|
||||
|
||||
browser_repositories(
|
||||
chromium = True,
|
||||
firefox = True,
|
||||
)
|
||||
# Temporary work-around for https://github.com/angular/angular/issues/28681
|
||||
# TODO(gregmagolan): go back to @io_bazel_rules_webtesting browser_repositories
|
||||
load("@angular//:browser_repositories.bzl", "browser_repositories")
|
||||
|
||||
browser_repositories()
|
||||
|
||||
# Setup the rules_typescript tooolchain
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")
|
||||
|
||||
ts_setup_workspace()
|
||||
|
||||
load("@angular//:index.bzl", "ng_setup_workspace")
|
||||
|
||||
ng_setup_workspace()
|
||||
|
||||
##################################
|
||||
# Skylark documentation generation
|
||||
|
||||
# Setup the rules_sass toolchain
|
||||
load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories")
|
||||
|
||||
sass_repositories()
|
||||
|
||||
# Setup the skydoc toolchain
|
||||
load("@io_bazel_skydoc//skylark:skylark.bzl", "skydoc_repositories")
|
||||
|
||||
skydoc_repositories()
|
||||
|
@ -26,8 +26,8 @@ ARG AIO_GITHUB_ORGANIZATION=angular
|
||||
ARG TEST_AIO_GITHUB_ORGANIZATION=test-org
|
||||
ARG AIO_GITHUB_REPO=angular
|
||||
ARG TEST_AIO_GITHUB_REPO=test-repo
|
||||
ARG AIO_GITHUB_TEAM_SLUGS=team,aio-contributors
|
||||
ARG TEST_AIO_GITHUB_TEAM_SLUGS=team,aio-contributors
|
||||
ARG AIO_GITHUB_TEAM_SLUGS=aio-contributors
|
||||
ARG TEST_AIO_GITHUB_TEAM_SLUGS=aio-contributors
|
||||
ARG AIO_NGINX_HOSTNAME=$AIO_DOMAIN_NAME
|
||||
ARG TEST_AIO_NGINX_HOSTNAME=$TEST_AIO_DOMAIN_NAME
|
||||
ARG AIO_NGINX_PORT_HTTP=80
|
||||
|
@ -104,6 +104,9 @@
|
||||
},
|
||||
"archive": {
|
||||
"browserTarget": "site:build:archive"
|
||||
},
|
||||
"ci": {
|
||||
"progress": false
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -166,6 +169,11 @@
|
||||
"options": {
|
||||
"protractorConfig": "tests/e2e/protractor.conf.js",
|
||||
"devServerTarget": "site:serve"
|
||||
},
|
||||
"configurations": {
|
||||
"ci": {
|
||||
"devServerTarget": "site:serve:ci"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
|
6
aio/content/examples/.gitignore
vendored
6
aio/content/examples/.gitignore
vendored
@ -57,7 +57,9 @@ dist/
|
||||
|
||||
# aot
|
||||
**/*.ngsummary.json
|
||||
upgrade-module/tsconfig-aot.json
|
||||
!rollup-config.js
|
||||
upgrade-module/rollup-config.js
|
||||
aot-compiler/**/*.d.ts
|
||||
aot-compiler/**/*.factory.d.ts
|
||||
upgrade-phonecat-2-hybrid/aot/**/*
|
||||
@ -84,5 +86,9 @@ upgrade-phonecat-2-hybrid/aot/**/*
|
||||
*stackblitz.no-link.html
|
||||
|
||||
# ngUpgrade testing
|
||||
upgrade-phonecat-1-typescript/tsconfig-aot.json
|
||||
upgrade-phonecat-1-typescript/rollup-config.js
|
||||
upgrade-phonecat-3-final/tsconfig-aot.json
|
||||
upgrade-phonecat-3-final/rollup-config.js
|
||||
!upgrade-phonecat-*/**/karma.conf.js
|
||||
!upgrade-phonecat-*/**/karma-test-shim.js
|
||||
|
@ -20,7 +20,7 @@ export class AppComponent {
|
||||
movies: IMovie[] = [];
|
||||
showImage = true;
|
||||
title = 'AngularJS to Angular Quick Ref Cookbook';
|
||||
toggleImage(event: UIEvent) {
|
||||
toggleImage(event?: UIEvent) {
|
||||
this.showImage = !this.showImage;
|
||||
this.eventType = (event && event.type) || 'not provided';
|
||||
}
|
||||
|
@ -1,14 +0,0 @@
|
||||
import { Injectable, Pipe, PipeTransform } from '@angular/core';
|
||||
import { DatePipe } from '@angular/common';
|
||||
|
||||
@Injectable()
|
||||
// #docregion date-pipe
|
||||
@Pipe({name: 'date', pure: true})
|
||||
export class StringSafeDatePipe extends DatePipe implements PipeTransform {
|
||||
transform(value: any, format: string): string {
|
||||
value = typeof value === 'string' ?
|
||||
Date.parse(value) : value;
|
||||
return super.transform(value, format);
|
||||
}
|
||||
}
|
||||
// #enddocregion date-pipe
|
@ -19,6 +19,7 @@ import { HeroListAutoCalcPageComponent } from './hero-list-auto-page.component';
|
||||
import { HeroListAutoComponent } from './hero-list-auto.component';
|
||||
import { HomeComponent } from './home.component';
|
||||
import { AboutComponent } from './about.component';
|
||||
import { InsertRemoveComponent } from './insert-remove.component';
|
||||
|
||||
|
||||
@NgModule({
|
||||
@ -56,6 +57,7 @@ import { AboutComponent } from './about.component';
|
||||
HeroListAutoCalcPageComponent,
|
||||
HeroListAutoComponent,
|
||||
HomeComponent,
|
||||
InsertRemoveComponent,
|
||||
AboutComponent
|
||||
],
|
||||
bootstrap: [AppComponent]
|
||||
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"e2e": [
|
||||
{
|
||||
"cmd": "yarn",
|
||||
"args": [
|
||||
"e2e",
|
||||
"--no-webdriver-update"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -19,20 +19,20 @@ const DifferentParent = Parent;
|
||||
// #enddocregion provide-the-parent
|
||||
// The `parentType` defaults to `Parent` when omitting the second parameter.
|
||||
// #docregion provide-the-parent
|
||||
const provideParent =
|
||||
export function provideParent
|
||||
// #enddocregion provide-parent, provide-the-parent
|
||||
// #docregion provide-parent
|
||||
(component: any, parentType?: any) => {
|
||||
(component: any, parentType?: any) {
|
||||
return { provide: parentType || Parent, useExisting: forwardRef(() => component) };
|
||||
};
|
||||
}
|
||||
// #enddocregion provide-parent
|
||||
|
||||
// Simpler syntax version that always provides the component in the name of `Parent`.
|
||||
const provideTheParent =
|
||||
export function provideTheParent
|
||||
// #docregion provide-the-parent
|
||||
(component: any) => {
|
||||
(component: any) {
|
||||
return { provide: Parent, useExisting: forwardRef(() => component) };
|
||||
};
|
||||
}
|
||||
// #enddocregion provide-the-parent
|
||||
|
||||
|
||||
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"e2e": [
|
||||
{
|
||||
"cmd": "yarn",
|
||||
"args": [
|
||||
"e2e",
|
||||
"--no-webdriver-update"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -28,10 +28,7 @@ let checkLogForMessage = (message: string) => {
|
||||
expect(page.logList.getText()).toContain(message);
|
||||
};
|
||||
|
||||
// TODO(i): temorarily disable these tests because angular-in-memory-web-api is not compatible with rxjs v6 yet
|
||||
// and we don't have the backwards compatibility package yet.
|
||||
// Reenable after rxjs v6 compatibility package is out or angular-in-memory-web-api is compatible with rxjs v6
|
||||
xdescribe('Http Tests', function() {
|
||||
describe('Http Tests', function() {
|
||||
beforeEach(() => {
|
||||
browser.get('');
|
||||
});
|
||||
|
@ -1,3 +1,12 @@
|
||||
{
|
||||
"projectType": "i18n"
|
||||
}
|
||||
"projectType": "i18n",
|
||||
"e2e": [
|
||||
{
|
||||
"cmd": "yarn",
|
||||
"args": [
|
||||
"e2e",
|
||||
"--no-webdriver-update"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
47
aio/content/examples/interpolation/e2e/src/app.e2e-spec.ts
Normal file
47
aio/content/examples/interpolation/e2e/src/app.e2e-spec.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import { browser, element, by } from 'protractor';
|
||||
|
||||
describe('Interpolation e2e tests', () => {
|
||||
|
||||
beforeEach(function () {
|
||||
browser.get('');
|
||||
});
|
||||
|
||||
it('should display Interpolation and Template Expressions', function () {
|
||||
expect(element(by.css('h1')).getText()).toEqual('Interpolation and Template Expressions');
|
||||
});
|
||||
|
||||
it('should display Current customer: Maria', function () {
|
||||
expect(element.all(by.css('h3')).get(0).getText()).toBe(`Current customer: Maria`);
|
||||
});
|
||||
|
||||
it('should display The sum of 1 + 1 is not 4.', function () {
|
||||
expect(element.all(by.css('p:last-child')).get(0).getText()).toBe(`The sum of 1 + 1 is not 4.`);
|
||||
});
|
||||
|
||||
it('should display Expression Context', function () {
|
||||
expect(element.all(by.css('h2')).get(1).getText()).toBe(`Expression Context`);
|
||||
});
|
||||
|
||||
it('should display a list of customers', function () {
|
||||
expect(element.all(by.css('li')).get(0).getText()).toBe(`Maria`);
|
||||
});
|
||||
|
||||
it('should display two pictures', function() {
|
||||
let pottedPlant = element.all(by.css('img')).get(0);
|
||||
let lamp = element.all(by.css('img')).get(1);
|
||||
|
||||
expect(pottedPlant.getAttribute('src')).toContain('pottedPlant');
|
||||
expect(pottedPlant.isDisplayed()).toBe(true);
|
||||
|
||||
expect(lamp.getAttribute('src')).toContain('lamp');
|
||||
expect(lamp.isDisplayed()).toBe(true);
|
||||
});
|
||||
|
||||
it('should support user input', function () {
|
||||
let input = element(by.css('input'));
|
||||
let label = element(by.css('label'));
|
||||
expect(label.getText()).toEqual('Type something:');
|
||||
input.sendKeys('abc');
|
||||
expect(label.getText()).toEqual('Type something: abc');
|
||||
});
|
||||
});
|
@ -0,0 +1,59 @@
|
||||
|
||||
<div>
|
||||
<h1>Interpolation and Template Expressions</h1>
|
||||
<hr />
|
||||
|
||||
<div>
|
||||
<h2>Interpolation</h2>
|
||||
<!-- #docregion interpolation-example1 -->
|
||||
<h3>Current customer: {{ currentCustomer }}</h3>
|
||||
<!-- #enddocregion interpolation-example1 -->
|
||||
|
||||
<!-- #docregion component-property -->
|
||||
<p>{{title}}</p>
|
||||
<div><img src="{{itemImageUrl}}"></div>
|
||||
<!-- #enddocregion component-property -->
|
||||
|
||||
<h3>Evaluating template expressions </h3>
|
||||
<h4>Simple evaluation (to a string):</h4>
|
||||
<!-- #docregion convert-string -->
|
||||
<!-- "The sum of 1 + 1 is 2" -->
|
||||
<p>The sum of 1 + 1 is {{1 + 1}}.</p>
|
||||
<!-- #enddocregion convert-string -->
|
||||
|
||||
<h4>Evaluates using a method (also evaluates to a string):</h4>
|
||||
<!-- #docregion invoke-method -->
|
||||
<!-- "The sum of 1 + 1 is not 4" -->
|
||||
<p>The sum of 1 + 1 is not {{1 + 1 + getVal()}}.</p>
|
||||
<!-- #enddocregion invoke-method -->
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<h2>Expression Context</h2>
|
||||
|
||||
<div>
|
||||
<h3>Component context, properties of app.component.ts:</h3>
|
||||
<!-- #docregion component-context -->
|
||||
<h4>{{recommended}}</h4>
|
||||
<img [src]="itemImageUrl2">
|
||||
<!-- #enddocregion component-context -->
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4>Template context, template input variables (let customer):</h4>
|
||||
<!-- #docregion template-input-variable -->
|
||||
<ul>
|
||||
<li *ngFor="let customer of customers">{{customer.name}}</li>
|
||||
</ul>
|
||||
<!-- #enddocregion template-input-variable -->
|
||||
</div>
|
||||
|
||||
<div (keyup)="0">
|
||||
<h4>Template context: template reference variables (#customerInput):</h4>
|
||||
<label>Type something:
|
||||
<!-- #docregion template-reference-variable -->
|
||||
<input #customerInput>{{customerInput.value}}</label>
|
||||
<!-- #enddocregion template-reference-variable -->
|
||||
</div>
|
||||
|
||||
</div>
|
@ -0,0 +1,27 @@
|
||||
import { TestBed, async } from '@angular/core/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
}).compileComponents();
|
||||
}));
|
||||
it('should create the app', async(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.debugElement.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
}));
|
||||
it(`should have as title 'Featured product:'`, async(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.debugElement.componentInstance;
|
||||
expect(app.title).toEqual('Featured product:');
|
||||
}));
|
||||
it('should render title in a p tag', async(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.debugElement.nativeElement;
|
||||
expect(compiled.querySelector('p').textContent).toContain('Featured product:');
|
||||
}));
|
||||
});
|
25
aio/content/examples/interpolation/src/app/app.component.ts
Normal file
25
aio/content/examples/interpolation/src/app/app.component.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { CUSTOMERS } from './customers';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
export class AppComponent {
|
||||
customers = CUSTOMERS;
|
||||
|
||||
currentCustomer = 'Maria';
|
||||
title = 'Featured product:';
|
||||
itemImageUrl = '../assets/pottedPlant.png';
|
||||
|
||||
recommended = 'You might also like:';
|
||||
itemImageUrl2 = '../assets/lamp.png';
|
||||
|
||||
|
||||
|
||||
getVal(): number { return 2; }
|
||||
|
||||
|
||||
}
|
18
aio/content/examples/interpolation/src/app/app.module.ts
Normal file
18
aio/content/examples/interpolation/src/app/app.module.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
3
aio/content/examples/interpolation/src/app/customer.ts
Normal file
3
aio/content/examples/interpolation/src/app/customer.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export class Customer {
|
||||
name: string;
|
||||
}
|
9
aio/content/examples/interpolation/src/app/customers.ts
Normal file
9
aio/content/examples/interpolation/src/app/customers.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { Customer } from './customer';
|
||||
|
||||
export const CUSTOMERS: Customer[] = [
|
||||
{ name: 'Maria' },
|
||||
{ name: 'Oliver' },
|
||||
{ name: 'Walter' },
|
||||
{ name: 'Lakshmi' },
|
||||
{ name: 'Yasha' }
|
||||
];
|
BIN
aio/content/examples/interpolation/src/assets/lamp.png
Normal file
BIN
aio/content/examples/interpolation/src/assets/lamp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
BIN
aio/content/examples/interpolation/src/assets/potted-plant.png
Normal file
BIN
aio/content/examples/interpolation/src/assets/potted-plant.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Demo</title>
|
||||
<title>Interpolation</title>
|
||||
<base href="/">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
12
aio/content/examples/interpolation/src/main.ts
Normal file
12
aio/content/examples/interpolation/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/interpolation/stackblitz.json
Normal file
10
aio/content/examples/interpolation/stackblitz.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"description": "Interpolation",
|
||||
"files": [
|
||||
"!**/*.d.ts",
|
||||
"!**/*.js",
|
||||
"!**/*.[1,2].*"
|
||||
],
|
||||
"file": "src/app/app.component.ts",
|
||||
"tags": ["interpolation"]
|
||||
}
|
@ -13,8 +13,8 @@ import { AppComponent } from './app.component';
|
||||
// #enddocregion
|
||||
*/
|
||||
// #docregion
|
||||
import { HighlightDirective } from './highlight.directive';
|
||||
import { TitleComponent } from './title.component';
|
||||
import { HighlightDirective } from './highlight.directive.1';
|
||||
import { TitleComponent } from './title.component.1';
|
||||
import { UserService } from './user.service';
|
||||
|
||||
/* Routing Module */
|
||||
|
@ -1,10 +0,0 @@
|
||||
// #docregion
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
|
||||
@Pipe({ name: 'awesome' })
|
||||
/** Precede the input string with the word "Awesome " */
|
||||
export class AwesomePipe implements PipeTransform {
|
||||
transform(phrase: string) {
|
||||
return phrase ? 'Awesome ' + phrase : '';
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
// #docplaster
|
||||
// Same directive name and selector as
|
||||
// HighlightDirective in parent AppModule
|
||||
// It selects for both input boxes and 'highlight' attr
|
||||
// and it highlights in blue instead of gold
|
||||
|
||||
// #docregion
|
||||
import { Directive, ElementRef } from '@angular/core';
|
||||
|
||||
// Highlight the host element or any InputElement in blue
|
||||
@Directive({ selector: '[highlight], input' })
|
||||
export class ContactHighlightDirective {
|
||||
constructor(el: ElementRef) {
|
||||
el.nativeElement.style.backgroundColor = 'powderblue';
|
||||
// #enddocregion
|
||||
console.log(`* Contact highlight called for ${el.nativeElement.tagName}`);
|
||||
// #docregion
|
||||
}
|
||||
}
|
||||
// #enddocregion
|
@ -1,14 +0,0 @@
|
||||
// #docregion
|
||||
import { Directive, ElementRef } from '@angular/core';
|
||||
|
||||
// Same directive name and selector as
|
||||
// HighlightDirective in parent AppRootModule
|
||||
// It selects for both input boxes and 'highlight' attr
|
||||
// and it highlights in beige instead of yellow
|
||||
@Directive({ selector: '[highlight]' })
|
||||
export class HighlightDirective {
|
||||
constructor(el: ElementRef) {
|
||||
el.nativeElement.style.backgroundColor = 'beige';
|
||||
console.log(`* Hero highlight called for ${el.nativeElement.tagName}`);
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ import { UserService } from './user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-title',
|
||||
templateUrl: './title.component.html'
|
||||
templateUrl: './title.component.1.html'
|
||||
})
|
||||
export class TitleComponent {
|
||||
title = 'Angular Modules';
|
@ -16,7 +16,7 @@ const ITEMS: Item[] = [
|
||||
|
||||
const FETCH_LATENCY = 500;
|
||||
|
||||
/** Simulate a data service that retrieves crises from a server */
|
||||
/** Simulate a data service that retrieves items from a server */
|
||||
@Injectable()
|
||||
export class ItemService implements OnDestroy {
|
||||
|
||||
|
@ -61,7 +61,7 @@ export class Routable1Component implements OnInit {
|
||||
navStart: Observable<NavigationStart>;
|
||||
|
||||
constructor(private router: Router) {
|
||||
// Create a new Observable the publishes only the NavigationStart event
|
||||
// Create a new Observable that publishes only the NavigationStart event
|
||||
this.navStart = router.events.pipe(
|
||||
filter(evt => evt instanceof NavigationStart)
|
||||
) as Observable<NavigationStart>;
|
||||
|
@ -5,10 +5,9 @@ import { retryWhen, map, mergeMap } from 'rxjs/operators';
|
||||
|
||||
function backoff(maxTries, ms) {
|
||||
return pipe(
|
||||
retryWhen(attempts => range(1, maxTries)
|
||||
retryWhen(attempts => zip(range(1, maxTries), attempts)
|
||||
.pipe(
|
||||
zip(attempts, (i) => i),
|
||||
map(i => i * i),
|
||||
map(([i]) => i * i),
|
||||
mergeMap(i => timer(i * ms))
|
||||
)
|
||||
)
|
||||
|
@ -0,0 +1,30 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
export class AppComponent {
|
||||
itemImageUrl = '../assets/lamp.png';
|
||||
isUnchanged = true;
|
||||
classes = 'special';
|
||||
// #docregion parent-data-type
|
||||
parentItem = 'bananas';
|
||||
// #enddocregion parent-data-type
|
||||
|
||||
// #docregion pass-object
|
||||
currentItem = [{
|
||||
id: 21,
|
||||
name: 'peaches'
|
||||
}];
|
||||
// #enddocregion pass-object
|
||||
|
||||
interpolationTitle = 'Interpolation';
|
||||
propertyTitle = 'Property binding';
|
||||
|
||||
// #docregion malicious-content
|
||||
evilTitle = 'Template <script>alert("evil never sleeps")</script>Syntax';
|
||||
// #enddocregion malicious-content
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"server": {
|
||||
"baseDir": "src",
|
||||
"routes": {
|
||||
"/node_modules": "node_modules"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
// #docregion
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
template: `<h1>Hello {{name}}</h1>`
|
||||
})
|
||||
export class AppComponent { name = 'Angular'; }
|
@ -1,11 +0,0 @@
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [ BrowserModule ],
|
||||
declarations: [ AppComponent ],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
export class AppModule { }
|
@ -1,31 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Angular Quickstart</title>
|
||||
<base href="/">
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
body {color:#369;font-family: Arial,Helvetica,sans-serif;}
|
||||
</style>
|
||||
|
||||
<!-- Polyfills -->
|
||||
<!-- #docregion polyfills -->
|
||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
||||
<!-- #enddocregion polyfills -->
|
||||
|
||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||
<script src="systemjs.config.js"></script>
|
||||
<script>
|
||||
System.import('main.js').catch(function(err){ console.error(err); });
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- #docregion my-app-->
|
||||
<my-app>Loading AppComponent content here ...</my-app>
|
||||
<!-- #enddocregion my-app-->
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,5 +0,0 @@
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
import { AppModule } from './app/app.module';
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
@ -1,13 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"sourceMap": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"lib": [ "es2015", "dom" ],
|
||||
"noImplicitAny": true,
|
||||
"suppressImplicitAnyIndexErrors": true
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"description": "QuickStart",
|
||||
"files": [
|
||||
"src/app/app.component.ts",
|
||||
"src/app/app.module.ts",
|
||||
"src/main.ts",
|
||||
"src/index.html"
|
||||
],
|
||||
"file": "src/app/app.component.ts",
|
||||
"tags": ["quickstart"]
|
||||
}
|
@ -4,7 +4,7 @@ import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-crisis-list',
|
||||
templateUrl: './crisis-list.component.html',
|
||||
styleUrls: ['./crisis-list.component.css']
|
||||
templateUrl: './crisis-list.component.1.html',
|
||||
styleUrls: ['./crisis-list.component.1.css']
|
||||
})
|
||||
export class CrisisListComponent { }
|
@ -4,7 +4,7 @@ import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-hero-list',
|
||||
templateUrl: './hero-list.component.html',
|
||||
styleUrls: ['./hero-list.component.css']
|
||||
templateUrl: './hero-list.component.1.html',
|
||||
styleUrls: ['./hero-list.component.1.css']
|
||||
})
|
||||
export class HeroListComponent { }
|
@ -1,10 +1,10 @@
|
||||
|
||||
// #docregion promise
|
||||
|
||||
import { fromPromise } from 'rxjs';
|
||||
import { from } from 'rxjs';
|
||||
|
||||
// Create an Observable out of a promise
|
||||
const data = fromPromise(fetch('/api/endpoint'));
|
||||
const data = from(fetch('/api/endpoint'));
|
||||
// Subscribe to begin listening for async result
|
||||
data.subscribe({
|
||||
next(response) { console.log(response); },
|
||||
|
@ -34,8 +34,9 @@ describe('sw-example App', () => {
|
||||
expect(items[3].getText()).toBe('Angular blog');
|
||||
});
|
||||
});
|
||||
// Check for a rejected promise as the service worker is not enabled
|
||||
it('SwUpdate.checkForUpdate() should return a rejected promise', () => {
|
||||
|
||||
// Check for a rejected promise as the service worker is not enabled
|
||||
it('SwUpdate.checkForUpdate() should return a rejected promise', () => {
|
||||
const button = element(by.css('button'));
|
||||
const rejectMessage = element(by.css('p'));
|
||||
button.click();
|
||||
|
@ -0,0 +1,10 @@
|
||||
{
|
||||
"projectType": "service-worker",
|
||||
"e2e": [
|
||||
{"cmd": "yarn", "args": ["e2e", "--no-webdriver-update"]},
|
||||
{"cmd": "yarn", "args": ["build", "--prod"]},
|
||||
{"cmd": "node", "args": ["--eval", "assert(fs.existsSync('./dist/ngsw.json'), 'ngsw.json is missing')"]},
|
||||
{"cmd": "node", "args": ["--eval", "assert(fs.existsSync('./dist/ngsw-worker.js'), 'ngsw-worker.js is missing')"]},
|
||||
{"cmd": "node", "args": ["--eval", "assert(require('./package.json').dependencies['@angular/service-worker'], '@angular/service-worker is missing')"]}
|
||||
]
|
||||
}
|
||||
|
@ -12,9 +12,9 @@ export class AppComponent {
|
||||
constructor(private update: SwUpdate) {}
|
||||
|
||||
updateCheck(): void {
|
||||
this.update
|
||||
this.update
|
||||
.checkForUpdate()
|
||||
.then(() => this.updateCheckText = 'resolved')
|
||||
.catch(err => this.updateCheckText = `rejected: ${err.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,17 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ApplicationRef, Injectable } from '@angular/core';
|
||||
import { SwUpdate } from '@angular/service-worker';
|
||||
|
||||
|
||||
// #docregion sw-check-update
|
||||
import { interval } from 'rxjs';
|
||||
import { concat, interval } from 'rxjs';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable()
|
||||
export class CheckForUpdateService {
|
||||
|
||||
constructor(updates: SwUpdate) {
|
||||
interval(6 * 60 * 60).subscribe(() => updates.checkForUpdate());
|
||||
constructor(appRef: ApplicationRef, updates: SwUpdate) {
|
||||
// Allow the app to stabilize first, before starting polling for updates with `interval()`.
|
||||
const appIsStable$ = appRef.isStable.pipe(first(isStable => isStable === true));
|
||||
const everySixHours$ = interval(6 * 60 * 60 * 1000);
|
||||
const everySixHoursOnceAppIsStable$ = concat(appIsStable$, everySixHours$);
|
||||
|
||||
everySixHoursOnceAppIsStable$.subscribe(() => updates.checkForUpdate());
|
||||
}
|
||||
}
|
||||
// #enddocregion sw-check-update
|
||||
|
@ -1,17 +0,0 @@
|
||||
'use strict'; // necessary for es6 output in node
|
||||
|
||||
import { browser, element, by } from 'protractor';
|
||||
|
||||
describe('QuickStart E2E Tests', function () {
|
||||
|
||||
let expectedMsg = 'Hello Angular';
|
||||
|
||||
beforeEach(function () {
|
||||
browser.get('');
|
||||
});
|
||||
|
||||
it(`should display: ${expectedMsg}`, function () {
|
||||
expect(element(by.css('h1')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
});
|
@ -1,3 +1,2 @@
|
||||
// #docregion
|
||||
export * from './spinner.component';
|
||||
export * from './spinner.service';
|
||||
|
@ -1,16 +0,0 @@
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||
|
||||
import { SpinnerService } from './spinner.service';
|
||||
|
||||
@Component({
|
||||
selector: 'toh-spinner',
|
||||
template: '<div>spinner</div>'
|
||||
})
|
||||
|
||||
export class SpinnerComponent implements OnDestroy, OnInit {
|
||||
constructor(private spinnerService: SpinnerService) { }
|
||||
|
||||
ngOnInit() { }
|
||||
|
||||
ngOnDestroy() { }
|
||||
}
|
@ -1,3 +1,2 @@
|
||||
// #docregion
|
||||
export * from './toast.component';
|
||||
export * from './toast.service';
|
||||
|
@ -1,13 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { ToastService } from './toast.service';
|
||||
|
||||
@Component({
|
||||
selector: 'toh-toast',
|
||||
template: '<div>toast</div>'
|
||||
})
|
||||
export class ToastComponent implements OnInit {
|
||||
constructor(toastService: ToastService) { }
|
||||
|
||||
ngOnInit() { }
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { ToastService } from '../../core';
|
||||
|
||||
@Component({
|
||||
selector: 'toh-toast',
|
||||
template: '<div>toast</div>'
|
||||
})
|
||||
export class ToastComponent implements OnInit {
|
||||
constructor(toastService: ToastService) { }
|
||||
|
||||
ngOnInit() { }
|
||||
}
|
@ -4,4 +4,7 @@ import { Component } from '@angular/core';
|
||||
selector: 'sg-app',
|
||||
templateUrl: './app.component.html'
|
||||
})
|
||||
export class AppComponent { }
|
||||
export class AppComponent {
|
||||
|
||||
doSomething() {}
|
||||
}
|
||||
|
@ -4,4 +4,7 @@ import { Component } from '@angular/core';
|
||||
selector: 'sg-app',
|
||||
templateUrl: './app.component.html'
|
||||
})
|
||||
export class AppComponent { }
|
||||
export class AppComponent {
|
||||
|
||||
onSavedTheDay(event$: any) { }
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ export class AppComponent implements AfterViewInit, OnInit {
|
||||
|
||||
currentHero: Hero;
|
||||
|
||||
deleteHero(hero: Hero) {
|
||||
deleteHero(hero?: Hero) {
|
||||
this.alert(`Delete ${hero ? hero.name : 'the hero'}.`);
|
||||
}
|
||||
|
||||
@ -105,18 +105,18 @@ export class AppComponent implements AfterViewInit, OnInit {
|
||||
|
||||
get nullHero(): Hero { return null; }
|
||||
|
||||
onClickMe(event: KeyboardEvent) {
|
||||
onClickMe(event?: KeyboardEvent) {
|
||||
let evtMsg = event ? ' Event target class is ' + (<HTMLElement>event.target).className : '';
|
||||
this.alert('Click me.' + evtMsg);
|
||||
}
|
||||
|
||||
onSave(event: KeyboardEvent) {
|
||||
onSave(event?: KeyboardEvent) {
|
||||
let evtMsg = event ? ' Event target is ' + (<HTMLElement>event.target).textContent : '';
|
||||
this.alert('Saved.' + evtMsg);
|
||||
if (event) { event.stopPropagation(); }
|
||||
}
|
||||
|
||||
onSubmit() {/* referenced but not used */}
|
||||
onSubmit(data: any) {/* referenced but not used */}
|
||||
|
||||
product = {
|
||||
name: 'frimfram',
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Directive, Input } from '@angular/core';
|
||||
import { Directive, Input, HostListener } from '@angular/core';
|
||||
|
||||
// export for convenience.
|
||||
export { RouterLink} from '@angular/router';
|
||||
@ -6,13 +6,13 @@ export { RouterLink} from '@angular/router';
|
||||
/* tslint:disable:directive-class-suffix */
|
||||
// #docregion router-link
|
||||
@Directive({
|
||||
selector: '[routerLink]',
|
||||
host: { '(click)': 'onClick()' }
|
||||
selector: '[routerLink]'
|
||||
})
|
||||
export class RouterLinkDirectiveStub {
|
||||
@Input('routerLink') linkParams: any;
|
||||
navigatedTo: any = null;
|
||||
|
||||
@HostListener('click')
|
||||
onClick() {
|
||||
this.navigatedTo = this.linkParams;
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ export class HeroService {
|
||||
/** POST: add a new hero to the server */
|
||||
addHero (hero: Hero): Observable<Hero> {
|
||||
return this.http.post<Hero>(this.heroesUrl, hero, httpOptions).pipe(
|
||||
tap((hero: Hero) => this.log(`added hero w/ id=${hero.id}`)),
|
||||
tap((newHero: Hero) => this.log(`added hero w/ id=${newHero.id}`)),
|
||||
catchError(this.handleError<Hero>('addHero'))
|
||||
);
|
||||
}
|
||||
|
@ -23,15 +23,6 @@ module.exports = function(config) {
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
|
||||
customLaunchers: {
|
||||
// From the CLI. Not used here but interesting
|
||||
// chrome setup for travis CI using chromium
|
||||
Chrome_travis_ci: {
|
||||
base: 'Chrome',
|
||||
flags: ['--no-sandbox']
|
||||
}
|
||||
},
|
||||
|
||||
files: [
|
||||
// System.js for module loading
|
||||
'node_modules/systemjs/dist/system.src.js',
|
||||
|
@ -23,15 +23,6 @@ module.exports = function(config) {
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
|
||||
customLaunchers: {
|
||||
// From the CLI. Not used here but interesting
|
||||
// chrome setup for travis CI using chromium
|
||||
Chrome_travis_ci: {
|
||||
base: 'Chrome',
|
||||
flags: ['--no-sandbox']
|
||||
}
|
||||
},
|
||||
|
||||
files: [
|
||||
// System.js for module loading
|
||||
'node_modules/systemjs/dist/system.src.js',
|
||||
|
@ -1508,7 +1508,7 @@ done manually.
|
||||
|
||||
When `true`, this option tells the compiler not to check the TypeScript version.
|
||||
The compiler will skip checking and will not error out when an unsupported version of TypeScript is used.
|
||||
Setting this option to `true` is not recommended because unsupported versions of TypeScript might have undefined behaviour.
|
||||
Setting this option to `true` is not recommended because unsupported versions of TypeScript might have undefined behavior.
|
||||
|
||||
This option is `false` by default.
|
||||
|
||||
|
@ -372,6 +372,27 @@ Here are the features which may require additional polyfills:
|
||||
|
||||
</tr>
|
||||
|
||||
<tr style="vertical-align: top">
|
||||
|
||||
<td>
|
||||
|
||||
[Router](guide/router)
|
||||
|
||||
when using [hash-based routing](guide/router#appendix-locationstrategy-and-browser-url-styles)
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
[ES7/array](guide/browser-support#core-es7-array)
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
IE 11
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
@ -402,7 +423,7 @@ Below are the polyfills which are used to test the framework itself. They are a
|
||||
|
||||
<td>
|
||||
|
||||
<a id='core-es7-reflect' href="https://github.com/zloirock/core-js/blob/master/es7/reflect.js">ES7/reflect</a>
|
||||
<a id='core-es7-reflect' href="https://github.com/zloirock/core-js/tree/v2/fn/reflect">ES7/reflect</a>
|
||||
|
||||
</td>
|
||||
|
||||
@ -416,6 +437,24 @@ Below are the polyfills which are used to test the framework itself. They are a
|
||||
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
<td>
|
||||
|
||||
<a id='core-es7-array' href="https://github.com/zloirock/core-js/tree/v2/fn/array">ES7/array</a>
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
MIT
|
||||
</td>
|
||||
|
||||
<td>
|
||||
0.1KB
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
<td>
|
||||
|
@ -273,8 +273,8 @@ The CLI uses [Autoprefixer](https://github.com/postcss/autoprefixer) to ensure c
|
||||
You may find it necessary to target specific browsers or exclude certain browser versions from your build.
|
||||
|
||||
Internally, Autoprefixer relies on a library called [Browserslist](https://github.com/browserslist/browserslist) to figure out which browsers to support with prefixing.
|
||||
Browserlist looks for configuration options in a `browserlist` property of the package configuration file, or in a configuration file named `.browserslistrc`.
|
||||
Autoprefixer looks for the Browserlist configuration when it prefixes your CSS.
|
||||
Browserlist looks for configuration options in a `browserslist` property of the package configuration file, or in a configuration file named `.browserslistrc`.
|
||||
Autoprefixer looks for the `browserslist` configuration when it prefixes your CSS.
|
||||
|
||||
* You can tell Autoprefixer what browsers to target by adding a browserslist property to the package configuration file, `package.json`:
|
||||
```
|
||||
|
189
aio/content/guide/creating-libraries.md
Normal file
189
aio/content/guide/creating-libraries.md
Normal file
@ -0,0 +1,189 @@
|
||||
# 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.
|
||||
|
||||
An simple example might be a button that sends users to your company website, that would be included in all apps that your company builds.
|
||||
|
||||
## Getting started
|
||||
|
||||
Use the Angular CLI to generate a new library skeleton with the following command:
|
||||
|
||||
<code-example format="." language="bash">
|
||||
ng generate library my-lib
|
||||
</code-example>
|
||||
|
||||
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'.
|
||||
|
||||
<code-example format="json">
|
||||
"projects": {
|
||||
...
|
||||
"my-lib": {
|
||||
"root": "projects/my-lib",
|
||||
"sourceRoot": "projects/my-lib/src",
|
||||
"projectType": "library",
|
||||
"prefix": "lib",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
...
|
||||
</code-example>
|
||||
|
||||
You can build, test, and lint the project with CLI commands:
|
||||
|
||||
<code-example format="." language="bash">
|
||||
ng build my-lib
|
||||
ng test my-lib
|
||||
ng lint my-lib
|
||||
</code-example>
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
The public API for your library is maintained in the `index.ts` file of your library folder.
|
||||
Anything exported from this file is made public when your library is imported into an application.
|
||||
Use an NgModule to expose services and components.
|
||||
|
||||
Your library should supply documentation (typically a README file) for installation and maintenance.
|
||||
|
||||
## Refactoring parts of an app into a library
|
||||
|
||||
To make your solution reusable, you need to adjust it so that it does not depend on app-specific code.
|
||||
Here are some things to consider in migrating application functionality to a library.
|
||||
|
||||
* Declarations such as components and pipes should be designed as stateless, meaning they don’t rely on or alter external variables. If you do rely on state, you need to evaluate every case and decide whether it is application state or state that the library would manage.
|
||||
|
||||
* Any observables that the components subscribe to internally should be cleaned up and disposed of during the lifecycle of those components.
|
||||
|
||||
* Components should expose their interactions through inputs for providing context, and outputs for communicating events to other components.
|
||||
|
||||
* Services should declare their own providers (rather than declaring providers in the NgModule or a component), so that they are *tree-shakable*. This allows the compiler to leave the service out of the bundle if it never gets injected into the application that imports the library. For more about this, see [Tree-shakable providers](guide/dependency-injection-providers#tree-shakable-providers).
|
||||
|
||||
* If you register global service providers or share providers across multiple NgModules, use the [`forRoot()` and `forChild()` patterns](guide/singleton-services) provided by the [RouterModule](api/router/RouterModule).
|
||||
|
||||
* Check all internal dependencies.
|
||||
* For custom classes or interfaces used in components or service, check whether they depend on additional classes or interfaces that also need to be migrated.
|
||||
* Similarly, if your library code depends on a service, that service needs to be migrated.
|
||||
* If your library code or its templates depend on other libraries (such a Angular Material, for instance), you must configure your library with those dependencies.
|
||||
|
||||
## Reusable code and schematics
|
||||
|
||||
A library typically includes *reusable code* that defines components, services, and other Angular artifacts (pipes, directives, and so on) that you simply import into a project.
|
||||
A library is packaged into an npm package for publishing and sharing, and this package can also include [schematics](guide/glossary#schematic) that provide instructions for generating or transforming code directly in your project, in the same way that the CLI creates a generic skeleton app with `ng generate component`.
|
||||
A schematic that is combined with a library can, for example, provide the Angular CLI with the information it needs to generate a particular component defined in that library.
|
||||
|
||||
What you include in your library is determined by the kind of task you are trying to accomplish.
|
||||
For example, if you want a dropdown with some canned data to show how to add it to your app, your library could define a schematic to create it.
|
||||
For a component like a dropdown that would contain different passed-in values each time, you could provide it as a component in a shared library.
|
||||
|
||||
Suppose you want to read a configuration file and then generate a form based on that configuration.
|
||||
If that form will need additional customization by the user, it might work best as a schematic.
|
||||
However, if the forms will always be the same and not need much customization by developers, then you could create a dynamic component that takes the configuration and generates the form.
|
||||
In general, the more complex the customization, the more useful the schematic approach.
|
||||
|
||||
## Integrating with the CLI
|
||||
|
||||
A library can include [schematics](guide/glossary#schematic) that allow it to integrate with the Angular CLI.
|
||||
|
||||
* Include an installation schematic so that `ng add` can add your library to a project.
|
||||
|
||||
* Include generation schematics in your library so that `ng generate` can scaffold your defined artifacts (components, services, tests, and so on) in a project.
|
||||
|
||||
* Include an update schematic so that `ng update` can update your library’s dependencies and provide migrations for breaking changes in new releases.
|
||||
|
||||
To learn more, see [Schematics — An Introduction](https://blog.angular.io/schematics-an-introduction-dc1dfbc2a2b2).
|
||||
|
||||
## Publishing your library
|
||||
|
||||
Use the Angular CLI and the npm package manager to build and publish your library as an npm package.
|
||||
Libraries are built in [AoT mode](guide/aot-compiler) by default, so you do not need to specify the `-prod` flag when building for publication.
|
||||
|
||||
<code-example format="." language="bash">
|
||||
ng build my-lib
|
||||
cd dist/my-lib
|
||||
npm publish
|
||||
</code-example>
|
||||
|
||||
If you've never published a package in npm before, you must create a user account. Read more in [Publishing npm Packages](https://docs.npmjs.com/getting-started/publishing-npm-packages).
|
||||
|
||||
## Linked libraries
|
||||
|
||||
While working on a published library, you can use [npm link](https://docs.npmjs.com/cli/link) to avoid reinstalling the library on every build.
|
||||
|
||||
The library must be rebuilt on every change.
|
||||
When linking a library, make sure that the build step runs in watch mode, and that the library's `package.json` configuration points at the correct entry points.
|
||||
For example, `main` should point at a JavaScript file, not a TypeScript file.
|
||||
|
||||
## Use TypeScript path mapping for peer dependencies
|
||||
|
||||
Angular libraries should list all `@angular/*` dependencies as peer dependencies.
|
||||
This insures that when modules ask for Angular, they all get the exact same module.
|
||||
If a library lists `@angular/core` in `dependencies` instead of `peerDependencies`, it might get a different Angular module instead, which would cause your application to break.
|
||||
|
||||
While developing a library, you must install all peer dependencies through `devDependencies` to ensure that the library compiles properly.
|
||||
A linked library will then have its own set of Angular libraries that it uses for building, located in its `node_modules` folder.
|
||||
However, this can cause problems while building or running your application.
|
||||
|
||||
To get around this problem you can use TypeScript path mapping to tell TypeScript that it should load some modules from a specific location.
|
||||
List all the peer dependencies that your library uses in the TypeScript configuration file `./tsconfig.json`, and point them at the local copy in the app's `node_modules` folder.
|
||||
|
||||
```
|
||||
{
|
||||
"compilerOptions": {
|
||||
// ...
|
||||
// paths are relative to `baseUrl` path.
|
||||
"paths": {
|
||||
"@angular/*": [
|
||||
"../node_modules/@angular/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This mapping ensures that your library always loads the local copies of the modules it needs.
|
||||
|
||||
## Using your own library in apps
|
||||
|
||||
You don't have to publish your library to the npm package manager in order to use it in your own apps, but you do have to build it first.
|
||||
|
||||
To use your own library in an app:
|
||||
|
||||
* Build the library. You cannot use a library before it is built.
|
||||
<code-example format="." language="bash">
|
||||
ng build my-lib
|
||||
</code-example>
|
||||
|
||||
* In your apps, import from the library by name:
|
||||
```
|
||||
import { my-export } from 'my-lib';
|
||||
```
|
||||
|
||||
### Building and rebuilding your library
|
||||
|
||||
The build step is important if you haven't published your library as an npm package and then installed the package back into your app from npm.
|
||||
For instance, if you clone your git repository and run `npm install`, your editor will show the `my-lib` imports as missing if you haven't yet built your library.
|
||||
|
||||
<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 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.
|
||||
The Angular CLI uses the `tsconfig` paths to tell the build system where to find the library.
|
||||
|
||||
</div>
|
||||
|
||||
If you find that changes to your library are not reflected in your app, your app is probably using an old build of the library.
|
||||
|
||||
You can rebuild your library whenever you make changes to it, but this extra step takes time.
|
||||
*Incremental builds* functionality improves the library-development experience.
|
||||
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:
|
||||
|
||||
<code-example format="." language="bash">
|
||||
ng build my-lib --watch
|
||||
</code-example>
|
@ -52,16 +52,16 @@ When all dependencies are in place, `AppComponent` displays the user information
|
||||
|
||||
## Limit service scope to a component subtree
|
||||
|
||||
An Angular application has multiple injectors, arranged in a tree hierarchy that parallels the component tree.
|
||||
Each injector creates a singleton instance of a dependency.
|
||||
An Angular application has multiple injectors, arranged in a tree hierarchy that parallels the component tree.
|
||||
Each injector creates a singleton instance of a dependency.
|
||||
That same instance is injected wherever that injector provides that service.
|
||||
A particular service can be provided and created at any level of the injector hierarchy,
|
||||
which means that there can be multiple instances of a service if it is provided by multiple injectors.
|
||||
|
||||
Dependencies provided by the root injector can be injected into *any* component *anywhere* in the application.
|
||||
In some cases, you might want to restrict service availability to a particular region of the application.
|
||||
Dependencies provided by the root injector can be injected into *any* component *anywhere* in the application.
|
||||
In some cases, you might want to restrict service availability to a particular region of the application.
|
||||
For instance, you might want to let users explicitly opt in to use a service,
|
||||
rather than letting the root injector provide it automatically.
|
||||
rather than letting the root injector provide it automatically.
|
||||
|
||||
You can limit the scope of an injected service to a *branch* of the application hierarchy
|
||||
by providing that service *at the sub-root component for that branch*.
|
||||
@ -146,34 +146,34 @@ and confirm that the three `HeroBioComponent` instances have their own cached he
|
||||
When a class requires a dependency, that dependency is added to the constructor as a parameter.
|
||||
When Angular needs to instantiate the class, it calls upon the DI framework to supply the dependency.
|
||||
By default, the DI framework searches for a provider in the injector hierarchy,
|
||||
starting at the component's local injector of the component, and if necessary bubbling up
|
||||
starting at the component's local injector of the component, and if necessary bubbling up
|
||||
through the injector tree until it reaches the root injector.
|
||||
|
||||
* The first injector configured with a provider supplies the dependency (a service instance or value) to the constructor.
|
||||
* The first injector configured with a provider supplies the dependency (a service instance or value) to the constructor.
|
||||
|
||||
* If no provider is found in the root injector, the DI framework returns null to the constructor.
|
||||
|
||||
There are a number of options for modifying the default search behavior, using _parameter decorators_
|
||||
on the service-valued parameters of a class constructor.
|
||||
on the service-valued parameters of a class constructor.
|
||||
|
||||
{@a optional}
|
||||
|
||||
### Make a dependency `@Optional` and limit search with `@Host`
|
||||
|
||||
Dependencies can be registered at any level in the component hierarchy.
|
||||
When a component requests a dependency, Angular starts with that component's injector
|
||||
and walks up the injector tree until it finds the first suitable provider.
|
||||
Dependencies can be registered at any level in the component hierarchy.
|
||||
When a component requests a dependency, Angular starts with that component's injector
|
||||
and walks up the injector tree until it finds the first suitable provider.
|
||||
Angular throws an error if it can't find the dependency during that walk.
|
||||
|
||||
In some cases, you need to limit the search or accommodate a missing dependency.
|
||||
You can modify Angular's search behavior with the `@Host` and `@Optional` qualifying
|
||||
decorators on a service-valued parameter of the component's constructor.
|
||||
decorators on a service-valued parameter of the component's constructor.
|
||||
|
||||
* The `@Optional` property decorator tells Angular to return null when it can't find the dependency.
|
||||
|
||||
* The `@Host` property decorator stops the upward search at the *host component*.
|
||||
The host component is typically the component requesting the dependency.
|
||||
However, when this component is projected into a *parent* component,
|
||||
* The `@Host` property decorator stops the upward search at the *host component*.
|
||||
The host component is typically the component requesting the dependency.
|
||||
However, when this component is projected into a *parent* component,
|
||||
that parent component becomes the host. The following example covers this second case.
|
||||
|
||||
These decorators can be used individually or together, as shown in the example.
|
||||
@ -238,8 +238,8 @@ Here's `HeroBiosAndContactsComponent` in action.
|
||||
|
||||
|
||||
If you comment out the `@Host()` decorator, Angular walks up the injector ancestor tree
|
||||
until it finds the logger at the `AppComponent` level.
|
||||
The logger logic kicks in and the hero display updates
|
||||
until it finds the logger at the `AppComponent` level.
|
||||
The logger logic kicks in and the hero display updates
|
||||
with the "!!!" marker to indicate that the logger was found.
|
||||
|
||||
<figure>
|
||||
@ -254,7 +254,7 @@ the app throws an exception when it cannot find the required logger at the host
|
||||
|
||||
### Supply a custom provider with `@Inject`
|
||||
|
||||
Using a custom provider allows you to provide a concrete implementation for implicit dependencies, such as built-in browser APIs. The following example uses an `InjectionToken` to provide the [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) browser API as a dependency in the `BrowserStorageService`.
|
||||
Using a custom provider allows you to provide a concrete implementation for implicit dependencies, such as built-in browser APIs. The following example uses an `InjectionToken` to provide the [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) browser API as a dependency in the `BrowserStorageService`.
|
||||
|
||||
<code-example path="dependency-injection-in-action/src/app/storage.service.ts" header="src/app/storage.service.ts">
|
||||
|
||||
@ -262,6 +262,8 @@ Using a custom provider allows you to provide a concrete implementation for impl
|
||||
|
||||
The `factory` function returns the `localStorage` property that is attached to the browser window object. The `Inject` decorator is a constructor parameter used to specify a custom provider of a dependency. This custom provider can now be overridden during testing with a mock API of `localStorage` instead of interactive with real browser APIs.
|
||||
|
||||
{@a skip}
|
||||
|
||||
### Modify the provider search with `@Self` and `@SkipSelf`
|
||||
|
||||
Providers can also be scoped by injector through constructor parameter decorators. The following example overrides the `BROWSER_STORAGE` token in the `Component` class `providers` with the `sessionStorage` browser API. The same `BrowserStorageService` is injected twice in the constructor, decorated with `@Self` and `@SkipSelf` to define which injector handles the provider dependency.
|
||||
@ -291,7 +293,7 @@ The directive sets the background to a highlight color when the user mouses over
|
||||
DOM element to which the directive is applied.
|
||||
|
||||
Angular sets the constructor's `el` parameter to the injected `ElementRef`.
|
||||
(An `ElementRef` is a wrapper around a DOM element,
|
||||
(An `ElementRef` is a wrapper around a DOM element,
|
||||
whose `nativeElement` property exposes the DOM element for the directive to manipulate.)
|
||||
|
||||
The sample code applies the directive's `myHighlight` attribute to two `<div>` tags,
|
||||
@ -332,7 +334,7 @@ Angular asks the injector for the service associated with `LoggerService`
|
||||
and assigns the returned value to the `logger` parameter.
|
||||
|
||||
If the injector has already cached an instance of the service associated with the token,
|
||||
it provides that instance.
|
||||
it provides that instance.
|
||||
If it doesn't, it needs to make one using the provider associated with the token.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
@ -346,7 +348,7 @@ If the search fails, the injector throws an error—unless the request was [
|
||||
|
||||
A new injector has no providers.
|
||||
Angular initializes the injectors it creates with a set of preferred providers.
|
||||
You have to configure providers for your own app-specific dependencies.
|
||||
You have to configure providers for your own app-specific dependencies.
|
||||
|
||||
|
||||
{@a defining-providers}
|
||||
@ -355,7 +357,7 @@ You have to configure providers for your own app-specific dependencies.
|
||||
### Defining providers
|
||||
|
||||
A dependency can't always be created by the default method of instantiating a class.
|
||||
You learned about some other methods in [Dependency Providers](guide/dependency-injection-providers).
|
||||
You learned about some other methods in [Dependency Providers](guide/dependency-injection-providers).
|
||||
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.
|
||||
|
||||
@ -364,7 +366,7 @@ It's visually simple: a few properties and the logs produced by a logger.
|
||||
</figure>
|
||||
|
||||
The code behind it customizes how and where the DI framework provides dependencies.
|
||||
The use cases illustrate different ways to use the [*provide* object literal](guide/dependency-injection-providers#provide) to associate a definition object with a DI token.
|
||||
The use cases illustrate different ways to use the [*provide* object literal](guide/dependency-injection-providers#provide) to associate a definition object with a DI token.
|
||||
|
||||
<code-example path="dependency-injection-in-action/src/app/hero-of-the-month.component.ts" region="hero-of-the-month" header="hero-of-the-month.component.ts">
|
||||
|
||||
@ -389,13 +391,13 @@ The `HeroOfTheMonthComponent` example has two value providers.
|
||||
</code-example>
|
||||
|
||||
* The first provides an existing instance of the `Hero` class to use for the `Hero` token, rather than
|
||||
requiring the injector to create a new instance with `new` or use its own cached instance.
|
||||
requiring the injector to create a new instance with `new` or use its own cached instance.
|
||||
Here, the token is the class itself.
|
||||
|
||||
* The second specifies a literal string resource to use for the `TITLE` token.
|
||||
The `TITLE` provider token is *not* a class, but is instead a
|
||||
special kind of provider lookup key called an [injection token](guide/dependency-injection-in-action#injection-token), represented by
|
||||
an `InjectionToken` instance.
|
||||
an `InjectionToken` instance.
|
||||
|
||||
You can use an injection token for any kind of provider but it's particularly
|
||||
helpful when the dependency is a simple value like a string, a number, or a function.
|
||||
@ -414,12 +416,12 @@ Other types of providers can create their values *lazily*; that is, when they're
|
||||
{@a useclass}
|
||||
|
||||
|
||||
#### Class providers: `useClass`
|
||||
#### Class providers: `useClass`
|
||||
|
||||
The `useClass` provider key lets you create and return a new instance of the specified class.
|
||||
|
||||
You can use this type of provider to substitute an *alternative implementation*
|
||||
for a common or default class.
|
||||
for a common or default class.
|
||||
The alternative implementation could, for example, implement a different strategy,
|
||||
extend the default class, or emulate the behavior of the real class in a test case.
|
||||
|
||||
@ -502,7 +504,7 @@ This is illustrated in the following image, which displays the logging date.
|
||||
|
||||
{@a usefactory}
|
||||
|
||||
#### Factory providers: `useFactory`
|
||||
#### Factory providers: `useFactory`
|
||||
|
||||
The `useFactory` provider key lets you create a dependency object by calling a factory function,
|
||||
as in the following example.
|
||||
@ -537,7 +539,7 @@ the passed-in state value and the injected services `Hero` and `HeroService`.
|
||||
The provider factory function (returned by `runnersUpFactory()`) returns the actual dependency object,
|
||||
the string of names.
|
||||
|
||||
* The function takes a winning `Hero` and a `HeroService` as arguments.
|
||||
* The function takes a winning `Hero` and a `HeroService` as arguments.
|
||||
Angular supplies these arguments from injected values identified by
|
||||
the two *tokens* in the `deps` array.
|
||||
|
||||
@ -588,7 +590,7 @@ But they did neither.
|
||||
`MinimalLogger` is used only as a dependency injection token.
|
||||
|
||||
When you use a class this way, it's called a *class interface*.
|
||||
|
||||
|
||||
As mentioned in [DI Providers](guide/dependency-injection-providers#interface-not-valid-token),
|
||||
an interface is not a valid DI token because it is a TypeScript artifact that doesn't exist at run time.
|
||||
Use this abstract class interface to get the strong typing of an interface,
|
||||
@ -609,7 +611,7 @@ The `MinimalLogger` transpiles to this unoptimized, pre-minified JavaScript for
|
||||
</code-example>
|
||||
|
||||
Notice that it doesn't have any members. It never grows no matter how many members you add to the class,
|
||||
as long as those members are typed but not implemented.
|
||||
as long as those members are typed but not implemented.
|
||||
|
||||
Look again at the TypeScript `MinimalLogger` class to confirm that it has no implementation.
|
||||
|
||||
@ -736,7 +738,7 @@ Break the circularity with `forwardRef`.
|
||||
</code-example>
|
||||
|
||||
|
||||
<!--- Waiting for good examples
|
||||
<!--- Waiting for good examples
|
||||
|
||||
{@a directive-level-providers}
|
||||
|
||||
@ -744,15 +746,15 @@ Break the circularity with `forwardRef`.
|
||||
|
||||
## Element-level providers
|
||||
|
||||
A component is a specialization of directive, and the `@Component()` decorator inherits the `providers` property from `@Directive`. The injector is at the element level, so a provider configured with any element-level injector is available to any component, directive, or pipe attached to the same element.
|
||||
A component is a specialization of directive, and the `@Component()` decorator inherits the `providers` property from `@Directive`. The injector is at the element level, so a provider configured with any element-level injector is available to any component, directive, or pipe attached to the same element.
|
||||
|
||||
Here's a live example that implements a custom form control, taking advantage of an injector that is shared by a component and a directive on the same element.
|
||||
|
||||
https://stackblitz.com/edit/basic-form-control
|
||||
|
||||
The component, `custom-control`, configures a provider for the DI token `NG_VALUE_ACCESSOR`.
|
||||
The component, `custom-control`, configures a provider for the DI token `NG_VALUE_ACCESSOR`.
|
||||
In the template, the `FormControlName` directive is instantiated along with the custom component.
|
||||
It can inject the `NG_VALUE_ACCESSOR` dependency because they share the same injector.
|
||||
It can inject the `NG_VALUE_ACCESSOR` dependency because they share the same injector.
|
||||
(Notice that this example also makes use of `forwardRef()` to resolve a circularity in the definitions.)
|
||||
|
||||
### Sharing a service among components
|
||||
@ -784,4 +786,3 @@ If you want to show only one of them, use the directive to make sure __??of what
|
||||
`<hero-overview heroCache></hero-overview>`
|
||||
|
||||
--->
|
||||
|
||||
|
@ -162,7 +162,7 @@ Here's the revised component, making use of the injected service, side-by-side w
|
||||
</code-pane>
|
||||
</code-tabs>
|
||||
|
||||
`HeroService` must provided in some parent injector. The code in `HeroListComponent` doesn't depend on where `HeroService` comes from.
|
||||
`HeroService` must be provided in some parent injector. The code in `HeroListComponent` doesn't depend on where `HeroService` comes from.
|
||||
If you decided to provide `HeroService` in `AppModule`, `HeroListComponent` wouldn't change.
|
||||
|
||||
{@a singleton-services}
|
||||
|
@ -35,7 +35,7 @@ Make a note of the user name and project name in GitHub.
|
||||
|
||||
1. Build your project using Github project name, with the Angular CLI command [`ng build`](cli/build) and the options shown here:
|
||||
<code-example language="none" class="code-shell">
|
||||
ng build --prod --output-path docs --base-href <project_name>
|
||||
ng build --prod --output-path docs --base-href /<project_name>/
|
||||
</code-example>
|
||||
|
||||
1. When the build is complete, make a copy of `docs/index.html` and name it `docs/404.html`.
|
||||
@ -46,9 +46,9 @@ Make a note of the user name and project name in GitHub.
|
||||
|
||||
You can see your deployed page at `https://<user_name>.github.io/<project_name>/`.
|
||||
|
||||
<div class="alert is-helpful>
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Check out [angular-cli-ghpages](https://github.com/angular-buch/angular-cli-ghpages), a full featured package that does all this for you and has extra functionality.
|
||||
Check out [angular-cli-ghpages](https://github.com/angular-buch/angular-cli-ghpages), a full featured package that does all this for you and has extra functionality.
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -149,7 +149,7 @@ In either style, the template data bindings have the same access to the componen
|
||||
Although this example uses variable assignment to initialize the components, you could instead declare and initialize the properties using a constructor:
|
||||
|
||||
|
||||
<code-example path="displaying-data/src/app/app-ctor.component.ts" linenums="false" region="class">
|
||||
<code-example path="displaying-data/src/app/app-ctor.component.1.ts" linenums="false" region="class">
|
||||
|
||||
</code-example>
|
||||
|
||||
|
@ -53,7 +53,7 @@ Workspace-wide `node_modules` dependencies are visible to this project.
|
||||
| `app/` | Contains the component files in which your app logic and data are defined. See details in [App source folder](#app-src) below. |
|
||||
| `assets/` | Contains image files and other asset files to be copied as-is when you build your application. |
|
||||
| `environments/` | Contains build configuration options for particular target environments. By default there is an unnamed standard development environment and a production ("prod") environment. You can define additional target environment configurations. |
|
||||
| `browserlist` | Configures sharing of target browsers and Node.js versions among various front-end tools. See [Browserlist on GitHub](https://github.com/browserslist/browserslist) for more information. |
|
||||
| `browserslist` | Configures sharing of target browsers and Node.js versions among various front-end tools. See [Browserslist on GitHub](https://github.com/browserslist/browserslist) for more information. |
|
||||
| `favicon.ico` | An icon to use for this app in the bookmark bar. |
|
||||
| `index.html` | The main HTML page that is served when someone visits your site. The CLI automatically adds all JavaScript and CSS files when building your app, so you typically don't need to add any `<script>` or` <link>` tags here manually. |
|
||||
| `main.ts` | The main entry point for your app. Compiles the application with the [JIT compiler](https://angular.io/guide/glossary#jit) and bootstraps the application's root module (AppModule) to run in the browser. You can also use the [AOT compiler](https://angular.io/guide/aot-compiler) without changing any code by appending the `--aot` flag to the CLI `build` and `serve` commands. |
|
||||
|
@ -19,18 +19,18 @@ unexpected definitions.
|
||||
|
||||
## ahead-of-time (AOT) compilation
|
||||
|
||||
The Angular ahead-of-time (AOT) compiler converts Angular HTML and TypeScript code
|
||||
into efficient JavaScript code during the build phase, before the browser downloads
|
||||
and runs that code.
|
||||
The Angular ahead-of-time (AOT) compiler converts Angular HTML and TypeScript code
|
||||
into efficient JavaScript code during the build phase, before the browser downloads
|
||||
and runs that code.
|
||||
This is the best compilation mode for production environments, with decreased load time and increased performance compared to [just-in-time (JIT) compilation](guide/glossary#jit).
|
||||
|
||||
By compiling your application using the `ngc` command-line tool, you can bootstrap directly to a module factory, so you don't need to include the Angular compiler in your JavaScript bundle.
|
||||
|
||||
{@a angular-element}
|
||||
{@a angular-element}
|
||||
|
||||
## Angular element
|
||||
|
||||
An Angular [component](guide/glossary#component) packaged as a [custom element](guide/glossary#custom-element).
|
||||
An Angular [component](guide/glossary#component) packaged as a [custom element](guide/glossary#custom-element).
|
||||
|
||||
Learn more in [Angular Elements Overview](guide/elements).
|
||||
|
||||
@ -62,8 +62,8 @@ Learn more in [Attribute Directives](guide/attribute-directives).
|
||||
|
||||
## binding
|
||||
|
||||
Generally, the practice of setting a variable or property to a data value.
|
||||
Within Angular, typically refers to [data binding](guide/glossary#data-binding),
|
||||
Generally, the practice of setting a variable or property to a data value.
|
||||
Within Angular, typically refers to [data binding](guide/glossary#data-binding),
|
||||
which coordinates DOM object properties with data object properties.
|
||||
|
||||
Sometimes refers to a [dependency-injection](guide/glossary#dependency-injection) binding
|
||||
@ -75,7 +75,7 @@ between a [token](guide/glossary#token) and a dependency [provider](guide/glossa
|
||||
|
||||
A way to initialize and launch an app or system.
|
||||
|
||||
In Angular, an app's root NgModule (`AppModule`) has a `bootstrap` property that identifies the app's top-level [components](guide/glossary#component).
|
||||
In Angular, an app's root NgModule (`AppModule`) has a `bootstrap` property that identifies the app's top-level [components](guide/glossary#component).
|
||||
During the bootstrap process, Angular creates and inserts these components into the `index.html` host web page.
|
||||
You can bootstrap multiple apps in the same `index.html`. Each app contains its own components.
|
||||
|
||||
@ -90,7 +90,7 @@ Learn more in [Bootstrapping](guide/bootstrapping).
|
||||
|
||||
## case types
|
||||
|
||||
Angular uses capitalization conventions to distinguish the names of various types, as described in the [naming guidelines section](guide/styleguide#02-01) of the Style Guide. Here's a summary of the case types:
|
||||
Angular uses capitalization conventions to distinguish the names of various types, as described in the [naming guidelines section](guide/styleguide#02-01) of the Style Guide. Here's a summary of the case types:
|
||||
|
||||
* camelCase : Symbols, properties, methods, pipe names, non-component directive selectors, constants.
|
||||
Standard or lower camel case uses lowercase on the first letter of the item. For example, "selectedHero".
|
||||
@ -124,7 +124,13 @@ The following decorators can declare Angular class types:
|
||||
|
||||
## class field decorator
|
||||
|
||||
A [decorator](guide/glossary#decorator) statement immediately before a field in a class definition that declares the type of that field. Some examples are `@Input` and `@Output`.
|
||||
A [decorator](guide/glossary#decorator) statement immediately before a field in a class definition that declares the type of that field. Some examples are `@Input` and `@Output`.
|
||||
|
||||
{@a collection}
|
||||
|
||||
## collection
|
||||
|
||||
In Angular, a set of related [schematics](#schematic) collected in an [npm package](#npm-package).
|
||||
|
||||
{@a cli}
|
||||
|
||||
@ -135,13 +141,15 @@ The [Angular CLI](cli) is a command-line tool for managing the Angular developme
|
||||
* To begin using the CLI for a new project, see [Getting Started](guide/quickstart).
|
||||
* To learn more about the full capabilities of the CLI, see the [CLI command reference](cli).
|
||||
|
||||
See also [Schematics CLI](#schematics-cli).
|
||||
|
||||
{@a component}
|
||||
|
||||
## component
|
||||
|
||||
A class with the `@Component()` [decorator](guide/glossary#decorator) that associates it with a companion [template](guide/glossary#template). Together, the component and template define a [view](guide/glossary#view).
|
||||
A component is a special type of [directive](guide/glossary#directive).
|
||||
The `@Component()` decorator extends the `@Directive()` decorator with template-oriented features.
|
||||
The `@Component()` decorator extends the `@Directive()` decorator with template-oriented features.
|
||||
|
||||
An Angular component class is responsible for exposing data and handling most of the view's display and user-interaction logic through [data binding](guide/glossary#data-binding).
|
||||
|
||||
@ -151,7 +159,7 @@ Read more about components, templates, and views in [Architecture Overview](guid
|
||||
|
||||
## custom element
|
||||
|
||||
A web platform feature, currently supported by most browsers and available in other browsers through polyfills (see [Browser support](guide/browser-support)).
|
||||
A web platform feature, currently supported by most browsers and available in other browsers through polyfills (see [Browser support](guide/browser-support)).
|
||||
|
||||
The custom element feature extends HTML by allowing you to define a tag whose content is created and controlled by JavaScript code. A custom element (also called a *web component*) is recognized by a browser when it's added to the [CustomElementRegistry](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry).
|
||||
|
||||
@ -189,7 +197,7 @@ Read about the following forms of binding in [Template Syntax](guide/template-sy
|
||||
|
||||
## declarable
|
||||
|
||||
A class type that you can add to the `declarations` list of an [NgModule](guide/glossary#ngmodule).
|
||||
A class type that you can add to the `declarations` list of an [NgModule](guide/glossary#ngmodule).
|
||||
You can declare [components](guide/glossary#component), [directives](guide/glossary#directive), and [pipes](guide/glossary#pipe).
|
||||
|
||||
Don't declare the following:
|
||||
@ -204,16 +212,15 @@ Don't declare the following:
|
||||
|
||||
{@a decoration}
|
||||
|
||||
|
||||
## decorator | decoration
|
||||
|
||||
A function that modifies a class or property definition. Decorators (also called *annotations*) are an experimental (stage 2) [JavaScript language feature](https://github.com/wycats/javascript-decorators).
|
||||
A function that modifies a class or property definition. Decorators (also called *annotations*) are an experimental (stage 2) [JavaScript language feature](https://github.com/wycats/javascript-decorators).
|
||||
TypeScript adds support for decorators.
|
||||
|
||||
Angular defines decorators that attach metadata to classes or properties
|
||||
so that it knows what those classes or properties mean and how they should work.
|
||||
so that it knows what those classes or properties mean and how they should work.
|
||||
|
||||
See [class decorator](guide/glossary#class-decorator), [class field decorator](guide/glossary#class-field-decorator).
|
||||
See [class decorator](guide/glossary#class-decorator), [class field decorator](guide/glossary#class-field-decorator).
|
||||
|
||||
{@a di}
|
||||
|
||||
@ -251,15 +258,15 @@ There are three categories of directive:
|
||||
|
||||
* [Structural directives](guide/glossary#structural-directive) modify the structure of the DOM.
|
||||
|
||||
Angular supplies a number of built-in directives that begin with the `ng` prefix.
|
||||
You can also create new directives to implement your own functionality.
|
||||
Angular supplies a number of built-in directives that begin with the `ng` prefix.
|
||||
You can also create new directives to implement your own functionality.
|
||||
You associate a *selector* (an HTML tag such as `<my-directive>`) with a custom directive, thereby extending the [template syntax](guide/template-syntax) that you can use in your apps.
|
||||
|
||||
{@a dom}
|
||||
|
||||
## domain-specific language (DSL)
|
||||
|
||||
A special-purpose library or API; see [Domain-specific language](https://en.wikipedia.org/wiki/Domain-specific_language).
|
||||
A special-purpose library or API; see [Domain-specific language](https://en.wikipedia.org/wiki/Domain-specific_language).
|
||||
Angular extends TypeScript with domain-specific languages for a number of domains relevant to Angular apps, defined in NgModules such as [animations](guide/animations), [forms](guide/forms), and [routing and navigation](guide/router).
|
||||
|
||||
{@a dynamic-components}
|
||||
@ -270,6 +277,7 @@ A technique for adding a component to the DOM at run time. Requires that you exc
|
||||
|
||||
See also [custom element](guide/glossary#custom-element), which provides an easier path with the same result.
|
||||
|
||||
|
||||
{@a E}
|
||||
|
||||
{@a eager-loading}
|
||||
@ -287,7 +295,7 @@ See [lazy loading](guide/glossary#lazy-load).
|
||||
|
||||
The [official JavaScript language specification](https://en.wikipedia.org/wiki/ECMAScript).
|
||||
|
||||
Not all browsers support the latest ECMAScript standard, but you can use a [transpiler](guide/glossary#transpile) (like [TypeScript](guide/glossary#typescript)) to write code using the latest features, which will then be transpiled to code that runs on versions that are supported by browsers.
|
||||
Not all browsers support the latest ECMAScript standard, but you can use a [transpiler](guide/glossary#transpile) (like [TypeScript](guide/glossary#typescript)) to write code using the latest features, which will then be transpiled to code that runs on versions that are supported by browsers.
|
||||
|
||||
To learn more, see [Browser Support](guide/browser-support).
|
||||
|
||||
@ -296,8 +304,8 @@ To learn more, see [Browser Support](guide/browser-support).
|
||||
|
||||
## element
|
||||
|
||||
Angular defines an `ElementRef` class to wrap render-specific native UI elements.
|
||||
In most cases, this allows you to use Angular templates and data binding to access DOM elements
|
||||
Angular defines an `ElementRef` class to wrap render-specific native UI elements.
|
||||
In most cases, this allows you to use Angular templates and data binding to access DOM elements
|
||||
without reference to the native element.
|
||||
|
||||
The documentation generally refers to *elements* (`ElementRef` instances), as distinct from *DOM elements*
|
||||
@ -309,7 +317,7 @@ Compare to [custom element](guide/glossary#custom-element).
|
||||
|
||||
## entry point
|
||||
|
||||
A JavaScript symbol that makes parts of an [npm package](guide/npm-packages) available for import by other code.
|
||||
A JavaScript symbol that makes parts of an [npm package](guide/npm-packages) available for import by other code.
|
||||
The Angular [scoped packages](guide/glossary#scoped-package) each have an entry point named `index`.
|
||||
|
||||
Within Angular, use [NgModules](guide/glossary#ngmodule) to make public parts available for import by other NgModules.
|
||||
@ -369,7 +377,7 @@ An Angular class or other definition that provides a dependency using the [depen
|
||||
|
||||
An object in the Angular [dependency-injection](guide/glossary#dependency-injection) system
|
||||
that can find a named dependency in its cache or create a dependency
|
||||
using a configured [provider](guide/glossary#provider).
|
||||
using a configured [provider](guide/glossary#provider).
|
||||
Injectors are created for NgModules automatically as part of the bootstrap process
|
||||
and are inherited through the component hierarchy.
|
||||
|
||||
@ -385,7 +393,7 @@ Learn more about the injector hierarchy in [Hierarchical Dependency Injectors](g
|
||||
|
||||
## input
|
||||
|
||||
When defining a [directive](guide/glossary#directive), the `@Input()` decorator on a directive property
|
||||
When defining a [directive](guide/glossary#directive), the `@Input()` decorator on a directive property
|
||||
makes that property available as a *target* of a [property binding](guide/template-syntax#property-binding).
|
||||
Data values flow into an input property from the data source identified
|
||||
in the [template expression](guide/glossary#template-expression) to the right of the equal sign.
|
||||
@ -396,7 +404,7 @@ To learn more, see [input and output properties](guide/template-syntax#inputs-ou
|
||||
|
||||
## interpolation
|
||||
|
||||
A form of property [data binding](guide/glossary#data-binding) in which a [template expression](guide/glossary#template-expression) between double-curly braces renders as text.
|
||||
A form of property [data binding](guide/glossary#data-binding) in which a [template expression](guide/glossary#template-expression) between double-curly braces renders as text.
|
||||
That text can be concatenated with neighboring text before it is assigned to an element property
|
||||
or displayed between element tags, as in this example.
|
||||
|
||||
@ -423,11 +431,11 @@ See [ECMAScript](guide/glossary#ecma), [TypeScript](guide/glossary#typescript).
|
||||
|
||||
## just-in-time (JIT) compilation
|
||||
|
||||
The Angular just-in-time (JIT) compiler converts your Angular HTML and TypeScript code into
|
||||
The Angular just-in-time (JIT) compiler converts your Angular HTML and TypeScript code into
|
||||
efficient JavaScript code at run time, as part of bootstrapping.
|
||||
|
||||
JIT compilation is the default (as opposed to AOT compilation) when you run Angular's `ng build` and `ng serve` CLI commands, and is a good choice during development.
|
||||
JIT mode is strongly discouraged for production use
|
||||
JIT compilation is the default (as opposed to AOT compilation) when you run Angular's `ng build` and `ng serve` CLI commands, and is a good choice during development.
|
||||
JIT mode is strongly discouraged for production use
|
||||
because it results in large application payloads that hinder the bootstrap performance.
|
||||
|
||||
Compare to [ahead-of-time (AOT) compilation](guide/glossary#aot).
|
||||
@ -442,22 +450,24 @@ Compare to [ahead-of-time (AOT) compilation](guide/glossary#aot).
|
||||
|
||||
## lazy loading
|
||||
|
||||
A process that speeds up application load time by splitting the application into multiple bundles and loading them on demand.
|
||||
For example, dependencies can be lazy loaded as needed—as opposed to [eager-loaded](guide/glossary#eager-loading) modules that are required by the root module and are thus loaded on launch.
|
||||
A process that speeds up application load time by splitting the application into multiple bundles and loading them on demand.
|
||||
For example, dependencies can be lazy loaded as needed—as opposed to [eager-loaded](guide/glossary#eager-loading) modules that are required by the root module and are thus loaded on launch.
|
||||
|
||||
The [router](guide/glossary#router) makes use of lazy loading to load child views only when the parent view is activated.
|
||||
The [router](guide/glossary#router) makes use of lazy loading to load child views only when the parent view is activated.
|
||||
Similarly, you can build custom elements that can be loaded into an Angular app when needed.
|
||||
|
||||
{@a library}
|
||||
|
||||
## library
|
||||
|
||||
In Angular, a [project](guide/glossary#project) that provides functionality that can be included in other Angular apps.
|
||||
A library isn't a complete Angular app and can't run independently.
|
||||
In Angular, a [project](guide/glossary#project) that provides functionality that can be included in other Angular apps.
|
||||
A library isn't a complete Angular app and can't run independently.
|
||||
|
||||
* Library developers can use the [CLI](guide/glossary#cli) to `generate` scaffolding for a new library in an existing [workspace](guide/glossary#workspace), and can publish a library as an `npm` package.
|
||||
* Library developers can use the [Angular CLI](guide/glossary#cli) to `generate` scaffolding for a new library in an existing [workspace](guide/glossary#workspace), and can publish a library as an `npm` package.
|
||||
|
||||
* App developers can use the [CLI](guide/glossary#cli) to `add` a published library for use with an app in the same [workspace](guide/glossary#workspace).
|
||||
* Application developers can use the [Angular CLI](guide/glossary#cli) to `add` a published library for use with an application in the same [workspace](guide/glossary#workspace).
|
||||
|
||||
See also [schematic](#schematic).
|
||||
|
||||
{@a lifecycle-hook}
|
||||
|
||||
@ -488,7 +498,7 @@ To learn more, see [Lifecycle Hooks](guide/lifecycle-hooks).
|
||||
|
||||
## module
|
||||
|
||||
In general, a module collects a block of code dedicated to a single purpose. Angular uses standard JavaScript modules and also defines an Angular module, `NgModule`.
|
||||
In general, a module collects a block of code dedicated to a single purpose. Angular uses standard JavaScript modules and also defines an Angular module, `NgModule`.
|
||||
|
||||
In JavaScript (ECMAScript), each file is a module and all objects defined in the file belong to that module. Objects can exported, making them public, and public objects can be imported for use by other modules.
|
||||
|
||||
@ -516,9 +526,9 @@ To learn more, see [NgModules](guide/ngmodules).
|
||||
|
||||
{@a npm-package}
|
||||
|
||||
## npm package
|
||||
## npm package
|
||||
|
||||
The [npm package manager](https://docs.npmjs.com/getting-started/what-is-npm) is used to distribute and load Angular modules and libraries.
|
||||
The [npm package manager](https://docs.npmjs.com/getting-started/what-is-npm) is used to distribute and load Angular modules and libraries.
|
||||
|
||||
Learn more about how Angular uses [Npm Packages](guide/npm-packages).
|
||||
|
||||
@ -528,11 +538,11 @@ Learn more about how Angular uses [Npm Packages](guide/npm-packages).
|
||||
|
||||
## observable
|
||||
|
||||
A producer of multiple values, which it pushes to [subscribers](guide/glossary#subscriber). Used for asynchronous event handling throughout Angular. You execute an observable by subscribing to it with its `subscribe()` method, passing callbacks for notifications of new values, errors, or completion.
|
||||
A producer of multiple values, which it pushes to [subscribers](guide/glossary#subscriber). Used for asynchronous event handling throughout Angular. You execute an observable by subscribing to it with its `subscribe()` method, passing callbacks for notifications of new values, errors, or completion.
|
||||
|
||||
Observables can deliver single or multiple values of any type to subscribers, either synchronously (as a function delivers a value to its caller) or on a schedule. A subscriber receives notification of new values as they are produced and notification of either normal completion or error completion.
|
||||
Observables can deliver single or multiple values of any type to subscribers, either synchronously (as a function delivers a value to its caller) or on a schedule. A subscriber receives notification of new values as they are produced and notification of either normal completion or error completion.
|
||||
|
||||
Angular uses a third-party library called [Reactive Extensions (RxJS)](http://reactivex.io/rxjs/).
|
||||
Angular uses a third-party library called [Reactive Extensions (RxJS)](http://reactivex.io/rxjs/).
|
||||
|
||||
To learn more, see [Observables](guide/observables).
|
||||
|
||||
@ -547,8 +557,8 @@ An object passed to the `subscribe()` method for an [observable](guide/glossary#
|
||||
|
||||
## output
|
||||
|
||||
When defining a [directive](guide/glossary#directive), the `@Output{}` decorator on a directive property
|
||||
makes that property available as a *target* of [event binding](guide/template-syntax#event-binding).
|
||||
When defining a [directive](guide/glossary#directive), the `@Output{}` decorator on a directive property
|
||||
makes that property available as a *target* of [event binding](guide/template-syntax#event-binding).
|
||||
Events stream *out* of this property to the receiver identified
|
||||
in the [template expression](guide/glossary#template-expression) to the right of the equal sign.
|
||||
|
||||
@ -562,22 +572,22 @@ To learn more, see [Input and Output Properties](guide/template-syntax#inputs-ou
|
||||
## pipe
|
||||
|
||||
A class which is preceded by the `@Pipe{}` decorator and which defines a function that transforms input values to output values for display in a [view](guide/glossary#view). Angular defines various pipes, and you can define new pipes.
|
||||
|
||||
|
||||
To learn more, see [Pipes](guide/pipes).
|
||||
|
||||
{@a polyfill}
|
||||
|
||||
## polyfill
|
||||
|
||||
An [npm package](guide/npm-packages) that plugs gaps in a browser's JavaScript implementation.
|
||||
See [Browser Support](guide/browser-support) for polyfills that support particular functionality for particular platforms.
|
||||
An [npm package](guide/npm-packages) that plugs gaps in a browser's JavaScript implementation.
|
||||
See [Browser Support](guide/browser-support) for polyfills that support particular functionality for particular platforms.
|
||||
|
||||
{@a project}
|
||||
|
||||
## project
|
||||
|
||||
In Angular, a folder within a [workspace](guide/glossary#workspace) that contains an Angular app or [library](guide/glossary#library).
|
||||
A workspace can contain multiple projects.
|
||||
A workspace can contain multiple projects.
|
||||
All apps in a workspace can use libraries in the same workspace.
|
||||
|
||||
{@a provider}
|
||||
@ -588,7 +598,7 @@ An object that implements one of the [`Provider`](api/core/Provider) interfaces.
|
||||
An [injector](guide/glossary#injector) uses the provider to create a new instance of a dependency
|
||||
for a class that requires it.
|
||||
|
||||
Angular registers its own providers with every injector, for services that Angular defines.
|
||||
Angular registers its own providers with every injector, for services that Angular defines.
|
||||
You can register your own providers for services that your app needs.
|
||||
|
||||
See also [service](guide/glossary#service), [dependency injection](guide/glossary#di).
|
||||
@ -625,7 +635,7 @@ The alternative is a template-driven form. For an introduction and comparison of
|
||||
A tool that configures and implements navigation among states and [views](guide/glossary#view) within an Angular app.
|
||||
|
||||
The `Router` module is an [NgModule](guide/glossary#ngmodule) that provides the necessary service providers and directives for navigating through application views. A [routing component](guide/glossary#routing-component) is one that imports the `Router` module and whose template contains a `RouterOutlet` element where it can display views produced by the router.
|
||||
|
||||
|
||||
The router defines navigation among views on a single page, as opposed to navigation among pages. It interprets URL-like links to determine which views to create or destroy, and which components to load or unload. It allows you to take advantage of [lazy loading](guide/glossary#lazy-load) in your Angular apps.
|
||||
|
||||
To learn more, see [Routing and Navigation](guide/router).
|
||||
@ -644,6 +654,10 @@ An Angular [component](guide/glossary#component) with a `RouterOutlet` directive
|
||||
|
||||
For more information, see [Routing and Navigation](guide/router).
|
||||
|
||||
{@a rule}
|
||||
|
||||
In [schematics](#schematic), a function that operates on a [file tree](#file-tree) to create, delete, or modify files in a specific manner, and returns a new `Tree` object.
|
||||
|
||||
|
||||
{@a S}
|
||||
|
||||
@ -651,22 +665,37 @@ For more information, see [Routing and Navigation](guide/router).
|
||||
|
||||
## schematic
|
||||
|
||||
A scaffolding library that defines how to generate or transform a programming project by creating, modifying, refactoring, or moving files and code.
|
||||
The Angular [CLI](guide/glossary#cli) uses schematics to generate and modify [Angular projects](guide/glossary#project) and parts of projects.
|
||||
A scaffolding library that defines how to generate or transform a programming project by creating, modifying, refactoring, or moving files and code.
|
||||
A schematic defines [rules](#rule) that operate on a virtual file system called a [tree](#file-tree).
|
||||
The [Angular CLI](guide/glossary#cli) uses schematics to generate and modify [Angular projects](guide/glossary#project) and parts of projects.
|
||||
|
||||
* Angular provides a set of schematics for use with the CLI. See the [Angular CLI command reference](cli). The [`ng add`](cli/add) command runs schematics as part of adding a library to your project. The [`ng generate`](cli/generate) command runs schematics to create apps, libraries, and Angular code constructs.
|
||||
* Angular provides a set of schematics for use with the CLI. See the [Angular CLI command reference](cli). The [`ng add`](cli/add) command runs schematics as part of adding a library to your project. The [`ng generate`](cli/generate) command runs schematics to create apps, libraries, and Angular code constructs.
|
||||
|
||||
* Library developers can create schematics that enable the CLI to generate their published libraries.
|
||||
For more information, see [devkit documentation](https://www.npmjs.com/package/@angular-devkit/schematics).
|
||||
* [Library](#library) developers can use the [Schematics CLI](#schematics-cli) to create schematics that enable the Angular CLI to add and update their published libraries, and to generate artifacts the library defines.
|
||||
|
||||
For more information, see [devkit documentation](https://www.npmjs.com/package/@angular-devkit/schematics).
|
||||
|
||||
{@a schematics-cli}
|
||||
|
||||
## Schematics CLI
|
||||
|
||||
Schematics come with their own command-line tool.
|
||||
Using Node 6.9 or above, install the Schematics CLI globally:
|
||||
|
||||
<code-example format="." language="bash">
|
||||
npm install -g @angular-devkit/schematics-cli
|
||||
</code-example>
|
||||
|
||||
This installs the `schematics` executable, which you can use to create a new project, add a new schematic to an existing project, or extend an existing schematic.
|
||||
|
||||
{@a scoped-package}
|
||||
|
||||
## scoped package
|
||||
|
||||
A way to group related [npm packages](guide/npm-packages).
|
||||
A way to group related [npm packages](guide/npm-packages).
|
||||
NgModules are delivered within scoped packages whose names begin with the Angular *scope name* `@angular`. For example, `@angular/core`, `@angular/common`, `@angular/forms`, and `@angular/router`.
|
||||
|
||||
Import a scoped package in the same way that you import a normal package.
|
||||
Import a scoped package in the same way that you import a normal package.
|
||||
|
||||
<code-example path="architecture/src/app/app.component.ts" linenums="false" header="architecture/src/app/app.component.ts (import)" region="import">
|
||||
|
||||
@ -676,11 +705,11 @@ Import a scoped package in the same way that you import a normal package.
|
||||
|
||||
## service
|
||||
|
||||
In Angular, a class with the [@Injectable()](guide/glossary#injectable) decorator that encapsulates non-UI logic and code that can be reused across an application.
|
||||
In Angular, a class with the [@Injectable()](guide/glossary#injectable) decorator that encapsulates non-UI logic and code that can be reused across an application.
|
||||
Angular distinguishes components from services to increase modularity and reusability.
|
||||
|
||||
The `@Injectable()` metadata allows the service class to be used with the [dependency injection](guide/glossary#di) mechanism.
|
||||
The injectable class is instantiated by a [provider](guide/glossary#provider).
|
||||
The `@Injectable()` metadata allows the service class to be used with the [dependency injection](guide/glossary#di) mechanism.
|
||||
The injectable class is instantiated by a [provider](guide/glossary#provider).
|
||||
[Injectors](guide/glossary#injector) maintain lists of providers and use them to provide service instances when they are required by components or other services.
|
||||
|
||||
To learn more, see [Introduction to Services and Dependency Injection](guide/architecture-services).
|
||||
@ -713,13 +742,13 @@ The `subscribe()` method takes a JavaScript object (called an [observer](guide/g
|
||||
|
||||
## template
|
||||
|
||||
Code associated with a component that defines how to render the component's [view](guide/glossary#view).
|
||||
Code associated with a component that defines how to render the component's [view](guide/glossary#view).
|
||||
|
||||
A template combines straight HTML with Angular [data-binding](guide/glossary#data-binding) syntax, [directives](guide/glossary#directive),
|
||||
and [template expressions](guide/glossary#template-expression) (logical constructs).
|
||||
A template combines straight HTML with Angular [data-binding](guide/glossary#data-binding) syntax, [directives](guide/glossary#directive),
|
||||
and [template expressions](guide/glossary#template-expression) (logical constructs).
|
||||
The Angular elements insert or calculate values that modify the HTML elements before the page is displayed.
|
||||
|
||||
A template is associated with a [component](guide/glossary#component) class through the `@Component()` [decorator](guide/glossary#decorator). The HTML can be provided inline, as the value of the `template` property, or in a separate HTML file linked through the `templateUrl` property.
|
||||
|
||||
A template is associated with a [component](guide/glossary#component) class through the `@Component()` [decorator](guide/glossary#decorator). The HTML can be provided inline, as the value of the `template` property, or in a separate HTML file linked through the `templateUrl` property.
|
||||
|
||||
Additional templates, represented by `TemplateRef` objects, can define alternative or *embedded* views, which can be referenced from multiple components.
|
||||
|
||||
@ -759,17 +788,23 @@ An opaque identifier used for efficient table lookup. In Angular, a [DI token](g
|
||||
|
||||
The translation process that transforms one version of JavaScript to another version; for example, down-leveling ES2015 to the older ES5 version.
|
||||
|
||||
{@a file-tree}
|
||||
|
||||
## tree
|
||||
|
||||
In [schematics](#schematic), a virtual file system represented by the `Tree` class.
|
||||
Schematic [rules](#rule) take a tree object as input, operate on them, and return a new tree object.
|
||||
|
||||
{@a typescript}
|
||||
|
||||
## TypeScript
|
||||
|
||||
A programming language based on JavaScript that is notable for its optional typing system.
|
||||
A programming language based on JavaScript that is notable for its optional typing system.
|
||||
TypeScript provides compile-time type checking and strong tooling support (such as
|
||||
code completion, refactoring, inline documentation, and intelligent search).
|
||||
code completion, refactoring, inline documentation, and intelligent search).
|
||||
Many code editors and IDEs support TypeScript either natively or with plug-ins.
|
||||
|
||||
TypeScript is the preferred language for Angular development.
|
||||
TypeScript is the preferred language for Angular development.
|
||||
Read more about TypeScript at [typescriptlang.org](http://www.typescriptlang.org/).
|
||||
|
||||
|
||||
@ -781,16 +816,16 @@ Read more about TypeScript at [typescriptlang.org](http://www.typescriptlang.org
|
||||
|
||||
## view
|
||||
|
||||
The smallest grouping of display elements that can be created and destroyed together.
|
||||
The smallest grouping of display elements that can be created and destroyed together.
|
||||
Angular renders a view under the control of one or more [directives](guide/glossary#directive),
|
||||
especially [component](guide/glossary#component) directives and their companion [templates](guide/glossary#template).
|
||||
especially [component](guide/glossary#component) directives and their companion [templates](guide/glossary#template).
|
||||
|
||||
A view is specifically represented by a `ViewRef` instance associated with the component.
|
||||
A view that belongs to a component is called a *host view*.
|
||||
Views are typically collected into [view hierarchies](guide/glossary#view-tree).
|
||||
A view is specifically represented by a `ViewRef` instance associated with the component.
|
||||
A view that belongs to a component is called a *host view*.
|
||||
Views are typically collected into [view hierarchies](guide/glossary#view-tree).
|
||||
|
||||
Properties of elements in a view can change dynamically, in response to user actions;
|
||||
the structure (number and order) of elements in a view can't.
|
||||
Properties of elements in a view can change dynamically, in response to user actions;
|
||||
the structure (number and order) of elements in a view can't.
|
||||
You can change the structure of elements by inserting, moving, or removing nested views within their view containers.
|
||||
|
||||
View hierarchies can be loaded and unloaded dynamically as the user navigates through the application, typically under the control of a [router](guide/glossary#router).
|
||||
@ -799,7 +834,7 @@ View hierarchies can be loaded and unloaded dynamically as the user navigates th
|
||||
|
||||
## view hierarchy
|
||||
|
||||
A tree of related views that can be acted on as a unit. The root view is a component's *host view*. A host view can be the root of a tree of *embedded views*, collected in a *view container* (`ViewContainerRef`) attached to an anchor element in the hosting component. The view hierarchy is a key part of Angular change detection.
|
||||
A tree of related views that can be acted on as a unit. The root view is a component's *host view*. A host view can be the root of a tree of *embedded views*, collected in a *view container* (`ViewContainerRef`) attached to an anchor element in the hosting component. The view hierarchy is a key part of Angular change detection.
|
||||
|
||||
The view hierarchy doesn't imply a component hierarchy. Views that are embedded in the context of a particular hierarchy can be host views of other components. Those components can be in the same NgModule as the hosting component, or belong to other NgModules.
|
||||
|
||||
@ -815,8 +850,8 @@ See [custom element](guide/glossary#custom-element).
|
||||
## workspace
|
||||
|
||||
In Angular, a folder that contains [projects](guide/glossary#project) (that is, apps and libraries).
|
||||
The [CLI](guide/glossary#cli) `ng new` command creates a workspace to contain projects.
|
||||
Commands that create or operate on apps and libraries (such as `add` and `generate`) must be executed from within a workspace folder.
|
||||
The [CLI](guide/glossary#cli) `ng new` command creates a workspace to contain projects.
|
||||
Commands that create or operate on apps and libraries (such as `add` and `generate`) must be executed from within a workspace folder.
|
||||
|
||||
{@a X}
|
||||
|
||||
@ -833,7 +868,7 @@ An execution context for a set of asynchronous tasks. Useful for debugging, prof
|
||||
|
||||
An Angular app runs in a zone where it can respond to asynchronous events by checking for data changes and updating the information it displays by resolving [data bindings](guide/glossary#data-binding).
|
||||
|
||||
A zone client can take action before and after an async operation completes.
|
||||
A zone client can take action before and after an async operation completes.
|
||||
|
||||
Learn more about zones in this
|
||||
[Brian Ford video](https://www.youtube.com/watch?v=3IqtmUscE_U).
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Hierarchical Dependency Injectors
|
||||
|
||||
The Angular dependency injection system is _hierarchical_.
|
||||
There is a tree of injectors that parallel an app's component tree.
|
||||
There is a tree of injectors that parallels an app's component tree.
|
||||
You can reconfigure the injectors at any level of that component tree.
|
||||
|
||||
This guide explores this system and how to use it to your advantage.
|
||||
@ -42,7 +42,7 @@ Learn more about dependency resolution through the injector hierarchy:
|
||||
|
||||
*NgModule-level* providers can be specified with `@NgModule()` `providers` metadata option, or in the `@Injectable()` `providedIn` option (with some module other than the root `AppModule`).
|
||||
|
||||
Use the `@NgModule()` `provides` option if a module is [lazy loaded](guide/lazy-loading-ngmodules). The module's own injector is configured with the provider when that module is loaded, and Angular can inject the corresponding services in any class it creates in that module. If you use the `@Injectable()` option `providedIn: MyLazyloadModule`, the provider could be shaken out at compile time, if it is not used anywhere else in the app.
|
||||
Use the `@NgModule()` `providers` option if a module is [lazy loaded](guide/lazy-loading-ngmodules). The module's own injector is configured with the provider when that module is loaded, and Angular can inject the corresponding services in any class it creates in that module. If you use the `@Injectable()` option `providedIn: MyLazyloadModule`, the provider could be shaken out at compile time, if it is not used anywhere else in the app.
|
||||
|
||||
* Learn more about [tree-shakable providers](guide/dependency-injection-providers#tree-shakable-providers).
|
||||
|
||||
|
30
aio/content/guide/libraries.md
Normal file
30
aio/content/guide/libraries.md
Normal file
@ -0,0 +1,30 @@
|
||||
# Overview of Angular Libraries
|
||||
|
||||
Many applications need to solve the same general problems, such as presenting a unified user interface, presenting data, and allowing data entry.
|
||||
Developers can create general solutions for particular domains that can be adapted for re-use in different apps.
|
||||
Such a solution can be built as Angular *libraries* and these libraries can be published and shared as *npm packages*.
|
||||
|
||||
An Angular library is an Angular [project](guide/glossary#project) that differs from an app in that it cannot run on its own.
|
||||
A library must be imported and used in an app.
|
||||
|
||||
Libraries extend Angular's base functionality. For example, to add [reactive forms](guide/reactive-forms) to an app, add the library package using `ng add @angular/forms`, then import the `ReactiveFormsModule` from the `@angular/forms` library in your application code.
|
||||
Similarly, adding the [service worker](guide/service-worker-intro) library to an Angular application is one of the steps for turning an application into a [Progressive Web App](https://developers.google.com/web/progressive-web-apps/) (PWA).
|
||||
[Angular Material](https://material.angular.io/) is an example of a large, general-purpose library that provides sophisticated, reusable, and adaptable UI components.
|
||||
|
||||
Any app developer can use these and other libraries that have been published as npm packages by the Angular team or by third parties. See [Using Published Libraries](guide/using-libraries).
|
||||
|
||||
## Creating libraries
|
||||
|
||||
If you have developed functionality that is suitable for reuse, you can create your own libraries.
|
||||
These libraries can be used locally in your workspace, or you can publish them as [npm packages](guide/npm-packages) to share with other projects or other Angular developers.
|
||||
These packages can be published to the npm registry, a private npm Enterprise registry, or a private package management system that supports npm packages.
|
||||
See [Creating Libraries](guide/creating-libraries).
|
||||
|
||||
Whether you decide to package functionality as a library is an architectural decision, similar to deciding whether a piece of functionality is a component or a service, or deciding on the scope of a component.
|
||||
|
||||
Packaging functionality as a library forces the artifacts in the library to be decoupled from the application's business logic.
|
||||
This can help to avoid various bad practices or architecture mistakes that can make it difficult to decouple and reuse code in the future.
|
||||
|
||||
Putting code into a separate library is more complex than simply putting everything in one app.
|
||||
It requires more of an investment in time and thought for managing, maintaining, and updating the library.
|
||||
This complexity can pay off, however, when the library is being used in multiple apps.
|
@ -124,7 +124,7 @@ calls the lifecycle hook methods in the following sequence at specific moments:
|
||||
|
||||
Respond after Angular checks the component's views and child views / the view that a directive is in.
|
||||
|
||||
Called after the `ngAfterViewInit` and every subsequent `ngAfterContentChecked()`.
|
||||
Called after the `ngAfterViewInit()` and every subsequent `ngAfterContentChecked()`.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user