Compare commits
35 Commits
Author | SHA1 | Date | |
---|---|---|---|
1033a0285b | |||
376c5fceb5 | |||
48a7581e1e | |||
d0c32e03b9 | |||
a57ea2640a | |||
4ea54a777f | |||
0fe6110b97 | |||
ffe705066f | |||
0ac6406f00 | |||
57ffb41a70 | |||
c60edabd70 | |||
b3b8e102c0 | |||
87c449a085 | |||
52d47b4696 | |||
917933bb9e | |||
80ccd6c19b | |||
b7e3d80879 | |||
4bbf60ed01 | |||
299a43c7f8 | |||
c92fe6f6fb | |||
c8875f2dbb | |||
3ca56a6d5c | |||
7223f60060 | |||
8b034188bd | |||
579f1295ac | |||
2914b10eba | |||
c00544ac51 | |||
a9038ef13c | |||
b0c345324a | |||
26efc682d5 | |||
8b6128759c | |||
54c171cded | |||
642f6046af | |||
d0e213d137 | |||
7418c901c2 |
31
.bazelrc
31
.bazelrc
@ -1,3 +1,12 @@
|
|||||||
|
###############################
|
||||||
|
# Typescript / Angular / Sass #
|
||||||
|
###############################
|
||||||
|
|
||||||
|
# Make compilation fast, by keeping a few copies of the compilers
|
||||||
|
# running as daemons, and cache SourceFile AST's to reduce parse time.
|
||||||
|
build --strategy=AngularTemplateCompile=worker
|
||||||
|
build --strategy=TypeScriptCompile=worker
|
||||||
|
|
||||||
# Enable debugging tests with --config=debug
|
# Enable debugging tests with --config=debug
|
||||||
test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test_strategy=exclusive --test_timeout=9999 --nocache_test_results
|
test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test_strategy=exclusive --test_timeout=9999 --nocache_test_results
|
||||||
|
|
||||||
@ -36,6 +45,22 @@ build --incompatible_strict_action_env
|
|||||||
run --incompatible_strict_action_env
|
run --incompatible_strict_action_env
|
||||||
test --incompatible_strict_action_env
|
test --incompatible_strict_action_env
|
||||||
|
|
||||||
|
###############################
|
||||||
|
# Saucelabs support #
|
||||||
|
# Turn on these settings with #
|
||||||
|
# --config=saucelabs #
|
||||||
|
###############################
|
||||||
|
|
||||||
|
# Expose SauceLabs environment to actions
|
||||||
|
# These environment variables are needed by
|
||||||
|
# web_test_karma to run on Saucelabs
|
||||||
|
test:saucelabs --action_env=SAUCE_USERNAME
|
||||||
|
test:saucelabs --action_env=SAUCE_ACCESS_KEY
|
||||||
|
test:saucelabs --action_env=SAUCE_READY_FILE
|
||||||
|
test:saucelabs --action_env=SAUCE_PID_FILE
|
||||||
|
test:saucelabs --action_env=SAUCE_TUNNEL_IDENTIFIER
|
||||||
|
test:saucelabs --define=KARMA_WEB_TEST_MODE=SL_REQUIRED
|
||||||
|
|
||||||
###############################
|
###############################
|
||||||
# Release support #
|
# Release support #
|
||||||
# Turn on these settings with #
|
# Turn on these settings with #
|
||||||
@ -58,6 +83,12 @@ query --output=label_kind
|
|||||||
# By default, failing tests don't print any output, it goes to the log file
|
# By default, failing tests don't print any output, it goes to the log file
|
||||||
test --test_output=errors
|
test --test_output=errors
|
||||||
|
|
||||||
|
# Show which actions are run under workers,
|
||||||
|
# and print all the actions running in parallel.
|
||||||
|
# Helps to demonstrate that bazel uses all the cores on the machine.
|
||||||
|
build --experimental_ui
|
||||||
|
test --experimental_ui
|
||||||
|
|
||||||
################################
|
################################
|
||||||
# Settings for CircleCI #
|
# Settings for CircleCI #
|
||||||
################################
|
################################
|
||||||
|
@ -28,14 +28,3 @@ test --flaky_test_attempts=2
|
|||||||
|
|
||||||
# More details on failures
|
# More details on failures
|
||||||
build --verbose_failures=true
|
build --verbose_failures=true
|
||||||
|
|
||||||
# We have seen some flakiness in using TS workers on CircleCI
|
|
||||||
# https://angular-team.slack.com/archives/C07DT5M6V/p1562693245183400
|
|
||||||
# > failures like `ERROR: /home/circleci/ng/packages/core/test/BUILD.bazel:5:1:
|
|
||||||
# > Compiling TypeScript (devmode) //packages/core/test:test_lib failed: Worker process did not return a WorkResponse:`
|
|
||||||
# > I saw that issue a couple times today.
|
|
||||||
# > Example job: https://circleci.com/gh/angular/angular/385517
|
|
||||||
# We expect that TypeScript compilations will parallelize wider than the number of local cores anyway
|
|
||||||
# so we should saturate remote workers with TS compilations
|
|
||||||
build --strategy=AngularTemplateCompile=local
|
|
||||||
build --strategy=TypeScriptCompile=local
|
|
||||||
|
@ -58,7 +58,17 @@ var_5: &setup_bazel_remote_execution
|
|||||||
# cause decryption failures based on the openssl version. https://stackoverflow.com/a/39641378/4317734
|
# 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
|
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
|
||||||
./.circleci/setup-rbe.sh .bazelrc.user
|
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
|
||||||
@ -141,11 +151,6 @@ var_14: ¬ify_dev_infra_on_fail
|
|||||||
notificationJson="{\"text\":\":x: \`$CIRCLE_JOB\` job for $CIRCLE_BRANCH branch failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}"
|
notificationJson="{\"text\":\":x: \`$CIRCLE_JOB\` job for $CIRCLE_BRANCH branch failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}"
|
||||||
curl --request POST --header "Content-Type: application/json" --data "$notificationJson" $SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
curl --request POST --header "Content-Type: application/json" --data "$notificationJson" $SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
||||||
|
|
||||||
# Cache key for the Material unit tests job. **Note** when updating the SHA in the cache keys,
|
|
||||||
# also update the SHA for the "MATERIAL_REPO_COMMIT" environment variable.
|
|
||||||
var_15: &material_unit_tests_cache_key v4-angular-material-18b9ef3f5529f0fa8f034944681486447af7b879
|
|
||||||
var_16: &material_unit_tests_cache_key_short v4-angular-material
|
|
||||||
|
|
||||||
version: 2
|
version: 2
|
||||||
jobs:
|
jobs:
|
||||||
setup:
|
setup:
|
||||||
@ -198,6 +203,13 @@ jobs:
|
|||||||
# 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
|
||||||
|
- run: mkdir ~/testlogs
|
||||||
|
- run: cp -Lr dist/testlogs/* ~/testlogs
|
||||||
|
- store_test_results:
|
||||||
|
# Bazel always writes test.xml files under this directory
|
||||||
|
path: ~/testlogs
|
||||||
|
- store_artifacts:
|
||||||
|
path: ~/testlogs
|
||||||
|
|
||||||
# Temporary job to test what will happen when we flip the Ivy flag to true
|
# Temporary job to test what will happen when we flip the Ivy flag to true
|
||||||
test_ivy_aot:
|
test_ivy_aot:
|
||||||
@ -233,11 +245,6 @@ jobs:
|
|||||||
path: dist/bin/packages/core/test/bundling/todo/bundle.min.js.br
|
path: dist/bin/packages/core/test/bundling/todo/bundle.min.js.br
|
||||||
destination: core/todo/bundle.br
|
destination: core/todo/bundle.br
|
||||||
|
|
||||||
# This job is currently a PoC for running tests on SauceLabs via bazel. It runs a subset of the
|
|
||||||
# tests in `legacy-unit-tests-saucelabs` (see
|
|
||||||
# [BUILD.bazel](https://github.com/angular/angular/blob/ef44f51d5/BUILD.bazel#L66-L92)).
|
|
||||||
#
|
|
||||||
# NOTE: This is currently limited to master builds only. See the `default_workflow` configuration.
|
|
||||||
test_saucelabs_bazel:
|
test_saucelabs_bazel:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
||||||
@ -249,19 +256,23 @@ jobs:
|
|||||||
- *init_environment
|
- *init_environment
|
||||||
- *setup_circleci_bazel_config
|
- *setup_circleci_bazel_config
|
||||||
- run:
|
- run:
|
||||||
name: Run Bazel tests in saucelabs
|
name: Preparing environment for running tests on Saucelabs.
|
||||||
# All web tests are contained within a single //:test_web_all target for Saucelabs
|
command: setSecretVar SAUCE_ACCESS_KEY $(echo $SAUCE_ACCESS_KEY | rev)
|
||||||
# as running each set of tests as a separate target will attempt to acquire too
|
- run:
|
||||||
# many browsers on Saucelabs (7 per target currently) and some tests will always
|
name: Starting Saucelabs tunnel
|
||||||
# fail to acquire browsers. For example:
|
command: ./scripts/saucelabs/start-tunnel.sh
|
||||||
# 14 02 2019 19:52:33.170:WARN [launcher]: chrome beta on SauceLabs have not captured in 180000 ms, killing.
|
background: true
|
||||||
# //packages/forms/test:web_test_sauce TIMEOUT in 315.0s
|
# Waits for the Saucelabs tunnel to be ready. This ensures that we don't run tests
|
||||||
command: |
|
# too early without Saucelabs not being ready.
|
||||||
./scripts/saucelabs/run-bazel-via-tunnel.sh \
|
- run: ./scripts/saucelabs/wait-for-tunnel.sh
|
||||||
--tunnel-id angular-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_INDEX} \
|
# All web tests are contained within a single //:test_web_all target for Saucelabs
|
||||||
--username $SAUCE_USERNAME \
|
# as running each set of tests as a separate target will attempt to acquire too
|
||||||
--key $(echo $SAUCE_ACCESS_KEY | rev) \
|
# many browsers on Saucelabs (7 per target currently) and some tests will always
|
||||||
yarn bazel test //:test_web_all
|
# fail to acquire browsers. For example:
|
||||||
|
# 14 02 2019 19:52:33.170:WARN [launcher]: chrome beta on SauceLabs have not captured in 180000 ms, killing.
|
||||||
|
# //packages/forms/test:web_test_sauce TIMEOUT in 315.0s
|
||||||
|
- run: yarn bazel test --config=saucelabs //:test_web_all
|
||||||
|
- run: ./scripts/saucelabs/stop-tunnel.sh
|
||||||
- *notify_dev_infra_on_fail
|
- *notify_dev_infra_on_fail
|
||||||
|
|
||||||
test_aio:
|
test_aio:
|
||||||
@ -282,8 +293,6 @@ jobs:
|
|||||||
- run: yarn --cwd aio e2e --configuration=ci
|
- run: yarn --cwd aio e2e --configuration=ci
|
||||||
# Run PWA-score tests
|
# Run PWA-score tests
|
||||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||||
# Run accessibility tests
|
|
||||||
- run: yarn --cwd aio test-a11y-score-localhost
|
|
||||||
# Check the bundle sizes.
|
# Check the bundle sizes.
|
||||||
- run: yarn --cwd aio payload-size
|
- run: yarn --cwd aio payload-size
|
||||||
# Run unit tests for Firebase redirects
|
# Run unit tests for Firebase redirects
|
||||||
@ -310,7 +319,7 @@ jobs:
|
|||||||
- *attach_workspace
|
- *attach_workspace
|
||||||
- *init_environment
|
- *init_environment
|
||||||
# Build aio (with local Angular packages)
|
# Build aio (with local Angular packages)
|
||||||
- run: yarn --cwd aio build-local-ci
|
- run: yarn --cwd aio build-local --progress=false
|
||||||
# Run unit tests
|
# Run unit tests
|
||||||
- run: yarn --cwd aio test --progress=false --watch=false
|
- run: yarn --cwd aio test --progress=false --watch=false
|
||||||
# Run e2e tests
|
# Run e2e tests
|
||||||
@ -329,7 +338,7 @@ jobs:
|
|||||||
- *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-ci
|
- run: yarn --cwd aio build-with-ivy --progress=false
|
||||||
# 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
|
||||||
@ -609,36 +618,40 @@ jobs:
|
|||||||
resource_class: xlarge
|
resource_class: xlarge
|
||||||
docker:
|
docker:
|
||||||
- image: *browsers_docker_image
|
- image: *browsers_docker_image
|
||||||
|
# The Material unit tests support splitting the browsers across multiple CircleCI
|
||||||
|
# instances. Since by default this job launches two browsers, we run each browser
|
||||||
|
# in its own container instance.
|
||||||
|
# https://github.com/angular/material2/blob/7baeaa797b19da2d2998f0d26f6fede3c8a13714/test/karma.conf.js#L107-L110
|
||||||
|
parallelism: 2
|
||||||
|
environment:
|
||||||
|
# The Material unit tests also support launching the same browser multiple times by
|
||||||
|
# sharding individual specs across the defined multiple instances.
|
||||||
|
# See: https://github.com/angular/material2/blob/7baeaa797b19da2d2998f0d26f6fede3c8a13714/test/karma.conf.js#L113-L116
|
||||||
|
KARMA_PARALLEL_BROWSERS: 3
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- *attach_workspace
|
||||||
- *init_environment
|
- *init_environment
|
||||||
# Although RBE is configured below for the Material repo, also setup RBE in the Angular repo
|
|
||||||
# to provision Angular's GCP token into the environment variables.
|
|
||||||
- *setup_bazel_remote_execution
|
|
||||||
# Restore the cache before cloning the repository because the clone script re-uses
|
|
||||||
# the restored repository if present. This reduces the amount of times the components
|
|
||||||
# repository needs to be cloned (this is slow and increases based on commits in the repo).
|
|
||||||
- restore_cache:
|
|
||||||
keys:
|
|
||||||
- *material_unit_tests_cache_key
|
|
||||||
- *material_unit_tests_cache_key_short
|
|
||||||
- run:
|
- run:
|
||||||
name: "Fetching Material repository"
|
name: "Cloning Material repository"
|
||||||
command: ./scripts/ci/clone_angular_material_repo.sh
|
command: ./scripts/ci/clone_angular_material_repo.sh
|
||||||
|
- restore_cache:
|
||||||
|
# Material directory must be kept in sync with the `$MATERIAL_REPO_TMP_DIR` env variable.
|
||||||
|
# It needs to be hardcoded here, because env variables interpolation is not supported.
|
||||||
|
keys:
|
||||||
|
- v2-angular-material-{{ checksum "/tmp/material2/yarn.lock" }}
|
||||||
|
- v2-angular-material-
|
||||||
- run:
|
- run:
|
||||||
# Run yarn install to fetch the Bazel binaries as used in the Material repo.
|
|
||||||
name: Installing Material dependencies.
|
name: Installing Material dependencies.
|
||||||
command: yarn --cwd ${MATERIAL_REPO_TMP_DIR} install --frozen-lockfile --non-interactive
|
command: yarn --cwd ${MATERIAL_REPO_TMP_DIR} install --frozen-lockfile --non-interactive
|
||||||
|
# Save the cache before we run the Material unit tests script. This is necessary
|
||||||
|
# because we don't want to cache the node modules which have been modified to contain
|
||||||
|
# the attached Ivy package output.
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: *material_unit_tests_cache_key
|
# Material directory must be kept in sync with the `$MATERIAL_REPO_TMP_DIR` env variable.
|
||||||
|
# It needs to be hardcoded here, because env variables interpolation is not supported.
|
||||||
|
key: v2-angular-material-{{ checksum "/tmp/material2/yarn.lock" }}
|
||||||
paths:
|
paths:
|
||||||
# Material directory must be kept in sync with the `$MATERIAL_REPO_TMP_DIR` env variable.
|
- "/tmp/material2/node_modules"
|
||||||
# It needs to be hardcoded here, because env variables interpolation is not supported.
|
|
||||||
- "/tmp/material2"
|
|
||||||
- run:
|
|
||||||
name: "Setup Bazel RBE remote execution in Material repo"
|
|
||||||
command: |
|
|
||||||
./.circleci/setup-rbe.sh "${MATERIAL_REPO_TMP_DIR}/.bazelrc.user"
|
|
||||||
- run:
|
- run:
|
||||||
name: "Running Material unit tests"
|
name: "Running Material unit tests"
|
||||||
command: ./scripts/ci/run_angular_material_unit_tests.sh
|
command: ./scripts/ci/run_angular_material_unit_tests.sh
|
||||||
@ -653,56 +666,39 @@ jobs:
|
|||||||
# Run zone.js tools tests
|
# Run zone.js tools tests
|
||||||
- run: yarn --cwd packages/zone.js promisetest
|
- run: yarn --cwd packages/zone.js promisetest
|
||||||
- run: yarn --cwd packages/zone.js promisefinallytest
|
- run: yarn --cwd packages/zone.js promisefinallytest
|
||||||
- run: yarn bazel build //packages/zone.js:npm_package &&
|
|
||||||
cp dist/bin/packages/zone.js/npm_package/dist/zone-mix.js ./packages/zone.js/test/extra/ &&
|
|
||||||
cp dist/bin/packages/zone.js/npm_package/dist/zone-patch-electron.js ./packages/zone.js/test/extra/ &&
|
|
||||||
yarn --cwd packages/zone.js electrontest
|
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
version: 2
|
version: 2
|
||||||
default_workflow:
|
default_workflow:
|
||||||
jobs:
|
jobs:
|
||||||
- setup:
|
- setup
|
||||||
filters:
|
|
||||||
branches:
|
|
||||||
ignore: g3
|
|
||||||
- lint:
|
- lint:
|
||||||
requires:
|
requires:
|
||||||
- setup
|
- setup
|
||||||
- test:
|
- test:
|
||||||
requires:
|
requires:
|
||||||
- setup
|
- setup
|
||||||
- test_ivy_aot:
|
- test_ivy_aot:
|
||||||
requires:
|
requires:
|
||||||
- setup
|
- setup
|
||||||
- build-npm-packages:
|
- build-npm-packages:
|
||||||
requires:
|
requires:
|
||||||
- setup
|
- setup
|
||||||
- build-ivy-npm-packages:
|
- build-ivy-npm-packages:
|
||||||
requires:
|
requires:
|
||||||
- setup
|
- setup
|
||||||
- legacy-misc-tests:
|
|
||||||
requires:
|
|
||||||
- build-npm-packages
|
|
||||||
- legacy-unit-tests-saucelabs:
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
- test_saucelabs_bazel:
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
# This job is currently a PoC and a subset of `legacy-unit-tests-saucelabs`. Running on
|
|
||||||
# master only to avoid wasting resources.
|
|
||||||
#
|
|
||||||
# TODO: Run this job on all branches (including PRs) as soon as it is not a PoC.
|
|
||||||
filters:
|
|
||||||
branches:
|
|
||||||
only: master
|
|
||||||
- test_aio:
|
- test_aio:
|
||||||
requires:
|
requires:
|
||||||
- setup
|
- setup
|
||||||
|
- legacy-unit-tests-saucelabs:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
- deploy_aio:
|
- deploy_aio:
|
||||||
requires:
|
requires:
|
||||||
- test_aio
|
- test_aio
|
||||||
|
- legacy-misc-tests:
|
||||||
|
requires:
|
||||||
|
- build-npm-packages
|
||||||
- test_aio_local:
|
- test_aio_local:
|
||||||
requires:
|
requires:
|
||||||
- build-npm-packages
|
- build-npm-packages
|
||||||
@ -759,6 +755,22 @@ workflows:
|
|||||||
requires:
|
requires:
|
||||||
- setup
|
- setup
|
||||||
|
|
||||||
|
saucelabs_tests:
|
||||||
|
jobs:
|
||||||
|
- setup
|
||||||
|
- test_saucelabs_bazel:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
|
triggers:
|
||||||
|
- schedule:
|
||||||
|
# Runs the Saucelabs legacy tests every hour. We still want to run Saucelabs
|
||||||
|
# frequently as the caretaker needs up-to-date results when merging PRs or creating
|
||||||
|
# a new release. Also we primarily moved the Saucelabs job into a cronjob that doesn't
|
||||||
|
# run for PRs, in order to ensure that PRs are not affected by Saucelabs flakiness or
|
||||||
|
# incidents. This is still guaranteed (even if we run the job every hour).
|
||||||
|
cron: "0 * * * *"
|
||||||
|
filters: *publish_branches_filter
|
||||||
|
|
||||||
aio_monitoring:
|
aio_monitoring:
|
||||||
jobs:
|
jobs:
|
||||||
- setup
|
- setup
|
||||||
@ -776,3 +788,9 @@ workflows:
|
|||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
|
|
||||||
|
# TODO:
|
||||||
|
# - don't build the g3 branch
|
||||||
|
# - verify that we are bootstrapping with the right yarn version coming from the docker image
|
||||||
|
# - check local chrome version pulled from docker image
|
||||||
|
# - remove /tools/ngcontainer
|
||||||
|
@ -61,7 +61,6 @@ else
|
|||||||
setPublicVar SAUCE_USERNAME "angular-ci";
|
setPublicVar SAUCE_USERNAME "angular-ci";
|
||||||
setSecretVar SAUCE_ACCESS_KEY "9b988f434ff8-fbca-8aa4-4ae3-35442987";
|
setSecretVar SAUCE_ACCESS_KEY "9b988f434ff8-fbca-8aa4-4ae3-35442987";
|
||||||
fi
|
fi
|
||||||
# TODO(josephperrott): Remove environment variables once all saucelabs tests are via bazel method.
|
|
||||||
setPublicVar SAUCE_LOG_FILE /tmp/angular/sauce-connect.log
|
setPublicVar SAUCE_LOG_FILE /tmp/angular/sauce-connect.log
|
||||||
setPublicVar SAUCE_READY_FILE /tmp/angular/sauce-connect-ready-file.lock
|
setPublicVar SAUCE_READY_FILE /tmp/angular/sauce-connect-ready-file.lock
|
||||||
setPublicVar SAUCE_PID_FILE /tmp/angular/sauce-connect-pid-file.lock
|
setPublicVar SAUCE_PID_FILE /tmp/angular/sauce-connect-pid-file.lock
|
||||||
@ -78,9 +77,7 @@ setPublicVar SAUCE_READY_FILE_TIMEOUT 120
|
|||||||
# their separate build setups.
|
# their separate build setups.
|
||||||
setPublicVar MATERIAL_REPO_TMP_DIR "/tmp/material2"
|
setPublicVar MATERIAL_REPO_TMP_DIR "/tmp/material2"
|
||||||
setPublicVar MATERIAL_REPO_URL "https://github.com/angular/material2.git"
|
setPublicVar MATERIAL_REPO_URL "https://github.com/angular/material2.git"
|
||||||
setPublicVar MATERIAL_REPO_BRANCH "master"
|
setPublicVar MATERIAL_REPO_BRANCH "ivy-2019"
|
||||||
# **NOTE**: When updating the commit SHA, also update the cache key in the CircleCI "config.yml".
|
|
||||||
setPublicVar MATERIAL_REPO_COMMIT "18b9ef3f5529f0fa8f034944681486447af7b879"
|
|
||||||
|
|
||||||
# Source `$BASH_ENV` to make the variables available immediately.
|
# Source `$BASH_ENV` to make the variables available immediately.
|
||||||
source $BASH_ENV;
|
source $BASH_ENV;
|
||||||
|
Binary file not shown.
@ -1,20 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -u -e -o pipefail
|
|
||||||
|
|
||||||
# The path of the .bazelrc.user file to update should be passed as first parameter to this script.
|
|
||||||
# This allows to setup RBE for both the Angular repo and the Material repo.
|
|
||||||
bazelrc_user="$1"
|
|
||||||
|
|
||||||
echo "Writing RBE configuration to ${bazelrc_user}"
|
|
||||||
|
|
||||||
touch ${bazelrc_user}
|
|
||||||
echo -e 'build --config=remote\n' >> ${bazelrc_user}
|
|
||||||
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
|
|
||||||
echo -e 'build:remote --remote_upload_local_results=true\n' >> ${bazelrc_user}
|
|
||||||
echo "Uploading local build results to remote cache."
|
|
||||||
else
|
|
||||||
echo -e 'build:remote --remote_upload_local_results=false\n' >> ${bazelrc_user}
|
|
||||||
echo "Not uploading local build results to remote cache."
|
|
||||||
fi
|
|
120
.codefresh/Dockerfile.win-1809
Normal file
120
.codefresh/Dockerfile.win-1809
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
# escape=`
|
||||||
|
|
||||||
|
ARG core=mcr.microsoft.com/windows/servercore:1809
|
||||||
|
ARG target=mcr.microsoft.com/powershell:windowsservercore-1809
|
||||||
|
|
||||||
|
FROM $core as download
|
||||||
|
|
||||||
|
ARG node_version=10.13.0
|
||||||
|
ARG yarn_version=1.13.0
|
||||||
|
|
||||||
|
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
||||||
|
|
||||||
|
ENV GPG_VERSION 2.3.4
|
||||||
|
|
||||||
|
RUN Invoke-WebRequest $('https://files.gpg4win.org/gpg4win-vanilla-{0}.exe' -f $env:GPG_VERSION) -OutFile 'gpg4win.exe' -UseBasicParsing ; `
|
||||||
|
Start-Process .\gpg4win.exe -ArgumentList '/S' -NoNewWindow -Wait
|
||||||
|
|
||||||
|
RUN @( `
|
||||||
|
'94AE36675C464D64BAFA68DD7434390BDBE9B9C5', `
|
||||||
|
'FD3A5288F042B6850C66B31F09FE44734EB7990E', `
|
||||||
|
'71DCFD284A79C3B38668286BC97EC7A07EDE3FC1', `
|
||||||
|
'DD8F2338BAE7501E3DD5AC78C273792F7D83545D', `
|
||||||
|
'C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8', `
|
||||||
|
'B9AE9905FFD7803F25714661B63B535A4C206CA9', `
|
||||||
|
'77984A986EBC2AA786BC0F66B01FBB92821C587A', `
|
||||||
|
'8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600', `
|
||||||
|
'4ED778F539E3634C779C87C6D7062848A1AB005C', `
|
||||||
|
'A48C2BEE680E841632CD4E44F07496B3EB3C1762', `
|
||||||
|
'B9E2F5981AA6E0CD28160D9FF13993A75599653C' `
|
||||||
|
) | foreach { `
|
||||||
|
gpg --keyserver ha.pool.sks-keyservers.net --recv-keys $_ ; `
|
||||||
|
}
|
||||||
|
|
||||||
|
ENV NODE_VERSION=$node_version
|
||||||
|
|
||||||
|
RUN Invoke-WebRequest $('https://nodejs.org/dist/v{0}/SHASUMS256.txt.asc' -f $env:NODE_VERSION) -OutFile 'SHASUMS256.txt.asc' -UseBasicParsing ; `
|
||||||
|
gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc
|
||||||
|
|
||||||
|
RUN Invoke-WebRequest $('https://nodejs.org/dist/v{0}/node-v{0}-win-x64.zip' -f $env:NODE_VERSION) -OutFile 'node.zip' -UseBasicParsing ; `
|
||||||
|
$sum = $(cat SHASUMS256.txt.asc | sls $(' node-v{0}-win-x64.zip' -f $env:NODE_VERSION)) -Split ' ' ; `
|
||||||
|
if ((Get-FileHash node.zip -Algorithm sha256).Hash -ne $sum[0]) { Write-Error 'SHA256 mismatch' } ; `
|
||||||
|
Expand-Archive node.zip -DestinationPath C:\ ; `
|
||||||
|
Rename-Item -Path $('C:\node-v{0}-win-x64' -f $env:NODE_VERSION) -NewName 'C:\nodejs'
|
||||||
|
|
||||||
|
ENV YARN_VERSION=$yarn_version
|
||||||
|
|
||||||
|
RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ; `
|
||||||
|
Invoke-WebRequest $('https://yarnpkg.com/downloads/{0}/yarn-{0}.msi' -f $env:YARN_VERSION) -OutFile yarn.msi -UseBasicParsing ; `
|
||||||
|
$sig = Get-AuthenticodeSignature yarn.msi ; `
|
||||||
|
if ($sig.Status -ne 'Valid') { Write-Error 'Authenticode signature is not valid' } ; `
|
||||||
|
Write-Output $sig.SignerCertificate.Thumbprint ; `
|
||||||
|
if (@( `
|
||||||
|
'7E253367F8A102A91D04829E37F3410F14B68A5F', `
|
||||||
|
'AF764E1EA56C762617BDC757C8B0F3780A0CF5F9' `
|
||||||
|
) -notcontains $sig.SignerCertificate.Thumbprint) { Write-Error 'Unknown signer certificate' } ; `
|
||||||
|
Start-Process msiexec.exe -ArgumentList '/i', 'yarn.msi', '/quiet', '/norestart' -NoNewWindow -Wait
|
||||||
|
|
||||||
|
ENV GIT_VERSION 2.20.1
|
||||||
|
ENV GIT_DOWNLOAD_URL https://github.com/git-for-windows/git/releases/download/v${GIT_VERSION}.windows.1/MinGit-${GIT_VERSION}-busybox-64-bit.zip
|
||||||
|
ENV GIT_SHA256 9817ab455d9cbd0b09d8664b4afbe4bbf78d18b556b3541d09238501a749486c
|
||||||
|
|
||||||
|
RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ; `
|
||||||
|
Invoke-WebRequest -UseBasicParsing $env:GIT_DOWNLOAD_URL -OutFile git.zip; `
|
||||||
|
if ((Get-FileHash git.zip -Algorithm sha256).Hash -ne $env:GIT_SHA256) {exit 1} ; `
|
||||||
|
Expand-Archive git.zip -DestinationPath C:\git; `
|
||||||
|
Remove-Item git.zip
|
||||||
|
|
||||||
|
FROM $target as baseimage
|
||||||
|
|
||||||
|
ENV NPM_CONFIG_LOGLEVEL info
|
||||||
|
|
||||||
|
COPY --from=download /nodejs /nodejs
|
||||||
|
COPY --from=download [ "/Program Files (x86)/yarn", "/yarn" ]
|
||||||
|
COPY --from=download /git /git
|
||||||
|
|
||||||
|
ARG SETX=/M
|
||||||
|
RUN setx %SETX% PATH "%PATH%;C:\nodejs;C:\yarn\bin;C:\git\cmd;C:\git\mingw64\bin;C:\git\usr\bin"
|
||||||
|
|
||||||
|
CMD [ "node.exe" ]
|
||||||
|
|
||||||
|
FROM baseimage
|
||||||
|
|
||||||
|
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
||||||
|
|
||||||
|
RUN Invoke-WebRequest -UseBasicParsing 'https://www.7-zip.org/a/7z1805-x64.exe' -OutFile 7z.exe; `
|
||||||
|
Start-Process -FilePath 'C:\\7z.exe' -ArgumentList '/S', '/D=C:\\7zip0' -NoNewWindow -Wait; `
|
||||||
|
Invoke-WebRequest -UseBasicParsing 'http://repo.msys2.org/distrib/x86_64/msys2-base-x86_64-20180531.tar.xz' -OutFile msys2.tar.xz; `
|
||||||
|
Start-Process -FilePath 'C:\\7zip\\7z' -ArgumentList 'e', 'msys2.tar.xz' -Wait; `
|
||||||
|
Start-Process -FilePath 'C:\\7zip\\7z' -ArgumentList 'x', 'msys2.tar', '-oC:\\' -Wait; `
|
||||||
|
Remove-Item msys2.tar.xz; `
|
||||||
|
Remove-Item msys2.tar; `
|
||||||
|
Remove-Item 7z.exe; `
|
||||||
|
Remove-Item -Recurse 7zip; `
|
||||||
|
[Environment]::SetEnvironmentVariable('Path', $env:Path + ';C:\msys64\usr\bin', [System.EnvironmentVariableTarget]::Machine); `
|
||||||
|
[Environment]::SetEnvironmentVariable('BAZEL_SH', 'C:\msys64\usr\bin\bash.exe', [System.EnvironmentVariableTarget]::Machine)
|
||||||
|
|
||||||
|
# Install VS Build Tools
|
||||||
|
RUN Invoke-WebRequest -UseBasicParsing https://download.visualstudio.microsoft.com/download/pr/df649173-11e9-4af2-8eb7-0eb02ba8958a/cadb5bdac41e55bb8f6a6b7c45273370/vs_buildtools.exe -OutFile vs_BuildTools.exe; `
|
||||||
|
# Installer won't detect DOTNET_SKIP_FIRST_TIME_EXPERIENCE if ENV is used, must use setx /M
|
||||||
|
setx /M DOTNET_SKIP_FIRST_TIME_EXPERIENCE 1; `
|
||||||
|
Start-Process vs_BuildTools.exe `
|
||||||
|
-ArgumentList `
|
||||||
|
'--add', 'Microsoft.VisualStudio.Workload.VCTools', `
|
||||||
|
'--add', 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', `
|
||||||
|
'--add', 'Microsoft.Component.VC.Runtime.UCRTSDK', `
|
||||||
|
'--add', 'Microsoft.VisualStudio.Component.Windows10SDK.17763', `
|
||||||
|
'--quiet', '--norestart', '--nocache' `
|
||||||
|
-NoNewWindow -Wait; `
|
||||||
|
Remove-Item -Force vs_buildtools.exe; `
|
||||||
|
Remove-Item -Force -Recurse \"${Env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\"; `
|
||||||
|
Remove-Item -Force -Recurse ${Env:TEMP}\*; `
|
||||||
|
Remove-Item -Force -Recurse \"${Env:ProgramData}\Package Cache\"; `
|
||||||
|
[Environment]::SetEnvironmentVariable('BAZEL_VC', \"${Env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\BuildTools\VC\", [System.EnvironmentVariableTarget]::Machine)
|
||||||
|
|
||||||
|
# Install Python
|
||||||
|
RUN Invoke-WebRequest -UseBasicParsing https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe -OutFile python-3.5.1.exe; `
|
||||||
|
Start-Process python-3.5.1.exe -ArgumentList '/quiet InstallAllUsers=1 PrependPath=1' -Wait; `
|
||||||
|
Remove-Item -Force python-3.5.1.exe
|
||||||
|
|
||||||
|
CMD ["cmd.exe"]
|
33
.codefresh/README.md
Normal file
33
.codefresh/README.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# CodeFresh configuration
|
||||||
|
|
||||||
|
[](https://g.codefresh.io/public/accounts/angular/pipelines/angular/angular/angular)
|
||||||
|
|
||||||
|
This folder contains configuration for the [CodeFresh](<https://codefresh.io/>) based CI checks for this repository.
|
||||||
|
|
||||||
|
## The build pipeline
|
||||||
|
|
||||||
|
CodeFresh uses a several pipeline for each repository. The `codefresh.yml` file defines pipeline [build steps](https://codefresh.io/docs/docs/configure-ci-cd-pipeline/introduction-to-codefresh-pipelines/) for this repository.
|
||||||
|
|
||||||
|
Run results can be seen in the GitHub checks interface and in the [public pipeline](https://g.codefresh.io/public/accounts/angular/pipelines/angular/angular/angular)
|
||||||
|
|
||||||
|
Although most configuration is done via `pipeline.yml`, some options are only available in the online [pipeline settings](https://g.codefresh.io/pipelines/angular/services?repoOwner=angular&repoName=angular&project=angular%2Fangular&context=github&serviceName=angular%2Fangular), which needs a login to access.
|
||||||
|
|
||||||
|
|
||||||
|
## Caretaker
|
||||||
|
|
||||||
|
CodeFresh status can be found at <http://status.codefresh.io/>.
|
||||||
|
|
||||||
|
Issues related to the CodeFresh setup should be escalated to the Tools Team via the current caretaker, followed by Alex Eagle and Filipe Silva.
|
||||||
|
|
||||||
|
## Rollout strategy
|
||||||
|
|
||||||
|
Currently it is only used for tests on Windows platforms, on the master branch, and without pushing user-facing reports. It's only possible to see current builds in the [public pipeline dashboard](https://g.codefresh.io/public/accounts/angular/pipelines/angular/angular/angular).
|
||||||
|
|
||||||
|
After a week or two of running like this, we should reassess how stable and reliable it is.
|
||||||
|
|
||||||
|
Next steps include:
|
||||||
|
- building PRs
|
||||||
|
- showing build status publicly
|
||||||
|
- blocking PRs that break the build
|
||||||
|
- expanding the test suite
|
||||||
|
|
38
.codefresh/bazel.rc
Normal file
38
.codefresh/bazel.rc
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# These options are enabled when running on CI
|
||||||
|
# We do this by copying this file to /etc/bazel.bazelrc at the start of the build.
|
||||||
|
# See documentation in /docs/BAZEL.md
|
||||||
|
|
||||||
|
# Save built files and downloaded repositories in a location that can be cached by CodeFresh and
|
||||||
|
# shared between builds. This helps speed up the analysis time significantly with Bazel managed node
|
||||||
|
# dependencies on the CI.
|
||||||
|
# https://codefresh.io/docs/docs/configure-ci-cd-pipeline/introduction-to-codefresh-pipelines/#caching-the-artifacts-of-your-build-system
|
||||||
|
build --repository_cache=C:/codefresh/volume/bazel_repository_cache
|
||||||
|
# Setting the output_base to a Docker volume is currently broken because of a Docker bug on Windows:
|
||||||
|
# https://github.com/moby/moby/issues/37024
|
||||||
|
# This affects Bazel because bazel_output_base\external\bazel_tools is an absolute path junction.
|
||||||
|
# When its fixed we can uncomment this line, and use a different output_base for Ivy tests (they
|
||||||
|
# use a separate compiler and destructively replace the cache).
|
||||||
|
# startup --output_base=C:/codefresh/volume/bazel_output_base
|
||||||
|
|
||||||
|
# Don't be spammy in the logs
|
||||||
|
# TODO(gmagolan): Hide progress again once build performance improves
|
||||||
|
# Presently, CircleCI can timeout during bazel test ... with the following
|
||||||
|
# error: Too long with no output (exceeded 10m0s)
|
||||||
|
build --noshow_progress
|
||||||
|
|
||||||
|
# Print all the options that apply to the build.
|
||||||
|
# This helps us diagnose which options override others
|
||||||
|
# (e.g. /etc/bazel.bazelrc vs. tools/bazel.rc)
|
||||||
|
build --announce_rc
|
||||||
|
|
||||||
|
# Workaround https://github.com/bazelbuild/bazel/issues/3645
|
||||||
|
# Bazel doesn't calculate the memory ceiling correctly when running under Docker.
|
||||||
|
# Limit Bazel to consuming resources that fit in CodeFresh VMs
|
||||||
|
# TODO(filipesilva): determine the correct memory limit
|
||||||
|
build --local_resources=10240,8.0,1.0
|
||||||
|
|
||||||
|
# Retry in the event of flakes, eg. https://circleci.com/gh/angular/angular/31309
|
||||||
|
test --flaky_test_attempts=2
|
||||||
|
|
||||||
|
# More details on failures
|
||||||
|
build --verbose_failures=true
|
28
.codefresh/codefresh.yml
Normal file
28
.codefresh/codefresh.yml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
version: '1.0'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
BuildImage:
|
||||||
|
title: Build Docker image
|
||||||
|
type: build
|
||||||
|
image_name: node-bazel-windows
|
||||||
|
working_directory: ./.codefresh
|
||||||
|
no_cf_cache: true
|
||||||
|
build_arguments:
|
||||||
|
- node_version=10.13.0
|
||||||
|
- yarn_version=1.13.0
|
||||||
|
dockerfile: ./Dockerfile.win-1809
|
||||||
|
|
||||||
|
RunTests:
|
||||||
|
title: Run Bazel tests
|
||||||
|
image: ${{BuildImage}}
|
||||||
|
commands:
|
||||||
|
# Install dependencies
|
||||||
|
- yarn install --frozen-lockfile --non-interactive --network-timeout 100000 --no-progress
|
||||||
|
# Add Bazel CI config
|
||||||
|
- copy .codefresh\bazel.rc %ProgramData%\bazel.bazelrc
|
||||||
|
# Run tests
|
||||||
|
# At the moment 'browser:chromium-local' are broken in CI while locally they work
|
||||||
|
# VE
|
||||||
|
- yarn bazel test --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only,-browser:chromium-local //...
|
||||||
|
# Ivy
|
||||||
|
- yarn bazel test --define=compile=aot --build_tag_filters=-no-ivy-aot,-fixme-ivy-aot --test_tag_filters=-no-ivy-aot,-fixme-ivy-aot,-browser:chromium-local //...
|
10
.github/CODEOWNERS
vendored
10
.github/CODEOWNERS
vendored
@ -101,6 +101,7 @@
|
|||||||
#
|
#
|
||||||
# - brandonroberts
|
# - brandonroberts
|
||||||
# - gkalpak
|
# - gkalpak
|
||||||
|
# - jenniferfell
|
||||||
# - petebacondarwin
|
# - petebacondarwin
|
||||||
|
|
||||||
|
|
||||||
@ -883,6 +884,7 @@ testing/** @angular/fw-test
|
|||||||
/* @angular/fw-dev-infra
|
/* @angular/fw-dev-infra
|
||||||
/.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
|
||||||
/.devcontainer/** @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
|
||||||
@ -910,6 +912,14 @@ testing/** @angular/fw-test
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ================================================
|
||||||
|
# Material CI
|
||||||
|
# ================================================
|
||||||
|
|
||||||
|
/tools/material-ci/** @angular/fw-core @angular/framework-global-approvers
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
# Public API
|
# Public API
|
||||||
# ================================================
|
# ================================================
|
||||||
|
150
CHANGELOG.md
150
CHANGELOG.md
@ -1,153 +1,3 @@
|
|||||||
<a name="8.2.4"></a>
|
|
||||||
## [8.2.4](https://github.com/angular/angular/compare/8.2.3...8.2.4) (2019-08-28)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="8.2.3"></a>
|
|
||||||
## [8.2.3](https://github.com/angular/angular/compare/8.2.2...8.2.3) (2019-08-21)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **bazel:** pin `[@microsoft](https://github.com/microsoft)/api-extractor` ([#32187](https://github.com/angular/angular/issues/32187)) ([a7b9478](https://github.com/angular/angular/commit/a7b9478))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="8.2.2"></a>
|
|
||||||
## [8.2.2](https://github.com/angular/angular/compare/8.2.1...8.2.2) (2019-08-12)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **bazel:** disable treeshaking when generating FESM and UMD bundles ([#32069](https://github.com/angular/angular/issues/32069)) ([3420d29](https://github.com/angular/angular/commit/3420d29))
|
|
||||||
|
|
||||||
|
|
||||||
<a name="8.2.1"></a>
|
|
||||||
## [8.2.1](https://github.com/angular/angular/compare/8.2.0...8.2.1) (2019-08-08)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **upgrade:** compile downgraded components synchronously (if possible) ([#31840](https://github.com/angular/angular/issues/31840)) ([04ebd59](https://github.com/angular/angular/commit/04ebd59)), closes [#27217](https://github.com/angular/angular/issues/27217) [#30330](https://github.com/angular/angular/issues/30330)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="8.2.0"></a>
|
|
||||||
# [8.2.0](https://github.com/angular/angular/compare/8.2.0-rc.0...8.2.0) (2019-07-31)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **core:** DebugElement.listeners not cleared on destroy ([#31820](https://github.com/angular/angular/issues/31820)) ([46b160e](https://github.com/angular/angular/commit/46b160e))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="8.2.0-rc.0"></a>
|
|
||||||
# [8.2.0-rc.0](https://github.com/angular/angular/compare/8.2.0-next.2...8.2.0-rc.0) (2019-07-26)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **bazel:** increase memory limit of ngc under bazel from 2 to 4 GB ([#31784](https://github.com/angular/angular/issues/31784)) ([5a8eb92](https://github.com/angular/angular/commit/5a8eb92))
|
|
||||||
* **core:** allow Z variations of CSS transforms in sanitizer ([#29264](https://github.com/angular/angular/issues/29264)) ([78e7fdd](https://github.com/angular/angular/commit/78e7fdd))
|
|
||||||
* **elements:** handle falsy initial value ([#31604](https://github.com/angular/angular/issues/31604)) ([7151eae](https://github.com/angular/angular/commit/7151eae)), closes [angular/angular#30834](https://github.com/angular/angular/issues/30834)
|
|
||||||
* **platform-browser:** debug element query predicates not compatible with strictFunctionTypes ([#30993](https://github.com/angular/angular/issues/30993)) ([10a1e19](https://github.com/angular/angular/commit/10a1e19))
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **bazel:** compile targets used for indexing by Kythe with Ivy ([#31786](https://github.com/angular/angular/issues/31786)) ([82055b2](https://github.com/angular/angular/commit/82055b2))
|
|
||||||
* **upgrade:** support $element in upgraded component template/templateUrl functions ([#31637](https://github.com/angular/angular/issues/31637)) ([29e1c53](https://github.com/angular/angular/commit/29e1c53))
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
|
|
||||||
* **compiler:** avoid copying from prototype while cloning an object ([#31638](https://github.com/angular/angular/issues/31638)) ([24ca582](https://github.com/angular/angular/commit/24ca582)), closes [#31627](https://github.com/angular/angular/issues/31627)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="8.1.3"></a>
|
|
||||||
## [8.1.3](https://github.com/angular/angular/compare/8.1.2...8.1.3) (2019-07-26)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **elements:** handle falsy initial value ([#31604](https://github.com/angular/angular/issues/31604)) ([434b796](https://github.com/angular/angular/commit/434b796)), closes [angular/angular#30834](https://github.com/angular/angular/issues/30834)
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
|
|
||||||
* **compiler:** avoid copying from prototype while cloning an object ([#31638](https://github.com/angular/angular/issues/31638)) ([1f3daa0](https://github.com/angular/angular/commit/1f3daa0)), closes [#31627](https://github.com/angular/angular/issues/31627)
|
|
||||||
|
|
||||||
|
|
||||||
<a name="8.2.0-next.2"></a>
|
|
||||||
# [8.2.0-next.2](https://github.com/angular/angular/compare/8.2.0-next.1...8.2.0-next.2) (2019-07-17)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* use the correct WTF array to iterate over ([#31208](https://github.com/angular/angular/issues/31208)) ([9204de9](https://github.com/angular/angular/commit/9204de9))
|
|
||||||
* **bazel:** pass custom bazel compiler host rather than rewriting one ([#31496](https://github.com/angular/angular/issues/31496)) ([0c61a35](https://github.com/angular/angular/commit/0c61a35))
|
|
||||||
* **compiler-cli:** Return original sourceFile instead of redirected sourceFile from getSourceFile ([#26036](https://github.com/angular/angular/issues/26036)) ([3166cff](https://github.com/angular/angular/commit/3166cff)), closes [#22524](https://github.com/angular/angular/issues/22524)
|
|
||||||
* **language-service:** Eagarly initialize data members ([#31577](https://github.com/angular/angular/issues/31577)) ([0110de2](https://github.com/angular/angular/commit/0110de2))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="8.1.2"></a>
|
|
||||||
## [8.1.2](https://github.com/angular/angular/compare/8.1.0...8.1.2) (2019-07-17)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* use the correct WTF array to iterate over ([#31208](https://github.com/angular/angular/issues/31208)) ([4aed480](https://github.com/angular/angular/commit/4aed480))
|
|
||||||
* **compiler-cli:** Return original sourceFile instead of redirected sourceFile from getSourceFile ([#26036](https://github.com/angular/angular/issues/26036)) ([13dbb98](https://github.com/angular/angular/commit/13dbb98)), closes [#22524](https://github.com/angular/angular/issues/22524)
|
|
||||||
* **core:** export provider interfaces that are part of the public API types ([#31377](https://github.com/angular/angular/issues/31377)) ([bebf089](https://github.com/angular/angular/commit/bebf089)), closes [/github.com/angular/angular/pull/31377#discussion_r299254408](https://github.com//github.com/angular/angular/pull/31377/issues/discussion_r299254408) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L365-L366](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L365-L366) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L283-L284](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L283-L284) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts#L23](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts/issues/L23)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="8.2.0-next.1"></a>
|
|
||||||
# [8.2.0-next.1](https://github.com/angular/angular/compare/8.2.0-next.0...8.2.0-next.1) (2019-07-10)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **bazel:** revert location of xi18n outputs to bazel-genfiles ([#31410](https://github.com/angular/angular/issues/31410)) ([1d3e227](https://github.com/angular/angular/commit/1d3e227))
|
|
||||||
* **compiler:** give ASTWithSource its own visit method ([#31347](https://github.com/angular/angular/issues/31347)) ([6aaca21](https://github.com/angular/angular/commit/6aaca21))
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **core:** add automatic migration from Renderer to Renderer2 ([#30936](https://github.com/angular/angular/issues/30936)) ([c095597](https://github.com/angular/angular/commit/c095597))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="8.1.1"></a>
|
|
||||||
## [8.1.1](https://github.com/angular/angular/compare/8.1.0...8.1.1) (2019-07-10)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **core:** export provider interfaces that are part of the public API types ([#31377](https://github.com/angular/angular/issues/31377)) ([bebf089](https://github.com/angular/angular/commit/bebf089)), closes [/github.com/angular/angular/pull/31377#discussion_r299254408](https://github.com//github.com/angular/angular/pull/31377/issues/discussion_r299254408) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L365-L366](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L365-L366) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L283-L284](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L283-L284) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts#L23](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts/issues/L23)
|
|
||||||
|
|
||||||
|
|
||||||
<a name="8.2.0-next.0"></a>
|
|
||||||
# [8.2.0-next.0](https://github.com/angular/angular/compare/8.1.0-rc.0...8.2.0-next.0) (2019-07-02)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **core:** handle `undefined` meta in `injectArgs` ([#31333](https://github.com/angular/angular/issues/31333)) ([80ccd6c](https://github.com/angular/angular/commit/80ccd6c)), closes [CLI #14888](https://github.com/angular/angular-cli/issues/14888)
|
|
||||||
* **service-worker:** cache opaque responses in data groups with `freshness` strategy ([#30977](https://github.com/angular/angular/issues/30977)) ([d7be38f](https://github.com/angular/angular/commit/d7be38f)), closes [#30968](https://github.com/angular/angular/issues/30968)
|
|
||||||
* **service-worker:** cache opaque responses when requests exceeds timeout threshold ([#30977](https://github.com/angular/angular/issues/30977)) ([93abc35](https://github.com/angular/angular/commit/93abc35))
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **bazel:** allow passing a custom bazel compiler host to ngc compile ([#31341](https://github.com/angular/angular/issues/31341)) ([a29dc96](https://github.com/angular/angular/commit/a29dc96))
|
|
||||||
* **bazel:** allow passing and rewriting an old bazel host ([#31381](https://github.com/angular/angular/issues/31381)) ([11a208f](https://github.com/angular/angular/commit/11a208f)), closes [#31341](https://github.com/angular/angular/issues/31341)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="8.1.0"></a>
|
<a name="8.1.0"></a>
|
||||||
# [8.1.0](https://github.com/angular/angular/compare/8.1.0-rc.0...8.1.0) (2019-07-02)
|
# [8.1.0](https://github.com/angular/angular/compare/8.1.0-rc.0...8.1.0) (2019-07-02)
|
||||||
|
|
||||||
|
@ -233,7 +233,6 @@ There are currently a few exceptions to the "use package name" rule:
|
|||||||
* **docs-infra**: used for docs-app (angular.io) related changes within the /aio directory of the
|
* **docs-infra**: used for docs-app (angular.io) related changes within the /aio directory of the
|
||||||
repo
|
repo
|
||||||
* **ivy**: used for changes to the [Ivy renderer](https://github.com/angular/angular/issues/21706).
|
* **ivy**: used for changes to the [Ivy renderer](https://github.com/angular/angular/issues/21706).
|
||||||
* **ngcc**: used for changes to the [Angular Compatibility Compiler](./packages/compiler-cli/ngcc/README.md)
|
|
||||||
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all
|
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all
|
||||||
packages (e.g. `style: add missing semicolons`) and for docs changes that are not related to a
|
packages (e.g. `style: add missing semicolons`) and for docs changes that are not related to a
|
||||||
specific package (e.g. `docs: fix typo in tutorial`).
|
specific package (e.g. `docs: fix typo in tutorial`).
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
# Angular
|
# Angular
|
||||||
|
|
||||||
Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages.
|
Angular is a development platform for building mobile and desktop web applications using Typescript/JavaScript and other languages.
|
||||||
|
|
||||||
## Quickstart
|
## Quickstart
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ Angular is a development platform for building mobile and desktop web applicatio
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
[Learn about the latest improvements][changelog].
|
[Learn about the latest improvements][changelog].
|
||||||
|
|
||||||
## Want to help?
|
## Want to help?
|
||||||
|
|
||||||
|
15
WORKSPACE
15
WORKSPACE
@ -18,11 +18,8 @@ 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",
|
||||||
patch_args = ["-p1"],
|
sha256 = "6d4edbf28ff6720aedf5f97f9b9a7679401bf7fca9d14a0fff80f644a99992b4",
|
||||||
# Patch https://github.com/bazelbuild/rules_nodejs/pull/903
|
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.32.2/rules_nodejs-0.32.2.tar.gz"],
|
||||||
patches = ["//tools:rollup_bundle_commonjs_ignoreGlobal.patch"],
|
|
||||||
sha256 = "7c4a690268be97c96f04d505224ec4cb1ae53c2c2b68be495c9bd2634296a5cd",
|
|
||||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.34.0/rules_nodejs-0.34.0.tar.gz"],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check the bazel version and download npm dependencies
|
# Check the bazel version and download npm dependencies
|
||||||
@ -53,8 +50,7 @@ Try running `yarn bazel` instead.
|
|||||||
# - 0.32.0 yarn_install and npm_install no longer puts build files under symlinked node_modules
|
# - 0.32.0 yarn_install and npm_install no longer puts build files under symlinked node_modules
|
||||||
# - 0.32.1 remove override of @bazel/tsetse & exclude typescript lib declarations in node_module_library transitive_declarations
|
# - 0.32.1 remove override of @bazel/tsetse & exclude typescript lib declarations in node_module_library transitive_declarations
|
||||||
# - 0.32.2 resolves bug in @bazel/hide-bazel-files postinstall step
|
# - 0.32.2 resolves bug in @bazel/hide-bazel-files postinstall step
|
||||||
# - 0.34.0 introduces protractor rule
|
check_rules_nodejs_version(minimum_version_string = "0.32.2")
|
||||||
check_rules_nodejs_version(minimum_version_string = "0.34.0")
|
|
||||||
|
|
||||||
# Setup the Node.js toolchain
|
# Setup the Node.js toolchain
|
||||||
node_repositories(
|
node_repositories(
|
||||||
@ -92,11 +88,6 @@ load("//packages/bazel:package.bzl", "rules_angular_dev_dependencies")
|
|||||||
|
|
||||||
rules_angular_dev_dependencies()
|
rules_angular_dev_dependencies()
|
||||||
|
|
||||||
# Load protractor dependencies
|
|
||||||
load("@npm_bazel_protractor//:package.bzl", "npm_bazel_protractor_dependencies")
|
|
||||||
|
|
||||||
npm_bazel_protractor_dependencies()
|
|
||||||
|
|
||||||
# Load karma dependencies
|
# Load karma dependencies
|
||||||
load("@npm_bazel_karma//:package.bzl", "rules_karma_dependencies")
|
load("@npm_bazel_karma//:package.bzl", "rules_karma_dependencies")
|
||||||
|
|
||||||
|
@ -14,12 +14,10 @@ Here are the most important tasks you might need to use:
|
|||||||
|
|
||||||
* `yarn` - install all the dependencies.
|
* `yarn` - install all the dependencies.
|
||||||
* `yarn setup` - install all the dependencies, boilerplate, stackblitz, zips and run dgeni on the docs.
|
* `yarn setup` - install all the dependencies, boilerplate, stackblitz, zips and run dgeni on the docs.
|
||||||
* `yarn setup-local` - same as `setup`, but build the Angular packages from the source code and use these locally built versions (instead of the ones fetched from npm) for aio and docs examples boilerplate.
|
* `yarn setup-local` - same as `setup`, but use the locally built Angular packages for aio and docs examples boilerplate.
|
||||||
|
|
||||||
* `yarn build` - create a production build of the application (after installing dependencies, boilerplate, etc).
|
* `yarn build` - create a production build of the application (after installing dependencies, boilerplate, etc).
|
||||||
* `yarn build-local` - same as `build`, but use `setup-local` instead of `setup`.
|
* `yarn build-local` - same as `build`, but use `setup-local` instead of `setup`.
|
||||||
* `yarn build-with-ivy` - same as `build-local`, but in addition also turns on `ivy` mode in aio.
|
|
||||||
(Note: To turn on `ivy` mode in examples, see `yarn boilerplate:add` below.)
|
|
||||||
|
|
||||||
* `yarn start` - run a development web server that watches the files; then builds the doc-viewer and reloads the page, as necessary.
|
* `yarn start` - run a development web server that watches the files; then builds the doc-viewer and reloads the page, as necessary.
|
||||||
* `yarn serve-and-sync` - run both the `docs-watch` and `start` in the same console.
|
* `yarn serve-and-sync` - run both the `docs-watch` and `start` in the same console.
|
||||||
@ -33,10 +31,7 @@ Here are the most important tasks you might need to use:
|
|||||||
* `yarn docs-lint` - check that the doc gen code follows our style rules.
|
* `yarn docs-lint` - check that the doc gen code follows our style rules.
|
||||||
* `yarn docs-test` - run the unit tests for the doc generation code.
|
* `yarn docs-test` - run the unit tests for the doc generation code.
|
||||||
|
|
||||||
* `yarn boilerplate:add` - generate all the boilerplate code for the examples, so that they can be run locally.
|
* `yarn boilerplate:add` - generate all the boilerplate code for the examples, so that they can be run locally. Add the option `--local` to use your local version of Angular contained in the "dist" folder.
|
||||||
- Add the option `--local` to use your local version of Angular contained in the "dist" folder.
|
|
||||||
- Add the option `--ivy` to turn on `ivy` mode.
|
|
||||||
|
|
||||||
* `yarn boilerplate:remove` - remove all the boilerplate code that was added via `yarn boilerplate:add`.
|
* `yarn boilerplate:remove` - remove all the boilerplate code that was added via `yarn boilerplate:add`.
|
||||||
* `yarn generate-stackblitz` - generate the stackblitz files that are used by the `live-example` tags in the docs.
|
* `yarn generate-stackblitz` - generate the stackblitz files that are used by the `live-example` tags in the docs.
|
||||||
* `yarn generate-zips` - generate the zip files from the examples. Zip available via the `live-example` tags in the docs.
|
* `yarn generate-zips` - generate the zip files from the examples. Zip available via the `live-example` tags in the docs.
|
||||||
@ -46,15 +41,6 @@ Here are the most important tasks you might need to use:
|
|||||||
- `yarn example-e2e --filter=foo` - limit e2e tests to those containing the word "foo"
|
- `yarn example-e2e --filter=foo` - limit e2e tests to those containing the word "foo"
|
||||||
- `yarn example-e2e --setup --local` - run e2e tests with the local version of Angular contained in the "dist" folder
|
- `yarn example-e2e --setup --local` - run e2e tests with the local version of Angular contained in the "dist" folder
|
||||||
|
|
||||||
> **Note for Windows users**
|
|
||||||
>
|
|
||||||
> Setting up the examples involves creating some [symbolic links](https://en.wikipedia.org/wiki/Symbolic_link) (see [here](./tools/examples/README.md#symlinked-node_modules) for details). On Windows, this requires to either have [Developer Mode enabled](https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10) (supported on Windows 10 or newer) or run the setup commands as administrator.
|
|
||||||
>
|
|
||||||
> The affected commands are:
|
|
||||||
> - `yarn setup` / `yarn setup-*`
|
|
||||||
> - `yarn build` / `yarn build-*`
|
|
||||||
> - `yarn boilerplate:add`
|
|
||||||
> - `yarn example-e2e --setup`
|
|
||||||
|
|
||||||
## Using ServiceWorker locally
|
## Using ServiceWorker locally
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ The Angular CLI is a command-line interface tool that you use to initialize, dev
|
|||||||
Major versions of Angular CLI follow the supported major version of Angular, but minor versions can be released separately.
|
Major versions of Angular CLI follow the supported major version of Angular, but minor versions can be released separately.
|
||||||
|
|
||||||
Install the CLI using the `npm` package manager:
|
Install the CLI using the `npm` package manager:
|
||||||
<code-example language="bash">
|
<code-example format="." language="bash">
|
||||||
npm install -g @angular/cli
|
npm install -g @angular/cli
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
@ -20,14 +20,14 @@ Invoke the tool on the command line through the `ng` executable.
|
|||||||
Online help is available on the command line.
|
Online help is available on the command line.
|
||||||
Enter the following to list commands or options for a given command (such as [generate](cli/generate)) with a short description.
|
Enter the following to list commands or options for a given command (such as [generate](cli/generate)) with a short description.
|
||||||
|
|
||||||
<code-example language="bash">
|
<code-example format="." language="bash">
|
||||||
ng help
|
ng help
|
||||||
ng generate --help
|
ng generate --help
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
To create, build, and serve a new, basic Angular project on a development server, go to the parent directory of your new workspace use the following commands:
|
To create, build, and serve a new, basic Angular project on a development server, go to the parent directory of your new workspace use the following commands:
|
||||||
|
|
||||||
<code-example language="bash">
|
<code-example format="." language="bash">
|
||||||
ng new my-first-project
|
ng new my-first-project
|
||||||
cd my-first-project
|
cd my-first-project
|
||||||
ng serve
|
ng serve
|
||||||
@ -36,14 +36,6 @@ ng serve
|
|||||||
In your browser, open http://localhost:4200/ to see the new app run.
|
In your browser, open http://localhost:4200/ to see the new app run.
|
||||||
When you use the [ng serve](cli/serve) command to build an app and serve it locally, the server automatically rebuilds the app and reloads the page when you change any of the source files.
|
When you use the [ng serve](cli/serve) command to build an app and serve it locally, the server automatically rebuilds the app and reloads the page when you change any of the source files.
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
|
|
||||||
When you run `ng new my-first-project` a new folder, named `my-first-project`, will be created in the current working directory. Since you want to be able to create files inside that folder, make sure you have sufficient rights in the current working directory before running the command.
|
|
||||||
|
|
||||||
If the current working directory is not the right place for your project, you can change to a more appropriate directory by running `cd <path-to-other-directory>` first.
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## Workspaces and project files
|
## Workspaces and project files
|
||||||
|
|
||||||
The [ng new](cli/new) command creates an *Angular workspace* folder and generates a new app skeleton.
|
The [ng new](cli/new) command creates an *Angular workspace* folder and generates a new app skeleton.
|
||||||
@ -82,8 +74,8 @@ Command syntax is shown as follows:
|
|||||||
* Option names are prefixed with a double dash (--).
|
* Option names are prefixed with a double dash (--).
|
||||||
Option aliases are prefixed with a single dash (-).
|
Option aliases are prefixed with a single dash (-).
|
||||||
Arguments are not prefixed.
|
Arguments are not prefixed.
|
||||||
For example:
|
For example:
|
||||||
<code-example language="bash">
|
<code-example format="." language="bash">
|
||||||
ng build my-app -c production
|
ng build my-app -c production
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
@ -113,5 +105,5 @@ Schematic options are supplied to the command in the same format as immediate co
|
|||||||
|
|
||||||
### Building with Bazel
|
### Building with Bazel
|
||||||
|
|
||||||
Optionally, you can configure the Angular CLI to use [Bazel](https://docs.bazel.build) as the build tool. For more information, see [Building with Bazel](guide/bazel).
|
Optionally, you can configure the Angular CLI to use [Bazel](https://docs.bazel.build) as the build tool. For more information, see [Building with Bazel](guide/bazel).
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@ describe('Attribute directives', () => {
|
|||||||
greenRb.click();
|
greenRb.click();
|
||||||
browser.actions().mouseMove(highlightedEle).perform();
|
browser.actions().mouseMove(highlightedEle).perform();
|
||||||
|
|
||||||
// Wait for up to 4s for the background color to be updated,
|
// Wait for up to 2s for the background color to be updated,
|
||||||
// to account for slow environments (e.g. CI).
|
// to account for slow environments (e.g. CI).
|
||||||
browser.wait(() => highlightedEle.getCssValue('background-color').then(c => c === lightGreen), 4000);
|
browser.wait(() => highlightedEle.getCssValue('background-color').then(c => c === lightGreen), 2000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 32 KiB |
@ -18,7 +18,7 @@ export class AppComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deleteItem(item: Item) {
|
deleteItem(item: Item) {
|
||||||
alert(`Delete the ${item.name}.`);
|
alert(`Delete the ${item}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
onClickMe(event?: KeyboardEvent) {
|
onClickMe(event?: KeyboardEvent) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion imports
|
// #docregion imports
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { CartService } from '../cart.service';
|
import { CartService } from '../cart.service';
|
||||||
// #enddocregion imports
|
// #enddocregion imports
|
||||||
|
|
||||||
@ -10,14 +10,12 @@ import { CartService } from '../cart.service';
|
|||||||
styleUrls: ['./cart.component.css']
|
styleUrls: ['./cart.component.css']
|
||||||
})
|
})
|
||||||
// #docregion props-services, submit
|
// #docregion props-services, submit
|
||||||
export class CartComponent implements OnInit {
|
export class CartComponent {
|
||||||
items;
|
items;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private cartService: CartService
|
private cartService: CartService
|
||||||
) { }
|
) {
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.items = this.cartService.getItems();
|
this.items = this.cartService.getItems();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,20 +16,16 @@
|
|||||||
<!-- #enddocregion checkout-form-1 -->
|
<!-- #enddocregion checkout-form-1 -->
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label for="name">
|
<label>Name</label>
|
||||||
Name
|
<input type="text" formControlName="name">
|
||||||
</label>
|
|
||||||
<input id="name" type="text" formControlName="name">
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label for="address">
|
<label>Address</label>
|
||||||
Address
|
<input type="text" formControlName="address">
|
||||||
</label>
|
|
||||||
<input id="address" type="text" formControlName="address">
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="button" type="submit">Purchase</button>
|
<button class="button" type="submit">Purchase</button>
|
||||||
|
|
||||||
<!-- #docregion checkout-form-1 -->
|
<!-- #docregion checkout-form-1 -->
|
||||||
</form>
|
</form>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion imports
|
// #docregion imports
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
import { CartService } from '../cart.service';
|
import { CartService } from '../cart.service';
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
@ -11,7 +11,7 @@ import { CartService } from '../cart.service';
|
|||||||
styleUrls: ['./shipping.component.css']
|
styleUrls: ['./shipping.component.css']
|
||||||
})
|
})
|
||||||
// #docregion props, ctor
|
// #docregion props, ctor
|
||||||
export class ShippingComponent implements OnInit {
|
export class ShippingComponent {
|
||||||
shippingCosts;
|
shippingCosts;
|
||||||
// #enddocregion props
|
// #enddocregion props
|
||||||
|
|
||||||
@ -19,12 +19,10 @@ export class ShippingComponent implements OnInit {
|
|||||||
constructor(
|
constructor(
|
||||||
private cartService: CartService
|
private cartService: CartService
|
||||||
) {
|
) {
|
||||||
|
// #enddocregion inject-cart-service
|
||||||
|
this.shippingCosts = this.cartService.getShippingPrices();
|
||||||
|
// #docregion inject-cart-service
|
||||||
}
|
}
|
||||||
// #enddocregion inject-cart-service
|
// #enddocregion inject-cart-service
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.shippingCosts = this.cartService.getShippingPrices();
|
|
||||||
}
|
|
||||||
|
|
||||||
// #docregion props
|
// #docregion props
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<h1>HTTP Sample</h1>
|
<h1>HTTP Sample</h1>
|
||||||
<div>
|
<div>
|
||||||
<input type="checkbox" id="heroes" [checked]="showHeroes" (click)="toggleHeroes()">
|
<input type="checkbox" id="heroes" [checked]="toggleHeroes" (click)="toggleHeroes()">
|
||||||
<label for="heroes">Heroes</label>
|
<label for="heroes">Heroes</label>
|
||||||
|
|
||||||
<input type="checkbox" id="config" [checked]="showConfig" (click)="toggleConfig()">
|
<input type="checkbox" id="config" [checked]="showConfig" (click)="toggleConfig()">
|
||||||
|
@ -12,7 +12,7 @@ if (environment.production) {
|
|||||||
// use the require method provided by webpack
|
// use the require method provided by webpack
|
||||||
declare const require;
|
declare const require;
|
||||||
// we use the webpack raw-loader to return the content as a string
|
// we use the webpack raw-loader to return the content as a string
|
||||||
const translations = require('raw-loader!./locale/messages.fr.xlf').default;
|
const translations = require(`raw-loader!./locale/messages.fr.xlf`);
|
||||||
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule, {
|
platformBrowserDynamic().bootstrapModule(AppModule, {
|
||||||
providers: [
|
providers: [
|
||||||
|
@ -10,6 +10,7 @@ export class AppComponent {
|
|||||||
gender = 'female';
|
gender = 'female';
|
||||||
fly = true;
|
fly = true;
|
||||||
logo = 'https://angular.io/assets/images/logos/angular/angular.png';
|
logo = 'https://angular.io/assets/images/logos/angular/angular.png';
|
||||||
|
heroes: string[] = ['Magneta', 'Celeritas', 'Dynama'];
|
||||||
inc(i: number) {
|
inc(i: number) {
|
||||||
this.minutes = Math.min(5, Math.max(0, this.minutes + i));
|
this.minutes = Math.min(5, Math.max(0, this.minutes + i));
|
||||||
}
|
}
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
// imports
|
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
|
||||||
|
|
||||||
// @NgModule decorator with its metadata
|
|
||||||
@NgModule({
|
|
||||||
declarations: [AppComponent],
|
|
||||||
imports: [BrowserModule],
|
|
||||||
providers: [],
|
|
||||||
bootstrap: [AppComponent]
|
|
||||||
})
|
|
||||||
export class AppModule {}
|
|
@ -1,24 +0,0 @@
|
|||||||
import { browser, element, by } from 'protractor';
|
|
||||||
import { logging } from 'selenium-webdriver';
|
|
||||||
|
|
||||||
describe('Providers and ViewProviders', function () {
|
|
||||||
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
browser.get('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shows basic flower emoji', function() {
|
|
||||||
expect(element.all(by.css('p')).get(0).getText()).toContain('🌺');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shows whale emoji', function() {
|
|
||||||
expect(element.all(by.css('p')).get(1).getText()).toContain('🐳');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shows sunflower from FlowerService', function() {
|
|
||||||
expect(element.all(by.css('p')).get(8).getText()).toContain('🌻');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
|||||||
// #docregion animal-service
|
|
||||||
import { Injectable } from '@angular/core';
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root'
|
|
||||||
})
|
|
||||||
export class AnimalService {
|
|
||||||
emoji = '🐳';
|
|
||||||
}
|
|
||||||
// #enddocregion animal-service
|
|
@ -1,15 +0,0 @@
|
|||||||
import { Component } from '@angular/core';
|
|
||||||
import { FlowerService } from './flower.service';
|
|
||||||
import { AnimalService } from './animal.service';
|
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-root',
|
|
||||||
templateUrl: './app.component.html',
|
|
||||||
styleUrls: [ './app.component.css' ]
|
|
||||||
})
|
|
||||||
// #docregion injection
|
|
||||||
export class AppComponent {
|
|
||||||
constructor(public flower: FlowerService) {}
|
|
||||||
}
|
|
||||||
// #enddocregion injection
|
|
@ -1,15 +0,0 @@
|
|||||||
|
|
||||||
<h2>From AppComponent:</h2>
|
|
||||||
<!-- #docregion binding-flower -->
|
|
||||||
<p>Emoji from FlowerService: {{flower.emoji}}</p>
|
|
||||||
<!-- #enddocregion binding-flower -->
|
|
||||||
<!-- #docregion binding-animal -->
|
|
||||||
<p>Emoji from AnimalService: {{animal.emoji}}</p>
|
|
||||||
<!-- #enddocregion binding-animal -->
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<h2>From ChildComponent:</h2>
|
|
||||||
<!-- #docregion content-projection -->
|
|
||||||
<app-child><app-inspector></app-inspector></app-child>
|
|
||||||
<!-- #enddocregion content-projection -->
|
|
@ -1,15 +0,0 @@
|
|||||||
import { Component } from '@angular/core';
|
|
||||||
import { FlowerService } from './flower.service';
|
|
||||||
import { AnimalService } from './animal.service';
|
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-root',
|
|
||||||
templateUrl: './app.component.html',
|
|
||||||
styleUrls: [ './app.component.css' ]
|
|
||||||
})
|
|
||||||
// #docregion inject-animal-service
|
|
||||||
export class AppComponent {
|
|
||||||
constructor(public flower: FlowerService, public animal: AnimalService) {}
|
|
||||||
}
|
|
||||||
// #enddocregion inject-animal-service
|
|
@ -1,17 +0,0 @@
|
|||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
|
||||||
import { FormsModule } from '@angular/forms';
|
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
|
||||||
import { ChildComponent } from './child/child.component';
|
|
||||||
import { InspectorComponent } from './inspector/inspector.component';
|
|
||||||
|
|
||||||
// #docregion appmodule
|
|
||||||
@NgModule({
|
|
||||||
imports: [ BrowserModule, FormsModule ],
|
|
||||||
declarations: [ AppComponent, ChildComponent, InspectorComponent ],
|
|
||||||
bootstrap: [ AppComponent ],
|
|
||||||
providers: []
|
|
||||||
})
|
|
||||||
export class AppModule { }
|
|
||||||
// #enddocregion appmodule
|
|
@ -1,19 +0,0 @@
|
|||||||
import { Component, OnInit, Host, SkipSelf, Optional } from '@angular/core';
|
|
||||||
import { FlowerService } from '../flower.service';
|
|
||||||
|
|
||||||
// #docregion flowerservice
|
|
||||||
@Component({
|
|
||||||
selector: 'app-child',
|
|
||||||
templateUrl: './child.component.html',
|
|
||||||
styleUrls: ['./child.component.css'],
|
|
||||||
// use the providers array to provide a service
|
|
||||||
providers: [{ provide: FlowerService, useValue: { emoji: '🌻' } }]
|
|
||||||
})
|
|
||||||
|
|
||||||
export class ChildComponent {
|
|
||||||
// inject the service
|
|
||||||
constructor( public flower: FlowerService) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
// #enddocregion flowerservice
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
|||||||
.container {
|
|
||||||
border: 1px solid darkblue;
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
<!-- #docplaster -->
|
|
||||||
<!-- #docregion child-component -->
|
|
||||||
<!-- #docregion flower-binding -->
|
|
||||||
<p>Emoji from FlowerService: {{flower.emoji}}</p>
|
|
||||||
<!-- #enddocregion flower-binding -->
|
|
||||||
<!-- #docregion animal-binding -->
|
|
||||||
<p>Emoji from AnimalService: {{animal.emoji}}</p>
|
|
||||||
<!-- #enddocregion animal-binding -->
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<h3>Content projection</h3>
|
|
||||||
<!-- #enddocregion child-component -->
|
|
||||||
<p>The following is coming from content. It doesn't get to see the puppy because the puppy is declared inside the view only.</p>
|
|
||||||
<!-- #docregion child-component -->
|
|
||||||
<ng-content></ng-content>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h3>Inside the view</h3>
|
|
||||||
<!-- #enddocregion child-component -->
|
|
||||||
<p>The following is inside the view so it does see the puppy.</p>
|
|
||||||
<!-- #docregion child-component -->
|
|
||||||
<app-inspector></app-inspector>
|
|
||||||
<!-- #enddocregion child-component -->
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
|||||||
// #docplaster
|
|
||||||
import { Component, OnInit, Host, SkipSelf, Optional } from '@angular/core';
|
|
||||||
import { FlowerService } from '../flower.service';
|
|
||||||
import { AnimalService } from '../animal.service';
|
|
||||||
|
|
||||||
// #docregion provide-animal-service
|
|
||||||
@Component({
|
|
||||||
selector: 'app-child',
|
|
||||||
templateUrl: './child.component.html',
|
|
||||||
styleUrls: ['./child.component.css'],
|
|
||||||
// provide services
|
|
||||||
providers: [{ provide: FlowerService, useValue: { emoji: '🌻' } }],
|
|
||||||
viewProviders: [{ provide: AnimalService, useValue: { emoji: '🐶' } }]
|
|
||||||
})
|
|
||||||
|
|
||||||
export class ChildComponent {
|
|
||||||
// inject service
|
|
||||||
constructor( public flower: FlowerService, public animal: AnimalService) { }
|
|
||||||
// #enddocregion provide-animal-service
|
|
||||||
|
|
||||||
// viewProviders ensures that only the view gets to see this.
|
|
||||||
// With the AnimalService in the viewProviders, the
|
|
||||||
// InspectorComponent doesn't get to see it because the
|
|
||||||
// inspector is in the content.
|
|
||||||
|
|
||||||
|
|
||||||
// constructor( public flower: FlowerService, @Optional() @Host() public animal: AnimalService) { }
|
|
||||||
|
|
||||||
// Comment out the above constructor and alternately
|
|
||||||
// uncomment the two following constructors to see the
|
|
||||||
// effects of @Host() and @Host() + @SkipSelf().
|
|
||||||
|
|
||||||
// constructor(
|
|
||||||
// @Host() public animal : AnimalService,
|
|
||||||
// @Host() @Optional() public flower : FlowerService) { }
|
|
||||||
|
|
||||||
// constructor(
|
|
||||||
// @SkipSelf() @Host() public animal : AnimalService,
|
|
||||||
// @SkipSelf() @Host() @Optional() public flower : FlowerService) { }
|
|
||||||
|
|
||||||
// #docregion provide-animal-service
|
|
||||||
}
|
|
||||||
// #enddocregion provide-animal-service
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
|
|
||||||
// #docregion flowerservice
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root'
|
|
||||||
})
|
|
||||||
export class FlowerService {
|
|
||||||
emoji = '🌺';
|
|
||||||
}
|
|
||||||
// #enddocregion flowerservice
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
|||||||
<!-- #docregion binding -->
|
|
||||||
<p>Emoji from FlowerService: {{flower.emoji}}</p>
|
|
||||||
<p>Emoji from AnimalService: {{animal.emoji}}</p>
|
|
||||||
<!-- #enddocregion binding -->
|
|
@ -1,14 +0,0 @@
|
|||||||
import { Component } from '@angular/core';
|
|
||||||
import { FlowerService } from '../flower.service';
|
|
||||||
import { AnimalService } from '../animal.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-inspector',
|
|
||||||
templateUrl: './inspector.component.html',
|
|
||||||
styleUrls: ['./inspector.component.css']
|
|
||||||
})
|
|
||||||
// #docregion injection
|
|
||||||
export class InspectorComponent {
|
|
||||||
constructor(public flower: FlowerService, public animal: AnimalService) { }
|
|
||||||
}
|
|
||||||
// #enddocregion injection
|
|
@ -1,14 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>providers vs. viewProviders</title>
|
|
||||||
<base href="/">
|
|
||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<app-root></app-root>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,12 +0,0 @@
|
|||||||
import { enableProdMode } from '@angular/core';
|
|
||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
|
||||||
|
|
||||||
import { AppModule } from './app/app.module';
|
|
||||||
import { environment } from './environments/environment';
|
|
||||||
|
|
||||||
if (environment.production) {
|
|
||||||
enableProdMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule)
|
|
||||||
.catch(err => console.log(err));
|
|
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Inputs and Outputs",
|
|
||||||
"files": [
|
|
||||||
"!**/*.d.ts",
|
|
||||||
"!**/*.js",
|
|
||||||
"!**/*.[1,2].*"
|
|
||||||
],
|
|
||||||
"file": "src/app/app.component.ts",
|
|
||||||
"tags": ["Inputs and Outputs"]
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
import { browser, element, by } from 'protractor';
|
|
||||||
|
|
||||||
describe('Resolution-modifiers-example', function () {
|
|
||||||
|
|
||||||
beforeAll(function () {
|
|
||||||
browser.get('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shows basic flower emoji', function() {
|
|
||||||
expect(element.all(by.css('p')).get(0).getText()).toContain('🌸');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shows basic leaf emoji', function() {
|
|
||||||
expect(element.all(by.css('p')).get(1).getText()).toContain('🌿');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shows yellow flower in host child', function() {
|
|
||||||
expect(element.all(by.css('p')).get(9).getText()).toContain('🌼');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
@ -1,14 +0,0 @@
|
|||||||
<h1>DI resolution modifiers</h1>
|
|
||||||
|
|
||||||
<p>Basic flower service: {{flower.emoji}}</p>
|
|
||||||
<p>Basic leaf service: {{leaf.emoji}}</p>
|
|
||||||
|
|
||||||
<app-optional></app-optional>
|
|
||||||
|
|
||||||
<app-self></app-self>
|
|
||||||
|
|
||||||
<app-self-no-data></app-self-no-data>
|
|
||||||
|
|
||||||
<app-skipself></app-skipself>
|
|
||||||
|
|
||||||
<app-host-parent></app-host-parent>
|
|
@ -1,13 +0,0 @@
|
|||||||
import { Component } from '@angular/core';
|
|
||||||
import { LeafService } from './leaf.service';
|
|
||||||
import { FlowerService } from './flower.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-root',
|
|
||||||
templateUrl: './app.component.html',
|
|
||||||
styleUrls: [ './app.component.css' ]
|
|
||||||
})
|
|
||||||
export class AppComponent {
|
|
||||||
name = 'Angular';
|
|
||||||
constructor(public flower: FlowerService, public leaf: LeafService) {}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
;
|
|
||||||
import { OptionalComponent } from './optional/optional.component';
|
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
|
||||||
import { FormsModule } from '@angular/forms';
|
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
|
||||||
import { SelfNoDataComponent } from './self-no-data/self-no-data.component';
|
|
||||||
import { HostComponent } from './host/host.component';
|
|
||||||
import { SelfComponent } from './self/self.component';
|
|
||||||
import { SkipselfComponent } from './skipself/skipself.component';
|
|
||||||
import { HostParentComponent } from './host-parent/host-parent.component';
|
|
||||||
import { HostChildComponent } from './host-child/host-child.component';
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [
|
|
||||||
BrowserModule,
|
|
||||||
FormsModule
|
|
||||||
],
|
|
||||||
declarations: [
|
|
||||||
AppComponent,
|
|
||||||
OptionalComponent,
|
|
||||||
SelfComponent,
|
|
||||||
SelfNoDataComponent,
|
|
||||||
HostComponent,
|
|
||||||
SkipselfComponent,
|
|
||||||
HostParentComponent,
|
|
||||||
HostChildComponent
|
|
||||||
],
|
|
||||||
bootstrap: [AppComponent],
|
|
||||||
providers: []
|
|
||||||
})
|
|
||||||
export class AppModule { }
|
|
@ -1,9 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root' // provide this service in the root ModuleInjector
|
|
||||||
|
|
||||||
})
|
|
||||||
export class FlowerService {
|
|
||||||
emoji = '🌸';
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
.section {
|
|
||||||
border: 2px solid #369;
|
|
||||||
padding: 1rem;
|
|
||||||
margin: 1rem 0;
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
<div class="section">
|
|
||||||
<h2>Child of @Host() Component</h2>
|
|
||||||
<p>Flower emoji: {{flower.emoji}}</p>
|
|
||||||
</div>
|
|
@ -1,11 +0,0 @@
|
|||||||
import { Component } from '@angular/core';
|
|
||||||
import { FlowerService } from '../flower.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-host-child',
|
|
||||||
templateUrl: './host-child.component.html',
|
|
||||||
styleUrls: ['./host-child.component.css']
|
|
||||||
})
|
|
||||||
export class HostChildComponent {
|
|
||||||
constructor(public flower: FlowerService) { }
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
.section {
|
|
||||||
border: 2px solid #369;
|
|
||||||
padding: 1rem;
|
|
||||||
margin: 1rem 0;
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
<div class="section">
|
|
||||||
<h2>Parent of @Host() Component</h2>
|
|
||||||
<p>Flower emoji: {{flower.emoji}}</p>
|
|
||||||
<app-host></app-host>
|
|
||||||
</div>
|
|
@ -1,16 +0,0 @@
|
|||||||
import { Component } from '@angular/core';
|
|
||||||
import { FlowerService } from '../flower.service';
|
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-host-parent',
|
|
||||||
templateUrl: './host-parent.component.html',
|
|
||||||
styleUrls: ['./host-parent.component.css'],
|
|
||||||
providers: [{ provide: FlowerService, useValue: { emoji: '🌺' } }]
|
|
||||||
|
|
||||||
})
|
|
||||||
export class HostParentComponent {
|
|
||||||
|
|
||||||
constructor(public flower: FlowerService) { }
|
|
||||||
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
.section {
|
|
||||||
border: 2px solid #369;
|
|
||||||
padding: 1rem;
|
|
||||||
margin: 1rem 0;
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
<div class="section">
|
|
||||||
<h2>@Host() Component</h2>
|
|
||||||
<p>Flower emoji: {{flower.emoji}}</p>
|
|
||||||
<p><i>(@Host() stops it here)</i></p>
|
|
||||||
<app-host-child></app-host-child>
|
|
||||||
</div>
|
|
@ -1,21 +0,0 @@
|
|||||||
import { Component, Host, Optional } from '@angular/core';
|
|
||||||
import { FlowerService } from '../flower.service';
|
|
||||||
|
|
||||||
// #docregion host-component
|
|
||||||
@Component({
|
|
||||||
selector: 'app-host',
|
|
||||||
templateUrl: './host.component.html',
|
|
||||||
styleUrls: ['./host.component.css'],
|
|
||||||
// provide the service
|
|
||||||
providers: [{ provide: FlowerService, useValue: { emoji: '🌼' } }]
|
|
||||||
})
|
|
||||||
export class HostComponent {
|
|
||||||
// use @Host() in the constructor when injecting the service
|
|
||||||
constructor(@Host() @Optional() public flower: FlowerService) { }
|
|
||||||
|
|
||||||
}
|
|
||||||
// #enddocregion host-component
|
|
||||||
|
|
||||||
// if you take out @Host() and the providers array, flower will be red hibiscus
|
|
||||||
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root'
|
|
||||||
})
|
|
||||||
// #docregion leafservice
|
|
||||||
export class LeafService {
|
|
||||||
emoji = '🌿';
|
|
||||||
}
|
|
||||||
// #enddocregion leafservice
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class OptionalService {
|
|
||||||
}
|
|
||||||
|
|
||||||
// This service isn't provided anywhere.
|
|
@ -1,5 +0,0 @@
|
|||||||
.section {
|
|
||||||
border: 2px solid #369;
|
|
||||||
padding: 1rem;
|
|
||||||
margin: 1rem 0;
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
<div class="section">
|
|
||||||
<h2>@Optional() Component</h2>
|
|
||||||
<p>This component still works even though the OptionalService (notice @Optional() in the consturctor isn't provided or configured anywhere. Angular goes through tree and visibilty rules, and if it doesn't find the requested service, returns null.</p>
|
|
||||||
</div>
|
|
@ -1,21 +0,0 @@
|
|||||||
import { Component, Optional } from '@angular/core';
|
|
||||||
import { OptionalService } from '../optional.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-optional',
|
|
||||||
templateUrl: './optional.component.html',
|
|
||||||
styleUrls: ['./optional.component.css']
|
|
||||||
})
|
|
||||||
|
|
||||||
// #docregion optional-component
|
|
||||||
export class OptionalComponent {
|
|
||||||
constructor(@Optional() public optional: OptionalService) {}
|
|
||||||
}
|
|
||||||
// #enddocregion optional-component
|
|
||||||
|
|
||||||
// The OptionalService isn't provided here, in the @Injectable()
|
|
||||||
// providers array, or in the NgModule. If you remove @Optional()
|
|
||||||
// from the constructor, you'll get an error.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
.section {
|
|
||||||
border: 2px solid #369;
|
|
||||||
padding: 1rem;
|
|
||||||
margin: 1rem 0;
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
<div class="section">
|
|
||||||
<h2>@Self() Component (without a provider)</h2>
|
|
||||||
<p>Leaf emoji: {{leaf?.emoji}}</p>
|
|
||||||
</div>
|
|
@ -1,18 +0,0 @@
|
|||||||
import { Component, Self, Optional } from '@angular/core';
|
|
||||||
import { LeafService } from '../leaf.service';
|
|
||||||
|
|
||||||
// #docregion self-no-data-component
|
|
||||||
@Component({
|
|
||||||
selector: 'app-self-no-data',
|
|
||||||
templateUrl: './self-no-data.component.html',
|
|
||||||
styleUrls: ['./self-no-data.component.css']
|
|
||||||
})
|
|
||||||
export class SelfNoDataComponent {
|
|
||||||
constructor(@Self() @Optional() public leaf: LeafService) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
// #enddocregion self-no-data-component
|
|
||||||
|
|
||||||
// The app doesn't break because the value being available at self is optional.
|
|
||||||
// If you remove @Optional(), the app breaks.
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
.section {
|
|
||||||
border: 2px solid #369;
|
|
||||||
padding: 1rem;
|
|
||||||
margin: 1rem 0;
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
<div class="section">
|
|
||||||
<h2>@Self() Component</h2>
|
|
||||||
<p>Flower emoji: {{flower?.emoji}}</p>
|
|
||||||
</div>
|
|
@ -1,19 +0,0 @@
|
|||||||
import { Component, Self } from '@angular/core';
|
|
||||||
import { FlowerService } from '../flower.service';
|
|
||||||
|
|
||||||
// #docregion self-component
|
|
||||||
@Component({
|
|
||||||
selector: 'app-self',
|
|
||||||
templateUrl: './self.component.html',
|
|
||||||
styleUrls: ['./self.component.css'],
|
|
||||||
providers: [{ provide: FlowerService, useValue: { emoji: '🌼' } }]
|
|
||||||
|
|
||||||
})
|
|
||||||
export class SelfComponent {
|
|
||||||
constructor(@Self() public flower: FlowerService) {}
|
|
||||||
}
|
|
||||||
// #enddocregion self-component
|
|
||||||
|
|
||||||
// This component provides the FlowerService so the injector
|
|
||||||
// doesn't have to look further up the injector tree
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
.section {
|
|
||||||
border: 2px solid #369;
|
|
||||||
padding: 1rem;
|
|
||||||
margin: 1rem 0;
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
<div class="section">
|
|
||||||
<h2>@SkipSelf() Component</h2>
|
|
||||||
<p>Leaf emoji: {{leaf.emoji}}</p>
|
|
||||||
</div>
|
|
@ -1,18 +0,0 @@
|
|||||||
import { Component, SkipSelf } from '@angular/core';
|
|
||||||
import { LeafService } from '../leaf.service';
|
|
||||||
|
|
||||||
// #docregion skipself-component
|
|
||||||
@Component({
|
|
||||||
selector: 'app-skipself',
|
|
||||||
templateUrl: './skipself.component.html',
|
|
||||||
styleUrls: ['./skipself.component.css'],
|
|
||||||
// Angular would ignore this LeafService instance
|
|
||||||
providers: [{ provide: LeafService, useValue: { emoji: '🍁' } }]
|
|
||||||
})
|
|
||||||
export class SkipselfComponent {
|
|
||||||
// Use @SkipSelf() in the constructor
|
|
||||||
constructor(@SkipSelf() public leaf: LeafService) { }
|
|
||||||
}
|
|
||||||
// #enddocregion skipself-component
|
|
||||||
|
|
||||||
// @SkipSelf(): Specifies that the dependency resolution should start from the parent injector, not here.
|
|
@ -1,14 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>DI Resolution Modifiers Example</title>
|
|
||||||
<base href="/">
|
|
||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<app-root>Loading...</app-root>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,11 +0,0 @@
|
|||||||
import { enableProdMode } from '@angular/core';
|
|
||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
|
||||||
|
|
||||||
import { AppModule } from './app/app.module';
|
|
||||||
import { environment } from './environments/environment';
|
|
||||||
|
|
||||||
if (environment.production) {
|
|
||||||
enableProdMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
|
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "NgModules",
|
|
||||||
"files": [
|
|
||||||
"!**/*.d.ts",
|
|
||||||
"!**/*.js",
|
|
||||||
"!**/*.[1,2].*"
|
|
||||||
],
|
|
||||||
"file": "src/app/app.component.ts",
|
|
||||||
"tags": ["NgModules"]
|
|
||||||
}
|
|
@ -7,9 +7,9 @@ import { from } from 'rxjs';
|
|||||||
const data = from(fetch('/api/endpoint'));
|
const data = from(fetch('/api/endpoint'));
|
||||||
// Subscribe to begin listening for async result
|
// Subscribe to begin listening for async result
|
||||||
data.subscribe({
|
data.subscribe({
|
||||||
next(response) { console.log(response); },
|
next(response) { console.log(response); },
|
||||||
error(err) { console.error('Error: ' + err); },
|
error(err) { console.error('Error: ' + err); },
|
||||||
complete() { console.log('Completed'); }
|
complete() { console.log('Completed'); }
|
||||||
});
|
});
|
||||||
|
|
||||||
// #enddocregion promise
|
// #enddocregion promise
|
||||||
|
12
aio/content/examples/setup/quickstart-specs.stackblitz.json
Normal file
12
aio/content/examples/setup/quickstart-specs.stackblitz.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"description": "Quickstart AppComponent Testing",
|
||||||
|
"files":[
|
||||||
|
"src/browser-test-shim.js",
|
||||||
|
"src/app/app.component.ts",
|
||||||
|
"src/app/app.component.spec.ts",
|
||||||
|
"src/quickstart-specs.html"
|
||||||
|
],
|
||||||
|
"main": "src/quickstart-specs.html",
|
||||||
|
"file": "src/app/app.component.spec.ts",
|
||||||
|
"tags": ["quickstart", "setup", "testing"]
|
||||||
|
}
|
36
aio/content/examples/setup/src/quickstart-specs.html
Normal file
36
aio/content/examples/setup/src/quickstart-specs.html
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<!-- Run application specs in a browser -->
|
||||||
|
<!-- #docregion -->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<base href="/">
|
||||||
|
<title>1st Specs</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
<link rel="stylesheet" href="node_modules/jasmine-core/lib/jasmine-core/jasmine.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- Polyfills -->
|
||||||
|
<script src="node_modules/core-js/client/shim.min.js"></script>
|
||||||
|
|
||||||
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
|
<script src="node_modules/jasmine-core/lib/jasmine-core/jasmine.js"></script>
|
||||||
|
<script src="node_modules/jasmine-core/lib/jasmine-core/jasmine-html.js"></script>
|
||||||
|
<script src="node_modules/jasmine-core/lib/jasmine-core/boot.js"></script>
|
||||||
|
|
||||||
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
|
<script src="node_modules/zone.js/dist/zone-testing.js"></script>
|
||||||
|
|
||||||
|
<!-- #docregion files -->
|
||||||
|
<script>
|
||||||
|
var __spec_files__ = [
|
||||||
|
'app/app.component.spec'
|
||||||
|
];
|
||||||
|
</script>
|
||||||
|
<!-- #enddocregion files-->
|
||||||
|
<script src="browser-test-shim.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
12
aio/content/examples/setup/stackblitz.json
Normal file
12
aio/content/examples/setup/stackblitz.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"description": "QuickStart Setup",
|
||||||
|
"files": [
|
||||||
|
"src/app/app.component.ts",
|
||||||
|
"src/app/app.module.ts",
|
||||||
|
"src/index.html",
|
||||||
|
"src/main.ts",
|
||||||
|
"src/styles.css"
|
||||||
|
],
|
||||||
|
"file": "src/app/app.component.ts",
|
||||||
|
"tags": ["quickstart", "setup", "seed"]
|
||||||
|
}
|
@ -1,22 +1,24 @@
|
|||||||
{
|
{
|
||||||
"description": "Testing - specs",
|
"description": "Testing - specs",
|
||||||
"files":[
|
"files":[
|
||||||
"src/expected.ts",
|
|
||||||
"src/index-specs.html",
|
|
||||||
"src/main-specs.ts",
|
|
||||||
"src/styles.css",
|
"src/styles.css",
|
||||||
"src/test.css",
|
|
||||||
"src/tests.sb.ts",
|
|
||||||
|
|
||||||
"e2e/src/**/*.ts",
|
|
||||||
|
|
||||||
"src/app/**/*.css",
|
"src/app/**/*.css",
|
||||||
"src/app/**/*.html",
|
"src/app/**/*.html",
|
||||||
"src/app/**/*.ts",
|
"src/app/**/*.ts",
|
||||||
|
"src/app/**/*.spec.ts",
|
||||||
|
|
||||||
"src/testing/**/*",
|
"src/testing/*.ts",
|
||||||
|
|
||||||
"src/**/*.spec.ts"
|
"!src/main.ts",
|
||||||
|
"!src/app/bag/*.*",
|
||||||
|
"!src/app/1st.spec.ts",
|
||||||
|
|
||||||
|
"src/expected.ts",
|
||||||
|
"src/test.css",
|
||||||
|
"src/tests.sb.ts",
|
||||||
|
"src/main-specs.ts",
|
||||||
|
"src/index-specs.html"
|
||||||
],
|
],
|
||||||
"main": "src/index-specs.html",
|
"main": "src/index-specs.html",
|
||||||
"tags": ["testing"]
|
"tags": ["testing"]
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
import jasmineRequire from 'jasmine-core/lib/jasmine-core/jasmine.js';
|
const jasmineRequire = require('jasmine-core/lib/jasmine-core/jasmine.js');
|
||||||
|
|
||||||
window['jasmineRequire'] = jasmineRequire;
|
window['jasmineRequire'] = jasmineRequire;
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
{
|
{
|
||||||
"description": "Heroes Test App",
|
"description": "Heroes Test App",
|
||||||
"files":[
|
"files":[
|
||||||
"src/index.html",
|
|
||||||
"src/main.ts",
|
|
||||||
"src/styles.css",
|
"src/styles.css",
|
||||||
"src/test.css",
|
|
||||||
|
|
||||||
"e2e/src/**/*.ts",
|
|
||||||
|
|
||||||
"src/app/**/*.css",
|
"src/app/**/*.css",
|
||||||
"src/app/**/*.html",
|
"src/app/**/*.html",
|
||||||
"src/app/**/*.ts",
|
"src/app/**/*.ts",
|
||||||
|
|
||||||
"!src/**/*.spec.ts"
|
"!src/app/bag/*.*",
|
||||||
|
|
||||||
|
"!src/test.ts",
|
||||||
|
|
||||||
|
"src/test.css",
|
||||||
|
"src/main.ts",
|
||||||
|
"src/index.html"
|
||||||
],
|
],
|
||||||
"tags": ["testing"]
|
"tags": ["testing"]
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
/* HeroesComponent's private CSS styles */
|
/* HeroesComponent's private CSS styles */
|
||||||
|
.selected {
|
||||||
|
background-color: #CFD8DC !important;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
.heroes {
|
.heroes {
|
||||||
margin: 0 0 2em 0;
|
margin: 0 0 2em 0;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
@ -15,18 +19,18 @@
|
|||||||
height: 1.6em;
|
height: 1.6em;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
.heroes li.selected:hover {
|
||||||
|
background-color: #BBD8DC !important;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
.heroes li:hover {
|
.heroes li:hover {
|
||||||
color: #607D8B;
|
color: #607D8B;
|
||||||
background-color: #DDD;
|
background-color: #DDD;
|
||||||
left: .1em;
|
left: .1em;
|
||||||
}
|
}
|
||||||
.heroes li.selected {
|
.heroes .text {
|
||||||
background-color: #CFD8DC;
|
position: relative;
|
||||||
color: white;
|
top: -3px;
|
||||||
}
|
|
||||||
.heroes li.selected:hover {
|
|
||||||
background-color: #BBD8DC;
|
|
||||||
color: white;
|
|
||||||
}
|
}
|
||||||
.heroes .badge {
|
.heroes .badge {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -34,7 +34,4 @@ export class HeroesComponent implements OnInit {
|
|||||||
this.selectedHero = hero;
|
this.selectedHero = hero;
|
||||||
}
|
}
|
||||||
// #enddocregion on-select
|
// #enddocregion on-select
|
||||||
// #docregion component
|
|
||||||
}
|
}
|
||||||
// #enddocregion component
|
|
||||||
|
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
/* HeroesComponent's private CSS styles */
|
/* HeroesComponent's private CSS styles */
|
||||||
|
.selected {
|
||||||
|
background-color: #CFD8DC !important;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
.heroes {
|
.heroes {
|
||||||
margin: 0 0 2em 0;
|
margin: 0 0 2em 0;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
@ -15,18 +19,18 @@
|
|||||||
height: 1.6em;
|
height: 1.6em;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
.heroes li.selected:hover {
|
||||||
|
background-color: #BBD8DC !important;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
.heroes li:hover {
|
.heroes li:hover {
|
||||||
color: #607D8B;
|
color: #607D8B;
|
||||||
background-color: #DDD;
|
background-color: #DDD;
|
||||||
left: .1em;
|
left: .1em;
|
||||||
}
|
}
|
||||||
.heroes li.selected {
|
.heroes .text {
|
||||||
background-color: #CFD8DC;
|
position: relative;
|
||||||
color: white;
|
top: -3px;
|
||||||
}
|
|
||||||
.heroes li.selected:hover {
|
|
||||||
background-color: #BBD8DC;
|
|
||||||
color: white;
|
|
||||||
}
|
}
|
||||||
.heroes .badge {
|
.heroes .badge {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
/* HeroesComponent's private CSS styles */
|
/* HeroesComponent's private CSS styles */
|
||||||
|
.selected {
|
||||||
|
background-color: #CFD8DC !important;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
.heroes {
|
.heroes {
|
||||||
margin: 0 0 2em 0;
|
margin: 0 0 2em 0;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
@ -15,18 +19,18 @@
|
|||||||
height: 1.6em;
|
height: 1.6em;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
.heroes li.selected:hover {
|
||||||
|
background-color: #BBD8DC !important;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
.heroes li:hover {
|
.heroes li:hover {
|
||||||
color: #607D8B;
|
color: #607D8B;
|
||||||
background-color: #DDD;
|
background-color: #DDD;
|
||||||
left: .1em;
|
left: .1em;
|
||||||
}
|
}
|
||||||
.heroes li.selected {
|
.heroes .text {
|
||||||
background-color: #CFD8DC;
|
position: relative;
|
||||||
color: white;
|
top: -3px;
|
||||||
}
|
|
||||||
.heroes li.selected:hover {
|
|
||||||
background-color: #BBD8DC;
|
|
||||||
color: white;
|
|
||||||
}
|
}
|
||||||
.heroes .badge {
|
.heroes .badge {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -39,6 +43,8 @@
|
|||||||
left: -1px;
|
left: -1px;
|
||||||
top: -4px;
|
top: -4px;
|
||||||
height: 1.8em;
|
height: 1.8em;
|
||||||
|
min-width: 16px;
|
||||||
|
text-align: right;
|
||||||
margin-right: .8em;
|
margin-right: .8em;
|
||||||
border-radius: 4px 0 0 4px;
|
border-radius: 4px 0 0 4px;
|
||||||
}
|
}
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
|
||||||
import { HeroesComponent } from './heroes/heroes.component';
|
|
||||||
|
|
||||||
const routes: Routes = [
|
|
||||||
{ path: 'heroes', component: HeroesComponent }
|
|
||||||
];
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [RouterModule.forRoot(routes)],
|
|
||||||
exports: [RouterModule]
|
|
||||||
})
|
|
||||||
export class AppRoutingModule { }
|
|
@ -7,7 +7,9 @@ import { RouterModule, Routes } from '@angular/router';
|
|||||||
// #docregion import-dashboard
|
// #docregion import-dashboard
|
||||||
import { DashboardComponent } from './dashboard/dashboard.component';
|
import { DashboardComponent } from './dashboard/dashboard.component';
|
||||||
// #enddocregion import-dashboard
|
// #enddocregion import-dashboard
|
||||||
|
// #docregion heroes-route
|
||||||
import { HeroesComponent } from './heroes/heroes.component';
|
import { HeroesComponent } from './heroes/heroes.component';
|
||||||
|
// #enddocregion heroes-route
|
||||||
// #docregion import-herodetail
|
// #docregion import-herodetail
|
||||||
import { HeroDetailComponent } from './hero-detail/hero-detail.component';
|
import { HeroDetailComponent } from './hero-detail/hero-detail.component';
|
||||||
// #enddocregion import-herodetail
|
// #enddocregion import-herodetail
|
||||||
@ -37,9 +39,7 @@ const routes: Routes = [
|
|||||||
imports: [ RouterModule.forRoot(routes) ],
|
imports: [ RouterModule.forRoot(routes) ],
|
||||||
// #enddocregion ngmodule-imports
|
// #enddocregion ngmodule-imports
|
||||||
// #docregion v1
|
// #docregion v1
|
||||||
// #docregion export-routermodule
|
|
||||||
exports: [ RouterModule ]
|
exports: [ RouterModule ]
|
||||||
// #enddocregion export-routermodule
|
|
||||||
})
|
})
|
||||||
export class AppRoutingModule {}
|
export class AppRoutingModule {}
|
||||||
// #enddocregion , v1
|
// #enddocregion , v1
|
||||||
|
@ -23,17 +23,13 @@ import { HeroSearchComponent } from './hero-search/hero-search.component';
|
|||||||
// #docregion v1
|
// #docregion v1
|
||||||
import { MessagesComponent } from './messages/messages.component';
|
import { MessagesComponent } from './messages/messages.component';
|
||||||
|
|
||||||
// #docregion import-httpclientmodule
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
// #enddocregion import-httpclientmodule
|
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
AppRoutingModule,
|
AppRoutingModule,
|
||||||
// #docregion in-mem-web-api-imports
|
// #docregion in-mem-web-api-imports
|
||||||
// #docregion import-httpclientmodule
|
|
||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
// #enddocregion import-httpclientmodule
|
|
||||||
|
|
||||||
// The HttpClientInMemoryWebApiModule module intercepts HTTP requests
|
// The HttpClientInMemoryWebApiModule module intercepts HTTP requests
|
||||||
// and returns simulated server responses.
|
// and returns simulated server responses.
|
||||||
@ -42,9 +38,7 @@ import { MessagesComponent } from './messages/messages.component';
|
|||||||
InMemoryDataService, { dataEncapsulation: false }
|
InMemoryDataService, { dataEncapsulation: false }
|
||||||
)
|
)
|
||||||
// #enddocregion in-mem-web-api-imports
|
// #enddocregion in-mem-web-api-imports
|
||||||
// #docregion import-httpclientmodule
|
|
||||||
],
|
],
|
||||||
// #enddocregion import-httpclientmodule
|
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
DashboardComponent,
|
DashboardComponent,
|
||||||
@ -56,9 +50,6 @@ import { MessagesComponent } from './messages/messages.component';
|
|||||||
// #docregion v1
|
// #docregion v1
|
||||||
],
|
],
|
||||||
bootstrap: [ AppComponent ]
|
bootstrap: [ AppComponent ]
|
||||||
// #docregion import-httpclientmodule
|
|
||||||
})
|
})
|
||||||
// #enddocregion import-httpclientmodule
|
|
||||||
|
|
||||||
export class AppModule { }
|
export class AppModule { }
|
||||||
// #enddocregion , v1
|
// #enddocregion , v1
|
||||||
|
@ -13,6 +13,11 @@ import { catchError, map, tap } from 'rxjs/operators';
|
|||||||
import { Hero } from './hero';
|
import { Hero } from './hero';
|
||||||
import { MessageService } from './message.service';
|
import { MessageService } from './message.service';
|
||||||
|
|
||||||
|
// #docregion http-options
|
||||||
|
const httpOptions = {
|
||||||
|
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
|
||||||
|
};
|
||||||
|
// #enddocregion http-options
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class HeroService {
|
export class HeroService {
|
||||||
@ -21,12 +26,6 @@ export class HeroService {
|
|||||||
private heroesUrl = 'api/heroes'; // URL to web api
|
private heroesUrl = 'api/heroes'; // URL to web api
|
||||||
// #enddocregion heroesUrl
|
// #enddocregion heroesUrl
|
||||||
|
|
||||||
// #docregion http-options
|
|
||||||
httpOptions = {
|
|
||||||
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
|
|
||||||
};
|
|
||||||
// #enddocregion http-options
|
|
||||||
|
|
||||||
// #docregion ctor
|
// #docregion ctor
|
||||||
constructor(
|
constructor(
|
||||||
private http: HttpClient,
|
private http: HttpClient,
|
||||||
@ -97,7 +96,7 @@ export class HeroService {
|
|||||||
// #docregion addHero
|
// #docregion addHero
|
||||||
/** POST: add a new hero to the server */
|
/** POST: add a new hero to the server */
|
||||||
addHero (hero: Hero): Observable<Hero> {
|
addHero (hero: Hero): Observable<Hero> {
|
||||||
return this.http.post<Hero>(this.heroesUrl, hero, this.httpOptions).pipe(
|
return this.http.post<Hero>(this.heroesUrl, hero, httpOptions).pipe(
|
||||||
tap((newHero: Hero) => this.log(`added hero w/ id=${newHero.id}`)),
|
tap((newHero: Hero) => this.log(`added hero w/ id=${newHero.id}`)),
|
||||||
catchError(this.handleError<Hero>('addHero'))
|
catchError(this.handleError<Hero>('addHero'))
|
||||||
);
|
);
|
||||||
@ -110,7 +109,7 @@ export class HeroService {
|
|||||||
const id = typeof hero === 'number' ? hero : hero.id;
|
const id = typeof hero === 'number' ? hero : hero.id;
|
||||||
const url = `${this.heroesUrl}/${id}`;
|
const url = `${this.heroesUrl}/${id}`;
|
||||||
|
|
||||||
return this.http.delete<Hero>(url, this.httpOptions).pipe(
|
return this.http.delete<Hero>(url, httpOptions).pipe(
|
||||||
tap(_ => this.log(`deleted hero id=${id}`)),
|
tap(_ => this.log(`deleted hero id=${id}`)),
|
||||||
catchError(this.handleError<Hero>('deleteHero'))
|
catchError(this.handleError<Hero>('deleteHero'))
|
||||||
);
|
);
|
||||||
@ -120,7 +119,7 @@ export class HeroService {
|
|||||||
// #docregion updateHero
|
// #docregion updateHero
|
||||||
/** PUT: update the hero on the server */
|
/** PUT: update the hero on the server */
|
||||||
updateHero (hero: Hero): Observable<any> {
|
updateHero (hero: Hero): Observable<any> {
|
||||||
return this.http.put(this.heroesUrl, hero, this.httpOptions).pipe(
|
return this.http.put(this.heroesUrl, hero, httpOptions).pipe(
|
||||||
tap(_ => this.log(`updated hero id=${hero.id}`)),
|
tap(_ => this.log(`updated hero id=${hero.id}`)),
|
||||||
catchError(this.handleError<any>('updateHero'))
|
catchError(this.handleError<any>('updateHero'))
|
||||||
);
|
);
|
||||||
|
@ -99,7 +99,7 @@ The following example shows how to make a simple progress bar accessible by usin
|
|||||||
|
|
||||||
// Sets the minimum and maximum values for the progressbar role.
|
// Sets the minimum and maximum values for the progressbar role.
|
||||||
'aria-valuemin': '0',
|
'aria-valuemin': '0',
|
||||||
'aria-valuemax': '100',
|
'aria-valuemax': '0',
|
||||||
|
|
||||||
// Binding that updates the current value of the progressbar.
|
// Binding that updates the current value of the progressbar.
|
||||||
'[attr.aria-valuenow]': 'value',
|
'[attr.aria-valuenow]': 'value',
|
||||||
@ -179,8 +179,3 @@ Books
|
|||||||
* "A Web for Everyone: Designing Accessible User Experiences", Sarah Horton and Whitney Quesenbery
|
* "A Web for Everyone: Designing Accessible User Experiences", Sarah Horton and Whitney Quesenbery
|
||||||
|
|
||||||
* "Inclusive Design Patterns", Heydon Pickering
|
* "Inclusive Design Patterns", Heydon Pickering
|
||||||
|
|
||||||
## More on accessibility
|
|
||||||
|
|
||||||
You may also be interested in the following:
|
|
||||||
* [Audit your Angular app's accessibility with codelyzer](https://web.dev/accessible-angular-with-codelyzer/).
|
|
||||||
|
@ -66,7 +66,7 @@ The following table lists some of the key AngularJS template features with their
|
|||||||
|
|
||||||
### Bindings/interpolation
|
### Bindings/interpolation
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.html" region="interpolation"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.html" region="interpolation" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
In Angular, a template expression in curly braces still denotes one-way binding.
|
In Angular, a template expression in curly braces still denotes one-way binding.
|
||||||
@ -102,7 +102,7 @@ The following table lists some of the key AngularJS template features with their
|
|||||||
|
|
||||||
### Pipes
|
### Pipes
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="uppercase"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="uppercase" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
In Angular you use similar syntax with the pipe (|) character to filter output, but now you call them **pipes**.
|
In Angular you use similar syntax with the pipe (|) character to filter output, but now you call them **pipes**.
|
||||||
@ -136,7 +136,7 @@ The following table lists some of the key AngularJS template features with their
|
|||||||
|
|
||||||
### Input variables
|
### Input variables
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="local"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="local" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
Angular has true template input variables that are explicitly defined using the `let` keyword.
|
Angular has true template input variables that are explicitly defined using the `let` keyword.
|
||||||
@ -202,10 +202,10 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
|
|
||||||
### Bootstrapping
|
### Bootstrapping
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/main.ts" header="main.ts"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/main.ts" header="main.ts" linenums="false"></code-example>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/app.module.1.ts" header="app.module.ts"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/app.module.1.ts" header="app.module.ts" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
Angular doesn't have a bootstrap directive.
|
Angular doesn't have a bootstrap directive.
|
||||||
@ -245,7 +245,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
|
|
||||||
### ngClass
|
### ngClass
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="ngClass"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="ngClass" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
In Angular, the `ngClass` directive works similarly.
|
In Angular, the `ngClass` directive works similarly.
|
||||||
@ -291,7 +291,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
|
|
||||||
### Bind to the `click` event
|
### Bind to the `click` event
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="event-binding"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="event-binding" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
AngularJS event-based directives do not exist in Angular.
|
AngularJS event-based directives do not exist in Angular.
|
||||||
@ -338,7 +338,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
|
|
||||||
### Component decorator
|
### Component decorator
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.ts" region="component"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.ts" region="component" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
In Angular, the template no longer specifies its associated controller.
|
In Angular, the template no longer specifies its associated controller.
|
||||||
@ -401,7 +401,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
|
|
||||||
### Bind to the `href` property
|
### Bind to the `href` property
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="href"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="href" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
Angular uses property binding; there is no built-in *href* directive.
|
Angular uses property binding; there is no built-in *href* directive.
|
||||||
@ -412,7 +412,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
|
|
||||||
In Angular, `href` is no longer used for routing. Routing uses `routerLink`, as shown in the following example.
|
In Angular, `href` is no longer used for routing. Routing uses `routerLink`, as shown in the following example.
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="router-link"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="router-link" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
For more information on routing, see the [RouterLink binding](guide/router#router-link)
|
For more information on routing, see the [RouterLink binding](guide/router#router-link)
|
||||||
@ -445,7 +445,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
|
|
||||||
### *ngIf
|
### *ngIf
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.html" region="ngIf"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.html" region="ngIf" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
The `*ngIf` directive in Angular works the same as the `ng-if` directive in AngularJS. It removes
|
The `*ngIf` directive in Angular works the same as the `ng-if` directive in AngularJS. It removes
|
||||||
@ -480,7 +480,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
|
|
||||||
### ngModel
|
### ngModel
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.html" region="ngModel"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.html" region="ngModel" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
In Angular, **two-way binding** is denoted by `[()]`, descriptively referred to as a "banana in a box". This syntax is a shortcut for defining both property binding (from the component to the view)
|
In Angular, **two-way binding** is denoted by `[()]`, descriptively referred to as a "banana in a box". This syntax is a shortcut for defining both property binding (from the component to the view)
|
||||||
@ -516,7 +516,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
|
|
||||||
### *ngFor
|
### *ngFor
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.html" region="ngFor"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.html" region="ngFor" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
The `*ngFor` directive in Angular is similar to the `ng-repeat` directive in AngularJS. It repeats
|
The `*ngFor` directive in Angular is similar to the `ng-repeat` directive in AngularJS. It repeats
|
||||||
@ -559,7 +559,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
|
|
||||||
### Bind to the `hidden` property
|
### Bind to the `hidden` property
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.html" region="hidden"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.html" region="hidden" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
Angular uses property binding; there is no built-in *show* directive.
|
Angular uses property binding; there is no built-in *show* directive.
|
||||||
@ -598,7 +598,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
|
|
||||||
### Bind to the `src` property
|
### Bind to the `src` property
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="src"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="src" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
Angular uses property binding; there is no built-in *src* directive.
|
Angular uses property binding; there is no built-in *src* directive.
|
||||||
@ -635,7 +635,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
|
|
||||||
### ngStyle
|
### ngStyle
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="ngStyle"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="ngStyle" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
In Angular, the `ngStyle` directive works similarly. It sets a CSS style on an HTML element based on an expression.
|
In Angular, the `ngStyle` directive works similarly. It sets a CSS style on an HTML element based on an expression.
|
||||||
@ -690,7 +690,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
|
|
||||||
### ngSwitch
|
### ngSwitch
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.html" region="ngSwitch"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.html" region="ngSwitch" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
In Angular, the `ngSwitch` directive works similarly.
|
In Angular, the `ngSwitch` directive works similarly.
|
||||||
@ -765,7 +765,7 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
|
|
||||||
### currency
|
### currency
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="currency"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="currency" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
The Angular `currency` pipe is similar although some of the parameters have changed.
|
The Angular `currency` pipe is similar although some of the parameters have changed.
|
||||||
@ -793,7 +793,7 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
|
|
||||||
### date
|
### date
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="date"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="date" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
The Angular `date` pipe is similar.
|
The Angular `date` pipe is similar.
|
||||||
@ -847,7 +847,7 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
|
|
||||||
### json
|
### json
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="json"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="json" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
The Angular `json` pipe does the same thing.
|
The Angular `json` pipe does the same thing.
|
||||||
@ -876,7 +876,7 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
|
|
||||||
### slice
|
### slice
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="slice"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="slice" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
The `SlicePipe` does the same thing but the *order of the parameters is reversed*, in keeping
|
The `SlicePipe` does the same thing but the *order of the parameters is reversed*, in keeping
|
||||||
@ -907,7 +907,7 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
|
|
||||||
### lowercase
|
### lowercase
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="lowercase"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="lowercase" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
The Angular `lowercase` pipe does the same thing.
|
The Angular `lowercase` pipe does the same thing.
|
||||||
@ -935,7 +935,7 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
|
|
||||||
### number
|
### number
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="number"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/app.component.html" region="number" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
The Angular `number` pipe is similar.
|
The Angular `number` pipe is similar.
|
||||||
@ -1068,7 +1068,7 @@ The Angular code is shown using TypeScript.
|
|||||||
|
|
||||||
### NgModules
|
### NgModules
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/app.module.1.ts"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/app.module.1.ts" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
NgModules, defined with the `NgModule` decorator, serve the same purpose:
|
NgModules, defined with the `NgModule` decorator, serve the same purpose:
|
||||||
@ -1109,7 +1109,7 @@ The Angular code is shown using TypeScript.
|
|||||||
|
|
||||||
### Component decorator
|
### Component decorator
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.ts" region="component"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.ts" region="component" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
Angular adds a decorator to the component class to provide any required metadata.
|
Angular adds a decorator to the component class to provide any required metadata.
|
||||||
@ -1145,7 +1145,7 @@ The Angular code is shown using TypeScript.
|
|||||||
|
|
||||||
### Component class
|
### Component class
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.ts" region="class"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.ts" region="class" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
In Angular, you create a component class.
|
In Angular, you create a component class.
|
||||||
@ -1184,7 +1184,7 @@ The Angular code is shown using TypeScript.
|
|||||||
|
|
||||||
### Dependency injection
|
### Dependency injection
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.ts" region="di"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.ts" region="di" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
In Angular, you pass in dependencies as arguments to the component class constructor.
|
In Angular, you pass in dependencies as arguments to the component class constructor.
|
||||||
@ -1254,7 +1254,7 @@ also encapsulate a style sheet within a specific component.
|
|||||||
|
|
||||||
|
|
||||||
### Styles configuration
|
### Styles configuration
|
||||||
<code-example hideCopy path="ajs-quick-reference/.angular-cli.1.json" region="styles"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/.angular-cli.1.json" region="styles" linenums="false"></code-example>
|
||||||
|
|
||||||
With the Angular CLI, you can configure your global styles in the `angular.json` file.
|
With the Angular CLI, you can configure your global styles in the `angular.json` file.
|
||||||
You can rename the extension to `.scss` to use sass.
|
You can rename the extension to `.scss` to use sass.
|
||||||
@ -1263,7 +1263,7 @@ also encapsulate a style sheet within a specific component.
|
|||||||
In Angular, you can use the `styles` or `styleUrls` property of the `@Component` metadata to define
|
In Angular, you can use the `styles` or `styleUrls` property of the `@Component` metadata to define
|
||||||
a style sheet for a particular component.
|
a style sheet for a particular component.
|
||||||
|
|
||||||
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.ts" region="style-url"></code-example>
|
<code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.ts" region="style-url" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
This allows you to set appropriate styles for individual components that won’t leak into
|
This allows you to set appropriate styles for individual components that won’t leak into
|
||||||
|
@ -1,179 +0,0 @@
|
|||||||
# Angular compiler options
|
|
||||||
|
|
||||||
When you use [AoT compilation](guide/aot-compiler), you can control how your application is compiled by specifying *template* compiler options in the `tsconfig.json` [TypeScript configuration file](guide/typescript-configuration).
|
|
||||||
|
|
||||||
The template options object, `angularCompilerOptions`, is a sibling to the `compilerOptions` object that supplies standard options to the TypeScript compiler.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"experimentalDecorators": true,
|
|
||||||
...
|
|
||||||
},
|
|
||||||
"angularCompilerOptions": {
|
|
||||||
"fullTemplateTypeCheck": true,
|
|
||||||
"preserveWhitespaces": true,
|
|
||||||
...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
{@a tsconfig-extends}
|
|
||||||
## Configuration inheritance with extends
|
|
||||||
|
|
||||||
Like the TypeScript compiler, The Angular AoT compiler also supports `extends` in the `angularCompilerOptions` section of the TypeScript configuration file, `tsconfig.json`.
|
|
||||||
The `extends` property is at the top level, parallel to `compilerOptions` and `angularCompilerOptions`.
|
|
||||||
|
|
||||||
A TypeScript configuration can inherit settings from another file using the `extends` property.
|
|
||||||
The configuration options from the base file are loaded first, then overridden by those in the inheriting `tsconfig` file.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"extends": "../tsconfig.base.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"experimentalDecorators": true,
|
|
||||||
...
|
|
||||||
},
|
|
||||||
"angularCompilerOptions": {
|
|
||||||
"fullTemplateTypeCheck": true,
|
|
||||||
"preserveWhitespaces": true,
|
|
||||||
...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
For more informaton, see the [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html).
|
|
||||||
|
|
||||||
## Template options
|
|
||||||
|
|
||||||
The following options are available for configuring the AoT template compiler.
|
|
||||||
|
|
||||||
### `allowEmptyCodegenFiles`
|
|
||||||
|
|
||||||
When true, generate all possible files even if they are empty. Default is false. Used by the Bazel build rules to simplify how Bazel rules track file dependencies. Do not use this option outside of the Bazel rules.
|
|
||||||
|
|
||||||
### `annotationsAs`
|
|
||||||
|
|
||||||
Modifies how Angular-specific annotations are emitted to improve tree-shaking. Non-Angular annotations are not affected. One of `static fields` (the default) or `decorators`.
|
|
||||||
|
|
||||||
* By default, the compiler replaces decorators with a static field in the class, which allows advanced tree-shakers like [Closure compiler](https://github.com/google/closure-compiler) to remove unused classes.
|
|
||||||
|
|
||||||
* The `decorators` value leaves the decorators in place, which makes compilation faster. TypeScript emits calls to the` __decorate` helper. Use `--emitDecoratorMetadata` for runtime reflection (but note that the resulting code will not properly tree-shake.
|
|
||||||
|
|
||||||
### `annotateForClosureCompiler`
|
|
||||||
|
|
||||||
When true, use [Tsickle](https://github.com/angular/tsickle) to annotate the emitted JavaScript with [JSDoc](http://usejsdoc.org/) comments needed by the
|
|
||||||
[Closure Compiler](https://github.com/google/closure-compiler). Default is false.
|
|
||||||
|
|
||||||
### `disableExpressionLowering`
|
|
||||||
|
|
||||||
When true (the default), transforms code that is or could be used in an annotation, to allow it to be imported from template factory modules. See [metadata rewriting](guide/aot-compiler#metadata-rewriting) for more information.
|
|
||||||
|
|
||||||
When `false`, disables this rewriting, requiring the rewriting to be done manually.
|
|
||||||
|
|
||||||
### `disableTypeScriptVersionCheck`
|
|
||||||
|
|
||||||
When `true`, the compiler does not check the TypeScript version and does not report an error when an unsupported version of TypeScript is used. Not recommended, as unsupported versions of TypeScript might have undefined behavior. Default is false.
|
|
||||||
|
|
||||||
### `enableResourceInlining`
|
|
||||||
|
|
||||||
When true, replaces the `templateUrl` and `styleUrls` property in all `@Component` decorators with inlined contents in `template` and `styles` properties.
|
|
||||||
|
|
||||||
When enabled, the `.js` output of `ngc` does not include any lazy-loaded template or style URLs.
|
|
||||||
|
|
||||||
|
|
||||||
{@a enablelegacytemplate}
|
|
||||||
|
|
||||||
### `enableLegacyTemplate`
|
|
||||||
|
|
||||||
When true, enables use of the `<template>` element, which was deprecated in Angular 4.0, in favor of `<ng-template>` (to avoid colliding with the DOM's element of the same name). Default is false. Might be required by some third-party Angular libraries. |
|
|
||||||
|
|
||||||
### `flatModuleId`
|
|
||||||
|
|
||||||
The module ID to use for importing a flat module (when `flatModuleOutFile` is true). References generated by the template compiler use this module name when importing symbols
|
|
||||||
from the flat module. Ignored if `flatModuleOutFile` is false.
|
|
||||||
|
|
||||||
### `flatModuleOutFile`
|
|
||||||
|
|
||||||
When true, generates a flat module index of the given file name and the corresponding flat module metadata. Use to create flat modules that are packaged similarly to `@angular/core` and `@angular/common`. When this option is used, the `package.json` for the library should refer
|
|
||||||
to the generated flat module index instead of the library index file.
|
|
||||||
|
|
||||||
Produces only one `.metadata.json` file, which contains all the metadata necessary
|
|
||||||
for symbols exported from the library index. In the generated `.ngfactory.js` files, the flat
|
|
||||||
module index is used to import symbols that includes both the public API from the library index
|
|
||||||
as well as shrowded internal symbols.
|
|
||||||
|
|
||||||
By default the `.ts` file supplied in the `files` field is assumed to be the library index.
|
|
||||||
If more than one `.ts` file is specified, `libraryIndex` is used to select the file to use.
|
|
||||||
If more than one `.ts` file is supplied without a `libraryIndex`, an error is produced.
|
|
||||||
|
|
||||||
A flat module index `.d.ts` and `.js` is created with the given `flatModuleOutFile` name in the same location as the library index `.d.ts` file.
|
|
||||||
|
|
||||||
For example, if a library uses the `public_api.ts` file as the library index of the module, the `tsconfig.json` `files` field would be `["public_api.ts"]`.
|
|
||||||
The `flatModuleOutFile` options could then be set to (for example) `"index.js"`, which produces `index.d.ts` and `index.metadata.json` files.
|
|
||||||
The `module` field of the library's `package.json` would be `"index.js"` and the `typings` field
|
|
||||||
would be `"index.d.ts"`.
|
|
||||||
|
|
||||||
### `fullTemplateTypeCheck`
|
|
||||||
|
|
||||||
When true (recommended), enables the [binding expression validation](guide/aot-compiler#binding-expression-validation) phase of the template compiler, which uses TypeScript to validate binding expressions.
|
|
||||||
|
|
||||||
Default is currently false.
|
|
||||||
|
|
||||||
### `generateCodeForLibraries`
|
|
||||||
|
|
||||||
When true (the default), generates factory files (`.ngfactory.js` and `.ngstyle.js`)
|
|
||||||
for `.d.ts` files with a corresponding `.metadata.json` file.
|
|
||||||
|
|
||||||
When false, factory files are generated only for `.ts` files. Do this when using factory summaries.
|
|
||||||
|
|
||||||
|
|
||||||
### `preserveWhitespaces`
|
|
||||||
|
|
||||||
When false (the default), removes blank text nodes from compiled templates, which results in smaller emitted template factory modules. Set to true to preserve blank text nodes.
|
|
||||||
|
|
||||||
### `skipMetadataEmit`
|
|
||||||
|
|
||||||
When true, does not to produce `.metadata.json` files. Default is `false`.
|
|
||||||
|
|
||||||
The `.metadata.json` files contain information needed by the template compiler from a `.ts`
|
|
||||||
file that is not included in the `.d.ts` file produced by the TypeScript compiler.
|
|
||||||
This information includes, for example, the content of annotations (such as a component's template), which TypeScript emits to the `.js` file but not to the `.d.ts` file.
|
|
||||||
|
|
||||||
You can set to `true` when using factory summaries, because the factory summaries
|
|
||||||
include a copy of the information that is in the `.metadata.json` file.
|
|
||||||
|
|
||||||
Set to `true` if you are using TypeScript's `--outFile` option, because the metadata files
|
|
||||||
are not valid for this style of TypeScript output. However, we do not recommend using `--outFile` with Angular. Use a bundler, such as [webpack](https://webpack.js.org/), instead.
|
|
||||||
|
|
||||||
### `skipTemplateCodegen`
|
|
||||||
|
|
||||||
When true, does not emit `.ngfactory.js` and `.ngstyle.js` files. This turns off most of the template compiler and disables the reporting of template diagnostics.
|
|
||||||
|
|
||||||
Can be used to instruct the template compiler to produce `.metadata.json` files for distribution with an `npm` package while avoiding the production of `.ngfactory.js` and `.ngstyle.js` files that cannot be distributed to `npm`.
|
|
||||||
|
|
||||||
### `strictMetadataEmit`
|
|
||||||
|
|
||||||
When true, reports an error to the `.metadata.json` file if `"skipMetadataEmit"` is `false`.
|
|
||||||
Default is false. Use only when `"skipMetadataEmit"` is false and `"skipTemplateCodeGen"` is true.
|
|
||||||
|
|
||||||
This option is intended to validate the `.metadata.json` files emitted for bundling with an `npm` package. The validation is strict and can emit errors for metadata that would never produce an error when used by the template compiler. You can choose to suppress the error emitted by this option for an exported symbol by including `@dynamic` in the comment documenting the symbol.
|
|
||||||
|
|
||||||
It is valid for `.metadata.json` files to contain errors.
|
|
||||||
The template compiler reports these errors if the metadata is used to determine the contents of an annotation.
|
|
||||||
The metadata collector cannot predict the symbols that are designed for use in an annotation, so it preemptively includes error nodes in the metadata for the exported symbols.
|
|
||||||
The template compiler can then use the error nodes to report an error if these symbols are used.
|
|
||||||
|
|
||||||
If the client of a library intends to use a symbol in an annotation, the template compiler does not normally report this until the client uses the symbol.
|
|
||||||
This option allows detection of these errors during the build phase of
|
|
||||||
the library and is used, for example, in producing Angular libraries themselves.
|
|
||||||
|
|
||||||
### `strictInjectionParameters`
|
|
||||||
|
|
||||||
When true (recommended), reports an error for a supplied parameter whose injection type cannot be determined. When false (currently the default), constructor parameters of classes marked with `@Injectable` whose type cannot be resolved produce a warning.
|
|
||||||
|
|
||||||
### `trace`
|
|
||||||
|
|
||||||
When true, prints extra information while compiling templates. Default is false.
|
|
@ -37,7 +37,8 @@ To get started with adding Angular animations to your project, import the animat
|
|||||||
|
|
||||||
Import `BrowserAnimationsModule`, which introduces the animation capabilities into your Angular root application module.
|
Import `BrowserAnimationsModule`, which introduces the animation capabilities into your Angular root application module.
|
||||||
|
|
||||||
<code-example path="animations/src/app/app.module.1.ts" header="src/app/app.module.ts" language="typescript"></code-example>
|
<code-example path="animations/src/app/app.module.1.ts" header="src/app/app.module.ts" language="typescript" linenums="false">
|
||||||
|
</code-example>
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
@ -128,7 +129,7 @@ The third argument, `easing`, controls how the animation [accelerates and decele
|
|||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
**Note:** See the Material Design website's topic on [Natural easing curves](https://material.io/design/motion/speed.html#easing) for general information on easing curves.
|
**Note:** See the Angular Material Design website's topic on [Natural easing curves](https://material.io/design/motion/speed.html#easing) for general information on easing curves.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
This example provides a state transition from `open` to `closed` with a one second transition between states.
|
This example provides a state transition from `open` to `closed` with a one second transition between states.
|
||||||
@ -179,7 +180,9 @@ In this example, we'll name the trigger `openClose`, and attach it to the `butto
|
|||||||
|
|
||||||
Animations are defined in the metadata of the component that controls the HTML element to be animated. Put the code that defines your animations under the `animations:` property within the `@Component()` decorator.
|
Animations are defined in the metadata of the component that controls the HTML element to be animated. Put the code that defines your animations under the `animations:` property within the `@Component()` decorator.
|
||||||
|
|
||||||
<code-example path="animations/src/app/open-close.component.ts" header="src/app/open-close.component.ts" language="typescript" region="component"></code-example>
|
<code-example path="animations/src/app/open-close.component.ts" header="src/app/open-close.component.ts" language="typescript"
|
||||||
|
region="component" linenums="false">
|
||||||
|
</code-example>
|
||||||
|
|
||||||
When you've defined an animation trigger for a component, you can attach it to an element in that component's template by wrapping the trigger name in brackets and preceding it with an `@` symbol. Then, you can bind the trigger to a template expression using standard Angular property binding syntax as shown below, where `triggerName` is the name of the trigger, and `expression` evaluates to a defined animation state.
|
When you've defined an animation trigger for a component, you can attach it to an element in that component's template by wrapping the trigger name in brackets and preceding it with an `@` symbol. Then, you can bind the trigger to a template expression using standard Angular property binding syntax as shown below, where `triggerName` is the name of the trigger, and `expression` evaluates to a defined animation state.
|
||||||
|
|
||||||
@ -260,7 +263,7 @@ What it does
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><code><a href="api/animations/state" class="code-anchor">state()</a></code></td>
|
<td><code>state()</code></td>
|
||||||
<td>Creates a named set of CSS styles that should be applied on successful transition to a given state. The state can then be referenced by name within other animation functions.</td>
|
<td>Creates a named set of CSS styles that should be applied on successful transition to a given state. The state can then be referenced by name within other animation functions.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
@ -280,7 +283,7 @@ What it does
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><code><a href="api/animations/group" class="code-anchor">group()</a></code></td>
|
<td><code>group()</code></td>
|
||||||
<td>Specifies a group of animation steps (<em>inner animations</em>) to be run in parallel. Animation continues only after all inner animation steps have completed. Used within <code>sequence()</code> or <code>transition().</code></td>
|
<td>Specifies a group of animation steps (<em>inner animations</em>) to be run in parallel. Animation continues only after all inner animation steps have completed. Used within <code>sequence()</code> or <code>transition().</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,540 +0,0 @@
|
|||||||
# AoT metadata errors
|
|
||||||
|
|
||||||
The following are metadata errors you may encounter, with explanations and suggested corrections.
|
|
||||||
|
|
||||||
[Expression form not supported](#expression-form-not-supported)<br>
|
|
||||||
[Reference to a local (non-exported) symbol](#reference-to-a-local-symbol)<br>
|
|
||||||
[Only initialized variables and constants](#only-initialized-variables)<br>
|
|
||||||
[Reference to a non-exported class](#reference-to-a-non-exported-class)<br>
|
|
||||||
[Reference to a non-exported function](#reference-to-a-non-exported-function)<br>
|
|
||||||
[Function calls are not supported](#function-calls-not-supported)<br>
|
|
||||||
[Destructured variable or constant not supported](#destructured-variable-not-supported)<br>
|
|
||||||
[Could not resolve type](#could-not-resolve-type)<br>
|
|
||||||
[Name expected](#name-expected)<br>
|
|
||||||
[Unsupported enum member name](#unsupported-enum-member-name)<br>
|
|
||||||
[Tagged template expressions are not supported](#tagged-template-expressions-not-supported)<br>
|
|
||||||
[Symbol reference expected](#symbol-reference-expected)<br>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
{@a expression-form-not-supported}
|
|
||||||
## Expression form not supported
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
|
|
||||||
*The compiler encountered an expression it didn't understand while evaluating Angular metadata.*
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
Language features outside of the compiler's [restricted expression syntax](guide/aot-compiler#expression-syntax)
|
|
||||||
can produce this error, as seen in the following example:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// ERROR
|
|
||||||
export class Fooish { ... }
|
|
||||||
...
|
|
||||||
const prop = typeof Fooish; // typeof is not valid in metadata
|
|
||||||
...
|
|
||||||
// bracket notation is not valid in metadata
|
|
||||||
{ provide: 'token', useValue: { [prop]: 'value' } };
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
You can use `typeof` and bracket notation in normal application code.
|
|
||||||
You just can't use those features within expressions that define Angular metadata.
|
|
||||||
|
|
||||||
Avoid this error by sticking to the compiler's [restricted expression syntax](guide/aot-compiler#expression-syntax)
|
|
||||||
when writing Angular metadata
|
|
||||||
and be wary of new or unusual TypeScript features.
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
{@a reference-to-a-local-symbol}
|
|
||||||
## Reference to a local (non-exported) symbol
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
|
|
||||||
_Reference to a local (non-exported) symbol 'symbol name'. Consider exporting the symbol._
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
The compiler encountered a referenced to a locally defined symbol that either wasn't exported or wasn't initialized.
|
|
||||||
|
|
||||||
Here's a `provider` example of the problem.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// ERROR
|
|
||||||
let foo: number; // neither exported nor initialized
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'my-component',
|
|
||||||
template: ... ,
|
|
||||||
providers: [
|
|
||||||
{ provide: Foo, useValue: foo }
|
|
||||||
]
|
|
||||||
})
|
|
||||||
export class MyComponent {}
|
|
||||||
```
|
|
||||||
The compiler generates the component factory, which includes the `useValue` provider code, in a separate module. _That_ factory module can't reach back to _this_ source module to access the local (non-exported) `foo` variable.
|
|
||||||
|
|
||||||
You could fix the problem by initializing `foo`.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
let foo = 42; // initialized
|
|
||||||
```
|
|
||||||
|
|
||||||
The compiler will [fold](guide/aot-compiler#code-folding) the expression into the provider as if you had written this.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
providers: [
|
|
||||||
{ provide: Foo, useValue: 42 }
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively, you can fix it by exporting `foo` with the expectation that `foo` will be assigned at runtime when you actually know its value.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// CORRECTED
|
|
||||||
export let foo: number; // exported
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'my-component',
|
|
||||||
template: ... ,
|
|
||||||
providers: [
|
|
||||||
{ provide: Foo, useValue: foo }
|
|
||||||
]
|
|
||||||
})
|
|
||||||
export class MyComponent {}
|
|
||||||
```
|
|
||||||
|
|
||||||
Adding `export` often works for variables referenced in metadata such as `providers` and `animations` because the compiler can generate _references_ to the exported variables in these expressions. It doesn't need the _values_ of those variables.
|
|
||||||
|
|
||||||
Adding `export` doesn't work when the compiler needs the _actual value_
|
|
||||||
in order to generate code.
|
|
||||||
For example, it doesn't work for the `template` property.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// ERROR
|
|
||||||
export let someTemplate: string; // exported but not initialized
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'my-component',
|
|
||||||
template: someTemplate
|
|
||||||
})
|
|
||||||
export class MyComponent {}
|
|
||||||
```
|
|
||||||
|
|
||||||
The compiler needs the value of the `template` property _right now_ to generate the component factory.
|
|
||||||
The variable reference alone is insufficient.
|
|
||||||
Prefixing the declaration with `export` merely produces a new error, "[`Only initialized variables and constants can be referenced`](#only-initialized-variables)".
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
{@a only-initialized-variables}
|
|
||||||
## Only initialized variables and constants
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
|
|
||||||
_Only initialized variables and constants can be referenced because the value of this variable is needed by the template compiler._
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
The compiler found a reference to an exported variable or static field that wasn't initialized.
|
|
||||||
It needs the value of that variable to generate code.
|
|
||||||
|
|
||||||
The following example tries to set the component's `template` property to the value of
|
|
||||||
the exported `someTemplate` variable which is declared but _unassigned_.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// ERROR
|
|
||||||
export let someTemplate: string;
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'my-component',
|
|
||||||
template: someTemplate
|
|
||||||
})
|
|
||||||
export class MyComponent {}
|
|
||||||
```
|
|
||||||
|
|
||||||
You'd also get this error if you imported `someTemplate` from some other module and neglected to initialize it there.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// ERROR - not initialized there either
|
|
||||||
import { someTemplate } from './config';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'my-component',
|
|
||||||
template: someTemplate
|
|
||||||
})
|
|
||||||
export class MyComponent {}
|
|
||||||
```
|
|
||||||
|
|
||||||
The compiler cannot wait until runtime to get the template information.
|
|
||||||
It must statically derive the value of the `someTemplate` variable from the source code
|
|
||||||
so that it can generate the component factory, which includes
|
|
||||||
instructions for building the element based on the template.
|
|
||||||
|
|
||||||
To correct this error, provide the initial value of the variable in an initializer clause _on the same line_.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// CORRECTED
|
|
||||||
export let someTemplate = '<h1>Greetings from Angular</h1>';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'my-component',
|
|
||||||
template: someTemplate
|
|
||||||
})
|
|
||||||
export class MyComponent {}
|
|
||||||
```
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
{@a reference-to-a-non-exported-class}
|
|
||||||
## Reference to a non-exported class
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
|
|
||||||
_Reference to a non-exported class <class name>. Consider exporting the class._
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
Metadata referenced a class that wasn't exported.
|
|
||||||
|
|
||||||
For example, you may have defined a class and used it as an injection token in a providers array
|
|
||||||
but neglected to export that class.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// ERROR
|
|
||||||
abstract class MyStrategy { }
|
|
||||||
|
|
||||||
...
|
|
||||||
providers: [
|
|
||||||
{ provide: MyStrategy, useValue: ... }
|
|
||||||
]
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
Angular generates a class factory in a separate module and that
|
|
||||||
factory [can only access exported classes](guide/aot-compiler#exported-symbols).
|
|
||||||
To correct this error, export the referenced class.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// CORRECTED
|
|
||||||
export abstract class MyStrategy { }
|
|
||||||
|
|
||||||
...
|
|
||||||
providers: [
|
|
||||||
{ provide: MyStrategy, useValue: ... }
|
|
||||||
]
|
|
||||||
...
|
|
||||||
```
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
{@a reference-to-a-non-exported-function}
|
|
||||||
## Reference to a non-exported function
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
|
|
||||||
*Metadata referenced a function that wasn't exported.*
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
For example, you may have set a providers `useFactory` property to a locally defined function that you neglected to export.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// ERROR
|
|
||||||
function myStrategy() { ... }
|
|
||||||
|
|
||||||
...
|
|
||||||
providers: [
|
|
||||||
{ provide: MyStrategy, useFactory: myStrategy }
|
|
||||||
]
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
Angular generates a class factory in a separate module and that
|
|
||||||
factory [can only access exported functions](guide/aot-compiler#exported-symbols).
|
|
||||||
To correct this error, export the function.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// CORRECTED
|
|
||||||
export function myStrategy() { ... }
|
|
||||||
|
|
||||||
...
|
|
||||||
providers: [
|
|
||||||
{ provide: MyStrategy, useFactory: myStrategy }
|
|
||||||
]
|
|
||||||
...
|
|
||||||
```
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
{@a function-calls-not-supported}
|
|
||||||
## Function calls are not supported
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
|
|
||||||
_Function calls are not supported. Consider replacing the function or lambda with a reference to an exported function._
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
The compiler does not currently support [function expressions or lambda functions](guide/aot-compiler#function-expression).
|
|
||||||
For example, you cannot set a provider's `useFactory` to an anonymous function or arrow function like this.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// ERROR
|
|
||||||
...
|
|
||||||
providers: [
|
|
||||||
{ provide: MyStrategy, useFactory: function() { ... } },
|
|
||||||
{ provide: OtherStrategy, useFactory: () => { ... } }
|
|
||||||
]
|
|
||||||
...
|
|
||||||
```
|
|
||||||
You also get this error if you call a function or method in a provider's `useValue`.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// ERROR
|
|
||||||
import { calculateValue } from './utilities';
|
|
||||||
|
|
||||||
...
|
|
||||||
providers: [
|
|
||||||
{ provide: SomeValue, useValue: calculateValue() }
|
|
||||||
]
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
To correct this error, export a function from the module and refer to the function in a `useFactory` provider instead.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// CORRECTED
|
|
||||||
import { calculateValue } from './utilities';
|
|
||||||
|
|
||||||
export function myStrategy() { ... }
|
|
||||||
export function otherStrategy() { ... }
|
|
||||||
export function someValueFactory() {
|
|
||||||
return calculateValue();
|
|
||||||
}
|
|
||||||
...
|
|
||||||
providers: [
|
|
||||||
{ provide: MyStrategy, useFactory: myStrategy },
|
|
||||||
{ provide: OtherStrategy, useFactory: otherStrategy },
|
|
||||||
{ provide: SomeValue, useFactory: someValueFactory }
|
|
||||||
]
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
{@a destructured-variable-not-supported}
|
|
||||||
## Destructured variable or constant not supported
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
|
|
||||||
_Referencing an exported destructured variable or constant is not supported by the template compiler. Consider simplifying this to avoid destructuring._
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
The compiler does not support references to variables assigned by [destructuring](https://www.typescriptlang.org/docs/handbook/variable-declarations.html#destructuring).
|
|
||||||
|
|
||||||
For example, you cannot write something like this:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// ERROR
|
|
||||||
import { configuration } from './configuration';
|
|
||||||
|
|
||||||
// destructured assignment to foo and bar
|
|
||||||
const {foo, bar} = configuration;
|
|
||||||
...
|
|
||||||
providers: [
|
|
||||||
{provide: Foo, useValue: foo},
|
|
||||||
{provide: Bar, useValue: bar},
|
|
||||||
]
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
To correct this error, refer to non-destructured values.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// CORRECTED
|
|
||||||
import { configuration } from './configuration';
|
|
||||||
...
|
|
||||||
providers: [
|
|
||||||
{provide: Foo, useValue: configuration.foo},
|
|
||||||
{provide: Bar, useValue: configuration.bar},
|
|
||||||
]
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
{@a could-not-resolve-type}
|
|
||||||
## Could not resolve type
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
|
|
||||||
*The compiler encountered a type and can't determine which module exports that type.*
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
This can happen if you refer to an ambient type.
|
|
||||||
For example, the `Window` type is an ambient type declared in the global `.d.ts` file.
|
|
||||||
|
|
||||||
You'll get an error if you reference it in the component constructor,
|
|
||||||
which the compiler must statically analyze.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// ERROR
|
|
||||||
@Component({ })
|
|
||||||
export class MyComponent {
|
|
||||||
constructor (private win: Window) { ... }
|
|
||||||
}
|
|
||||||
```
|
|
||||||
TypeScript understands ambient types so you don't import them.
|
|
||||||
The Angular compiler does not understand a type that you neglect to export or import.
|
|
||||||
|
|
||||||
In this case, the compiler doesn't understand how to inject something with the `Window` token.
|
|
||||||
|
|
||||||
Do not refer to ambient types in metadata expressions.
|
|
||||||
|
|
||||||
If you must inject an instance of an ambient type,
|
|
||||||
you can finesse the problem in four steps:
|
|
||||||
|
|
||||||
1. Create an injection token for an instance of the ambient type.
|
|
||||||
1. Create a factory function that returns that instance.
|
|
||||||
1. Add a `useFactory` provider with that factory function.
|
|
||||||
1. Use `@Inject` to inject the instance.
|
|
||||||
|
|
||||||
Here's an illustrative example.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// CORRECTED
|
|
||||||
import { Inject } from '@angular/core';
|
|
||||||
|
|
||||||
export const WINDOW = new InjectionToken('Window');
|
|
||||||
export function _window() { return window; }
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
...
|
|
||||||
providers: [
|
|
||||||
{ provide: WINDOW, useFactory: _window }
|
|
||||||
]
|
|
||||||
})
|
|
||||||
export class MyComponent {
|
|
||||||
constructor (@Inject(WINDOW) private win: Window) { ... }
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The `Window` type in the constructor is no longer a problem for the compiler because it
|
|
||||||
uses the `@Inject(WINDOW)` to generate the injection code.
|
|
||||||
|
|
||||||
Angular does something similar with the `DOCUMENT` token so you can inject the browser's `document` object (or an abstraction of it, depending upon the platform in which the application runs).
|
|
||||||
|
|
||||||
```ts
|
|
||||||
import { Inject } from '@angular/core';
|
|
||||||
import { DOCUMENT } from '@angular/platform-browser';
|
|
||||||
|
|
||||||
@Component({ ... })
|
|
||||||
export class MyComponent {
|
|
||||||
constructor (@Inject(DOCUMENT) private doc: Document) { ... }
|
|
||||||
}
|
|
||||||
```
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
{@a name-expected}
|
|
||||||
## Name expected
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
|
|
||||||
*The compiler expected a name in an expression it was evaluating.*
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
This can happen if you use a number as a property name as in the following example.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// ERROR
|
|
||||||
provider: [{ provide: Foo, useValue: { 0: 'test' } }]
|
|
||||||
```
|
|
||||||
|
|
||||||
Change the name of the property to something non-numeric.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// CORRECTED
|
|
||||||
provider: [{ provide: Foo, useValue: { '0': 'test' } }]
|
|
||||||
```
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
{@a unsupported-enum-member-name}
|
|
||||||
## Unsupported enum member name
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
|
|
||||||
*Angular couldn't determine the value of the [enum member](https://www.typescriptlang.org/docs/handbook/enums.html) that you referenced in metadata.*
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
The compiler can understand simple enum values but not complex values such as those derived from computed properties.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// ERROR
|
|
||||||
enum Colors {
|
|
||||||
Red = 1,
|
|
||||||
White,
|
|
||||||
Blue = "Blue".length // computed
|
|
||||||
}
|
|
||||||
|
|
||||||
...
|
|
||||||
providers: [
|
|
||||||
{ provide: BaseColor, useValue: Colors.White } // ok
|
|
||||||
{ provide: DangerColor, useValue: Colors.Red } // ok
|
|
||||||
{ provide: StrongColor, useValue: Colors.Blue } // bad
|
|
||||||
]
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
Avoid referring to enums with complicated initializers or computed properties.
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
{@a tagged-template-expressions-not-supported}
|
|
||||||
## Tagged template expressions are not supported
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
|
|
||||||
_Tagged template expressions are not supported in metadata._
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
The compiler encountered a JavaScript ES2015 [tagged template expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_template_literals) such as the following.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// ERROR
|
|
||||||
const expression = 'funky';
|
|
||||||
const raw = String.raw`A tagged template ${expression} string`;
|
|
||||||
...
|
|
||||||
template: '<div>' + raw + '</div>'
|
|
||||||
...
|
|
||||||
```
|
|
||||||
[`String.raw()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/raw)
|
|
||||||
is a _tag function_ native to JavaScript ES2015.
|
|
||||||
|
|
||||||
The AoT compiler does not support tagged template expressions; avoid them in metadata expressions.
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
{@a symbol-reference-expected}
|
|
||||||
## Symbol reference expected
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
|
|
||||||
*The compiler expected a reference to a symbol at the location specified in the error message.*
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
This error can occur if you use an expression in the `extends` clause of a class.
|
|
||||||
|
|
||||||
<!--
|
|
||||||
|
|
||||||
Chuck: After reviewing your PR comment I'm still at a loss. See [comment there](https://github.com/angular/angular/pull/17712#discussion_r132025495).
|
|
||||||
|
|
||||||
-->
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user