Compare commits
353 Commits
Author | SHA1 | Date | |
---|---|---|---|
9b812dc729 | |||
2eee8d59fe | |||
f0dc8cfc05 | |||
79471f7610 | |||
54f68c342b | |||
86bfb0172b | |||
52186165ee | |||
e9ae885982 | |||
8a1bd2c401 | |||
018b695ef2 | |||
1d193df360 | |||
0a46b2acfb | |||
b63aa4e7ef | |||
6aae19633b | |||
00242e8d6d | |||
4ea231fdbe | |||
6bad2ca586 | |||
dabf1325ed | |||
987b18596b | |||
f470e69fba | |||
980bcaf176 | |||
48f7f65bf4 | |||
7fe95b1882 | |||
266871baf4 | |||
bc54ecf66e | |||
274833ee94 | |||
ff5934597a | |||
09b60ed36a | |||
0bb83b2ba6 | |||
de04741863 | |||
8ea91887ca | |||
ff184b56eb | |||
15d138fdd3 | |||
1699b54860 | |||
07f6b2c018 | |||
4a193580fe | |||
9c222350f9 | |||
c36edffe2a | |||
13b984d72b | |||
f00eff5916 | |||
31ee45efdc | |||
b68f2d6fa5 | |||
d8def6d728 | |||
e8f464409c | |||
a73b8a62c8 | |||
2fe8f2b1e0 | |||
f1c08c6918 | |||
bf9de8ca53 | |||
df37c47ac5 | |||
788d19c036 | |||
8492499fe7 | |||
48174010a1 | |||
1460e46ba1 | |||
a7ff7d8d27 | |||
eb970b4626 | |||
18d301258a | |||
6a01fa532c | |||
e190a7e9de | |||
53c6425954 | |||
c198dc6c19 | |||
d1b26dd3a1 | |||
ce7131f3fb | |||
934702892e | |||
8a830a72e2 | |||
2abb54c4a1 | |||
44632bb700 | |||
e33b382ab4 | |||
c4da400db4 | |||
c40e6b2edc | |||
978fc27314 | |||
b9f2bbb7d1 | |||
9654d646ae | |||
7f214499e8 | |||
a3d55a9d27 | |||
e222b8761e | |||
1435c0b3a9 | |||
0a7aebbcf5 | |||
bd7f91feac | |||
3bbc89b958 | |||
52d98e563d | |||
b279f8bd62 | |||
954e34cc91 | |||
e1f6d15387 | |||
cbb3794931 | |||
77a5790a9d | |||
4ca401c394 | |||
3dcd5ebdbc | |||
49307f0595 | |||
762fc28fee | |||
338e58c278 | |||
7e2ed89208 | |||
56a3dcf44c | |||
501bacdcf6 | |||
c5f2979a87 | |||
fe02462b5f | |||
3000d19ad1 | |||
dcf9f05c9a | |||
ba56f3c15b | |||
865ad56e9a | |||
5cda2a041b | |||
6a484853a9 | |||
e6ac289518 | |||
4e8614bb92 | |||
9ace748d3a | |||
08c38a1f99 | |||
9aeef0afdb | |||
8aef446373 | |||
f7ee91a17c | |||
8ae0afd3f8 | |||
be82270493 | |||
4cef2c1236 | |||
26e3615e19 | |||
65f20107fe | |||
5a7bcd1862 | |||
152ea36c80 | |||
ea2adb104b | |||
19caace2ab | |||
ccc1c27461 | |||
97268b95f7 | |||
7c41abe64a | |||
991e138650 | |||
d00b421402 | |||
06ffed5141 | |||
5a15126520 | |||
9e4b2f1a4f | |||
393529d3b5 | |||
81b75590d7 | |||
151f0f4b2c | |||
f88f941008 | |||
0e17958640 | |||
e82b45c8a7 | |||
8422ef2a93 | |||
cdf586d0d2 | |||
3828c89792 | |||
0f352b6350 | |||
06bdecffb9 | |||
99ddec152b | |||
31aba96fcb | |||
facce2c9fd | |||
edaf058548 | |||
4bff2d0c8c | |||
cfc608aaf3 | |||
6d9f5fcddb | |||
b19a05c25a | |||
bd75b3b7b3 | |||
1c67b9063b | |||
9a9ae60e0e | |||
ae6fa9260a | |||
f8fa2f2a6c | |||
f3ee9a6144 | |||
d076c51455 | |||
38a7e2a775 | |||
c61c14a127 | |||
652b0959a8 | |||
002fbddcf1 | |||
4761d40a41 | |||
608e0f0d67 | |||
45718b3b21 | |||
b5756bcc39 | |||
60f0462049 | |||
9fd22959d3 | |||
d5dd907396 | |||
5a6bf7de0e | |||
d135bb5e6e | |||
8b9a3e49f2 | |||
44e55fe2e4 | |||
063cc308b6 | |||
c567135dd5 | |||
361f181c8c | |||
b40844523b | |||
c8af830ec8 | |||
e2c9ddb33e | |||
04196ec2d0 | |||
7323072c5c | |||
f0c5400cab | |||
3f2f937c9f | |||
256fe2421a | |||
e6f27bcb0c | |||
8abcf04a5e | |||
bf38df4eb9 | |||
79a025306a | |||
62c936aa49 | |||
77e1b34d91 | |||
26cb128b3c | |||
fdbe07982a | |||
c0e3209915 | |||
70880f0cea | |||
221a5ba634 | |||
68b08cf782 | |||
10560a0872 | |||
561e01ddfd | |||
d1345c78f0 | |||
276f9067c8 | |||
0e90a4263b | |||
e4cc1398aa | |||
8d1f993ceb | |||
df1ab49893 | |||
df03fec8a6 | |||
c01cae22e1 | |||
5a46f94987 | |||
5716605d52 | |||
8043e3131c | |||
54f7245081 | |||
5de24b6dfe | |||
4dc4d7f30a | |||
fcea1a3c22 | |||
8bc4da8665 | |||
a5a2d525ae | |||
4690dcecac | |||
722b2fa6ed | |||
124d1abf19 | |||
736d3ef820 | |||
9b0ad347e1 | |||
d2598ace0a | |||
4a25e4cf95 | |||
3f67bf208d | |||
d85476fd8c | |||
9763edf829 | |||
b6ae54c547 | |||
3de26a84ff | |||
8022d3691b | |||
581336a918 | |||
effc58086c | |||
766615c8a1 | |||
ede4246663 | |||
bb8a6abbf2 | |||
32daa930d0 | |||
b6aa99d3a7 | |||
e10b213784 | |||
a67cf99b0c | |||
04d04fd147 | |||
17361d2b2c | |||
9b88920aa9 | |||
b12e76d1d3 | |||
af001a8cbd | |||
db64b014f8 | |||
7e34975bb0 | |||
0fa48e8c00 | |||
fde3f467e2 | |||
7b378a6920 | |||
3136d9ff2e | |||
325e6cf557 | |||
381d7c4e44 | |||
1b6f3c1ead | |||
c38349127c | |||
a4817729a2 | |||
61c343e3eb | |||
24e6c1e80d | |||
42fc5c9b33 | |||
33e7b285ca | |||
74afdc37da | |||
3c1ffba0ad | |||
14c0017db8 | |||
4878f4890b | |||
b7edef0cd3 | |||
39fa937ab9 | |||
2977829c67 | |||
dbe845e048 | |||
e562acc884 | |||
e295c6a0ae | |||
10b43355f8 | |||
d4e7587bd8 | |||
cabe03cf6d | |||
0cefa9e342 | |||
e073daa48e | |||
994d48a96e | |||
806f8118c8 | |||
dd299f9eb2 | |||
49ec3f312c | |||
71eba450e6 | |||
192f108b0f | |||
dd8651db73 | |||
5bbbe3f684 | |||
a71d8a837b | |||
e8ceae14e1 | |||
c3246e6f16 | |||
685753361e | |||
6b07711f96 | |||
12fb639b7d | |||
644925fd0c | |||
bcc72b0924 | |||
e1091b2ba8 | |||
08841e31d9 | |||
d1fcc2bc13 | |||
fac00442d2 | |||
b8cbcbcf49 | |||
1ed45bd783 | |||
82fd1920b1 | |||
f6d7271ec7 | |||
c1f3faf1df | |||
97202278f9 | |||
132f01c5ca | |||
6a987f1b9c | |||
548b003ed3 | |||
48dc41de01 | |||
817c2b49bc | |||
fed07c735c | |||
390cac6874 | |||
8eb0b8bd40 | |||
d7283c6085 | |||
3fe3a84a4b | |||
28e4187bd6 | |||
7cbc69c890 | |||
1dc134bc6b | |||
6a61d37f95 | |||
8d2e92bcfe | |||
5038f5c909 | |||
6eeca70043 | |||
9f68c35fa9 | |||
21418ea109 | |||
02d8b4ed3c | |||
6748392edc | |||
d9fd301157 | |||
71c5d80ce7 | |||
9798229fde | |||
4b2fcfd5dc | |||
b4d291aa7a | |||
b0ecafdc2f | |||
6816bb62d7 | |||
4b05b8cea0 | |||
a0728aedf7 | |||
ea96f6112a | |||
b706800ea8 | |||
c6f95b1d70 | |||
d896126604 | |||
a20da5ddcc | |||
18878600ba | |||
d7e10f3f7e | |||
4d044ea5b2 | |||
e2d1e0cd98 | |||
4e056580bb | |||
e4c2e6a904 | |||
a50989832d | |||
525307b6a3 | |||
a3ab76b216 | |||
f2265d4b46 | |||
d3ac709b99 | |||
908d43a5bb | |||
71cdb0a08e | |||
c7fbbdfa99 | |||
10e4ab7712 | |||
5114c23c21 | |||
c3e585d7eb | |||
0776daec88 | |||
615e1a58b2 | |||
606758357e | |||
ba2a3595c6 | |||
a50bfe5054 | |||
c8983bc367 | |||
8d6d2c6704 | |||
6711f22e62 | |||
8dd9192fe3 | |||
870e0dab48 |
@ -4,4 +4,5 @@ aio/content
|
|||||||
aio/node_modules
|
aio/node_modules
|
||||||
aio/tools/examples/shared/node_modules
|
aio/tools/examples/shared/node_modules
|
||||||
integration/bazel
|
integration/bazel
|
||||||
|
integration/bazel-schematics/demo
|
||||||
packages/bazel/node_modules
|
packages/bazel/node_modules
|
||||||
|
52
.bazelrc
52
.bazelrc
@ -1,9 +1,3 @@
|
|||||||
################################
|
|
||||||
# Settings for Angular team members only
|
|
||||||
################################
|
|
||||||
# To enable this feature check the "Remote caching" section in docs/BAZEL.md.
|
|
||||||
build:angular-team --remote_http_cache=https://storage.googleapis.com/angular-team-cache
|
|
||||||
|
|
||||||
###############################
|
###############################
|
||||||
# Typescript / Angular / Sass #
|
# Typescript / Angular / Sass #
|
||||||
###############################
|
###############################
|
||||||
@ -116,27 +110,55 @@ build --define=compile=legacy
|
|||||||
# --config=remote
|
# --config=remote
|
||||||
###############################
|
###############################
|
||||||
|
|
||||||
# Load default settings for Remote Build Execution
|
# Load default settings for Remote Build Execution.
|
||||||
# When updating, the URLs of bazel_toolchains in packages/bazel/package.bzl
|
import %workspace%/third_party/github.com/bazelbuild/bazel-toolchains/bazelrc/.bazelrc.notoolchain
|
||||||
# may also need to be updated (see https://github.com/angular/angular/pull/27935)
|
|
||||||
import %workspace%/third_party/github.com/bazelbuild/bazel-toolchains/bazelrc/bazel-0.24.0.bazelrc
|
|
||||||
|
|
||||||
# Increase the default number of jobs by 50% because our build has lots of
|
# Increase the default number of jobs by 50% because our build has lots of
|
||||||
# parallelism
|
# parallelism
|
||||||
build:remote --jobs=150
|
build:remote --jobs=150
|
||||||
|
|
||||||
# Point to our custom execution platform; see tools/BUILD.bazel
|
# Toolchain and platform related flags
|
||||||
|
build:remote --host_javabase=@rbe_ubuntu1604_angular//java:jdk
|
||||||
|
build:remote --javabase=@rbe_ubuntu1604_angular//java:jdk
|
||||||
|
build:remote --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_hostjdk8
|
||||||
|
build:remote --java_toolchain=@bazel_tools//tools/jdk:toolchain_hostjdk8
|
||||||
|
build:remote --crosstool_top=@rbe_ubuntu1604_angular//cc:toolchain
|
||||||
|
build:remote --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1
|
||||||
|
build:remote --extra_toolchains=@rbe_ubuntu1604_angular//config:cc-toolchain
|
||||||
build:remote --extra_execution_platforms=//tools:rbe_ubuntu1604-angular
|
build:remote --extra_execution_platforms=//tools:rbe_ubuntu1604-angular
|
||||||
build:remote --host_platform=//tools:rbe_ubuntu1604-angular
|
build:remote --host_platform=//tools:rbe_ubuntu1604-angular
|
||||||
build:remote --platforms=//tools:rbe_ubuntu1604-angular
|
build:remote --platforms=//tools:rbe_ubuntu1604-angular
|
||||||
|
|
||||||
# Remote instance.
|
# Remote instance.
|
||||||
build:remote --remote_instance_name=projects/internal-200822/instances/default_instance
|
build:remote --remote_instance_name=projects/internal-200822/instances/default_instance
|
||||||
|
build:remote --project_id=internal-200822
|
||||||
|
|
||||||
# Do not accept remote cache.
|
# Remote caching
|
||||||
# We need to understand the security risks of using prior build artifacts.
|
build:remote --remote_cache=remotebuildexecution.googleapis.com
|
||||||
|
# By default, do not accept remote cache, to be set to true for CI based on environment
|
||||||
build:remote --remote_accept_cached=false
|
build:remote --remote_accept_cached=false
|
||||||
|
# By default, do not upload local results to cache, to be set to true for CI based on environment
|
||||||
|
build:remote --remote_upload_local_results=false
|
||||||
|
|
||||||
# Load any settings specific to the current user. Needs to be last statement in this
|
# Build Event Service Configuration
|
||||||
# config, as the user configuration should be able to overwrite flags from this file.
|
build:remote --bes_backend=buildeventservice.googleapis.com
|
||||||
|
build:remote --bes_timeout=30s
|
||||||
|
build:remote --bes_results_url="https://source.cloud.google.com/results/invocations/"
|
||||||
|
|
||||||
|
###############################
|
||||||
|
# NodeJS rules settings
|
||||||
|
# These settings are required for rules_nodejs
|
||||||
|
###############################
|
||||||
|
|
||||||
|
# Turn on managed directories feature in Bazel
|
||||||
|
# This allows us to avoid installing a second copy of node_modules
|
||||||
|
common --experimental_allow_incremental_repository_updates
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
# User bazel configuration
|
||||||
|
# NOTE: This needs to be the *last* entry in the config.
|
||||||
|
####################################################
|
||||||
|
|
||||||
|
# Load any settings which are specific to the current user. Needs to be *last* statement
|
||||||
|
# in this config, as the user configuration should be able to overwrite flags from this file.
|
||||||
try-import .bazelrc.user
|
try-import .bazelrc.user
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
# `CI_CHROMEDRIVER_VERSION_ARG` env var (in `.circleci/env.sh`) points to a ChromeDriver
|
# `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.
|
# 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.
|
# **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_1: &default_docker_image circleci/node:10.16
|
||||||
var_2: &browsers_docker_image circleci/node:10.12-browsers
|
var_2: &browsers_docker_image circleci/node:10.16-browsers
|
||||||
# We don't want to include the current branch name in the cache key because that would prevent
|
# We don't want to include the current branch name in the cache key because that would prevent
|
||||||
# PRs from being able to restore the cache since the branch names are always different for PRs.
|
# PRs from being able to restore the cache since the branch names are always different for PRs.
|
||||||
# The cache key should only consist of dynamic values that change whenever something in the
|
# The cache key should only consist of dynamic values that change whenever something in the
|
||||||
@ -26,7 +26,7 @@ var_2: &browsers_docker_image circleci/node:10.12-browsers
|
|||||||
# **NOTE 1 **: If you change the cache key prefix, also sync the restore_cache fallback to match.
|
# **NOTE 1 **: If you change the cache key prefix, also sync the restore_cache fallback to match.
|
||||||
# **NOTE 2 **: Keep the static part of the cache key as prefix to enable correct fallbacks.
|
# **NOTE 2 **: Keep the static part of the cache key as prefix to enable correct fallbacks.
|
||||||
# See https://circleci.com/docs/2.0/caching/#restoring-cache for how prefixes work in CircleCI.
|
# See https://circleci.com/docs/2.0/caching/#restoring-cache for how prefixes work in CircleCI.
|
||||||
var_3: &cache_key v3-angular-node-10.12-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
var_3: &cache_key v3-angular-node-10.16-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
||||||
|
|
||||||
# Initializes the CI environment by setting up common environment variables.
|
# Initializes the CI environment by setting up common environment variables.
|
||||||
var_4: &init_environment
|
var_4: &init_environment
|
||||||
@ -53,9 +53,22 @@ var_5: &setup_bazel_remote_execution
|
|||||||
run:
|
run:
|
||||||
name: "Setup bazel RBE remote execution"
|
name: "Setup bazel RBE remote execution"
|
||||||
command: |
|
command: |
|
||||||
openssl aes-256-cbc -d -in .circleci/gcp_token -k "$CI_REPO_NAME" -out /home/circleci/.gcp_credentials
|
# We need ensure that the same default digest is used for encoding and decoding
|
||||||
|
# with openssl. Openssl versions might have different default digests which can
|
||||||
|
# cause decryption failures based on the openssl version. https://stackoverflow.com/a/39641378/4317734
|
||||||
|
openssl aes-256-cbc -d -in .circleci/gcp_token -md md5 -k "$CI_REPO_NAME" -out /home/circleci/.gcp_credentials
|
||||||
echo "export GOOGLE_APPLICATION_CREDENTIALS=/home/circleci/.gcp_credentials" >> $BASH_ENV
|
echo "export GOOGLE_APPLICATION_CREDENTIALS=/home/circleci/.gcp_credentials" >> $BASH_ENV
|
||||||
sudo bash -c "echo 'build --config=remote' >> /etc/bazel.bazelrc"
|
touch .bazelrc.user
|
||||||
|
sudo bash -c "echo -e 'build --config=remote\n' >> .bazelrc.user"
|
||||||
|
sudo bash -c "echo -e 'build:remote --remote_accept_cached=true\n' >> .bazelrc.user"
|
||||||
|
echo "Reading from remote cache for bazel remote jobs."
|
||||||
|
if [[ "$CI_PULL_REQUEST" == "false" ]]; then
|
||||||
|
sudo bash -c "echo -e 'build:remote --remote_upload_local_results=true\n' >> .bazelrc.user"
|
||||||
|
echo "Uploading local build results to remote cache."
|
||||||
|
else
|
||||||
|
sudo bash -c "echo -e 'build:remote --remote_upload_local_results=false\n' >> .bazelrc.user"
|
||||||
|
echo "Not uploading local build results to remote cache."
|
||||||
|
fi
|
||||||
|
|
||||||
# Settings common to each job
|
# Settings common to each job
|
||||||
var_6: &job_defaults
|
var_6: &job_defaults
|
||||||
@ -99,11 +112,11 @@ var_10: &restore_cache
|
|||||||
keys:
|
keys:
|
||||||
- *cache_key
|
- *cache_key
|
||||||
# This fallback should be the cache_key without variables.
|
# This fallback should be the cache_key without variables.
|
||||||
- v3-angular-node-10.12-
|
- v3-angular-node-10.16-
|
||||||
|
|
||||||
# Branch filter that can be specified for jobs that should only run on publish branches
|
# Branch filter that can be specified for jobs that should only run on publish branches
|
||||||
# (e.g. master or the patch branch)
|
# (e.g. master or the patch branch)
|
||||||
var_12: &publish_branches_filter
|
var_11: &publish_branches_filter
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
@ -114,10 +127,30 @@ var_12: &publish_branches_filter
|
|||||||
# `build-npm-packages`.
|
# `build-npm-packages`.
|
||||||
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
|
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
|
||||||
# https://circleci.com/blog/deep-diving-into-circleci-workspaces/
|
# https://circleci.com/blog/deep-diving-into-circleci-workspaces/
|
||||||
var_13: &attach_workspace
|
var_12: &attach_workspace
|
||||||
attach_workspace:
|
attach_workspace:
|
||||||
at: ~/
|
at: ~/
|
||||||
|
|
||||||
|
var_13: ¬ify_caretaker_on_fail
|
||||||
|
run:
|
||||||
|
when: on_fail
|
||||||
|
name: Notify caretaker about failure
|
||||||
|
# `$SLACK_CARETAKER_WEBHOOK_URL` is a secret env var defined in CircleCI project settings.
|
||||||
|
# The URL comes from https://angular-team.slack.com/apps/A0F7VRE7N-circleci.
|
||||||
|
command: |
|
||||||
|
notificationJson="{\"text\":\":x: \`$CIRCLE_JOB\` job failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}"
|
||||||
|
curl --request POST --header "Content-Type: application/json" --data "$notificationJson" $SLACK_CARETAKER_WEBHOOK_URL
|
||||||
|
|
||||||
|
var_14: ¬ify_dev_infra_on_fail
|
||||||
|
run:
|
||||||
|
when: on_fail
|
||||||
|
name: Notify dev-infra about failure
|
||||||
|
# `$SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL` is a secret env var defined in CircleCI project settings.
|
||||||
|
# The URL comes from https://angular-team.slack.com/apps/A0F7VRE7N-circleci.
|
||||||
|
command: |
|
||||||
|
notificationJson="{\"text\":\":x: \`$CIRCLE_JOB\` job failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}"
|
||||||
|
curl --request POST --header "Content-Type: application/json" --data "$notificationJson" $SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
||||||
|
|
||||||
version: 2
|
version: 2
|
||||||
jobs:
|
jobs:
|
||||||
setup:
|
setup:
|
||||||
@ -167,7 +200,6 @@ jobs:
|
|||||||
- *attach_workspace
|
- *attach_workspace
|
||||||
- *init_environment
|
- *init_environment
|
||||||
- *setup_circleci_bazel_config
|
- *setup_circleci_bazel_config
|
||||||
|
|
||||||
# Setup remote execution and run RBE-compatible tests.
|
# Setup remote execution and run RBE-compatible tests.
|
||||||
- *setup_bazel_remote_execution
|
- *setup_bazel_remote_execution
|
||||||
- run: yarn bazel test //... --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only
|
- run: yarn bazel test //... --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only
|
||||||
@ -234,6 +266,7 @@ jobs:
|
|||||||
# //packages/forms/test:web_test_sauce TIMEOUT in 315.0s
|
# //packages/forms/test:web_test_sauce TIMEOUT in 315.0s
|
||||||
- run: yarn bazel test --config=saucelabs //:test_web_all
|
- run: yarn bazel test --config=saucelabs //:test_web_all
|
||||||
- run: ./scripts/saucelabs/stop-tunnel.sh
|
- run: ./scripts/saucelabs/stop-tunnel.sh
|
||||||
|
- *notify_dev_infra_on_fail
|
||||||
|
|
||||||
test_aio:
|
test_aio:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
@ -247,16 +280,14 @@ jobs:
|
|||||||
- run: yarn --cwd aio build --progress=false
|
- run: yarn --cwd aio build --progress=false
|
||||||
# Lint the code
|
# Lint the code
|
||||||
- run: yarn --cwd aio lint
|
- run: yarn --cwd aio lint
|
||||||
# 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
|
|
||||||
# Check the bundle sizes.
|
|
||||||
# (Run before unit and e2e tests, which destroy the `dist/` directory.)
|
|
||||||
- run: yarn --cwd aio payload-size
|
|
||||||
# Run unit tests
|
# Run unit tests
|
||||||
- run: yarn --cwd aio test --progress=false --watch=false
|
- run: yarn --cwd aio test --progress=false --watch=false
|
||||||
# Run e2e tests
|
# Run e2e tests
|
||||||
- run: yarn --cwd aio e2e --configuration=ci
|
- run: yarn --cwd aio e2e --configuration=ci
|
||||||
|
# Run PWA-score tests
|
||||||
|
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||||
|
# Check the bundle sizes.
|
||||||
|
- run: yarn --cwd aio payload-size
|
||||||
# Run unit tests for Firebase redirects
|
# Run unit tests for Firebase redirects
|
||||||
- run: yarn --cwd aio redirects-test
|
- run: yarn --cwd aio redirects-test
|
||||||
|
|
||||||
@ -269,7 +300,7 @@ jobs:
|
|||||||
- *attach_workspace
|
- *attach_workspace
|
||||||
- *init_environment
|
- *init_environment
|
||||||
# Deploy angular.io to production (if necessary)
|
# Deploy angular.io to production (if necessary)
|
||||||
- run: setPublicVar CI_STABLE_BRANCH "$(npm info @angular/core dist-tags.latest | sed -r 's/^\s*([0-9]+\.[0-9]+)\.[0-9]+.*$/\1.x/')"
|
- run: setPublicVar_CI_STABLE_BRANCH
|
||||||
- run: yarn --cwd aio deploy-production
|
- run: yarn --cwd aio deploy-production
|
||||||
|
|
||||||
test_aio_local:
|
test_aio_local:
|
||||||
@ -282,21 +313,33 @@ jobs:
|
|||||||
- *init_environment
|
- *init_environment
|
||||||
# Build aio (with local Angular packages)
|
# Build aio (with local Angular packages)
|
||||||
- run: yarn --cwd aio build-local --progress=false
|
- 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 unit tests
|
||||||
- run: yarn --cwd aio test --progress=false --watch=false
|
- run: yarn --cwd aio test --progress=false --watch=false
|
||||||
# Run e2e tests
|
# Run e2e tests
|
||||||
- run: yarn --cwd aio e2e --configuration=ci
|
- run: yarn --cwd aio e2e --configuration=ci
|
||||||
|
# Run PWA-score tests
|
||||||
|
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||||
|
# Check the bundle sizes.
|
||||||
|
- run: yarn --cwd aio payload-size aio-local
|
||||||
|
|
||||||
test_aio_local_ivy:
|
test_aio_local_ivy:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
|
docker:
|
||||||
|
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
||||||
|
- image: *browsers_docker_image
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- *attach_workspace
|
||||||
- *init_environment
|
- *init_environment
|
||||||
# Build aio with Ivy (using local Angular packages)
|
# Build aio with Ivy (using local Angular packages)
|
||||||
- run: yarn --cwd aio build-with-ivy --progress=false
|
- run: yarn --cwd aio build-with-ivy --progress=false
|
||||||
|
# Run unit tests
|
||||||
|
- run: yarn --cwd aio test --progress=false --watch=false
|
||||||
|
# Run e2e tests
|
||||||
|
- run: yarn --cwd aio e2e --configuration=ci
|
||||||
|
# Run PWA-score tests
|
||||||
|
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||||
|
# Check the bundle sizes.
|
||||||
|
- run: yarn --cwd aio payload-size aio-local-ivy
|
||||||
|
|
||||||
test_aio_tools:
|
test_aio_tools:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
@ -351,7 +394,7 @@ jobs:
|
|||||||
# Run examples tests with ivy. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
# 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
|
# 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.
|
# 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 --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL}
|
- 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`.
|
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
||||||
aio_preview:
|
aio_preview:
|
||||||
@ -483,29 +526,47 @@ jobs:
|
|||||||
- run: git config --global --unset "url.ssh://git@github.com.insteadof"
|
- run: git config --global --unset "url.ssh://git@github.com.insteadof"
|
||||||
- run:
|
- run:
|
||||||
name: Decrypt github credentials
|
name: Decrypt github credentials
|
||||||
command: 'openssl aes-256-cbc -d -in .circleci/github_token -k "${KEY}" -out ~/.git_credentials'
|
# We need ensure that the same default digest is used for encoding and decoding with
|
||||||
|
# openssl. Openssl versions might have different default digests which can cause
|
||||||
|
# decryption failures based on the installed openssl version. https://stackoverflow.com/a/39641378/4317734
|
||||||
|
command: 'openssl aes-256-cbc -d -in .circleci/github_token -md md5 -k "${KEY}" -out ~/.git_credentials'
|
||||||
- run: ./scripts/ci/publish-build-artifacts.sh
|
- run: ./scripts/ci/publish-build-artifacts.sh
|
||||||
|
|
||||||
aio_monitoring:
|
aio_monitoring_stable:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
docker:
|
docker:
|
||||||
# This job needs Chrome to be globally installed because the tests run with Protractor
|
# This job needs Chrome to be globally installed because the tests run with Protractor
|
||||||
# which does not load the browser through the Bazel webtesting rules.
|
# which does not load the browser through the Bazel webtesting rules.
|
||||||
- image: *browsers_docker_image
|
- image: *browsers_docker_image
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- *attach_workspace
|
||||||
- *post_checkout
|
- *init_environment
|
||||||
- *restore_cache
|
- run: setPublicVar_CI_STABLE_BRANCH
|
||||||
|
- run:
|
||||||
|
name: Check out `aio/` from the stable branch
|
||||||
|
command: |
|
||||||
|
git fetch origin $CI_STABLE_BRANCH
|
||||||
|
git checkout --force origin/$CI_STABLE_BRANCH -- aio/
|
||||||
|
- run:
|
||||||
|
name: Run tests against https://angular.io/
|
||||||
|
command: ./aio/scripts/test-production.sh https://angular.io/ $CI_AIO_MIN_PWA_SCORE
|
||||||
|
- *notify_caretaker_on_fail
|
||||||
|
- *notify_dev_infra_on_fail
|
||||||
|
|
||||||
|
aio_monitoring_next:
|
||||||
|
<<: *job_defaults
|
||||||
|
docker:
|
||||||
|
# This job needs Chrome to be globally installed because the tests run with Protractor
|
||||||
|
# which does not load the browser through the Bazel webtesting rules.
|
||||||
|
- image: *browsers_docker_image
|
||||||
|
steps:
|
||||||
|
- *attach_workspace
|
||||||
- *init_environment
|
- *init_environment
|
||||||
- run:
|
- run:
|
||||||
name: Run tests against the deployed apps
|
name: Run tests against https://next.angular.io/
|
||||||
command: ./aio/scripts/test-production.sh $CI_AIO_MIN_PWA_SCORE
|
command: ./aio/scripts/test-production.sh https://next.angular.io/ $CI_AIO_MIN_PWA_SCORE
|
||||||
- run:
|
- *notify_caretaker_on_fail
|
||||||
name: Notify caretaker about failure
|
- *notify_dev_infra_on_fail
|
||||||
# `$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-saucelabs:
|
legacy-unit-tests-saucelabs:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
@ -689,19 +750,23 @@ workflows:
|
|||||||
cron: "0 * * * *"
|
cron: "0 * * * *"
|
||||||
filters: *publish_branches_filter
|
filters: *publish_branches_filter
|
||||||
|
|
||||||
# This job is currently disabled due to a version skew problem.
|
aio_monitoring:
|
||||||
# More info is available here: https://github.com/angular/angular/issues/30101
|
jobs:
|
||||||
# aio_monitoring:
|
- setup
|
||||||
# jobs:
|
- aio_monitoring_stable:
|
||||||
# - aio_monitoring
|
requires:
|
||||||
# triggers:
|
- setup
|
||||||
# - schedule:
|
- aio_monitoring_next:
|
||||||
# # Runs AIO monitoring job at 00:00AM every day.
|
requires:
|
||||||
# cron: "0 0 * * *"
|
- setup
|
||||||
# filters:
|
triggers:
|
||||||
# branches:
|
- schedule:
|
||||||
# only:
|
# Runs AIO monitoring jobs at 10:00AM every day.
|
||||||
# - master
|
cron: "0 10 * * *"
|
||||||
|
filters:
|
||||||
|
branches:
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
|
||||||
# TODO:
|
# TODO:
|
||||||
# - don't build the g3 branch
|
# - don't build the g3 branch
|
||||||
|
@ -36,3 +36,38 @@ function setSecretVar() {
|
|||||||
# Restore original shell options.
|
# Restore original shell options.
|
||||||
eval "$originalShellOptions";
|
eval "$originalShellOptions";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Create a function to set an environment variable, when called.
|
||||||
|
#
|
||||||
|
# Use this function for creating setter for public environment variables that require expensive or
|
||||||
|
# time-consuming computaions and may not be needed. When needed, you can call this function to set
|
||||||
|
# the environment variable (which will be available through `$BASH_ENV` from that point onwards).
|
||||||
|
#
|
||||||
|
# Arguments:
|
||||||
|
# - `<name>`: The name of the environment variable. The generated setter function will be
|
||||||
|
# `setPublicVar_<name>`.
|
||||||
|
# - `<code>`: The code to run to compute the value for the variable. Since this code should be
|
||||||
|
# executed lazily, it must be properly escaped. For example:
|
||||||
|
# ```sh
|
||||||
|
# # DO NOT do this:
|
||||||
|
# createPublicVarSetter MY_VAR "$(whoami)"; # `whoami` will be evaluated eagerly
|
||||||
|
#
|
||||||
|
# # DO this isntead:
|
||||||
|
# createPublicVarSetter MY_VAR "\$(whoami)"; # `whoami` will NOT be evaluated eagerly
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# Usage: `createPublicVarSetter <name> <code>`
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# ```sh
|
||||||
|
# createPublicVarSetter MY_VAR 'echo "FOO"';
|
||||||
|
# echo $MY_VAR; # Not defined
|
||||||
|
#
|
||||||
|
# setPublicVar_MY_VAR;
|
||||||
|
# source $BASH_ENV;
|
||||||
|
# echo $MY_VAR; # FOO
|
||||||
|
# ```
|
||||||
|
function createPublicVarSetter() {
|
||||||
|
echo "setPublicVar_$1() { setPublicVar $1 \"$2\"; }" >> $BASH_ENV;
|
||||||
|
}
|
||||||
|
@ -23,7 +23,7 @@ setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
|
|||||||
# `.circleci/config.yml`. See http://chromedriver.chromium.org/downloads for a list of versions.
|
# `.circleci/config.yml`. See http://chromedriver.chromium.org/downloads for a list of versions.
|
||||||
# This variable is intended to be passed as an arg to the `webdriver-manager update` command (e.g.
|
# This variable is intended to be passed as an arg to the `webdriver-manager update` command (e.g.
|
||||||
# `"postinstall": "webdriver-manager update $CI_CHROMEDRIVER_VERSION_ARG"`).
|
# `"postinstall": "webdriver-manager update $CI_CHROMEDRIVER_VERSION_ARG"`).
|
||||||
setPublicVar CI_CHROMEDRIVER_VERSION_ARG "--versions.chrome 2.45";
|
setPublicVar CI_CHROMEDRIVER_VERSION_ARG "--versions.chrome 75.0.3770.90";
|
||||||
setPublicVar CI_COMMIT "$CIRCLE_SHA1";
|
setPublicVar CI_COMMIT "$CIRCLE_SHA1";
|
||||||
# `CI_COMMIT_RANGE` will only be available when `CIRCLE_COMPARE_URL` is also available (or can be
|
# `CI_COMMIT_RANGE` 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
|
# retrieved via `get-compare-url.js`), i.e. on push builds (a.k.a. non-PR, non-scheduled builds and
|
||||||
@ -34,6 +34,13 @@ setPublicVar CI_REPO_NAME "$CIRCLE_PROJECT_REPONAME";
|
|||||||
setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
|
setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
|
||||||
|
|
||||||
|
|
||||||
|
####################################################################################################
|
||||||
|
# Define "lazy" PUBLIC environment variables for CircleCI.
|
||||||
|
# (I.e. functions to set an environment variable when called.)
|
||||||
|
####################################################################################################
|
||||||
|
createPublicVarSetter CI_STABLE_BRANCH "\$(npm info @angular/core dist-tags.latest | sed -r 's/^\\s*([0-9]+\\.[0-9]+)\\.[0-9]+.*$/\\1.x/')";
|
||||||
|
|
||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
# Define SECRET environment variables for CircleCI.
|
# Define SECRET environment variables for CircleCI.
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
* node get-commit-range <build-number> [<compare-url> [<circle-token>]]
|
* 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
|
* Returns the commit range, either extracting it from `compare-url` (if defined), which is of the
|
||||||
* not a PR build (i.e. `CIRCLE_PR_NUMBER` is not defined), retrieves the equivalent of
|
* format of the `CIRCLE_COMPARE_URL` environment variable, or by retrieving the equivalent of
|
||||||
* `CIRCLE_COMPARE_URL` for jobs that are part of a rerun workflow.
|
* `CIRCLE_COMPARE_URL` for jobs that are part of a rerun workflow and extracting it from there.
|
||||||
*
|
*
|
||||||
* **Context:**
|
* **Context:**
|
||||||
* CircleCI sets the `CIRCLE_COMPARE_URL` environment variable (from which we can extract the commit
|
* CircleCI sets the `CIRCLE_COMPARE_URL` environment variable (from which we can extract the commit
|
||||||
|
@ -20,5 +20,7 @@ steps:
|
|||||||
# Add Bazel CI config
|
# Add Bazel CI config
|
||||||
- copy .codefresh\bazel.rc %ProgramData%\bazel.bazelrc
|
- copy .codefresh\bazel.rc %ProgramData%\bazel.bazelrc
|
||||||
# Run tests
|
# Run tests
|
||||||
- yarn bazel test //tools/ts-api-guardian:all
|
- yarn bazel test //tools/ts-api-guardian:all //packages/language-service/test //packages/compiler/test //packages/compiler-cli/test:ngc //packages/compiler-cli/test/ngtsc:ngtsc
|
||||||
- yarn test-ivy-aot //packages/animations/test //packages/common/test //packages/forms/test //packages/http/test //packages/platform-browser/test //packages/platform-browser-dynamic/test //packages/router/test
|
- yarn test-ivy-aot //packages/animations/test //packages/common/test //packages/forms/test //packages/http/test //packages/platform-browser/test //packages/platform-browser-dynamic/test //packages/router/test
|
||||||
|
- yarn bazel test //tools/public_api_guard/...
|
||||||
|
- yarn bazel test //packages/compiler-cli/integrationtest:integrationtest //packages/compiler-cli/test/compliance:compliance
|
||||||
|
22
.devcontainer/recommended-Dockerfile
Normal file
22
.devcontainer/recommended-Dockerfile
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Image metadata and config.
|
||||||
|
FROM circleci/node:10-browsers
|
||||||
|
|
||||||
|
LABEL name="Angular dev environment" \
|
||||||
|
description="This image can be used to create a dev environment for building Angular." \
|
||||||
|
vendor="angular" \
|
||||||
|
version="1.0"
|
||||||
|
|
||||||
|
EXPOSE 4000 4200 4433 5000 8080 9876
|
||||||
|
|
||||||
|
|
||||||
|
# Switch to `root` (CircleCI images use `circleci` as the user).
|
||||||
|
USER root
|
||||||
|
|
||||||
|
|
||||||
|
# Configure `Node.js`/`npm` and install utilities.
|
||||||
|
RUN npm config --global set user root
|
||||||
|
RUN npm install --global yarn@1.13.0 # This needs to be in sync with what we use on CI.
|
||||||
|
|
||||||
|
|
||||||
|
# Go! (And keep going.)
|
||||||
|
CMD ["tail", "--follow", "/dev/null"]
|
16
.devcontainer/recommended-devcontainer.json
Normal file
16
.devcontainer/recommended-devcontainer.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Reference: https://code.visualstudio.com/docs/remote/containers#_devcontainerjson-reference
|
||||||
|
{
|
||||||
|
"name": "Angular dev container",
|
||||||
|
"dockerFile": "Dockerfile",
|
||||||
|
"appPort": [4000, 4200, 4433, 5000, 8080, 9876],
|
||||||
|
"postCreateCommand": "yarn install",
|
||||||
|
"extensions": [
|
||||||
|
"devondcarew.bazel-code",
|
||||||
|
"gkalpak.aio-docs-utils",
|
||||||
|
"ms-vscode.vscode-typescript-tslint-plugin",
|
||||||
|
"xaver.clang-format",
|
||||||
|
// The following extensions are useful when working on angular.io (i.e. inside the `aio/` directory).
|
||||||
|
//"angular.ng-template",
|
||||||
|
//"dbaeumer.vscode-eslint",
|
||||||
|
],
|
||||||
|
}
|
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -5,5 +5,8 @@
|
|||||||
*.js eol=lf
|
*.js eol=lf
|
||||||
*.ts eol=lf
|
*.ts eol=lf
|
||||||
|
|
||||||
|
# API guardian patch must always use LF for tests to work
|
||||||
|
*.patch eol=lf
|
||||||
|
|
||||||
# Must keep Windows line ending to be parsed correctly
|
# Must keep Windows line ending to be parsed correctly
|
||||||
scripts/windows/packages.txt eol=crlf
|
scripts/windows/packages.txt eol=crlf
|
||||||
|
35
.github/CODEOWNERS
vendored
35
.github/CODEOWNERS
vendored
@ -53,6 +53,8 @@
|
|||||||
# IgorMinar - Igor Minar
|
# IgorMinar - Igor Minar
|
||||||
# jasonaden - Jason Aden
|
# jasonaden - Jason Aden
|
||||||
# jenniferfell - Jennifer Fell
|
# jenniferfell - Jennifer Fell
|
||||||
|
# JiaLiPassion - Jia Li
|
||||||
|
# josephperrott - Joey Perrott
|
||||||
# kara - Kara Erickson
|
# kara - Kara Erickson
|
||||||
# kyliau - Keen Yee Liau
|
# kyliau - Keen Yee Liau
|
||||||
# matsko - Matias Niemelä
|
# matsko - Matias Niemelä
|
||||||
@ -179,6 +181,7 @@
|
|||||||
# ===========================================================
|
# ===========================================================
|
||||||
#
|
#
|
||||||
# - kara
|
# - kara
|
||||||
|
# - jasonaden
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -218,6 +221,7 @@
|
|||||||
#
|
#
|
||||||
# - gkalpak
|
# - gkalpak
|
||||||
# - petebacondarwin
|
# - petebacondarwin
|
||||||
|
# - jasonaden
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -245,6 +249,15 @@
|
|||||||
# - mhevery
|
# - mhevery
|
||||||
|
|
||||||
|
|
||||||
|
# ===========================================================
|
||||||
|
# @angular/fw-zones
|
||||||
|
# ===========================================================
|
||||||
|
#
|
||||||
|
# - JiaLiPassion
|
||||||
|
# - mhevery
|
||||||
|
# - vikerman
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
# @angular/tools-benchpress
|
# @angular/tools-benchpress
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -344,7 +357,7 @@
|
|||||||
# - filipesilva
|
# - filipesilva
|
||||||
# - gkalpak
|
# - gkalpak
|
||||||
# - IgorMinar
|
# - IgorMinar
|
||||||
|
# - josephperrott
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -532,6 +545,15 @@
|
|||||||
/aio/content/examples/interpolation/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/interpolation/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/template-syntax/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/template-syntax/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/template-syntax/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/template-syntax/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/binding-syntax/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/property-binding/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/attribute-binding/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/two-way-binding/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/built-in-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/template-reference-variables/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/inputs-outputs/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/template-expression-operators/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
/aio/content/guide/pipes.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/pipes.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/pipes/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/pipes/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -657,8 +679,10 @@
|
|||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/packages/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/packages/common/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/packages/examples/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/examples/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/upgrade.md @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/upgrade.md @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/upgrade-lazy-load-ajs/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/upgrade-module/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/upgrade-module/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/upgrade-phonecat-1-typescript/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/upgrade-phonecat-1-typescript/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -717,6 +741,13 @@ testing/** @angular/fw-test
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ================================================
|
||||||
|
# zone.js
|
||||||
|
# ================================================
|
||||||
|
|
||||||
|
/packages/zone.js/** @angular/fw-zones @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
# benchpress
|
# benchpress
|
||||||
# ================================================
|
# ================================================
|
||||||
@ -809,6 +840,7 @@ testing/** @angular/fw-test
|
|||||||
/aio/content/guide/releases.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/releases.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/updating.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/updating.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/workspace-config.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/workspace-config.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/guide/deprecations.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -853,6 +885,7 @@ testing/** @angular/fw-test
|
|||||||
/.buildkite/** @angular/fw-dev-infra
|
/.buildkite/** @angular/fw-dev-infra
|
||||||
/.circleci/** @angular/fw-dev-infra
|
/.circleci/** @angular/fw-dev-infra
|
||||||
/.codefresh/** @angular/fw-dev-infra
|
/.codefresh/** @angular/fw-dev-infra
|
||||||
|
/.devcontainer/** @angular/fw-dev-infra
|
||||||
/.github/** @angular/fw-dev-infra
|
/.github/** @angular/fw-dev-infra
|
||||||
/.vscode/** @angular/fw-dev-infra
|
/.vscode/** @angular/fw-dev-infra
|
||||||
/docs/BAZEL.md @angular/fw-dev-infra
|
/docs/BAZEL.md @angular/fw-dev-infra
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -11,6 +11,9 @@ tools/gulp-tasks/cldr/cldr-data/
|
|||||||
pubspec.lock
|
pubspec.lock
|
||||||
.c9
|
.c9
|
||||||
.idea/
|
.idea/
|
||||||
|
.devcontainer/*
|
||||||
|
!.devcontainer/recommended-devcontainer.json
|
||||||
|
!.devcontainer/recommended-Dockerfile
|
||||||
.settings/
|
.settings/
|
||||||
.vscode/launch.json
|
.vscode/launch.json
|
||||||
.vscode/settings.json
|
.vscode/settings.json
|
||||||
|
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
@ -8,5 +8,8 @@
|
|||||||
"gkalpak.aio-docs-utils",
|
"gkalpak.aio-docs-utils",
|
||||||
"ms-vscode.vscode-typescript-tslint-plugin",
|
"ms-vscode.vscode-typescript-tslint-plugin",
|
||||||
"xaver.clang-format",
|
"xaver.clang-format",
|
||||||
|
// The following extensions are useful when working on angular.io (i.e. inside the `aio/` directory).
|
||||||
|
//"angular.ng-template",
|
||||||
|
//"dbaeumer.vscode-eslint",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
346
CHANGELOG.md
346
CHANGELOG.md
@ -1,3 +1,346 @@
|
|||||||
|
<a name="8.0.3"></a>
|
||||||
|
## [8.0.3](https://github.com/angular/angular/compare/8.0.2...8.0.3) (2019-06-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** exclude all angular schematics folders from metadata build ([#31237](https://github.com/angular/angular/issues/31237)) ([6bad2ca](https://github.com/angular/angular/commit/6bad2ca)), closes [#31235](https://github.com/angular/angular/issues/31235)
|
||||||
|
* **bazel:** remove unsupported Css pre-processors from ng new ([#31234](https://github.com/angular/angular/issues/31234)) ([980bcaf](https://github.com/angular/angular/commit/980bcaf)), closes [#31209](https://github.com/angular/angular/issues/31209)
|
||||||
|
* **bazel:** update ng new schema to match the current ng new schema of [@schematics](https://github.com/schematics)/angular ([#31234](https://github.com/angular/angular/issues/31234)) ([48f7f65](https://github.com/angular/angular/commit/48f7f65)), closes [#31233](https://github.com/angular/angular/issues/31233)
|
||||||
|
* **service-worker:** registration failed on Safari ([#31140](https://github.com/angular/angular/issues/31140)) ([f470e69](https://github.com/angular/angular/commit/f470e69)), closes [#31061](https://github.com/angular/angular/issues/31061)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.0.2"></a>
|
||||||
|
## [8.0.2](https://github.com/angular/angular/compare/8.0.1...8.0.2) (2019-06-19)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** builder workspace should use nodejs v10.16.0 ([#31088](https://github.com/angular/angular/issues/31088)) ([c198dc6](https://github.com/angular/angular/commit/c198dc6))
|
||||||
|
* **core:** temporarily remove [@deprecated](https://github.com/deprecated) jsdoc tag for a TextBedStatic.get overload ([#30714](https://github.com/angular/angular/issues/30714)) ([0a7aebb](https://github.com/angular/angular/commit/0a7aebb)), closes [#30514](https://github.com/angular/angular/issues/30514)
|
||||||
|
* **language-service:** Remove 'any' in getQuickInfoAtPosition ([#31014](https://github.com/angular/angular/issues/31014)) ([7f21449](https://github.com/angular/angular/commit/7f21449))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.0.1"></a>
|
||||||
|
## [8.0.1](https://github.com/angular/angular/compare/8.0.0...8.0.1) (2019-06-13)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** do not modify tsconfig.json ([#30984](https://github.com/angular/angular/issues/30984)) ([49307f0](https://github.com/angular/angular/commit/49307f0))
|
||||||
|
* **bazel:** Load global stylesheet in dev and prod ([#30879](https://github.com/angular/angular/issues/30879)) ([5a7bcd1](https://github.com/angular/angular/commit/5a7bcd1))
|
||||||
|
* **common:** expose the `HttpUploadProgressEvent` interface as public API ([#30852](https://github.com/angular/angular/issues/30852)) ([4e8614b](https://github.com/angular/angular/commit/4e8614b)), closes [#30814](https://github.com/angular/angular/issues/30814)
|
||||||
|
* **core:** TypeScript related migrations should cater for BOM ([#30719](https://github.com/angular/angular/issues/30719)) ([26e3615](https://github.com/angular/angular/commit/26e3615)), closes [/github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/src/tree/recorder.ts#L72](https://github.com//github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/src/tree/recorder.ts/issues/L72) [#30713](https://github.com/angular/angular/issues/30713)
|
||||||
|
* **service-worker:** avoid uncaught rejection warning when registration fails ([#30876](https://github.com/angular/angular/issues/30876)) ([08c38a1](https://github.com/angular/angular/commit/08c38a1))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.0.0"></a>
|
||||||
|
# [8.0.0](https://github.com/angular/angular/compare/8.0.0-rc.5...8.0.0) (2019-05-28)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add support for TypeScript 3.3 (and drop older versions) ([#29004](https://github.com/angular/angular/issues/29004)) ([75748d6](https://github.com/angular/angular/commit/75748d6))
|
||||||
|
* **common:** add ability to watch for AngularJS URL updates through `onUrlChange` hook ([#30466](https://github.com/angular/angular/issues/30466)) ([8022d36](https://github.com/angular/angular/commit/8022d36))
|
||||||
|
* **common:** stricter types for SlicePipe ([#30156](https://github.com/angular/angular/issues/30156)) ([722b2fa](https://github.com/angular/angular/commit/722b2fa))
|
||||||
|
* **bazel:** use rbe_autoconfig() and new container. ([#29336](https://github.com/angular/angular/issues/29336)) ([e562acc](https://github.com/angular/angular/commit/e562acc))
|
||||||
|
* **common:** add [@angular](https://github.com/angular)/common/upgrade package for $location-related APIs ([#30055](https://github.com/angular/angular/issues/30055)) ([152d99e](https://github.com/angular/angular/commit/152d99e))
|
||||||
|
* **common:** add ability to retrieve the state from Location service ([#30055](https://github.com/angular/angular/issues/30055)) ([b44b143](https://github.com/angular/angular/commit/b44b143))
|
||||||
|
* **common:** add ability to track all location changes ([#30055](https://github.com/angular/angular/issues/30055)) ([3a9cf3f](https://github.com/angular/angular/commit/3a9cf3f))
|
||||||
|
* **common:** add APIs to read component pieces of URL ([#30055](https://github.com/angular/angular/issues/30055)) ([b635fe8](https://github.com/angular/angular/commit/b635fe8))
|
||||||
|
* **common:** add MockPlatformLocation to enable more robust testing of Location services ([#30055](https://github.com/angular/angular/issues/30055)) ([d0672c2](https://github.com/angular/angular/commit/d0672c2))
|
||||||
|
* **common:** add UrlCodec type for use with upgrade applications ([#30055](https://github.com/angular/angular/issues/30055)) ([ec455e1](https://github.com/angular/angular/commit/ec455e1))
|
||||||
|
* **common:** provide replacement for AngularJS $location service ([#30055](https://github.com/angular/angular/issues/30055)) ([4277600](https://github.com/angular/angular/commit/4277600))
|
||||||
|
* remove deprecated DOCUMENT token from platform-browser ([#28117](https://github.com/angular/angular/issues/28117)) ([3a9d247](https://github.com/angular/angular/commit/3a9d247))
|
||||||
|
* **compiler:** support skipping leading trivia in template source-maps ([#30095](https://github.com/angular/angular/issues/30095)) ([304a12f](https://github.com/angular/angular/commit/304a12f))
|
||||||
|
* **core:** add missing ARIA attributes to html sanitizer ([#29685](https://github.com/angular/angular/issues/29685)) ([909557d](https://github.com/angular/angular/commit/909557d)), closes [#26815](https://github.com/angular/angular/issues/26815)
|
||||||
|
* **router:** deprecate loadChildren:string ([#30073](https://github.com/angular/angular/issues/30073)) ([c61df39](https://github.com/angular/angular/commit/c61df39))
|
||||||
|
* **service-worker:** allow configuring when the SW is registered ([#21842](https://github.com/angular/angular/issues/21842)) ([4cfba58](https://github.com/angular/angular/commit/4cfba58)), closes [#20970](https://github.com/angular/angular/issues/20970)
|
||||||
|
* **service-worker:** expose `SwRegistrationOptions` token to allow runtime config ([#21842](https://github.com/angular/angular/issues/21842)) ([39c0152](https://github.com/angular/angular/commit/39c0152))
|
||||||
|
* **service-worker:** support bypassing SW with specific header/query param ([#30010](https://github.com/angular/angular/issues/30010)) ([6200732](https://github.com/angular/angular/commit/6200732)), closes [#21191](https://github.com/angular/angular/issues/21191)
|
||||||
|
* **compiler-cli:** export tooling definitions ([#29929](https://github.com/angular/angular/issues/29929)) ([e1f51ea](https://github.com/angular/angular/commit/e1f51ea))
|
||||||
|
* **compiler-cli:** lower some exported expressions ([#30038](https://github.com/angular/angular/issues/30038)) ([8e73f9b](https://github.com/angular/angular/commit/8e73f9b))
|
||||||
|
* **core:** add schematics to move deprecated DOCUMENT import ([#29950](https://github.com/angular/angular/issues/29950)) ([645e305](https://github.com/angular/angular/commit/645e305))
|
||||||
|
* **bazel:** update the build to use the new architect api ([#29720](https://github.com/angular/angular/issues/29720)) ([902a53a](https://github.com/angular/angular/commit/902a53a))
|
||||||
|
* remove [@angular](https://github.com/angular)/http dependency from [@angular](https://github.com/angular)/platform-server ([#29408](https://github.com/angular/angular/issues/29408)) ([9745f55](https://github.com/angular/angular/commit/9745f55))
|
||||||
|
* **compiler-cli:** ngcc - make logging more configurable ([#29591](https://github.com/angular/angular/issues/29591)) ([8d3d75e](https://github.com/angular/angular/commit/8d3d75e))
|
||||||
|
* **core:** Add "AbstractType<T>" interface ([#29295](https://github.com/angular/angular/issues/29295)) ([afd4a4e](https://github.com/angular/angular/commit/afd4a4e)), closes [#26491](https://github.com/angular/angular/issues/26491)
|
||||||
|
* **core:** template-var-assignment update schematic ([#29608](https://github.com/angular/angular/issues/29608)) ([7c8f4e3](https://github.com/angular/angular/commit/7c8f4e3))
|
||||||
|
* **bazel:** Upgrade rules_nodejs and rules_sass ([#29388](https://github.com/angular/angular/issues/29388)) ([d6d081e](https://github.com/angular/angular/commit/d6d081e))
|
||||||
|
* **service-worker:** support multiple apps on different subpaths of a domain ([#27080](https://github.com/angular/angular/issues/27080)) ([e721c08](https://github.com/angular/angular/commit/e721c08)), closes [#21388](https://github.com/angular/angular/issues/21388)
|
||||||
|
* **bazel:** Eject Bazel ([#29167](https://github.com/angular/angular/issues/29167)) ([36a1550](https://github.com/angular/angular/commit/36a1550))
|
||||||
|
* **bazel:** Hide Bazel files in Bazel builder ([#29110](https://github.com/angular/angular/issues/29110)) ([7060d90](https://github.com/angular/angular/commit/7060d90))
|
||||||
|
* **forms:** clear (remove all) components from a FormArray ([#28918](https://github.com/angular/angular/issues/28918)) ([a68b1a1](https://github.com/angular/angular/commit/a68b1a1)), closes [#18531](https://github.com/angular/angular/issues/18531)
|
||||||
|
* **platform-server:** wait on returned BEFORE_APP_SERIALIZED promises ([#29120](https://github.com/angular/angular/issues/29120)) ([7102ea8](https://github.com/angular/angular/commit/7102ea8))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** allow ts_library interop with list-typed inputs ([#30600](https://github.com/angular/angular/issues/30600)) ([bf38df4](https://github.com/angular/angular/commit/bf38df4))
|
||||||
|
* **bazel:** Disable sandbox on Mac OS ([#30460](https://github.com/angular/angular/issues/30460)) ([3de26a8](https://github.com/angular/angular/commit/3de26a8))
|
||||||
|
* **bazel:** ng test should run specific ts_web_test_suite ([#30526](https://github.com/angular/angular/issues/30526)) ([8bc4da8](https://github.com/angular/angular/commit/8bc4da8))
|
||||||
|
* **core:** remove deprecated `TestBed.deprecatedOverrideProvider` API ([#30576](https://github.com/angular/angular/issues/30576)) ([5a46f94](https://github.com/angular/angular/commit/5a46f94))
|
||||||
|
* **core:** require 'static' flag on queries in typings ([#30641](https://github.com/angular/angular/issues/30641)) ([c8af830](https://github.com/angular/angular/commit/c8af830))
|
||||||
|
* **core:** temporarily remove [@deprecated](https://github.com/deprecated) jsdoc tag for a TextBed.get overload ([#30514](https://github.com/angular/angular/issues/30514)) ([561e01d](https://github.com/angular/angular/commit/561e01d)), closes [#29290](https://github.com/angular/angular/issues/29290) [#29905](https://github.com/angular/angular/issues/29905)
|
||||||
|
* **router:** type cast correctly for IE 11 bug breaking URL Unification when comparing objects ([#30464](https://github.com/angular/angular/issues/30464)) ([32daa93](https://github.com/angular/angular/commit/32daa93))
|
||||||
|
* **bazel:** Directly spawn native Bazel binary ([#30306](https://github.com/angular/angular/issues/30306)) ([d1fcc2b](https://github.com/angular/angular/commit/d1fcc2b))
|
||||||
|
* **bazel:** pass correct arguments to http_server in Windows ([#30346](https://github.com/angular/angular/issues/30346)) ([71eba45](https://github.com/angular/angular/commit/71eba45)), closes [#29785](https://github.com/angular/angular/issues/29785)
|
||||||
|
* **bazel:** Use existing npm/yarn lock files ([#30438](https://github.com/angular/angular/issues/30438)) ([3136d9f](https://github.com/angular/angular/commit/3136d9f))
|
||||||
|
* **compiler:** ensure strict mode when evaluating in JIT ([#30122](https://github.com/angular/angular/issues/30122)) ([192f108](https://github.com/angular/angular/commit/192f108))
|
||||||
|
* **core:** migrations not always migrating all files ([#30269](https://github.com/angular/angular/issues/30269)) ([e8ceae1](https://github.com/angular/angular/commit/e8ceae1))
|
||||||
|
* **core:** static-query migration errors not printed properly ([#30458](https://github.com/angular/angular/issues/30458)) ([fde3f46](https://github.com/angular/angular/commit/fde3f46))
|
||||||
|
* **core:** static-query migration fails with default parameter values ([#30269](https://github.com/angular/angular/issues/30269)) ([c3246e6](https://github.com/angular/angular/commit/c3246e6))
|
||||||
|
* **core:** static-query migration should gracefully exit if AOT compiler throws ([#30269](https://github.com/angular/angular/issues/30269)) ([a71d8a8](https://github.com/angular/angular/commit/a71d8a8))
|
||||||
|
* **core:** static-query migration should handle queries on accessors ([#30327](https://github.com/angular/angular/issues/30327)) ([dd299f9](https://github.com/angular/angular/commit/dd299f9))
|
||||||
|
* **core:** static-query migration should not fallback to test strategy ([#30458](https://github.com/angular/angular/issues/30458)) ([0fa48e8](https://github.com/angular/angular/commit/0fa48e8))
|
||||||
|
* **core:** static-query migration should not prompt if no queries are used ([#30254](https://github.com/angular/angular/issues/30254)) ([12fb639](https://github.com/angular/angular/commit/12fb639))
|
||||||
|
* **core:** static-query usage migration strategy should detect ambiguous query usage ([#30215](https://github.com/angular/angular/issues/30215)) ([e295c6a](https://github.com/angular/angular/commit/e295c6a))
|
||||||
|
* **router:** ensure navigations start with the current URL value incase redirect is skipped ([#30344](https://github.com/angular/angular/issues/30344)) ([9b88920](https://github.com/angular/angular/commit/9b88920)), closes [#30340](https://github.com/angular/angular/issues/30340) [#30160](https://github.com/angular/angular/issues/30160)
|
||||||
|
* **router:** IE 11 bug can break URL unification when comparing objects ([#30393](https://github.com/angular/angular/issues/30393)) ([c383491](https://github.com/angular/angular/commit/c383491))
|
||||||
|
* **bazel:** Bump ibazel to 0.10.1 for windows fixes ([#30196](https://github.com/angular/angular/issues/30196)) ([9f68c35](https://github.com/angular/angular/commit/9f68c35))
|
||||||
|
* **compiler-cli:** log ngcc skipping messages as debug instead of info ([#30232](https://github.com/angular/angular/issues/30232)) ([548b003](https://github.com/angular/angular/commit/548b003))
|
||||||
|
* **core:** fix interpolate identifier in AOT ([#30243](https://github.com/angular/angular/issues/30243)) ([3fe3a84](https://github.com/angular/angular/commit/3fe3a84))
|
||||||
|
* **router:** ensure `history.state` is set in `eager` update mode ([#30154](https://github.com/angular/angular/issues/30154)) ([9720227](https://github.com/angular/angular/commit/9720227))
|
||||||
|
* **router:** fix a problem with router not responding to back button ([#30160](https://github.com/angular/angular/issues/30160)) ([132f01c](https://github.com/angular/angular/commit/132f01c))
|
||||||
|
* **language-service:** Remove tsserverlibrary from rollup globals ([#30123](https://github.com/angular/angular/issues/30123)) ([b706800](https://github.com/angular/angular/commit/b706800))
|
||||||
|
* disable injectable-pipe migration ([#30180](https://github.com/angular/angular/issues/30180)) ([4b2fcfd](https://github.com/angular/angular/commit/4b2fcfd))
|
||||||
|
* **bazel:** Exclude common/upgrade* in metadata.tsconfig.json ([#30133](https://github.com/angular/angular/issues/30133)) ([6711f22](https://github.com/angular/angular/commit/6711f22))
|
||||||
|
* **bazel:** update peerDep ranges ([#30155](https://github.com/angular/angular/issues/30155)) ([6067583](https://github.com/angular/angular/commit/6067583))
|
||||||
|
* **bazel:** make name param in ng add optional ([#30074](https://github.com/angular/angular/issues/30074)) ([0b5f480](https://github.com/angular/angular/commit/0b5f480))
|
||||||
|
* **bazel:** Make sure only single copy of `[@angular](https://github.com/angular)/bazel` is installed ([#30072](https://github.com/angular/angular/issues/30072)) ([2905bf5](https://github.com/angular/angular/commit/2905bf5))
|
||||||
|
* **bazel:** transitive npm deps in ng_module ([#30065](https://github.com/angular/angular/issues/30065)) ([61365a9](https://github.com/angular/angular/commit/61365a9))
|
||||||
|
* **common:** add upgrade sub-package to ng_package rule for [@angular](https://github.com/angular)/common ([#30117](https://github.com/angular/angular/issues/30117)) ([6de4cbd](https://github.com/angular/angular/commit/6de4cbd)), closes [#30055](https://github.com/angular/angular/issues/30055) [#30116](https://github.com/angular/angular/issues/30116)
|
||||||
|
* **common:** adjust MockPlatformLocation to set state to new object ([#30055](https://github.com/angular/angular/issues/30055)) ([825efa8](https://github.com/angular/angular/commit/825efa8))
|
||||||
|
* **compiler:** Fix compiler crash due to isSkipSelf of null ([#30075](https://github.com/angular/angular/issues/30075)) ([28fd5ab](https://github.com/angular/angular/commit/28fd5ab))
|
||||||
|
* **upgrade:** do not break if `onMicrotaskEmpty` emits while a `$digest` is in progress ([#29794](https://github.com/angular/angular/issues/29794)) ([0ddf2e7](https://github.com/angular/angular/commit/0ddf2e7)), closes [#24680](https://github.com/angular/angular/issues/24680) [/github.com/angular/angular/blob/78146c189/packages/core/src/util/ng_dev_mode.ts#L12](https://github.com//github.com/angular/angular/blob/78146c189/packages/core/src/util/ng_dev_mode.ts/issues/L12) [#24680](https://github.com/angular/angular/issues/24680)
|
||||||
|
* **bazel:** do not typecheck core schematic files ([#29876](https://github.com/angular/angular/issues/29876)) ([2ba799d](https://github.com/angular/angular/commit/2ba799d))
|
||||||
|
* **bazel:** restore ng build --prod ([#30005](https://github.com/angular/angular/issues/30005)) ([96a8289](https://github.com/angular/angular/commit/96a8289))
|
||||||
|
* **common:** prevent repeated application of HttpParams mutations ([#29045](https://github.com/angular/angular/issues/29045)) ([8e8e89a](https://github.com/angular/angular/commit/8e8e89a)), closes [#20430](https://github.com/angular/angular/issues/20430)
|
||||||
|
* **common:** async pipe will properly check when it recieves an NaN value from an observable ([#22305](https://github.com/angular/angular/issues/22305)) ([3f6bf6d](https://github.com/angular/angular/commit/3f6bf6d)), closes [#15721](https://github.com/angular/angular/issues/15721)
|
||||||
|
* **core:** don't include a local `EventListener` in typings ([#29809](https://github.com/angular/angular/issues/29809)) ([4bde40f](https://github.com/angular/angular/commit/4bde40f)), closes [/github.com/angular/angular/blob/303eae918d997070a36b523ddc97e018f622c258/packages/core/src/debug/debug_node.ts#L32](https://github.com//github.com/angular/angular/blob/303eae918d997070a36b523ddc97e018f622c258/packages/core/src/debug/debug_node.ts/issues/L32) [#29806](https://github.com/angular/angular/issues/29806)
|
||||||
|
* **core:** use shakeable global definitions ([#29929](https://github.com/angular/angular/issues/29929)) ([e5905bb](https://github.com/angular/angular/commit/e5905bb)), closes [/github.com/angular/angular-cli/blob/5fc1f2499cbe57f9a95e4b0dfced130eb3a8046d/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/common.ts#L279-L282](https://github.com//github.com/angular/angular-cli/blob/5fc1f2499cbe57f9a95e4b0dfced130eb3a8046d/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/common.ts/issues/L279-L282)
|
||||||
|
* **language-service:** Use proper types instead of any ([#29942](https://github.com/angular/angular/issues/29942)) ([1a56cd5](https://github.com/angular/angular/commit/1a56cd5))
|
||||||
|
* **bazel:** Install packages after `ng add` when invoked independently ([#29852](https://github.com/angular/angular/issues/29852)) ([bd2ce9c](https://github.com/angular/angular/commit/bd2ce9c))
|
||||||
|
* **compiler-cli:** pass config path to ts.parseJsonConfigFileContent ([#29872](https://github.com/angular/angular/issues/29872)) ([86a3f90](https://github.com/angular/angular/commit/86a3f90)), closes [/github.com/Microsoft/TypeScript/blob/025d82633915b67003ea38ba40b9239a19721c13/src/compiler/emitter.ts#L56-L57](https://github.com//github.com/Microsoft/TypeScript/blob/025d82633915b67003ea38ba40b9239a19721c13/src/compiler/emitter.ts/issues/L56-L57)
|
||||||
|
* **router:** support non-NgFactory promise in loadChildren typings ([#29832](https://github.com/angular/angular/issues/29832)) ([2bfb6a0](https://github.com/angular/angular/commit/2bfb6a0))
|
||||||
|
* **bazel:** add configuration_env_vars = ["compile"] to generated [@npm](https://github.com/npm)//[@angular](https://github.com/angular)/bazel/bin:ngc-wrapped nodejs_binary ([#29694](https://github.com/angular/angular/issues/29694)) ([2e66ddf](https://github.com/angular/angular/commit/2e66ddf))
|
||||||
|
* **bazel:** docs formatting ([#29817](https://github.com/angular/angular/issues/29817)) ([cc2e4b6](https://github.com/angular/angular/commit/cc2e4b6))
|
||||||
|
* **bazel:** remove karma-jasmine from ts_web_test_suite ([#29695](https://github.com/angular/angular/issues/29695)) ([2bd9214](https://github.com/angular/angular/commit/2bd9214))
|
||||||
|
* **bazel:** support running ng-add on minimal applications ([#29681](https://github.com/angular/angular/issues/29681)) ([9810c6c](https://github.com/angular/angular/commit/9810c6c)), closes [#29680](https://github.com/angular/angular/issues/29680)
|
||||||
|
* **common:** add `@Injectable()` to common pipes ([#29834](https://github.com/angular/angular/issues/29834)) ([387fbb8](https://github.com/angular/angular/commit/387fbb8))
|
||||||
|
* **compiler-cli:** ensure LogicalProjectPaths always start with a slash ([#29627](https://github.com/angular/angular/issues/29627)) ([e02684e](https://github.com/angular/angular/commit/e02684e))
|
||||||
|
* **core:** add missing migration to npm package ([#29705](https://github.com/angular/angular/issues/29705)) ([96b76dc](https://github.com/angular/angular/commit/96b76dc))
|
||||||
|
* **core:** call ngOnDestroy for tree-shakeable providers ([#28943](https://github.com/angular/angular/issues/28943)) ([30b0442](https://github.com/angular/angular/commit/30b0442)), closes [#28927](https://github.com/angular/angular/issues/28927)
|
||||||
|
* **core:** Deprecate TestBed.get(...):any ([#29290](https://github.com/angular/angular/issues/29290)) ([609024f](https://github.com/angular/angular/commit/609024f)), closes [#13785](https://github.com/angular/angular/issues/13785) [#26491](https://github.com/angular/angular/issues/26491)
|
||||||
|
* **core:** resolve ts compile issues due to lenient tsconfig ([#29843](https://github.com/angular/angular/issues/29843)) ([54058ba](https://github.com/angular/angular/commit/54058ba))
|
||||||
|
* **platform-browser:** insert APP_ID in styles, contentAttr and hostAttr ([#17745](https://github.com/angular/angular/issues/17745)) ([712d60e](https://github.com/angular/angular/commit/712d60e))
|
||||||
|
* **bazel:** use //:tsconfig.json as the default for ng_module ([#29670](https://github.com/angular/angular/issues/29670)) ([#29711](https://github.com/angular/angular/issues/29711)) ([9e33dc3](https://github.com/angular/angular/commit/9e33dc3))
|
||||||
|
* **platform-browser:** insert APP_ID in styles, contentAttr and hostAttr ([#17745](https://github.com/angular/angular/issues/17745)) ([ca14509](https://github.com/angular/angular/commit/ca14509))
|
||||||
|
* **bazel:** Update schematics to support routing ([#29548](https://github.com/angular/angular/issues/29548)) ([401b8ee](https://github.com/angular/angular/commit/401b8ee))
|
||||||
|
* **bazel:** use //:tsconfig.json as the default for ng_module ([#29670](https://github.com/angular/angular/issues/29670)) ([b14537a](https://github.com/angular/angular/commit/b14537a))
|
||||||
|
* **compiler-cli:** ngcc - cope with processing entry-points multiple times ([#29657](https://github.com/angular/angular/issues/29657)) ([6b39c9c](https://github.com/angular/angular/commit/6b39c9c))
|
||||||
|
* **core:** static-query schematic should detect static queries in getters. ([#29609](https://github.com/angular/angular/issues/29609)) ([33016b8](https://github.com/angular/angular/commit/33016b8))
|
||||||
|
* **common:** escape query selector used when anchor scrolling ([#29577](https://github.com/angular/angular/issues/29577)) ([7671c73](https://github.com/angular/angular/commit/7671c73)), closes [#28193](https://github.com/angular/angular/issues/28193)
|
||||||
|
* **router:** adjust setting navigationTransition when a new navigation cancels an existing one ([#29636](https://github.com/angular/angular/issues/29636)) ([e884c0c](https://github.com/angular/angular/commit/e884c0c)), closes [#29389](https://github.com/angular/angular/issues/29389) [#29590](https://github.com/angular/angular/issues/29590)
|
||||||
|
* **bazel:** allow ng_module users to set createExternalSymbolFactoryReexports ([#29459](https://github.com/angular/angular/issues/29459)) ([21be0fb](https://github.com/angular/angular/commit/21be0fb))
|
||||||
|
* **bazel:** workaround problem reading summary files from node_modules ([#29459](https://github.com/angular/angular/issues/29459)) ([769d960](https://github.com/angular/angular/commit/769d960))
|
||||||
|
* **compiler:** inherit param types when class has a constructor which takes no declared parameters and delegates up ([#29232](https://github.com/angular/angular/issues/29232)) ([0007564](https://github.com/angular/angular/commit/0007564))
|
||||||
|
* **core:** parse incorrect ML open tag as text ([#29328](https://github.com/angular/angular/issues/29328)) ([dafbbf8](https://github.com/angular/angular/commit/dafbbf8)), closes [#29231](https://github.com/angular/angular/issues/29231)
|
||||||
|
* **core:** static-query schematic should detect queries in "ngDoCheck" and "ngOnChanges" ([#29492](https://github.com/angular/angular/issues/29492)) ([09fab58](https://github.com/angular/angular/commit/09fab58))
|
||||||
|
* **router:** support NgFactory promise in loadChildren typings ([#29392](https://github.com/angular/angular/issues/29392)) ([26a8c59](https://github.com/angular/angular/commit/26a8c59))
|
||||||
|
* **bazel:** correct regexp test for self-references in metadata ([#29346](https://github.com/angular/angular/issues/29346)) ([9d090cb](https://github.com/angular/angular/commit/9d090cb))
|
||||||
|
* **bazel:** don't produce self-references in metadata ([#29317](https://github.com/angular/angular/issues/29317)) ([3facdeb](https://github.com/angular/angular/commit/3facdeb)), closes [#29315](https://github.com/angular/angular/issues/29315)
|
||||||
|
* **bazel:** fix strict null checks compile error in packages/bazel/src/schematics/ng-add/index.ts ([#29282](https://github.com/angular/angular/issues/29282)) ([9a7f560](https://github.com/angular/angular/commit/9a7f560))
|
||||||
|
* **bazel:** Remove [@angular](https://github.com/angular)/upgrade from dev dependencies ([#29319](https://github.com/angular/angular/issues/29319)) ([1db8bf3](https://github.com/angular/angular/commit/1db8bf3))
|
||||||
|
* **bazel:** Support new e2e project layout ([#29318](https://github.com/angular/angular/issues/29318)) ([8ef690c](https://github.com/angular/angular/commit/8ef690c))
|
||||||
|
* **bazel:** turn off pure call tree shaking for ng_package ([#29210](https://github.com/angular/angular/issues/29210)) ([4990b93](https://github.com/angular/angular/commit/4990b93))
|
||||||
|
* **compiler-cli:** incorrect metadata bundle for multiple unnamed re-exports ([#29360](https://github.com/angular/angular/issues/29360)) ([105cfaf](https://github.com/angular/angular/commit/105cfaf)), closes [/github.com/angular/material2/blob/master/tools/package-tools/build-release.ts#L78-L85](https://github.com//github.com/angular/material2/blob/master/tools/package-tools/build-release.ts/issues/L78-L85)
|
||||||
|
* **core:** don't wrap `<tr>` and `<col>` elements into a required parent ([#29219](https://github.com/angular/angular/issues/29219)) ([f2dc32e](https://github.com/angular/angular/commit/f2dc32e))
|
||||||
|
* **core:** parse incorrect ML open tag as text ([#29328](https://github.com/angular/angular/issues/29328)) ([4605df8](https://github.com/angular/angular/commit/4605df8)), closes [#29231](https://github.com/angular/angular/issues/29231)
|
||||||
|
* **compiler-cli:** incorrect metadata bundle for multiple unnamed re-exports ([#29360](https://github.com/angular/angular/issues/29360)) ([cf8d934](https://github.com/angular/angular/commit/cf8d934)), closes [github.com/angular/material2/blob/master/tools/package-tools/build-release.ts#L78-L85](https://github.com/angular/material2/blob/master/tools/package-tools/build-release.ts#L78-L85)
|
||||||
|
* **bazel:** add missing binary path for api-extractor ([#29202](https://github.com/angular/angular/issues/29202)) ([df354d1](https://github.com/angular/angular/commit/df354d1))
|
||||||
|
* **bazel:** ng build should produce prod bundle ([#29136](https://github.com/angular/angular/issues/29136)) ([14ce8a9](https://github.com/angular/angular/commit/14ce8a9))
|
||||||
|
* **compiler:** ensure template is updated if an output is transformed ([#29041](https://github.com/angular/angular/issues/29041)) ([c7e4931](https://github.com/angular/angular/commit/c7e4931))
|
||||||
|
|
||||||
|
|
||||||
|
### DEPRECATIONS
|
||||||
|
|
||||||
|
* **core:** deprecate integration with the Web Tracing Framework (WTF) ([#30642](https://github.com/angular/angular/issues/30642)) ([b408445](https://github.com/angular/angular/commit/b408445))
|
||||||
|
* **platform-webworker:** deprecate platform-webworker ([#30642](https://github.com/angular/angular/issues/30642)) ([361f181](https://github.com/angular/angular/commit/361f181))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* **bazel:** @bazel/typescript is now a peerDependency of @angular/bazel so user's of @angular/bazel must add @bazel/typescript to their package.json
|
||||||
|
* **bazel:** ng_module now depends on a minimum of build_bazel_rules_nodejs 0.27.12
|
||||||
|
* **core:** In Angular version 8, it's required that all @ViewChild and @ContentChild
|
||||||
|
queries have a 'static' flag specifying whether the query is 'static' or
|
||||||
|
'dynamic'. The compiler previously sorted queries automatically, but in
|
||||||
|
8.0 developers are required to explicitly specify which behavior is wanted.
|
||||||
|
This is a temporary requirement as part of a migration; see
|
||||||
|
https://v8.angular.io/guide/static-query-migration for more details.
|
||||||
|
|
||||||
|
@ViewChildren and @ContentChildren queries are always dynamic, and so are
|
||||||
|
unaffected.
|
||||||
|
|
||||||
|
* `TestBed.get()` has two signatures, one which is typed and another which accepts and returns `any`. The signature for `any` is deprecated; all usage of `TestBed.get()` should go through the typed API. This mainly affects string tokens
|
||||||
|
(which aren't supported) and abstract class tokens.
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [{provide: "stringToken", useValue: new Service()}],
|
||||||
|
});
|
||||||
|
|
||||||
|
let service = TestBed.get("stringToken"); // type any
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const SERVICE_TOKEN = new InjectionToken<Service>("SERVICE_TOKEN");
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [{provide: SERVICE_TOKEN, useValue: new Service()}],
|
||||||
|
});
|
||||||
|
|
||||||
|
let service = TestBed.get(SERVICE_TOKEN); // type Service
|
||||||
|
```
|
||||||
|
|
||||||
|
* **core:** Certain elements (like `<tr>` or `<col>`) require parent elements to be of a certain type by the HTML specification
|
||||||
|
(ex. `<tr>` can only be inside `<tbody>` / `<thead>`). Before this change Angular template parser was auto-correcting
|
||||||
|
"invalid" HTML using the following rules:
|
||||||
|
- `<tr>` would be wrapped in `<tbody>` if not inside `<tbody>`, `<tfoot>` or `<thead>`;
|
||||||
|
- `<col>` would be wrapped in `<colgroup>` if not inside `<colgroup>`.
|
||||||
|
|
||||||
|
This meachanism of automatic wrapping / auto-correcting was problematic for several reasons:
|
||||||
|
- it is non-obvious and arbitrary (ex. there are more HTML elements that has rules for parent type);
|
||||||
|
- it is incorrect for cases where `<tr>` / `<col>` are at the root of a component's content, ex.:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<projecting-tr-inside-tbody>
|
||||||
|
<tr>...</tr>
|
||||||
|
</projecting-tr-inside-tbody>
|
||||||
|
```
|
||||||
|
|
||||||
|
In the above example the `<projecting-tr-inside-tbody>` component could be "surprised" to see additional
|
||||||
|
`<tbody>` elements inserted by Angular HTML parser.
|
||||||
|
|
||||||
|
|
||||||
|
* TypeScript 3.1 and 3.2 are no longer supported.
|
||||||
|
|
||||||
|
Please update your TypeScript version to 3.3
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.0.0-rc.5"></a>
|
||||||
|
# [8.0.0-rc.5](https://github.com/angular/angular/compare/8.0.0-rc.4...8.0.0-rc.5) (2019-05-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** allow ts_library interop with list-typed inputs ([#30600](https://github.com/angular/angular/issues/30600)) ([bf38df4](https://github.com/angular/angular/commit/bf38df4))
|
||||||
|
* **bazel:** Disable sandbox on Mac OS ([#30460](https://github.com/angular/angular/issues/30460)) ([3de26a8](https://github.com/angular/angular/commit/3de26a8))
|
||||||
|
* **bazel:** ng test should run specific ts_web_test_suite ([#30526](https://github.com/angular/angular/issues/30526)) ([8bc4da8](https://github.com/angular/angular/commit/8bc4da8))
|
||||||
|
* **core:** remove deprecated `TestBed.deprecatedOverrideProvider` API ([#30576](https://github.com/angular/angular/issues/30576)) ([5a46f94](https://github.com/angular/angular/commit/5a46f94))
|
||||||
|
* **core:** require 'static' flag on queries in typings ([#30641](https://github.com/angular/angular/issues/30641)) ([c8af830](https://github.com/angular/angular/commit/c8af830))
|
||||||
|
* **core:** temporarily remove [@deprecated](https://github.com/deprecated) jsdoc tag for a TextBed.get overload ([#30514](https://github.com/angular/angular/issues/30514)) ([561e01d](https://github.com/angular/angular/commit/561e01d)), closes [#29290](https://github.com/angular/angular/issues/29290) [#29905](https://github.com/angular/angular/issues/29905)
|
||||||
|
* **router:** type cast correctly for IE 11 bug breaking URL Unification when comparing objects ([#30464](https://github.com/angular/angular/issues/30464)) ([32daa93](https://github.com/angular/angular/commit/32daa93))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **common:** add ability to watch for AngularJS URL updates through `onUrlChange` hook ([#30466](https://github.com/angular/angular/issues/30466)) ([8022d36](https://github.com/angular/angular/commit/8022d36))
|
||||||
|
* **common:** stricter types for SlicePipe ([#30156](https://github.com/angular/angular/issues/30156)) ([722b2fa](https://github.com/angular/angular/commit/722b2fa))
|
||||||
|
|
||||||
|
|
||||||
|
### DEPRECATIONS
|
||||||
|
|
||||||
|
* **core:** deprecate integration with the Web Tracing Framework (WTF) ([#30642](https://github.com/angular/angular/issues/30642)) ([b408445](https://github.com/angular/angular/commit/b408445))
|
||||||
|
* **platform-webworker:** deprecate platform-webworker ([#30642](https://github.com/angular/angular/issues/30642)) ([361f181](https://github.com/angular/angular/commit/361f181))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* **core:** In Angular version 8, it's required that all @ViewChild and @ContentChild
|
||||||
|
queries have a 'static' flag specifying whether the query is 'static' or
|
||||||
|
'dynamic'. The compiler previously sorted queries automatically, but in
|
||||||
|
8.0 developers are required to explicitly specify which behavior is wanted.
|
||||||
|
This is a temporary requirement as part of a migration; see
|
||||||
|
https://v8.angular.io/guide/static-query-migration for more details.
|
||||||
|
|
||||||
|
@ViewChildren and @ContentChildren queries are always dynamic, and so are
|
||||||
|
unaffected.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.0.0-rc.4"></a>
|
||||||
|
# [8.0.0-rc.4](https://github.com/angular/angular/compare/8.0.0-rc.3...8.0.0-rc.4) (2019-05-15)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** Directly spawn native Bazel binary ([#30306](https://github.com/angular/angular/issues/30306)) ([d1fcc2b](https://github.com/angular/angular/commit/d1fcc2b))
|
||||||
|
* **bazel:** pass correct arguments to http_server in Windows ([#30346](https://github.com/angular/angular/issues/30346)) ([71eba45](https://github.com/angular/angular/commit/71eba45)), closes [#29785](https://github.com/angular/angular/issues/29785)
|
||||||
|
* **bazel:** Use existing npm/yarn lock files ([#30438](https://github.com/angular/angular/issues/30438)) ([3136d9f](https://github.com/angular/angular/commit/3136d9f))
|
||||||
|
* **compiler:** ensure strict mode when evaluating in JIT ([#30122](https://github.com/angular/angular/issues/30122)) ([192f108](https://github.com/angular/angular/commit/192f108))
|
||||||
|
* **core:** migrations not always migrating all files ([#30269](https://github.com/angular/angular/issues/30269)) ([e8ceae1](https://github.com/angular/angular/commit/e8ceae1))
|
||||||
|
* **core:** static-query migration errors not printed properly ([#30458](https://github.com/angular/angular/issues/30458)) ([fde3f46](https://github.com/angular/angular/commit/fde3f46))
|
||||||
|
* **core:** static-query migration fails with default parameter values ([#30269](https://github.com/angular/angular/issues/30269)) ([c3246e6](https://github.com/angular/angular/commit/c3246e6))
|
||||||
|
* **core:** static-query migration should gracefully exit if AOT compiler throws ([#30269](https://github.com/angular/angular/issues/30269)) ([a71d8a8](https://github.com/angular/angular/commit/a71d8a8))
|
||||||
|
* **core:** static-query migration should handle queries on accessors ([#30327](https://github.com/angular/angular/issues/30327)) ([dd299f9](https://github.com/angular/angular/commit/dd299f9))
|
||||||
|
* **core:** static-query migration should not fallback to test strategy ([#30458](https://github.com/angular/angular/issues/30458)) ([0fa48e8](https://github.com/angular/angular/commit/0fa48e8))
|
||||||
|
* **core:** static-query migration should not prompt if no queries are used ([#30254](https://github.com/angular/angular/issues/30254)) ([12fb639](https://github.com/angular/angular/commit/12fb639))
|
||||||
|
* **core:** static-query usage migration strategy should detect ambiguous query usage ([#30215](https://github.com/angular/angular/issues/30215)) ([e295c6a](https://github.com/angular/angular/commit/e295c6a))
|
||||||
|
* **router:** ensure navigations start with the current URL value incase redirect is skipped ([#30344](https://github.com/angular/angular/issues/30344)) ([9b88920](https://github.com/angular/angular/commit/9b88920)), closes [#30340](https://github.com/angular/angular/issues/30340) [#30160](https://github.com/angular/angular/issues/30160)
|
||||||
|
* **router:** IE 11 bug can break URL unification when comparing objects ([#30393](https://github.com/angular/angular/issues/30393)) ([c383491](https://github.com/angular/angular/commit/c383491))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **bazel:** use rbe_autoconfig() and new container. ([#29336](https://github.com/angular/angular/issues/29336)) ([e562acc](https://github.com/angular/angular/commit/e562acc))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.0.0-rc.3"></a>
|
||||||
|
# [8.0.0-rc.3](https://github.com/angular/angular/compare/8.0.0-rc.2...8.0.0-rc.3) (2019-05-07)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** Bump ibazel to 0.10.1 for windows fixes ([#30196](https://github.com/angular/angular/issues/30196)) ([9f68c35](https://github.com/angular/angular/commit/9f68c35))
|
||||||
|
* **compiler-cli:** log ngcc skipping messages as debug instead of info ([#30232](https://github.com/angular/angular/issues/30232)) ([548b003](https://github.com/angular/angular/commit/548b003))
|
||||||
|
* **core:** fix interpolate identifier in AOT ([#30243](https://github.com/angular/angular/issues/30243)) ([3fe3a84](https://github.com/angular/angular/commit/3fe3a84))
|
||||||
|
* **router:** ensure `history.state` is set in `eager` update mode ([#30154](https://github.com/angular/angular/issues/30154)) ([9720227](https://github.com/angular/angular/commit/9720227))
|
||||||
|
* **router:** fix a problem with router not responding to back button ([#30160](https://github.com/angular/angular/issues/30160)) ([132f01c](https://github.com/angular/angular/commit/132f01c))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.0.0-rc.2"></a>
|
||||||
|
# [8.0.0-rc.2](https://github.com/angular/angular/compare/8.0.0-rc.1...8.0.0-rc.2) (2019-04-29)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **language-service:** Remove tsserverlibrary from rollup globals ([#30123](https://github.com/angular/angular/issues/30123)) ([b706800](https://github.com/angular/angular/commit/b706800))
|
||||||
|
* disable injectable-pipe migration ([#30180](https://github.com/angular/angular/issues/30180)) ([4b2fcfd](https://github.com/angular/angular/commit/4b2fcfd))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.0.0-rc.1"></a>
|
||||||
|
# [8.0.0-rc.1](https://github.com/angular/angular/compare/8.0.0-rc.0...8.0.0-rc.1) (2019-04-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** Exclude common/upgrade* in metadata.tsconfig.json ([#30133](https://github.com/angular/angular/issues/30133)) ([6711f22](https://github.com/angular/angular/commit/6711f22))
|
||||||
|
* **bazel:** update peerDep ranges ([#30155](https://github.com/angular/angular/issues/30155)) ([6067583](https://github.com/angular/angular/commit/6067583))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="8.0.0-rc.0"></a>
|
<a name="8.0.0-rc.0"></a>
|
||||||
# [8.0.0-rc.0](https://github.com/angular/angular/compare/8.0.0-beta.14...8.0.0-rc.0) (2019-04-25)
|
# [8.0.0-rc.0](https://github.com/angular/angular/compare/8.0.0-beta.14...8.0.0-rc.0) (2019-04-25)
|
||||||
|
|
||||||
@ -976,7 +1319,6 @@ To learn about the release highlights and our new CLI-powered update workflow fo
|
|||||||
|
|
||||||
* **bazel:** protractor rule should include *.e2e-spec.js ([#25701](https://github.com/angular/angular/issues/25701)) ([ed6b68b](https://github.com/angular/angular/commit/ed6b68b))
|
* **bazel:** protractor rule should include *.e2e-spec.js ([#25701](https://github.com/angular/angular/issues/25701)) ([ed6b68b](https://github.com/angular/angular/commit/ed6b68b))
|
||||||
* **core:** size regression with closure compiler ([#25531](https://github.com/angular/angular/issues/25531)) ([ebcf762](https://github.com/angular/angular/commit/ebcf762))
|
* **core:** size regression with closure compiler ([#25531](https://github.com/angular/angular/issues/25531)) ([ebcf762](https://github.com/angular/angular/commit/ebcf762))
|
||||||
* **docs-infra:** show "suggest edits" only for /guide and /tutorial dirs ([#24378](https://github.com/angular/angular/issues/24378)) ([66b7870](https://github.com/angular/angular/commit/66b7870))
|
|
||||||
* **upgrade:** trigger `$destroy` event on upgraded component element ([#25357](https://github.com/angular/angular/issues/25357)) ([82e0676](https://github.com/angular/angular/commit/82e0676)), closes [#25334](https://github.com/angular/angular/issues/25334)
|
* **upgrade:** trigger `$destroy` event on upgraded component element ([#25357](https://github.com/angular/angular/issues/25357)) ([82e0676](https://github.com/angular/angular/commit/82e0676)), closes [#25334](https://github.com/angular/angular/issues/25334)
|
||||||
* **router:** warn if navigation triggered outside Angular zone ([#24959](https://github.com/angular/angular/issues/24959)) ([23a96dc](https://github.com/angular/angular/commit/23a96dc)), closes [#15770](https://github.com/angular/angular/issues/15770) [#15946](https://github.com/angular/angular/issues/15946) [#24728](https://github.com/angular/angular/issues/24728)
|
* **router:** warn if navigation triggered outside Angular zone ([#24959](https://github.com/angular/angular/issues/24959)) ([23a96dc](https://github.com/angular/angular/commit/23a96dc)), closes [#15770](https://github.com/angular/angular/issues/15770) [#15946](https://github.com/angular/angular/issues/15946) [#24728](https://github.com/angular/angular/issues/24728)
|
||||||
|
|
||||||
@ -1068,7 +1410,6 @@ Note: the 6.1.5 release on npm accidentally glitched-out midway, so we cut 6.1.6
|
|||||||
* **core:** Injector correctly honors the @Self flag ([#24520](https://github.com/angular/angular/issues/24520)) ([ccbda9d](https://github.com/angular/angular/commit/ccbda9d))
|
* **core:** Injector correctly honors the @Self flag ([#24520](https://github.com/angular/angular/issues/24520)) ([ccbda9d](https://github.com/angular/angular/commit/ccbda9d))
|
||||||
* **core:** avoid eager providers re-initialization ([#23559](https://github.com/angular/angular/issues/23559)) ([0c6dc45](https://github.com/angular/angular/commit/0c6dc45))
|
* **core:** avoid eager providers re-initialization ([#23559](https://github.com/angular/angular/issues/23559)) ([0c6dc45](https://github.com/angular/angular/commit/0c6dc45))
|
||||||
* **core:** call ngOnDestroy on all services that have it ([#23755](https://github.com/angular/angular/issues/23755)) ([fc03427](https://github.com/angular/angular/commit/fc03427)), closes [#22466](https://github.com/angular/angular/issues/22466) [#22240](https://github.com/angular/angular/issues/22240) [#14818](https://github.com/angular/angular/issues/14818)
|
* **core:** call ngOnDestroy on all services that have it ([#23755](https://github.com/angular/angular/issues/23755)) ([fc03427](https://github.com/angular/angular/commit/fc03427)), closes [#22466](https://github.com/angular/angular/issues/22466) [#22240](https://github.com/angular/angular/issues/22240) [#14818](https://github.com/angular/angular/issues/14818)
|
||||||
* **docs-infra:** fix table header layout in API pages ([#24919](https://github.com/angular/angular/issues/24919)) ([3cd9645](https://github.com/angular/angular/commit/3cd9645))
|
|
||||||
* **elements:** always check to create strategy ([#23825](https://github.com/angular/angular/issues/23825)) ([b1cda36](https://github.com/angular/angular/commit/b1cda36))
|
* **elements:** always check to create strategy ([#23825](https://github.com/angular/angular/issues/23825)) ([b1cda36](https://github.com/angular/angular/commit/b1cda36))
|
||||||
* **elements:** prevent closure renaming of platform properties ([#23843](https://github.com/angular/angular/issues/23843)) ([d4b8b24](https://github.com/angular/angular/commit/d4b8b24))
|
* **elements:** prevent closure renaming of platform properties ([#23843](https://github.com/angular/angular/issues/23843)) ([d4b8b24](https://github.com/angular/angular/commit/d4b8b24))
|
||||||
* **forms:** properly handle special properties in FormGroup.get ([#22249](https://github.com/angular/angular/issues/22249)) ([9367e91](https://github.com/angular/angular/commit/9367e91)), closes [#17195](https://github.com/angular/angular/issues/17195)
|
* **forms:** properly handle special properties in FormGroup.get ([#22249](https://github.com/angular/angular/issues/22249)) ([9367e91](https://github.com/angular/angular/commit/9367e91)), closes [#17195](https://github.com/angular/angular/issues/17195)
|
||||||
@ -1185,7 +1526,6 @@ For example:
|
|||||||
|
|
||||||
* **animations:** always render end-state styles for orphaned DOM nodes ([#24236](https://github.com/angular/angular/issues/24236)) ([0139173](https://github.com/angular/angular/commit/0139173))
|
* **animations:** always render end-state styles for orphaned DOM nodes ([#24236](https://github.com/angular/angular/issues/24236)) ([0139173](https://github.com/angular/angular/commit/0139173))
|
||||||
* **bazel:** Allow ng_module to depend on targets w no deps ([#24446](https://github.com/angular/angular/issues/24446)) ([ea3669e](https://github.com/angular/angular/commit/ea3669e))
|
* **bazel:** Allow ng_module to depend on targets w no deps ([#24446](https://github.com/angular/angular/issues/24446)) ([ea3669e](https://github.com/angular/angular/commit/ea3669e))
|
||||||
* **docs-infra:** use script nomodule to load IE polyfills, skip other polyfills ([#24317](https://github.com/angular/angular/issues/24317)) ([e876535](https://github.com/angular/angular/commit/e876535)), closes [#23647](https://github.com/angular/angular/issues/23647)
|
|
||||||
* **router:** fix lazy loading of aux routes ([#23459](https://github.com/angular/angular/issues/23459)) ([d20877b](https://github.com/angular/angular/commit/d20877b)), closes [#10981](https://github.com/angular/angular/issues/10981)
|
* **router:** fix lazy loading of aux routes ([#23459](https://github.com/angular/angular/issues/23459)) ([d20877b](https://github.com/angular/angular/commit/d20877b)), closes [#10981](https://github.com/angular/angular/issues/10981)
|
||||||
* **service-worker:** fix `SwPush.unsubscribe()` ([#24162](https://github.com/angular/angular/issues/24162)) ([ea2987c](https://github.com/angular/angular/commit/ea2987c)), closes [#24095](https://github.com/angular/angular/issues/24095)
|
* **service-worker:** fix `SwPush.unsubscribe()` ([#24162](https://github.com/angular/angular/issues/24162)) ([ea2987c](https://github.com/angular/angular/commit/ea2987c)), closes [#24095](https://github.com/angular/angular/issues/24095)
|
||||||
|
|
||||||
|
@ -231,6 +231,7 @@ There are currently a few exceptions to the "use package name" rule:
|
|||||||
* **changelog**: used for updating the release notes in CHANGELOG.md
|
* **changelog**: used for updating the release notes in CHANGELOG.md
|
||||||
* **docs-infra**: used for docs-app (angular.io) related changes within the /aio directory of the
|
* **docs-infra**: used for docs-app (angular.io) related changes within the /aio directory of the
|
||||||
repo
|
repo
|
||||||
|
* **ivy**: used for changes to the [Ivy renderer](https://github.com/angular/angular/issues/21706).
|
||||||
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all
|
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all
|
||||||
packages (e.g. `style: add missing semicolons`) and for docs changes that are not related to a
|
packages (e.g. `style: add missing semicolons`) and for docs changes that are not related to a
|
||||||
specific package (e.g. `docs: fix typo in tutorial`).
|
specific package (e.g. `docs: fix typo in tutorial`).
|
||||||
|
@ -23,6 +23,6 @@ guidelines for [contributing][contributing] and then check out one of our issues
|
|||||||
|
|
||||||
[browserstack]: https://www.browserstack.com/automate/public-build/LzF3RzBVVGt6VWE2S0hHaC9uYllOZz09LS1BVjNTclBKV0x4eVRlcjA4QVY1M0N3PT0=--eb4ce8c8dc2c1c5b2b5352d473ee12a73ac20e06
|
[browserstack]: https://www.browserstack.com/automate/public-build/LzF3RzBVVGt6VWE2S0hHaC9uYllOZz09LS1BVjNTclBKV0x4eVRlcjA4QVY1M0N3PT0=--eb4ce8c8dc2c1c5b2b5352d473ee12a73ac20e06
|
||||||
[contributing]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md
|
[contributing]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md
|
||||||
[quickstart]: https://angular.io/guide/quickstart
|
[quickstart]: https://angular.io/start
|
||||||
[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md
|
[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md
|
||||||
[ng]: https://angular.io
|
[ng]: https://angular.io
|
||||||
|
59
WORKSPACE
59
WORKSPACE
@ -1,4 +1,7 @@
|
|||||||
workspace(name = "angular")
|
workspace(
|
||||||
|
name = "angular",
|
||||||
|
managed_directories = {"@npm": ["node_modules"]},
|
||||||
|
)
|
||||||
|
|
||||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||||
|
|
||||||
@ -15,16 +18,15 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
|||||||
# Fetch rules_nodejs so we can install our npm dependencies
|
# Fetch rules_nodejs so we can install our npm dependencies
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "build_bazel_rules_nodejs",
|
name = "build_bazel_rules_nodejs",
|
||||||
sha256 = "3a3efbf223f6de733475602844ad3a8faa02abda25ab8cfe1d1ed0db134887cf",
|
sha256 = "e04a82a72146bfbca2d0575947daa60fda1878c8d3a3afe868a8ec39a6b968bb",
|
||||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.27.12/rules_nodejs-0.27.12.tar.gz"],
|
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.31.1/rules_nodejs-0.31.1.tar.gz"],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check the bazel version and download npm dependencies
|
# Check the bazel version and download npm dependencies
|
||||||
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "check_rules_nodejs_version", "node_repositories", "yarn_install")
|
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "check_rules_nodejs_version", "node_repositories", "yarn_install")
|
||||||
|
|
||||||
# Bazel version must be at least v0.21.0 because:
|
# Bazel version must be at least the following version because:
|
||||||
# - 0.21.0 Using --incompatible_strict_action_env flag fixes cache when running `yarn bazel`
|
# - 0.26.0 managed_directories feature added which is required for nodejs rules 0.30.0
|
||||||
# (see https://github.com/angular/angular/issues/27514#issuecomment-451438271)
|
|
||||||
check_bazel_version(
|
check_bazel_version(
|
||||||
message = """
|
message = """
|
||||||
You no longer need to install Bazel on your machine.
|
You no longer need to install Bazel on your machine.
|
||||||
@ -33,22 +35,28 @@ Try running `yarn bazel` instead.
|
|||||||
(If you did run that, check that you've got a fresh `yarn install`)
|
(If you did run that, check that you've got a fresh `yarn install`)
|
||||||
|
|
||||||
""",
|
""",
|
||||||
minimum_bazel_version = "0.21.0",
|
minimum_bazel_version = "0.26.0",
|
||||||
)
|
)
|
||||||
|
|
||||||
# The NodeJS rules version must be at least v0.15.3 because:
|
# The NodeJS rules version must be at least the following version because:
|
||||||
# - 0.15.2 Re-introduced the prod_only attribute on yarn_install
|
# - 0.15.2 Re-introduced the prod_only attribute on yarn_install
|
||||||
# - 0.15.3 Includes a fix for the `jasmine_node_test` rule ignoring target tags
|
# - 0.15.3 Includes a fix for the `jasmine_node_test` rule ignoring target tags
|
||||||
# - 0.16.8 Supports npm installed bazel workspaces
|
# - 0.16.8 Supports npm installed bazel workspaces
|
||||||
# - 0.26.0 Fix for data files in yarn_install and npm_install
|
# - 0.26.0 Fix for data files in yarn_install and npm_install
|
||||||
# - 0.27.12 Adds NodeModuleSources provider for transtive npm deps support
|
# - 0.27.12 Adds NodeModuleSources provider for transtive npm deps support
|
||||||
check_rules_nodejs_version("0.27.12")
|
# - 0.30.0 yarn_install now uses symlinked node_modules with new managed directories Bazel 0.26.0 feature
|
||||||
|
# - 0.31.1 entry_point attribute of nodejs_binary & rollup_bundle is now a label
|
||||||
|
check_rules_nodejs_version(minimum_version_string = "0.31.1")
|
||||||
|
|
||||||
# Setup the Node.js toolchain
|
# Setup the Node.js toolchain
|
||||||
node_repositories(
|
node_repositories(
|
||||||
node_version = "10.9.0",
|
node_repositories = {
|
||||||
|
"10.16.0-darwin_amd64": ("node-v10.16.0-darwin-x64.tar.gz", "node-v10.16.0-darwin-x64", "6c009df1b724026d84ae9a838c5b382662e30f6c5563a0995532f2bece39fa9c"),
|
||||||
|
"10.16.0-linux_amd64": ("node-v10.16.0-linux-x64.tar.xz", "node-v10.16.0-linux-x64", "1827f5b99084740234de0c506f4dd2202a696ed60f76059696747c34339b9d48"),
|
||||||
|
"10.16.0-windows_amd64": ("node-v10.16.0-win-x64.zip", "node-v10.16.0-win-x64", "aa22cb357f0fb54ccbc06b19b60e37eefea5d7dd9940912675d3ed988bf9a059"),
|
||||||
|
},
|
||||||
|
node_version = "10.16.0",
|
||||||
package_json = ["//:package.json"],
|
package_json = ["//:package.json"],
|
||||||
preserve_symlinks = True,
|
|
||||||
# yarn 1.13.0 under Bazel has a regression on Windows that causes build errors on rebuilds:
|
# yarn 1.13.0 under Bazel has a regression on Windows that causes build errors on rebuilds:
|
||||||
# ```
|
# ```
|
||||||
# ERROR: Source forest creation failed: C:/.../fyuc5c3n/execroot/angular/external (Directory not empty)
|
# ERROR: Source forest creation failed: C:/.../fyuc5c3n/execroot/angular/external (Directory not empty)
|
||||||
@ -71,6 +79,10 @@ yarn_install(
|
|||||||
package_json = "//:package.json",
|
package_json = "//:package.json",
|
||||||
# Don't install devDependencies, they are large and not used under Bazel
|
# Don't install devDependencies, they are large and not used under Bazel
|
||||||
prod_only = True,
|
prod_only = True,
|
||||||
|
# Temporarily disable node_modules symlinking until the fix for
|
||||||
|
# https://github.com/bazelbuild/bazel/issues/8487 makes it into a
|
||||||
|
# future Bazel release
|
||||||
|
symlink_node_modules = False,
|
||||||
yarn_lock = "//:yarn.lock",
|
yarn_lock = "//:yarn.lock",
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -96,7 +108,7 @@ web_test_repositories()
|
|||||||
|
|
||||||
# Temporary work-around for https://github.com/angular/angular/issues/28681
|
# Temporary work-around for https://github.com/angular/angular/issues/28681
|
||||||
# TODO(gregmagolan): go back to @io_bazel_rules_webtesting browser_repositories
|
# TODO(gregmagolan): go back to @io_bazel_rules_webtesting browser_repositories
|
||||||
load("@npm_bazel_karma//:browser_repositories.bzl", "browser_repositories")
|
load("//:browser_repositories.bzl", "browser_repositories")
|
||||||
|
|
||||||
browser_repositories()
|
browser_repositories()
|
||||||
|
|
||||||
@ -114,3 +126,26 @@ sass_repositories()
|
|||||||
load("@io_bazel_skydoc//skylark:skylark.bzl", "skydoc_repositories")
|
load("@io_bazel_skydoc//skylark:skylark.bzl", "skydoc_repositories")
|
||||||
|
|
||||||
skydoc_repositories()
|
skydoc_repositories()
|
||||||
|
|
||||||
|
load("@bazel_toolchains//rules:environments.bzl", "clang_env")
|
||||||
|
load("@bazel_toolchains//rules:rbe_repo.bzl", "rbe_autoconfig")
|
||||||
|
|
||||||
|
rbe_autoconfig(
|
||||||
|
name = "rbe_ubuntu1604_angular",
|
||||||
|
# Need to specify a base container digest in order to ensure that we can use the checked-in
|
||||||
|
# platform configurations for the "ubuntu16_04" image. Otherwise the autoconfig rule would
|
||||||
|
# need to pull the image and run it in order determine the toolchain configuration. See:
|
||||||
|
# https://github.com/bazelbuild/bazel-toolchains/blob/0.27.0/configs/ubuntu16_04_clang/versions.bzl
|
||||||
|
base_container_digest = "sha256:94d7d8552902d228c32c8c148cc13f0effc2b4837757a6e95b73fdc5c5e4b07b",
|
||||||
|
# Note that if you change the `digest`, you might also need to update the
|
||||||
|
# `base_container_digest` to make sure marketplace.gcr.io/google/rbe-ubuntu16-04-webtest:<digest>
|
||||||
|
# and marketplace.gcr.io/google/rbe-ubuntu16-04:<base_container_digest> have
|
||||||
|
# the same Clang and JDK installed. Clang is needed because of the dependency on
|
||||||
|
# @com_google_protobuf. Java is needed for the Bazel's test executor Java tool.
|
||||||
|
digest = "sha256:76e2e4a894f9ffbea0a0cb2fbde741b5d223d40f265dbb9bca78655430173990",
|
||||||
|
env = clang_env(),
|
||||||
|
registry = "marketplace.gcr.io",
|
||||||
|
# We can't use the default "ubuntu16_04" RBE image provided by the autoconfig because we need
|
||||||
|
# a specific Linux kernel that comes with "libx11" in order to run headless browser tests.
|
||||||
|
repository = "google/rbe-ubuntu16-04-webtest",
|
||||||
|
)
|
||||||
|
@ -6,8 +6,7 @@
|
|||||||
# For additional information see: https://developers.google.com/search/docs/guides/rendering
|
# For additional information see: https://developers.google.com/search/docs/guides/rendering
|
||||||
|
|
||||||
> 0.5%
|
> 0.5%
|
||||||
last 2 versions
|
last 2 major versions
|
||||||
Firefox ESR
|
Firefox ESR
|
||||||
not dead
|
not dead
|
||||||
IE 9-11 # For IE 9-11 support.
|
IE 11
|
||||||
Chrome 41 # For Googlebot support.
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<h1 class="no-toc">CLI Command Reference</h1>
|
# CLI Overview and Command Reference
|
||||||
|
|
||||||
The Angular CLI is a command-line interface tool that you use to initialize, develop, scaffold, and maintain Angular applications. You can use the tool directly in a command shell, or indirectly through an interactive UI such as [Angular Console](https://angularconsole.com).
|
The Angular CLI is a command-line interface tool that you use to initialize, develop, scaffold, and maintain Angular applications. You can use the tool directly in a command shell, or indirectly through an interactive UI such as [Angular Console](https://angularconsole.com).
|
||||||
|
|
||||||
|
3
aio/content/examples/.gitignore
vendored
3
aio/content/examples/.gitignore
vendored
@ -23,6 +23,9 @@
|
|||||||
**/bs-config.e2e.json
|
**/bs-config.e2e.json
|
||||||
**/bs-config.json
|
**/bs-config.json
|
||||||
**/package.json
|
**/package.json
|
||||||
|
**/tsconfig.json
|
||||||
|
**/tsconfig.app.json
|
||||||
|
**/tsconfig.spec.json
|
||||||
**/tslint.json
|
**/tslint.json
|
||||||
**/karma-test-shim.js
|
**/karma-test-shim.js
|
||||||
**/browser-test-shim.js
|
**/browser-test-shim.js
|
||||||
|
@ -67,8 +67,8 @@ describe('AngularJS to Angular Quick Reference Tests', function () {
|
|||||||
testFavoriteHero('Magneta', 'No movie, sorry!');
|
testFavoriteHero('Magneta', 'No movie, sorry!');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display a movie for Mr. Nice', function () {
|
it('should display a movie for Dr Nice', function () {
|
||||||
testFavoriteHero('Mr. Nice', 'Excellent choice!');
|
testFavoriteHero('Dr Nice', 'Excellent choice!');
|
||||||
});
|
});
|
||||||
|
|
||||||
function testImagesAreDisplayed(isDisplayed: boolean) {
|
function testImagesAreDisplayed(isDisplayed: boolean) {
|
||||||
|
@ -18,12 +18,12 @@ export class MovieService {
|
|||||||
approvalRating: .97
|
approvalRating: .97
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
hero: 'Mr. Nice',
|
hero: 'Dr Nice',
|
||||||
imageurl: 'assets/images/villain.png',
|
imageurl: 'assets/images/villain.png',
|
||||||
movieId: 2,
|
movieId: 2,
|
||||||
mpaa: 'pg-13',
|
mpaa: 'pg-13',
|
||||||
releaseDate: '2015-12-18T00:00:00',
|
releaseDate: '2015-12-18T00:00:00',
|
||||||
title: 'No More Mr. Nice Guy',
|
title: 'No More Dr Nice',
|
||||||
price: 14.95,
|
price: 14.95,
|
||||||
starRating: 4.6,
|
starRating: 4.6,
|
||||||
approvalRating: .94
|
approvalRating: .94
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { Hero } from './hero';
|
import { Hero } from './hero';
|
||||||
|
|
||||||
export const HEROES: Hero[] = [
|
export const HEROES: Hero[] = [
|
||||||
{ id: 11, name: 'Mr. Nice' },
|
{ id: 11, name: 'Dr Nice' },
|
||||||
{ id: 12, name: 'Narco' },
|
{ id: 12, name: 'Narco' },
|
||||||
{ id: 13, name: 'Bombasto' },
|
{ id: 13, name: 'Bombasto' },
|
||||||
{ id: 14, name: 'Celeritas' },
|
{ id: 14, name: 'Celeritas' },
|
||||||
|
@ -31,7 +31,7 @@ describe('Architecture', () => {
|
|||||||
|
|
||||||
function heroTests() {
|
function heroTests() {
|
||||||
|
|
||||||
const targetHero: Hero = { id: 2, name: 'Mr. Nice' };
|
const targetHero: Hero = { id: 2, name: 'Dr Nice' };
|
||||||
|
|
||||||
it('has the right number of heroes', () => {
|
it('has the right number of heroes', () => {
|
||||||
let page = getPageElts();
|
let page = getPageElts();
|
||||||
|
@ -5,7 +5,7 @@ import { Hero } from './hero';
|
|||||||
|
|
||||||
const HEROES = [
|
const HEROES = [
|
||||||
new Hero('Windstorm', 'Weather mastery'),
|
new Hero('Windstorm', 'Weather mastery'),
|
||||||
new Hero('Mr. Nice', 'Killing them with kindness'),
|
new Hero('Dr Nice', 'Killing them with kindness'),
|
||||||
new Hero('Magneta', 'Manipulates metallic objects')
|
new Hero('Magneta', 'Manipulates metallic objects')
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import { Component } from '@angular/core';
|
|||||||
// #enddocregion import-core-component
|
// #enddocregion import-core-component
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-app',
|
selector: 'app-root',
|
||||||
template: 'Welcome to Angular'
|
template: 'Welcome to Angular'
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
|
describe('Attribute binding example', function () {
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display Property Binding with Angular', function () {
|
||||||
|
expect(element(by.css('h1')).getText()).toEqual('Attribute, class, and style bindings');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display a table', function() {
|
||||||
|
expect(element.all(by.css('table')).isPresent()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display an Aria button', function () {
|
||||||
|
expect(element.all(by.css('button')).get(0).getText()).toBe('Go for it with Aria');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display a blue background on div', function () {
|
||||||
|
expect(element.all(by.css('div')).get(1).getCssValue('background-color')).toEqual('rgba(25, 118, 210, 1)');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display a blue div with a red border', function () {
|
||||||
|
expect(element.all(by.css('div')).get(4).getCssValue('border')).toEqual('2px solid rgb(212, 30, 46)');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display a div with replaced classes', function () {
|
||||||
|
expect(element.all(by.css('div')).get(5).getAttribute('class')).toEqual('new-class');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display four buttons', function() {
|
||||||
|
let redButton = element.all(by.css('button')).get(1);
|
||||||
|
let saveButton = element.all(by.css('button')).get(2);
|
||||||
|
let bigButton = element.all(by.css('button')).get(3);
|
||||||
|
let smallButton = element.all(by.css('button')).get(4);
|
||||||
|
|
||||||
|
expect(redButton.getCssValue('color')).toEqual('rgba(255, 0, 0, 1)');
|
||||||
|
expect(saveButton.getCssValue('background-color')).toEqual('rgba(0, 255, 255, 1)');
|
||||||
|
expect(bigButton.getText()).toBe('Big');
|
||||||
|
expect(smallButton.getText()).toBe('Small');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,22 @@
|
|||||||
|
.special {
|
||||||
|
background-color: #1976d2;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.clearance {
|
||||||
|
border: 2px solid #d41e2e;
|
||||||
|
|
||||||
|
}
|
||||||
|
.item-clearance {
|
||||||
|
font-style: italic;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.new-class {
|
||||||
|
background-color: #ed1b2f;
|
||||||
|
font-style: italic;
|
||||||
|
color: #fff;
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
|
||||||
|
<h1>Attribute, class, and style bindings</h1>
|
||||||
|
<h2>Attribute binding</h2>
|
||||||
|
<!-- #docregion attrib-binding-colspan -->
|
||||||
|
<table border=1>
|
||||||
|
<!-- expression calculates colspan=2 -->
|
||||||
|
<tr><td [attr.colspan]="1 + 1">One-Two</td></tr>
|
||||||
|
|
||||||
|
<!-- ERROR: There is no `colspan` property to set!
|
||||||
|
<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
|
||||||
|
-->
|
||||||
|
<!-- #docregion colSpan -->
|
||||||
|
<!-- Notice the colSpan property is camel case -->
|
||||||
|
<tr><td [colSpan]="1 + 1">Three-Four</td></tr>
|
||||||
|
<!-- #enddocregion colSpan -->
|
||||||
|
|
||||||
|
<tr><td>Five</td><td>Six</td></tr>
|
||||||
|
</table>
|
||||||
|
<!-- #enddocregion attrib-binding-colspan -->
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<!-- #docregion attrib-binding-aria -->
|
||||||
|
<!-- create and set an aria attribute for assistive technology -->
|
||||||
|
<button [attr.aria-label]="actionName">{{actionName}} with Aria</button>
|
||||||
|
<!-- #enddocregion attrib-binding-aria -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<h2>Class binding</h2>
|
||||||
|
|
||||||
|
<!-- #docregion is-special -->
|
||||||
|
<h3>toggle the "special" class on/off with a property:</h3>
|
||||||
|
<div [class.special]="isSpecial">The class binding is special.</div>
|
||||||
|
|
||||||
|
<h3>binding to class.special overrides the class attribute:</h3>
|
||||||
|
<div class="special" [class.special]="!isSpecial">This one is not so special.</div>
|
||||||
|
|
||||||
|
<h3>Using the bind- syntax:</h3>
|
||||||
|
<div bind-class.special="isSpecial">This class binding is special too.</div>
|
||||||
|
<!-- #enddocregion is-special -->
|
||||||
|
|
||||||
|
<!-- #docregion add-class -->
|
||||||
|
<h3>Add a class:</h3>
|
||||||
|
<div class="item clearance special" [class.item-clearance]="itemClearance">Add another class</div>
|
||||||
|
<!-- #enddocregion add-class -->
|
||||||
|
|
||||||
|
<!-- #docregion class-override -->
|
||||||
|
<h3>Overwrite all existing classes with a new class:</h3>
|
||||||
|
<div class="item clearance special" [attr.class]="resetClasses">Reset all classes at once</div>
|
||||||
|
<!-- #enddocregion class-override -->
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<h2>Style binding</h2>
|
||||||
|
|
||||||
|
<!-- #docregion style-binding-->
|
||||||
|
<button [style.color]="isSpecial ? 'red': 'green'">Red</button>
|
||||||
|
<button [style.background-color]="canSave ? 'cyan': 'grey'" >Save</button>
|
||||||
|
<!-- #enddocregion style-binding -->
|
||||||
|
|
||||||
|
<!-- #docregion style-binding-condition-->
|
||||||
|
<button [style.font-size.em]="isSpecial ? 3 : 1" >Big</button>
|
||||||
|
<button [style.font-size.%]="!isSpecial ? 150 : 50" >Small</button>
|
||||||
|
<!-- #enddocregion style-binding-condition-->
|
@ -8,23 +8,20 @@ describe('AppComponent', () => {
|
|||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should create the app', async(() => {
|
it('should create the app', async(() => {
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
const app = fixture.debugElement.componentInstance;
|
const app = fixture.debugElement.componentInstance;
|
||||||
expect(app).toBeTruthy();
|
expect(app).toBeTruthy();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it(`should have as title 'app'`, async(() => {
|
it(`should have as title 'app'`, async(() => {
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
const app = fixture.debugElement.componentInstance;
|
const app = fixture.debugElement.componentInstance;
|
||||||
expect(app.title).toMatch(/app/i);
|
expect(app.title).toEqual('app');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should render title in a h1 tag', async(() => {
|
it('should render title in a h1 tag', async(() => {
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const compiled = fixture.debugElement.nativeElement;
|
const compiled = fixture.debugElement.nativeElement;
|
||||||
expect(compiled.querySelector('h1').textContent).toMatch(/app/i);
|
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
|
||||||
}));
|
}));
|
||||||
});
|
});
|
@ -0,0 +1,15 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styleUrls: ['./app.component.css']
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
actionName = 'Go for it';
|
||||||
|
isSpecial = true;
|
||||||
|
itemClearance = true;
|
||||||
|
resetClasses = 'new-class';
|
||||||
|
canSave = true;
|
||||||
|
|
||||||
|
}
|
@ -1,8 +1,10 @@
|
|||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
|
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent
|
AppComponent
|
14
aio/content/examples/attribute-binding/src/index.html
Normal file
14
aio/content/examples/attribute-binding/src/index.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>AttributeBinding</title>
|
||||||
|
<base href="/">
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<app-root></app-root>
|
||||||
|
</body>
|
||||||
|
</html>
|
12
aio/content/examples/attribute-binding/src/main.ts
Normal file
12
aio/content/examples/attribute-binding/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/attribute-binding/stackblitz.json
Normal file
10
aio/content/examples/attribute-binding/stackblitz.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"description": "Attribute Binding",
|
||||||
|
"files": [
|
||||||
|
"!**/*.d.ts",
|
||||||
|
"!**/*.js",
|
||||||
|
"!**/*.[1,2].*"
|
||||||
|
],
|
||||||
|
"file": "src/app/app.component.ts",
|
||||||
|
"tags": ["Attribute Binding"]
|
||||||
|
}
|
76
aio/content/examples/binding-syntax/e2e/src/app.e2e-spec.ts
Normal file
76
aio/content/examples/binding-syntax/e2e/src/app.e2e-spec.ts
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
import { browser, element, by } from 'protractor';
|
||||||
|
import { logging } from 'selenium-webdriver';
|
||||||
|
|
||||||
|
describe('Binding syntax e2e tests', () => {
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// helper function used to test what's logged to the console
|
||||||
|
async function logChecker(button, contents) {
|
||||||
|
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
|
||||||
|
const message = logs.filter(({ message }) => message.indexOf(contents) !== -1 ? true : false);
|
||||||
|
expect(message.length).toBeGreaterThan(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
it('should display Binding syntax', function () {
|
||||||
|
expect(element(by.css('h1')).getText()).toEqual('Binding syntax');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display Save button', function () {
|
||||||
|
expect(element.all(by.css('button')).get(0).getText()).toBe('Save');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display HTML attributes and DOM properties', function () {
|
||||||
|
expect(element.all(by.css('h2')).get(1).getText()).toBe('HTML attributes and DOM properties');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display 1. Use the inspector...', function () {
|
||||||
|
expect(element.all(by.css('p')).get(0).getText()).toContain('1. Use the inspector');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display Disabled property vs. attribute', function () {
|
||||||
|
expect(element.all(by.css('h3')).get(0).getText()).toBe('Disabled property vs. attribute');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should log a message including Sarah', async () => {
|
||||||
|
let attributeButton = element.all(by.css('button')).get(1);
|
||||||
|
await attributeButton.click();
|
||||||
|
const contents = 'Sarah';
|
||||||
|
logChecker(attributeButton, contents);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should log a message including Sarah for DOM property', async () => {
|
||||||
|
let DOMPropertyButton = element.all(by.css('button')).get(2);
|
||||||
|
await DOMPropertyButton.click();
|
||||||
|
const contents = 'Sarah';
|
||||||
|
logChecker(DOMPropertyButton, contents);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should log a message including Sally for DOM property', async () => {
|
||||||
|
let DOMPropertyButton = element.all(by.css('button')).get(2);
|
||||||
|
let input = element(by.css('input'));
|
||||||
|
input.sendKeys('Sally');
|
||||||
|
await DOMPropertyButton.click();
|
||||||
|
const contents = 'Sally';
|
||||||
|
logChecker(DOMPropertyButton, contents);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should log a message that Test Button works', async () => {
|
||||||
|
let testButton = element.all(by.css('button')).get(3);
|
||||||
|
await testButton.click();
|
||||||
|
const contents = 'Test';
|
||||||
|
logChecker(testButton, contents);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should toggle Test Button disabled', async () => {
|
||||||
|
let toggleButton = element.all(by.css('button')).get(4);
|
||||||
|
await toggleButton.click();
|
||||||
|
const contents = 'true';
|
||||||
|
logChecker(toggleButton, contents);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,3 @@
|
|||||||
|
div {
|
||||||
|
padding: .25rem 0;
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
|
||||||
|
<div>
|
||||||
|
<h1>Binding syntax</h1>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h2>Button disabled state bound to isUnchanged property</h2>
|
||||||
|
<!-- #docregion disabled-button -->
|
||||||
|
<!-- Bind button disabled state to `isUnchanged` property -->
|
||||||
|
<button [disabled]="isUnchanged">Save</button>
|
||||||
|
<!-- #enddocregion disabled-button -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div (keyup)="0">
|
||||||
|
<h2>HTML attributes and DOM properties</h2>
|
||||||
|
<p>1. Use the inspector to see the HTML attribute and DOM property values. Click the buttons to log values to the console.</p>
|
||||||
|
|
||||||
|
<label>HTML Attribute Initializes to "Sarah":
|
||||||
|
<input type="text" value="Sarah" #bindingInput></label>
|
||||||
|
<div>
|
||||||
|
<button (click)="getHTMLAttributeValue()">Get HTML attribute value</button> Won't change.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button (click)="getDOMPropertyValue()">Get DOM property value</button> Changeable. Angular works with these.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>2. Change the name in the input and click the buttons again.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3>Disabled property vs. attribute</h3>
|
||||||
|
<p>Use the inspector to see the Test Button work and its disabled property toggle.</p>
|
||||||
|
<div>
|
||||||
|
<button id="testButton" (click)="working()">Test Button</button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button (click)="toggleDisabled()">Toggle disabled property for Test Button</button>
|
||||||
|
</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 'app'`, async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.debugElement.componentInstance;
|
||||||
|
expect(app.title).toEqual('app');
|
||||||
|
}));
|
||||||
|
it('should render title in a h1 tag', async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
const compiled = fixture.debugElement.nativeElement;
|
||||||
|
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
|
||||||
|
}));
|
||||||
|
});
|
33
aio/content/examples/binding-syntax/src/app/app.component.ts
Normal file
33
aio/content/examples/binding-syntax/src/app/app.component.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { Component, ViewChild, ElementRef } from '@angular/core';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styleUrls: ['./app.component.css']
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
|
||||||
|
@ViewChild('bindingInput', { static: false }) bindingInput: ElementRef;
|
||||||
|
|
||||||
|
isUnchanged = true;
|
||||||
|
|
||||||
|
getHTMLAttributeValue(): any {
|
||||||
|
console.warn('HTML attribute value: ' + this.bindingInput.nativeElement.getAttribute('value'));
|
||||||
|
}
|
||||||
|
|
||||||
|
getDOMPropertyValue(): any {
|
||||||
|
console.warn('DOM property value: ' + this.bindingInput.nativeElement.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
working(): any {
|
||||||
|
console.warn('Test Button works!');
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleDisabled(): any {
|
||||||
|
|
||||||
|
let testButton = <HTMLInputElement> document.getElementById('testButton');
|
||||||
|
testButton.disabled = !testButton.disabled;
|
||||||
|
console.warn(testButton.disabled);
|
||||||
|
}
|
||||||
|
}
|
18
aio/content/examples/binding-syntax/src/app/app.module.ts
Normal file
18
aio/content/examples/binding-syntax/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 { }
|
14
aio/content/examples/binding-syntax/src/index.html
Normal file
14
aio/content/examples/binding-syntax/src/index.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<!-- #docregion -->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<base href="/">
|
||||||
|
<title>Angular binding syntax example</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<app-root>Loading...</app-root>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
<!-- #enddocregion -->
|
12
aio/content/examples/binding-syntax/src/main.ts
Normal file
12
aio/content/examples/binding-syntax/src/main.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// #docregion
|
||||||
|
import { enableProdMode } from '@angular/core';
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
|
||||||
|
import { AppModule } from './app/app.module';
|
||||||
|
import { environment } from './environments/environment';
|
||||||
|
|
||||||
|
if (environment.production) {
|
||||||
|
enableProdMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
platformBrowserDynamic().bootstrapModule(AppModule);
|
10
aio/content/examples/binding-syntax/stackblitz.json
Normal file
10
aio/content/examples/binding-syntax/stackblitz.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"description": "Binding Syntax",
|
||||||
|
"files": [
|
||||||
|
"!**/*.d.ts",
|
||||||
|
"!**/*.js",
|
||||||
|
"!**/*.[1,2].*"
|
||||||
|
],
|
||||||
|
"file": "src/app/app.component.ts",
|
||||||
|
"tags": ["Binding Syntax"]
|
||||||
|
}
|
@ -9,6 +9,6 @@ describe('feature-modules App', () => {
|
|||||||
|
|
||||||
it('should display message saying app works', () => {
|
it('should display message saying app works', () => {
|
||||||
page.navigateTo();
|
page.navigateTo();
|
||||||
expect(page.getParagraphText()).toEqual('app works!');
|
expect(page.getTitleText()).toEqual('app works!');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
|
describe('Built-in Directives', function () {
|
||||||
|
|
||||||
|
beforeAll(function () {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have title Built-in Directives', function () {
|
||||||
|
let title = element.all(by.css('h1')).get(0);
|
||||||
|
expect(title.getText()).toEqual('Built-in Directives');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should change first Teapot header', async () => {
|
||||||
|
let firstLabel = element.all(by.css('p')).get(0);
|
||||||
|
let firstInput = element.all(by.css('input')).get(0);
|
||||||
|
|
||||||
|
expect(firstLabel.getText()).toEqual('Current item name: Teapot');
|
||||||
|
firstInput.sendKeys('abc');
|
||||||
|
expect(firstLabel.getText()).toEqual('Current item name: Teapotabc');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should modify sentence when modified checkbox checked', function () {
|
||||||
|
let modifiedChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(1);
|
||||||
|
let modifiedSentence = element.all(by.css('div')).get(1);
|
||||||
|
|
||||||
|
modifiedChkbxLabel.click();
|
||||||
|
expect(modifiedSentence.getText()).toContain('modified');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should modify sentence when normal checkbox checked', function () {
|
||||||
|
let normalChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(4);
|
||||||
|
let normalSentence = element.all(by.css('div')).get(7);
|
||||||
|
|
||||||
|
normalChkbxLabel.click();
|
||||||
|
expect(normalSentence.getText()).toContain('normal weight and, extra large');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should toggle app-item-detail', function () {
|
||||||
|
let toggleButton = element.all(by.css('button')).get(3);
|
||||||
|
let toggledDiv = element.all(by.css('app-item-detail')).get(0);
|
||||||
|
|
||||||
|
toggleButton.click();
|
||||||
|
expect(toggledDiv.isDisplayed()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should hide app-item-detail', function () {
|
||||||
|
let hiddenMessage = element.all(by.css('p')).get(11);
|
||||||
|
let hiddenDiv = element.all(by.css('app-item-detail')).get(2);
|
||||||
|
|
||||||
|
expect(hiddenMessage.getText()).toContain('in the DOM');
|
||||||
|
expect(hiddenDiv.isDisplayed()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have 10 lists each containing the string Teapot', function () {
|
||||||
|
let listDiv = element.all(by.cssContainingText('.box', 'Teapot'));
|
||||||
|
expect(listDiv.count()).toBe(10);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should switch case', function () {
|
||||||
|
let tvRadioButton = element.all(by.css('input[type="radio"]')).get(3);
|
||||||
|
let tvDiv = element(by.css('app-lost-item'));
|
||||||
|
|
||||||
|
let fishbowlRadioButton = element.all(by.css('input[type="radio"]')).get(4);
|
||||||
|
let fishbowlDiv = element(by.css('app-unknown-item'));
|
||||||
|
|
||||||
|
tvRadioButton.click();
|
||||||
|
expect(tvDiv.getText()).toContain('Television');
|
||||||
|
fishbowlRadioButton.click();
|
||||||
|
expect(fishbowlDiv.getText()).toContain('mysterious');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,75 @@
|
|||||||
|
|
||||||
|
button {
|
||||||
|
font-size: 100%;
|
||||||
|
margin: 0 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div[ng-reflect-ng-switch], app-unknown-item {
|
||||||
|
margin: .5rem 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#noTrackByCnt,
|
||||||
|
#withTrackByCnt {
|
||||||
|
color: darkred;
|
||||||
|
max-width: 450px;
|
||||||
|
margin: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box {
|
||||||
|
border: 1px solid black;
|
||||||
|
padding: 6px;
|
||||||
|
max-width: 450px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.child-div {
|
||||||
|
margin-left: 1em;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.context {
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parent-div {
|
||||||
|
margin-top: 1em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.course {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: x-large;
|
||||||
|
}
|
||||||
|
|
||||||
|
.helpful {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.saveable {
|
||||||
|
color: limegreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
.study,
|
||||||
|
.modified {
|
||||||
|
font-family: "Brush Script MT";
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toe {
|
||||||
|
margin-left: 1em;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.to-toc {
|
||||||
|
margin-top: 10px;
|
||||||
|
display: block;
|
||||||
|
}
|
@ -0,0 +1,253 @@
|
|||||||
|
<h1>Built-in Directives</h1>
|
||||||
|
|
||||||
|
<h2>Built-in attribute directives</h2>
|
||||||
|
|
||||||
|
<h3 id="ngModel">NgModel (two-way) Binding</h3>
|
||||||
|
|
||||||
|
<fieldset><h4>NgModel examples</h4>
|
||||||
|
<p>Current item name: {{currentItem.name}}</p>
|
||||||
|
<p>
|
||||||
|
<!-- #docregion without-NgModel -->
|
||||||
|
<label for="without">without NgModel:</label>
|
||||||
|
<input [value]="currentItem.name" (input)="currentItem.name=$event.target.value" id="without">
|
||||||
|
<!-- #enddocregion without-NgModel -->
|
||||||
|
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<!-- #docregion NgModel-1 -->
|
||||||
|
<label for="example-ngModel">[(ngModel)]:</label>
|
||||||
|
<input [(ngModel)]="currentItem.name" id="example-ngModel">
|
||||||
|
<!-- #enddocregion NgModel-1 -->
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<label for="example-bindon">bindon-ngModel: </label>
|
||||||
|
<input bindon-ngModel="currentItem.name" id="example-bindon">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<!-- #docregion NgModelChange -->
|
||||||
|
<label for="example-change">(ngModelChange)="...name=$event":</label>
|
||||||
|
<input [ngModel]="currentItem.name" (ngModelChange)="currentItem.name=$event" id="example-change">
|
||||||
|
<!-- #enddocregion NgModelChange -->
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<label for="example-uppercase">(ngModelChange)="setUppercaseName($event)"
|
||||||
|
<!-- #docregion uppercase -->
|
||||||
|
<input [ngModel]="currentItem.name" (ngModelChange)="setUppercaseName($event)" id="example-uppercase">
|
||||||
|
<!-- #enddocregion uppercase -->
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<hr><h2 id="ngClass">NgClass Binding</h2>
|
||||||
|
|
||||||
|
<p>currentClasses is {{currentClasses | json}}</p>
|
||||||
|
<!-- #docregion NgClass-1 -->
|
||||||
|
<div [ngClass]="currentClasses">This div is initially saveable, unchanged, and special.</div>
|
||||||
|
<!-- #enddocregion NgClass-1 -->
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<label for="saveable">saveable</label>
|
||||||
|
<input type="checkbox" [(ngModel)]="canSave" id="saveable">
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label for="modified">modified:</label>
|
||||||
|
<input type="checkbox" [value]="!isUnchanged" (change)="isUnchanged=!isUnchanged" id="modified"></li>
|
||||||
|
<li>
|
||||||
|
<label for="special">special: <input type="checkbox" [(ngModel)]="isSpecial" id="special"></label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<button (click)="setCurrentClasses()">Refresh currentClasses</button>
|
||||||
|
|
||||||
|
<div [ngClass]="currentClasses">
|
||||||
|
This div should be {{ canSave ? "": "not"}} saveable,
|
||||||
|
{{ isUnchanged ? "unchanged" : "modified" }} and
|
||||||
|
{{ isSpecial ? "": "not"}} special after clicking "Refresh".</div>
|
||||||
|
<br><br>
|
||||||
|
<!-- #docregion special-div -->
|
||||||
|
<!-- toggle the "special" class on/off with a property -->
|
||||||
|
<div [ngClass]="isSpecial ? 'special' : ''">This div is special</div>
|
||||||
|
<!-- #enddocregion special-div -->
|
||||||
|
<div class="helpful study course">Helpful study course</div>
|
||||||
|
<div [ngClass]="{'helpful':false, 'study':true, 'course':true}">Study course</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- NgStyle binding -->
|
||||||
|
<hr><h3>NgStyle Binding</h3>
|
||||||
|
<!-- #docregion without-ng-style -->
|
||||||
|
<div [style.font-size]="isSpecial ? 'x-large' : 'smaller'">
|
||||||
|
This div is x-large or smaller.
|
||||||
|
</div>
|
||||||
|
<!-- #enddocregion without-ng-style -->
|
||||||
|
|
||||||
|
|
||||||
|
<h4>[ngStyle] binding to currentStyles - CSS property names</h4>
|
||||||
|
<p>currentStyles is {{currentStyles | json}}</p>
|
||||||
|
|
||||||
|
<!-- #docregion NgStyle-2 -->
|
||||||
|
<div [ngStyle]="currentStyles">
|
||||||
|
This div is initially italic, normal weight, and extra large (24px).
|
||||||
|
</div>
|
||||||
|
<!-- #enddocregion NgStyle-2 -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<label>italic: <input type="checkbox" [(ngModel)]="canSave"></label> |
|
||||||
|
<label>normal: <input type="checkbox" [(ngModel)]="isUnchanged"></label> |
|
||||||
|
<label>xlarge: <input type="checkbox" [(ngModel)]="isSpecial"></label>
|
||||||
|
<button (click)="setCurrentStyles()">Refresh currentStyles</button>
|
||||||
|
<br><br>
|
||||||
|
<div [ngStyle]="currentStyles">
|
||||||
|
This div should be {{ canSave ? "italic": "plain"}},
|
||||||
|
{{ isUnchanged ? "normal weight" : "bold" }} and,
|
||||||
|
{{ isSpecial ? "extra large": "normal size"}} after clicking "Refresh".</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2>Built-in structural directives</h2>
|
||||||
|
<h3 id="ngIf">NgIf Binding</h3>
|
||||||
|
<div>
|
||||||
|
<p>If isActive is true, app-item-detail will render: </p>
|
||||||
|
<!-- #docregion NgIf-1 -->
|
||||||
|
<app-item-detail *ngIf="isActive" [item]="item"></app-item-detail>
|
||||||
|
<!-- #enddocregion NgIf-1 -->
|
||||||
|
|
||||||
|
<button (click)="isActiveToggle()">Toggle app-item-detail</button>
|
||||||
|
</div>
|
||||||
|
<p>If currentCustomer isn't null, say hello to Laura:</p>
|
||||||
|
<!-- #docregion NgIf-2 -->
|
||||||
|
<div *ngIf="currentCustomer">Hello, {{currentCustomer.name}}</div>
|
||||||
|
<!-- #enddocregion NgIf-2 -->
|
||||||
|
<p>nullCustomer is null by default. NgIf guards against null. Give it a value to show it:</p>
|
||||||
|
<!-- #docregion NgIf-2b -->
|
||||||
|
<div *ngIf="nullCustomer">Hello, <span>{{nullCustomer}}</span></div>
|
||||||
|
<!-- #enddocregion NgIf-2b -->
|
||||||
|
<button (click)="giveNullCustomerValue()">Give nullCustomer a value</button>
|
||||||
|
|
||||||
|
|
||||||
|
<h4>NgIf binding with template (no *)</h4>
|
||||||
|
|
||||||
|
<ng-template [ngIf]="currentItem">Add {{currentItem.name}} with template</ng-template>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h4>Show/hide vs. NgIf</h4>
|
||||||
|
<!-- #docregion NgIf-3 -->
|
||||||
|
<!-- isSpecial is true -->
|
||||||
|
<div [class.hidden]="!isSpecial">Show with class</div>
|
||||||
|
<div [class.hidden]="isSpecial">Hide with class</div>
|
||||||
|
|
||||||
|
<p>ItemDetail is in the DOM but hidden</p>
|
||||||
|
<app-item-detail [class.hidden]="isSpecial"></app-item-detail>
|
||||||
|
|
||||||
|
<div [style.display]="isSpecial ? 'block' : 'none'">Show with style</div>
|
||||||
|
<div [style.display]="isSpecial ? 'none' : 'block'">Hide with style</div>
|
||||||
|
<!-- #enddocregion NgIf-3 -->
|
||||||
|
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2 id="ngFor">NgFor Binding</h2>
|
||||||
|
|
||||||
|
<div class="box">
|
||||||
|
<!-- #docregion NgFor-1, NgFor-1-2 -->
|
||||||
|
<div *ngFor="let item of items">{{item.name}}</div>
|
||||||
|
<!-- #enddocregion NgFor-1, NgFor-1-2 -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>*ngFor with ItemDetailComponent element</p>
|
||||||
|
<div class="box">
|
||||||
|
<!-- #docregion NgFor-2, NgFor-1-2 -->
|
||||||
|
<app-item-detail *ngFor="let item of items" [item]="item"></app-item-detail>
|
||||||
|
<!-- #enddocregion NgFor-2, NgFor-1-2 -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<h4 id="ngFor-index">*ngFor with index</h4>
|
||||||
|
<p>with <i>semi-colon</i> separator</p>
|
||||||
|
<div class="box">
|
||||||
|
<!-- #docregion NgFor-3 -->
|
||||||
|
<div *ngFor="let item of items; let i=index">{{i + 1}} - {{item.name}}</div>
|
||||||
|
<!-- #enddocregion NgFor-3 -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>with <i>comma</i> separator</p>
|
||||||
|
<div class="box">
|
||||||
|
<div *ngFor="let item of items, let i=index">{{i + 1}} - {{item.name}}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h4 id="ngFor-trackBy">*ngFor trackBy</h4>
|
||||||
|
<button (click)="resetList()">Reset items</button>
|
||||||
|
<button (click)="changeIds()">Change ids</button>
|
||||||
|
<button (click)="clearTrackByCounts()">Clear counts</button>
|
||||||
|
|
||||||
|
<p><i>without</i> trackBy</p>
|
||||||
|
<div class="box">
|
||||||
|
<div #noTrackBy *ngFor="let item of items">({{item.id}}) {{item.name}}</div>
|
||||||
|
|
||||||
|
<div id="noTrackByCnt" *ngIf="itemsNoTrackByCount" >
|
||||||
|
Item DOM elements change #{{itemsNoTrackByCount}} without trackBy
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>with trackBy</p>
|
||||||
|
<div class="box">
|
||||||
|
<div #withTrackBy *ngFor="let item of items; trackBy: trackByItems">({{item.id}}) {{item.name}}</div>
|
||||||
|
|
||||||
|
<div id="withTrackByCnt" *ngIf="itemsWithTrackByCount">
|
||||||
|
Item DOM elements change #{{itemsWithTrackByCount}} with trackBy
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br><br><br>
|
||||||
|
|
||||||
|
<p>with trackBy and <i>semi-colon</i> separator</p>
|
||||||
|
<div class="box">
|
||||||
|
<!-- #docregion trackBy -->
|
||||||
|
<div *ngFor="let item of items; trackBy: trackByItems">
|
||||||
|
({{item.id}}) {{item.name}}
|
||||||
|
</div>
|
||||||
|
<!-- #enddocregion trackBy -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>with trackBy and <i>comma</i> separator</p>
|
||||||
|
<div class="box">
|
||||||
|
<div *ngFor="let item of items, trackBy: trackByItems">({{item.id}}) {{item.name}}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>with trackBy and <i>space</i> separator</p>
|
||||||
|
<div class="box">
|
||||||
|
<div *ngFor="let item of items trackBy: trackByItems">({{item.id}}) {{item.name}}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>with <i>generic</i> trackById function</p>
|
||||||
|
<div class="box">
|
||||||
|
<div *ngFor="let item of items, trackBy: trackById">({{item.id}}) {{item.name}}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr><h2>NgSwitch Binding</h2>
|
||||||
|
|
||||||
|
<p>Pick your favorite item</p>
|
||||||
|
<div>
|
||||||
|
<label *ngFor="let i of items">
|
||||||
|
<div><input type="radio" name="items" [(ngModel)]="currentItem" [value]="i">{{i.name}}
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- #docregion NgSwitch -->
|
||||||
|
<div [ngSwitch]="currentItem.feature">
|
||||||
|
<app-stout-item *ngSwitchCase="'stout'" [item]="currentItem"></app-stout-item>
|
||||||
|
<app-device-item *ngSwitchCase="'slim'" [item]="currentItem"></app-device-item>
|
||||||
|
<app-lost-item *ngSwitchCase="'vintage'" [item]="currentItem"></app-lost-item>
|
||||||
|
<app-best-item *ngSwitchCase="'bright'" [item]="currentItem"></app-best-item>
|
||||||
|
<!-- #enddocregion NgSwitch -->
|
||||||
|
<!-- #docregion NgSwitch-div -->
|
||||||
|
<div *ngSwitchCase="'bright'"> Are you as bright as {{currentItem.name}}?</div>
|
||||||
|
<!-- #enddocregion NgSwitch-div -->
|
||||||
|
<!-- #docregion NgSwitch -->
|
||||||
|
<app-unknown-item *ngSwitchDefault [item]="currentItem"></app-unknown-item>
|
||||||
|
</div>
|
||||||
|
<!-- #enddocregion NgSwitch -->
|
||||||
|
|
@ -0,0 +1,115 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { Item } from './item';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styleUrls: ['./app.component.css']
|
||||||
|
})
|
||||||
|
export class AppComponent implements OnInit {
|
||||||
|
|
||||||
|
canSave = true;
|
||||||
|
isSpecial = true;
|
||||||
|
isUnchanged = true;
|
||||||
|
|
||||||
|
isActive = true;
|
||||||
|
nullCustomer = null;
|
||||||
|
currentCustomer = {
|
||||||
|
name: 'Laura'
|
||||||
|
};
|
||||||
|
|
||||||
|
item: Item; // defined to demonstrate template context precedence
|
||||||
|
items: Item[];
|
||||||
|
|
||||||
|
currentItem: Item;
|
||||||
|
|
||||||
|
|
||||||
|
// trackBy change counting
|
||||||
|
itemsNoTrackByCount = 0;
|
||||||
|
itemsWithTrackByCount = 0;
|
||||||
|
itemsWithTrackByCountReset = 0;
|
||||||
|
itemIdIncrement = 1;
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.resetItems();
|
||||||
|
this.setCurrentClasses();
|
||||||
|
this.setCurrentStyles();
|
||||||
|
this.itemsNoTrackByCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
setUppercaseName(name: string) {
|
||||||
|
this.currentItem.name = name.toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #docregion setClasses
|
||||||
|
currentClasses: {};
|
||||||
|
setCurrentClasses() {
|
||||||
|
// CSS classes: added/removed per current state of component properties
|
||||||
|
this.currentClasses = {
|
||||||
|
'saveable': this.canSave,
|
||||||
|
'modified': !this.isUnchanged,
|
||||||
|
'special': this.isSpecial
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// #enddocregion setClasses
|
||||||
|
|
||||||
|
// #docregion setStyles
|
||||||
|
currentStyles: {};
|
||||||
|
setCurrentStyles() {
|
||||||
|
// CSS styles: set per current state of component properties
|
||||||
|
this.currentStyles = {
|
||||||
|
'font-style': this.canSave ? 'italic' : 'normal',
|
||||||
|
'font-weight': !this.isUnchanged ? 'bold' : 'normal',
|
||||||
|
'font-size': this.isSpecial ? '24px' : '12px'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// #enddocregion setStyles
|
||||||
|
|
||||||
|
isActiveToggle() {
|
||||||
|
this.isActive = !this.isActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
giveNullCustomerValue() {
|
||||||
|
!(this.nullCustomer = null) ? (this.nullCustomer = 'Kelly') : (this.nullCustomer = null);
|
||||||
|
}
|
||||||
|
|
||||||
|
resetNullItem() {
|
||||||
|
this.nullCustomer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetItems() {
|
||||||
|
this.items = Item.items.map(item => item.clone());
|
||||||
|
this.currentItem = this.items[0];
|
||||||
|
this.item = this.currentItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetList() {
|
||||||
|
this.resetItems()
|
||||||
|
this.itemsWithTrackByCountReset = 0;
|
||||||
|
this.itemsNoTrackByCount = ++this.itemsNoTrackByCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
changeIds() {
|
||||||
|
|
||||||
|
this.items.forEach(i => i.id += 1 * this.itemIdIncrement);
|
||||||
|
this.itemsWithTrackByCountReset = -1;
|
||||||
|
this.itemsNoTrackByCount = ++this.itemsNoTrackByCount;
|
||||||
|
this.itemsWithTrackByCount = ++this.itemsWithTrackByCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearTrackByCounts() {
|
||||||
|
this.resetItems();
|
||||||
|
this.itemsNoTrackByCount = 0;
|
||||||
|
this.itemsWithTrackByCount = 0;
|
||||||
|
this.itemIdIncrement = 1;
|
||||||
|
}
|
||||||
|
// #docregion trackByItems
|
||||||
|
trackByItems(index: number, item: Item): number { return item.id; }
|
||||||
|
// #enddocregion trackByItems
|
||||||
|
|
||||||
|
trackById(index: number, item: any): number { return item['id']; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
|||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
// #docregion import-forms-module
|
||||||
|
import { FormsModule } from '@angular/forms'; // <--- JavaScript import from Angular
|
||||||
|
// #enddocregion import-forms-module
|
||||||
|
|
||||||
|
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
import { ItemDetailComponent } from './item-detail/item-detail.component';
|
||||||
|
import { ItemSwitchComponents } from './item-switch.component';
|
||||||
|
|
||||||
|
|
||||||
|
// #docregion import-forms-module
|
||||||
|
@NgModule({
|
||||||
|
// #enddocregion import-forms-module
|
||||||
|
declarations: [
|
||||||
|
AppComponent,
|
||||||
|
ItemDetailComponent,
|
||||||
|
ItemSwitchComponents
|
||||||
|
],
|
||||||
|
// #docregion import-forms-module
|
||||||
|
|
||||||
|
imports: [
|
||||||
|
BrowserModule,
|
||||||
|
FormsModule // <--- import into the NgModule
|
||||||
|
],
|
||||||
|
// #enddocregion import-forms-module
|
||||||
|
providers: [],
|
||||||
|
bootstrap: [AppComponent]
|
||||||
|
// #docregion import-forms-module
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
||||||
|
// #enddocregion import-forms-module
|
||||||
|
|
@ -0,0 +1,3 @@
|
|||||||
|
<div>
|
||||||
|
<span>{{item?.name}}</span>
|
||||||
|
</div>
|
@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ItemDetailComponent } from './item-detail.component';
|
||||||
|
|
||||||
|
describe('ItemDetailComponent', () => {
|
||||||
|
let component: ItemDetailComponent;
|
||||||
|
let fixture: ComponentFixture<ItemDetailComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ ItemDetailComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ItemDetailComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,17 @@
|
|||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
|
||||||
|
import { Item } from '../item';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-item-detail',
|
||||||
|
templateUrl: './item-detail.component.html',
|
||||||
|
styleUrls: ['./item-detail.component.css']
|
||||||
|
})
|
||||||
|
export class ItemDetailComponent {
|
||||||
|
|
||||||
|
|
||||||
|
@Input() item: Item;
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
import { Item } from './item';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-stout-item',
|
||||||
|
template: `I'm a little {{item.name}}, short and stout!`
|
||||||
|
})
|
||||||
|
export class StoutItemComponent {
|
||||||
|
@Input() item: Item;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-best-item',
|
||||||
|
template: `This is the brightest {{item.name}} in town.`
|
||||||
|
})
|
||||||
|
export class BestItemComponent {
|
||||||
|
@Input() item: Item;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-device-item',
|
||||||
|
template: `Which is the slimmest {{item.name}}?`
|
||||||
|
})
|
||||||
|
export class DeviceItemComponent {
|
||||||
|
@Input() item: Item;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-lost-item',
|
||||||
|
template: `Has anyone seen my {{item.name}}?`
|
||||||
|
})
|
||||||
|
export class LostItemComponent {
|
||||||
|
@Input() item: Item;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-unknown-item',
|
||||||
|
template: `{{message}}`
|
||||||
|
})
|
||||||
|
export class UnknownItemComponent {
|
||||||
|
@Input() item: Item;
|
||||||
|
get message() {
|
||||||
|
return this.item && this.item.name ?
|
||||||
|
`${this.item.name} is strange and mysterious.` :
|
||||||
|
'A mystery wrapped in a fishbowl.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ItemSwitchComponents =
|
||||||
|
[ StoutItemComponent, BestItemComponent, DeviceItemComponent, LostItemComponent, UnknownItemComponent ];
|
30
aio/content/examples/built-in-directives/src/app/item.ts
Normal file
30
aio/content/examples/built-in-directives/src/app/item.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
export class Item {
|
||||||
|
static nextId = 0;
|
||||||
|
|
||||||
|
static items: Item[] = [
|
||||||
|
new Item(
|
||||||
|
null,
|
||||||
|
'Teapot',
|
||||||
|
'stout'
|
||||||
|
),
|
||||||
|
new Item(1, 'Lamp', 'bright'),
|
||||||
|
new Item(2, 'Phone', 'slim' ),
|
||||||
|
new Item(3, 'Television', 'vintage' ),
|
||||||
|
new Item(4, 'Fishbowl')
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public id?: number,
|
||||||
|
public name?: string,
|
||||||
|
public feature?: string,
|
||||||
|
public url?: string,
|
||||||
|
public rate = 100,
|
||||||
|
) {
|
||||||
|
this.id = id ? id : Item.nextId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
clone(): Item {
|
||||||
|
return Object.assign(new Item(), this);
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 32 KiB |
14
aio/content/examples/built-in-directives/src/index.html
Normal file
14
aio/content/examples/built-in-directives/src/index.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>BuiltInDirectives</title>
|
||||||
|
<base href="/">
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<app-root></app-root>
|
||||||
|
</body>
|
||||||
|
</html>
|
12
aio/content/examples/built-in-directives/src/main.ts
Normal file
12
aio/content/examples/built-in-directives/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/built-in-directives/stackblitz.json
Normal file
10
aio/content/examples/built-in-directives/stackblitz.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"description": "Built-in Directives",
|
||||||
|
"files": [
|
||||||
|
"!**/*.d.ts",
|
||||||
|
"!**/*.js",
|
||||||
|
"!**/*.[1,2].*"
|
||||||
|
],
|
||||||
|
"file": "src/app/app.component.ts",
|
||||||
|
"tags": ["Built-in Directives"]
|
||||||
|
}
|
@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"open": false,
|
|
||||||
"logLevel": "silent",
|
|
||||||
"port": 8080,
|
|
||||||
"server": {
|
|
||||||
"baseDir": "dist",
|
|
||||||
"middleware": {
|
|
||||||
"0": null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
'use strict'; // necessary for es6 output in node
|
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
|
||||||
|
|
||||||
describe('cli-quickstart App', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
return browser.get('/');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display message saying app works', () => {
|
|
||||||
let pageTitle = element(by.css('app-root h1')).getText();
|
|
||||||
expect(pageTitle).toEqual('Welcome to My First Angular App!!');
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"build": "build:cli",
|
|
||||||
"run": "serve:cli"
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
/* #docregion */
|
|
||||||
h1 {
|
|
||||||
color: #369;
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
font-size: 250%;
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
<!--The content below is only a placeholder and can be replaced.-->
|
|
||||||
<div style="text-align:center">
|
|
||||||
<h1>
|
|
||||||
Welcome to {{ title }}!
|
|
||||||
</h1>
|
|
||||||
<img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
|
|
||||||
</div>
|
|
||||||
<h2>Here are some links to help you start: </h2>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
@ -1,16 +0,0 @@
|
|||||||
// #docregion import
|
|
||||||
import { Component } from '@angular/core';
|
|
||||||
// #enddocregion import
|
|
||||||
|
|
||||||
// #docregion metadata, component
|
|
||||||
@Component({
|
|
||||||
selector: 'app-root',
|
|
||||||
templateUrl: './app.component.html',
|
|
||||||
styleUrls: ['./app.component.css']
|
|
||||||
})
|
|
||||||
// #enddocregion metadata
|
|
||||||
// #docregion title, class
|
|
||||||
export class AppComponent {
|
|
||||||
title = 'My First Angular App!';
|
|
||||||
}
|
|
||||||
// #enddocregion title, class, component
|
|
@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"files":[
|
|
||||||
"!**/*.d.ts",
|
|
||||||
"!**/*.js",
|
|
||||||
"!**/*.[0-9].*",
|
|
||||||
"angular.json",
|
|
||||||
"protractor.conf.js"
|
|
||||||
]
|
|
||||||
}
|
|
@ -13,7 +13,7 @@ describe('Component Communication Cookbook Tests', function () {
|
|||||||
describe('Parent-to-child communication', function() {
|
describe('Parent-to-child communication', function() {
|
||||||
// #docregion parent-to-child
|
// #docregion parent-to-child
|
||||||
// ...
|
// ...
|
||||||
let _heroNames = ['Mr. IQ', 'Magneta', 'Bombasto'];
|
let _heroNames = ['Dr IQ', 'Magneta', 'Bombasto'];
|
||||||
let _masterName = 'Master';
|
let _masterName = 'Master';
|
||||||
|
|
||||||
it('should pass properties to children properly', function () {
|
it('should pass properties to children properly', function () {
|
||||||
@ -36,7 +36,7 @@ describe('Component Communication Cookbook Tests', function () {
|
|||||||
// ...
|
// ...
|
||||||
it('should display trimmed, non-empty names', function () {
|
it('should display trimmed, non-empty names', function () {
|
||||||
let _nonEmptyNameIndex = 0;
|
let _nonEmptyNameIndex = 0;
|
||||||
let _nonEmptyName = '"Mr. IQ"';
|
let _nonEmptyName = '"Dr IQ"';
|
||||||
let parent = element.all(by.tagName('app-name-parent')).get(0);
|
let parent = element.all(by.tagName('app-name-parent')).get(0);
|
||||||
let hero = parent.all(by.tagName('app-name-child')).get(_nonEmptyNameIndex);
|
let hero = parent.all(by.tagName('app-name-child')).get(_nonEmptyNameIndex);
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ export class CountdownLocalVarParentComponent { }
|
|||||||
})
|
})
|
||||||
export class CountdownViewChildParentComponent implements AfterViewInit {
|
export class CountdownViewChildParentComponent implements AfterViewInit {
|
||||||
|
|
||||||
@ViewChild(CountdownTimerComponent)
|
@ViewChild(CountdownTimerComponent, {static: false})
|
||||||
private timerComponent: CountdownTimerComponent;
|
private timerComponent: CountdownTimerComponent;
|
||||||
|
|
||||||
seconds() { return 0; }
|
seconds() { return 0; }
|
||||||
|
@ -3,7 +3,7 @@ export class Hero {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const HEROES = [
|
export const HEROES = [
|
||||||
{name: 'Mr. IQ'},
|
{name: 'Dr IQ'},
|
||||||
{name: 'Magneta'},
|
{name: 'Magneta'},
|
||||||
{name: 'Bombasto'}
|
{name: 'Bombasto'}
|
||||||
];
|
];
|
||||||
|
@ -9,7 +9,7 @@ import { Component } from '@angular/core';
|
|||||||
`
|
`
|
||||||
})
|
})
|
||||||
export class NameParentComponent {
|
export class NameParentComponent {
|
||||||
// Displays 'Mr. IQ', '<no name set>', 'Bombasto'
|
// Displays 'Dr IQ', '<no name set>', 'Bombasto'
|
||||||
names = ['Mr. IQ', ' ', ' Bombasto '];
|
names = ['Dr IQ', ' ', ' Bombasto '];
|
||||||
}
|
}
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
@ -15,7 +15,7 @@ import { Component } from '@angular/core';
|
|||||||
export class VoteTakerComponent {
|
export class VoteTakerComponent {
|
||||||
agreed = 0;
|
agreed = 0;
|
||||||
disagreed = 0;
|
disagreed = 0;
|
||||||
voters = ['Mr. IQ', 'Ms. Universe', 'Bombasto'];
|
voters = ['Narco', 'Celeritas', 'Bombasto'];
|
||||||
|
|
||||||
onVoted(agreed: boolean) {
|
onVoted(agreed: boolean) {
|
||||||
agreed ? this.agreed++ : this.disagreed++;
|
agreed ? this.agreed++ : this.disagreed++;
|
||||||
|
@ -23,8 +23,8 @@ describe('Dependency Injection Cookbook', function () {
|
|||||||
expect(sortedHeroes).toBeDefined();
|
expect(sortedHeroes).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Mr. Nice should be in sorted heroes', function () {
|
it('Dr Nice should be in sorted heroes', function () {
|
||||||
let sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Mr. Nice" and position()=2]')).get(0);
|
let sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Dr Nice" and position()=2]')).get(0);
|
||||||
expect(sortedHero).toBeDefined();
|
expect(sortedHero).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ describe('Dependency Injection Cookbook', function () {
|
|||||||
|
|
||||||
it('should render Hero-of-the-Month runner-ups', function () {
|
it('should render Hero-of-the-Month runner-ups', function () {
|
||||||
let runnersUp = element(by.id('rups1')).getText();
|
let runnersUp = element(by.id('rups1')).getText();
|
||||||
expect(runnersUp).toContain('RubberMan, Mr. Nice');
|
expect(runnersUp).toContain('RubberMan, Dr Nice');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render DateLogger log entry in Hero-of-the-Month', function () {
|
it('should render DateLogger log entry in Hero-of-the-Month', function () {
|
||||||
|
@ -11,7 +11,7 @@ export class HeroService {
|
|||||||
private heroes: Array<Hero> = [
|
private heroes: Array<Hero> = [
|
||||||
new Hero(1, 'RubberMan', 'Hero of many talents', '123-456-7899'),
|
new Hero(1, 'RubberMan', 'Hero of many talents', '123-456-7899'),
|
||||||
new Hero(2, 'Magma', 'Hero of all trades', '555-555-5555'),
|
new Hero(2, 'Magma', 'Hero of all trades', '555-555-5555'),
|
||||||
new Hero(3, 'Mr. Nice', 'The name says it all', '111-222-3333')
|
new Hero(3, 'Dr Nice', 'The name says it all', '111-222-3333')
|
||||||
];
|
];
|
||||||
|
|
||||||
getHeroById(id: number): Hero {
|
getHeroById(id: number): Hero {
|
||||||
|
@ -29,10 +29,10 @@ export class StorageComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setSession() {
|
setSession() {
|
||||||
this.sessionStorageService.set('hero', 'Mr. Nice - Session');
|
this.sessionStorageService.set('hero', 'Dr Nice - Session');
|
||||||
}
|
}
|
||||||
|
|
||||||
setLocal() {
|
setLocal() {
|
||||||
this.localStorageService.set('hero', 'Mr. Nice - Local');
|
this.localStorageService.set('hero', 'Dr Nice - Local');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ describe('Dependency Injection Tests', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Hero displays as expected', function () {
|
it('Hero displays as expected', function () {
|
||||||
expectedMsg = 'Mr. Nice';
|
expectedMsg = 'Dr Nice';
|
||||||
expect(element(by.css('#hero')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#hero')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { Hero } from './hero';
|
import { Hero } from './hero';
|
||||||
|
|
||||||
export const HEROES: Hero[] = [
|
export const HEROES: Hero[] = [
|
||||||
{ id: 11, isSecret: false, name: 'Mr. Nice' },
|
{ id: 11, isSecret: false, name: 'Dr Nice' },
|
||||||
{ id: 12, isSecret: false, name: 'Narco' },
|
{ id: 12, isSecret: false, name: 'Narco' },
|
||||||
{ id: 13, isSecret: false, name: 'Bombasto' },
|
{ id: 13, isSecret: false, name: 'Bombasto' },
|
||||||
{ id: 14, isSecret: false, name: 'Celeritas' },
|
{ id: 14, isSecret: false, name: 'Celeritas' },
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-ctor',
|
selector: 'app-root',
|
||||||
template: `
|
template: `
|
||||||
<h1>{{title}} [Ctor version]</h1>
|
<h1>{{title}} [Ctor version]</h1>
|
||||||
<h2>My favorite hero is: {{myHero}}</h2>
|
<h2>My favorite hero is: {{myHero}}</h2>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
// #docregion class
|
// #docregion class
|
||||||
export class AppCtorComponent {
|
export class AppComponent {
|
||||||
title: string;
|
title: string;
|
||||||
myHero: string;
|
myHero: string;
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ export class Hero {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const HEROES: Hero[] = [
|
export const HEROES: Hero[] = [
|
||||||
{ id: 11, name: 'Mr. Nice' },
|
{ id: 11, name: 'Dr Nice' },
|
||||||
{ id: 12, name: 'Narco' },
|
{ id: 12, name: 'Narco' },
|
||||||
{ id: 13, name: 'Bombasto' },
|
{ id: 13, name: 'Bombasto' },
|
||||||
{ id: 14, name: 'Celeritas' }
|
{ id: 14, name: 'Celeritas' }
|
||||||
|
@ -20,7 +20,7 @@ import { AdComponent } from './ad.component';
|
|||||||
export class AdBannerComponent implements OnInit, OnDestroy {
|
export class AdBannerComponent implements OnInit, OnDestroy {
|
||||||
@Input() ads: AdItem[];
|
@Input() ads: AdItem[];
|
||||||
currentAdIndex = -1;
|
currentAdIndex = -1;
|
||||||
@ViewChild(AdDirective) adHost: AdDirective;
|
@ViewChild(AdDirective, {static: true}) adHost: AdDirective;
|
||||||
interval: any;
|
interval: any;
|
||||||
|
|
||||||
constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
|
constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
|
||||||
@ -36,14 +36,14 @@ export class AdBannerComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
loadComponent() {
|
loadComponent() {
|
||||||
this.currentAdIndex = (this.currentAdIndex + 1) % this.ads.length;
|
this.currentAdIndex = (this.currentAdIndex + 1) % this.ads.length;
|
||||||
let adItem = this.ads[this.currentAdIndex];
|
const adItem = this.ads[this.currentAdIndex];
|
||||||
|
|
||||||
let componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component);
|
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component);
|
||||||
|
|
||||||
let viewContainerRef = this.adHost.viewContainerRef;
|
const viewContainerRef = this.adHost.viewContainerRef;
|
||||||
viewContainerRef.clear();
|
viewContainerRef.clear();
|
||||||
|
|
||||||
let componentRef = viewContainerRef.createComponent(componentFactory);
|
const componentRef = viewContainerRef.createComponent(componentFactory);
|
||||||
(<AdComponent>componentRef.instance).data = adItem.data;
|
(<AdComponent>componentRef.instance).data = adItem.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"projectType": "elements"
|
|
||||||
}
|
|
||||||
|
@ -21,7 +21,7 @@ export class ItemDetailComponent {
|
|||||||
@Output() deleteRequest = new EventEmitter<Item>();
|
@Output() deleteRequest = new EventEmitter<Item>();
|
||||||
|
|
||||||
delete() {
|
delete() {
|
||||||
this.deleteRequest.emit(this.item.name);
|
this.deleteRequest.emit(this.item);
|
||||||
this.displayNone = this.displayNone ? '' : 'none';
|
this.displayNone = this.displayNone ? '' : 'none';
|
||||||
this.lineThrough = this.lineThrough ? '' : 'line-through';
|
this.lineThrough = this.lineThrough ? '' : 'line-through';
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ describe('feature-modules App', () => {
|
|||||||
|
|
||||||
it('should display message saying app works', () => {
|
it('should display message saying app works', () => {
|
||||||
page.navigateTo();
|
page.navigateTo();
|
||||||
expect(page.getParagraphText()).toEqual('app works!');
|
expect(page.getTitleText()).toEqual('app works!');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<!-- #docregion prices -->
|
<!-- #docregion prices -->
|
||||||
|
|
||||||
<div class="cart-item" *ngFor="let item of items">
|
<div class="cart-item" *ngFor="let item of items">
|
||||||
<span>{{ item.name }} </span>
|
<span>{{ item.name }}</span>
|
||||||
<span>{{ item.price | currency }}</span>
|
<span>{{ item.price | currency }}</span>
|
||||||
</div>
|
</div>
|
||||||
<!-- #enddocregion prices -->
|
<!-- #enddocregion prices -->
|
@ -1,6 +1,6 @@
|
|||||||
<h3>Shipping Prices</h3>
|
<h3>Shipping Prices</h3>
|
||||||
|
|
||||||
<div class="shipping-item" *ngFor="let shipping of shippingCosts | async">
|
<div class="shipping-item" *ngFor="let shipping of shippingCosts | async">
|
||||||
<span>{{ shipping.type }} </span>
|
<span>{{ shipping.type }}</span>
|
||||||
<span>{{ shipping.price | currency }}</span>
|
<span>{{ shipping.price | currency }}</span>
|
||||||
</div>
|
</div>
|
@ -16,7 +16,9 @@ export class ShippingComponent {
|
|||||||
// #enddocregion props
|
// #enddocregion props
|
||||||
|
|
||||||
// #docregion inject-cart-service
|
// #docregion inject-cart-service
|
||||||
constructor(private cartService: CartService) {
|
constructor(
|
||||||
|
private cartService: CartService
|
||||||
|
) {
|
||||||
// #enddocregion inject-cart-service
|
// #enddocregion inject-cart-service
|
||||||
this.shippingCosts = this.cartService.getShippingPrices();
|
this.shippingCosts = this.cartService.getShippingPrices();
|
||||||
// #docregion inject-cart-service
|
// #docregion inject-cart-service
|
||||||
|
29
aio/content/examples/getting-started/tsconfig.0.json
Normal file
29
aio/content/examples/getting-started/tsconfig.0.json
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// This tsconfig is used in the TypeScript
|
||||||
|
// configuration guide (../guide/typescript-configuration.md)
|
||||||
|
// to display the latest default configuration
|
||||||
|
// Note: Update with every major release to the latest default
|
||||||
|
// #docregion
|
||||||
|
{
|
||||||
|
"compileOnSave": false,
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "./",
|
||||||
|
"outDir": "./dist/out-tsc",
|
||||||
|
"sourceMap": true,
|
||||||
|
"declaration": false,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"importHelpers": true,
|
||||||
|
"target": "es2015",
|
||||||
|
"typeRoots": [
|
||||||
|
"node_modules/@types"
|
||||||
|
],
|
||||||
|
// #docregion lib
|
||||||
|
"lib": [
|
||||||
|
"es2018",
|
||||||
|
"dom"
|
||||||
|
]
|
||||||
|
// #enddocregion lib
|
||||||
|
}
|
||||||
|
}
|
@ -36,7 +36,7 @@ describe('Http Tests', function() {
|
|||||||
describe('Heroes', () => {
|
describe('Heroes', () => {
|
||||||
it('retrieves the list of heroes at startup', () => {
|
it('retrieves the list of heroes at startup', () => {
|
||||||
expect(page.heroesListItems.count()).toBe(4);
|
expect(page.heroesListItems.count()).toBe(4);
|
||||||
expect(page.heroesListItems.get(0).getText()).toContain('Mr. Nice');
|
expect(page.heroesListItems.get(0).getText()).toContain('Dr Nice');
|
||||||
checkLogForMessage('GET "api/heroes"');
|
checkLogForMessage('GET "api/heroes"');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -6,14 +6,14 @@ import { HeroesService } from './heroes.service';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-heroes',
|
selector: 'app-heroes',
|
||||||
templateUrl: './heroes.component.html',
|
templateUrl: './heroes.component.html',
|
||||||
providers: [ HeroesService ],
|
providers: [HeroesService],
|
||||||
styleUrls: ['./heroes.component.css']
|
styleUrls: ['./heroes.component.css']
|
||||||
})
|
})
|
||||||
export class HeroesComponent implements OnInit {
|
export class HeroesComponent implements OnInit {
|
||||||
heroes: Hero[];
|
heroes: Hero[];
|
||||||
editHero: Hero; // the hero currently being edited
|
editHero: Hero; // the hero currently being edited
|
||||||
|
|
||||||
constructor(private heroesService: HeroesService) { }
|
constructor(private heroesService: HeroesService) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.getHeroes();
|
this.getHeroes();
|
||||||
@ -21,18 +21,21 @@ export class HeroesComponent implements OnInit {
|
|||||||
|
|
||||||
getHeroes(): void {
|
getHeroes(): void {
|
||||||
this.heroesService.getHeroes()
|
this.heroesService.getHeroes()
|
||||||
.subscribe(heroes => this.heroes = heroes);
|
.subscribe(heroes => (this.heroes = heroes));
|
||||||
}
|
}
|
||||||
|
|
||||||
add(name: string): void {
|
add(name: string): void {
|
||||||
this.editHero = undefined;
|
this.editHero = undefined;
|
||||||
name = name.trim();
|
name = name.trim();
|
||||||
if (!name) { return; }
|
if (!name) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// The server will generate the id for this new hero
|
// The server will generate the id for this new hero
|
||||||
const newHero: Hero = { name } as Hero;
|
const newHero: Hero = { name } as Hero;
|
||||||
// #docregion add-hero-subscribe
|
// #docregion add-hero-subscribe
|
||||||
this.heroesService.addHero(newHero)
|
this.heroesService
|
||||||
|
.addHero(newHero)
|
||||||
.subscribe(hero => this.heroes.push(hero));
|
.subscribe(hero => this.heroes.push(hero));
|
||||||
// #enddocregion add-hero-subscribe
|
// #enddocregion add-hero-subscribe
|
||||||
}
|
}
|
||||||
@ -40,7 +43,9 @@ export class HeroesComponent implements OnInit {
|
|||||||
delete(hero: Hero): void {
|
delete(hero: Hero): void {
|
||||||
this.heroes = this.heroes.filter(h => h !== hero);
|
this.heroes = this.heroes.filter(h => h !== hero);
|
||||||
// #docregion delete-hero-subscribe
|
// #docregion delete-hero-subscribe
|
||||||
this.heroesService.deleteHero(hero.id).subscribe();
|
this.heroesService
|
||||||
|
.deleteHero(hero.id)
|
||||||
|
.subscribe();
|
||||||
// #enddocregion delete-hero-subscribe
|
// #enddocregion delete-hero-subscribe
|
||||||
/*
|
/*
|
||||||
// #docregion delete-hero-no-subscribe
|
// #docregion delete-hero-no-subscribe
|
||||||
@ -50,25 +55,29 @@ export class HeroesComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
edit(hero) {
|
edit(hero: Hero) {
|
||||||
this.editHero = hero;
|
this.editHero = hero;
|
||||||
}
|
}
|
||||||
|
|
||||||
search(searchTerm: string) {
|
search(searchTerm: string) {
|
||||||
this.editHero = undefined;
|
this.editHero = undefined;
|
||||||
if (searchTerm) {
|
if (searchTerm) {
|
||||||
this.heroesService.searchHeroes(searchTerm)
|
this.heroesService
|
||||||
.subscribe(heroes => this.heroes = heroes);
|
.searchHeroes(searchTerm)
|
||||||
|
.subscribe(heroes => (this.heroes = heroes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
if (this.editHero) {
|
if (this.editHero) {
|
||||||
this.heroesService.updateHero(this.editHero)
|
this.heroesService
|
||||||
|
.updateHero(this.editHero)
|
||||||
.subscribe(hero => {
|
.subscribe(hero => {
|
||||||
// replace the hero in the heroes list with update from server
|
// replace the hero in the heroes list with update from server
|
||||||
const ix = hero ? this.heroes.findIndex(h => h.id === hero.id) : -1;
|
const ix = hero ? this.heroes.findIndex(h => h.id === hero.id) : -1;
|
||||||
if (ix > -1) { this.heroes[ix] = hero; }
|
if (ix > -1) {
|
||||||
|
this.heroes[ix] = hero;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this.editHero = undefined;
|
this.editHero = undefined;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ import { InMemoryDbService } from 'angular-in-memory-web-api';
|
|||||||
export class InMemoryDataService implements InMemoryDbService {
|
export class InMemoryDataService implements InMemoryDbService {
|
||||||
createDb() {
|
createDb() {
|
||||||
const heroes = [
|
const heroes = [
|
||||||
{ id: 11, name: 'Mr. Nice' },
|
{ id: 11, name: 'Dr Nice' },
|
||||||
{ id: 12, name: 'Narco' },
|
{ id: 12, name: 'Narco' },
|
||||||
{ id: 13, name: 'Bombasto' },
|
{ id: 13, name: 'Bombasto' },
|
||||||
{ id: 14, name: 'Celeritas' },
|
{ id: 14, name: 'Celeritas' },
|
||||||
|
@ -48,7 +48,7 @@ export class PackageSearchService {
|
|||||||
// TODO: Add error handling
|
// TODO: Add error handling
|
||||||
return this.http.get(searchUrl, options).pipe(
|
return this.http.get(searchUrl, options).pipe(
|
||||||
map((data: any) => {
|
map((data: any) => {
|
||||||
return data.results.map(entry => ({
|
return data.results.map((entry: any) => ({
|
||||||
name: entry.name[0],
|
name: entry.name[0],
|
||||||
version: entry.version[0],
|
version: entry.version[0],
|
||||||
description: entry.description[0]
|
description: entry.description[0]
|
||||||
|
70
aio/content/examples/inputs-outputs/e2e/src/app.e2e-spec.ts
Normal file
70
aio/content/examples/inputs-outputs/e2e/src/app.e2e-spec.ts
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
import { browser, element, by } from 'protractor';
|
||||||
|
import { logging } from 'selenium-webdriver';
|
||||||
|
|
||||||
|
describe('Inputs and Outputs', function () {
|
||||||
|
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// helper function used to test what's logged to the console
|
||||||
|
async function logChecker(button, contents) {
|
||||||
|
const logs = await browser
|
||||||
|
.manage()
|
||||||
|
.logs()
|
||||||
|
.get(logging.Type.BROWSER);
|
||||||
|
const message = logs.filter(({ message }) =>
|
||||||
|
message.indexOf(contents) !== -1 ? true : false
|
||||||
|
);
|
||||||
|
console.log(message);
|
||||||
|
expect(message.length).toBeGreaterThan(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should have title Inputs and Outputs', function () {
|
||||||
|
let title = element.all(by.css('h1')).get(0);
|
||||||
|
expect(title.getText()).toEqual('Inputs and Outputs');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add 123 to the parent list', async () => {
|
||||||
|
let addToParentButton = element.all(by.css('button')).get(0);
|
||||||
|
let addToListInput = element.all(by.css('input')).get(0);
|
||||||
|
let addedItem = element.all(by.css('li')).get(4);
|
||||||
|
await addToListInput.sendKeys('123');
|
||||||
|
await addToParentButton.click();
|
||||||
|
expect(addedItem.getText()).toEqual('123');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should delete item', async () => {
|
||||||
|
let deleteButton = element.all(by.css('button')).get(1);
|
||||||
|
const contents = 'Child';
|
||||||
|
await deleteButton.click();
|
||||||
|
await logChecker(deleteButton, contents);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should log buy the item', async () => {
|
||||||
|
let buyButton = element.all(by.css('button')).get(2);
|
||||||
|
const contents = 'Child';
|
||||||
|
await buyButton.click();
|
||||||
|
await logChecker(buyButton, contents);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should save item for later', async () => {
|
||||||
|
let saveButton = element.all(by.css('button')).get(3);
|
||||||
|
const contents = 'Child';
|
||||||
|
await saveButton.click();
|
||||||
|
await logChecker(saveButton, contents);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add item to wishlist', async () => {
|
||||||
|
let addToParentButton = element.all(by.css('button')).get(4);
|
||||||
|
let addedItem = element.all(by.css('li')).get(6);
|
||||||
|
await addToParentButton.click();
|
||||||
|
expect(addedItem.getText()).toEqual('Television');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,7 @@
|
|||||||
|
<p>Save for later item: {{input1}}</p>
|
||||||
|
<button (click)="saveIt()"> Save for later</button>
|
||||||
|
|
||||||
|
|
||||||
|
<p>Item for wishlist: {{input2}}</p>
|
||||||
|
<button (click)="wishForIt()"> Add to wishlist</button>
|
||||||
|
|
@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { AliasingComponent } from './aliasing.component';
|
||||||
|
|
||||||
|
describe('AliasingComponent', () => {
|
||||||
|
let component: AliasingComponent;
|
||||||
|
let fixture: ComponentFixture<AliasingComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ AliasingComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(AliasingComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,46 @@
|
|||||||
|
/* tslint:disable:use-input-property-decorator */
|
||||||
|
/* tslint:disable:use-output-property-decorator */
|
||||||
|
|
||||||
|
/* tslint:disable:no-input-rename */
|
||||||
|
|
||||||
|
|
||||||
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-aliasing',
|
||||||
|
templateUrl: './aliasing.component.html',
|
||||||
|
styleUrls: ['./aliasing.component.css'],
|
||||||
|
// #docregion alias
|
||||||
|
// tslint:disable: no-inputs-metadata-property no-outputs-metadata-property
|
||||||
|
inputs: ['input1: saveForLaterItem'], // propertyName:alias
|
||||||
|
outputs: ['outputEvent1: saveForLaterEvent']
|
||||||
|
// tslint:disable: no-inputs-metadata-property no-outputs-metadata-property
|
||||||
|
// #enddocregion alias
|
||||||
|
|
||||||
|
})
|
||||||
|
export class AliasingComponent {
|
||||||
|
|
||||||
|
input1: string;
|
||||||
|
outputEvent1: EventEmitter<string> = new EventEmitter<string>();
|
||||||
|
|
||||||
|
// #docregion alias-input-output
|
||||||
|
@Input('wishListItem') input2: string; // @Input(alias)
|
||||||
|
@Output('wishEvent') outputEvent2 = new EventEmitter<string>(); // @Output(alias) propertyName = ...
|
||||||
|
// #enddocregion alias-input-output
|
||||||
|
|
||||||
|
|
||||||
|
saveIt() {
|
||||||
|
console.warn('Child says: emiting outputEvent1 with', this.input1);
|
||||||
|
this.outputEvent1.emit(this.input1);
|
||||||
|
}
|
||||||
|
|
||||||
|
wishForIt() {
|
||||||
|
console.warn('Child says: emiting outputEvent2', this.input2);
|
||||||
|
this.outputEvent2.emit(this.input2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/* tslint:enable:use-input-property-decorator */
|
||||||
|
/* tslint:enable:use-output-property-decorator */
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user