Compare commits
163 Commits
8.0.0-rc.2
...
8.0.0
Author | SHA1 | Date | |
---|---|---|---|
38a7e2a775 | |||
c61c14a127 | |||
652b0959a8 | |||
002fbddcf1 | |||
4761d40a41 | |||
608e0f0d67 | |||
45718b3b21 | |||
b5756bcc39 | |||
60f0462049 | |||
9fd22959d3 | |||
d5dd907396 | |||
5a6bf7de0e | |||
d135bb5e6e | |||
8b9a3e49f2 | |||
44e55fe2e4 | |||
063cc308b6 | |||
c567135dd5 | |||
361f181c8c | |||
b40844523b | |||
c8af830ec8 | |||
e2c9ddb33e | |||
04196ec2d0 | |||
7323072c5c | |||
f0c5400cab | |||
3f2f937c9f | |||
256fe2421a | |||
e6f27bcb0c | |||
8abcf04a5e | |||
bf38df4eb9 | |||
79a025306a | |||
62c936aa49 | |||
77e1b34d91 | |||
26cb128b3c | |||
fdbe07982a | |||
c0e3209915 | |||
70880f0cea | |||
221a5ba634 | |||
68b08cf782 | |||
10560a0872 | |||
561e01ddfd | |||
d1345c78f0 | |||
276f9067c8 | |||
0e90a4263b | |||
e4cc1398aa | |||
8d1f993ceb | |||
df1ab49893 | |||
df03fec8a6 | |||
c01cae22e1 | |||
5a46f94987 | |||
5716605d52 | |||
8043e3131c | |||
54f7245081 | |||
5de24b6dfe | |||
4dc4d7f30a | |||
fcea1a3c22 | |||
8bc4da8665 | |||
a5a2d525ae | |||
4690dcecac | |||
722b2fa6ed | |||
124d1abf19 | |||
736d3ef820 | |||
9b0ad347e1 | |||
d2598ace0a | |||
4a25e4cf95 | |||
3f67bf208d | |||
d85476fd8c | |||
9763edf829 | |||
b6ae54c547 | |||
3de26a84ff | |||
8022d3691b | |||
581336a918 | |||
effc58086c | |||
766615c8a1 | |||
ede4246663 | |||
bb8a6abbf2 | |||
32daa930d0 | |||
b6aa99d3a7 | |||
e10b213784 | |||
a67cf99b0c | |||
04d04fd147 | |||
17361d2b2c | |||
9b88920aa9 | |||
b12e76d1d3 | |||
af001a8cbd | |||
db64b014f8 | |||
7e34975bb0 | |||
0fa48e8c00 | |||
fde3f467e2 | |||
7b378a6920 | |||
3136d9ff2e | |||
325e6cf557 | |||
381d7c4e44 | |||
1b6f3c1ead | |||
c38349127c | |||
a4817729a2 | |||
61c343e3eb | |||
24e6c1e80d | |||
42fc5c9b33 | |||
33e7b285ca | |||
74afdc37da | |||
3c1ffba0ad | |||
14c0017db8 | |||
4878f4890b | |||
b7edef0cd3 | |||
39fa937ab9 | |||
2977829c67 | |||
dbe845e048 | |||
e562acc884 | |||
e295c6a0ae | |||
10b43355f8 | |||
d4e7587bd8 | |||
cabe03cf6d | |||
0cefa9e342 | |||
e073daa48e | |||
994d48a96e | |||
806f8118c8 | |||
dd299f9eb2 | |||
49ec3f312c | |||
71eba450e6 | |||
192f108b0f | |||
dd8651db73 | |||
5bbbe3f684 | |||
a71d8a837b | |||
e8ceae14e1 | |||
c3246e6f16 | |||
685753361e | |||
6b07711f96 | |||
12fb639b7d | |||
644925fd0c | |||
bcc72b0924 | |||
e1091b2ba8 | |||
08841e31d9 | |||
d1fcc2bc13 | |||
fac00442d2 | |||
b8cbcbcf49 | |||
1ed45bd783 | |||
82fd1920b1 | |||
f6d7271ec7 | |||
c1f3faf1df | |||
97202278f9 | |||
132f01c5ca | |||
6a987f1b9c | |||
548b003ed3 | |||
48dc41de01 | |||
817c2b49bc | |||
fed07c735c | |||
390cac6874 | |||
8eb0b8bd40 | |||
d7283c6085 | |||
3fe3a84a4b | |||
28e4187bd6 | |||
7cbc69c890 | |||
1dc134bc6b | |||
6a61d37f95 | |||
8d2e92bcfe | |||
5038f5c909 | |||
6eeca70043 | |||
9f68c35fa9 | |||
21418ea109 | |||
02d8b4ed3c | |||
6748392edc | |||
d9fd301157 | |||
71c5d80ce7 |
15
.bazelrc
15
.bazelrc
@ -116,16 +116,21 @@ build --define=compile=legacy
|
||||
# --config=remote
|
||||
###############################
|
||||
|
||||
# Load default settings for Remote Build Execution
|
||||
# When updating, the URLs of bazel_toolchains in packages/bazel/package.bzl
|
||||
# may also need to be updated (see https://github.com/angular/angular/pull/27935)
|
||||
import %workspace%/third_party/github.com/bazelbuild/bazel-toolchains/bazelrc/bazel-0.24.0.bazelrc
|
||||
# Load default settings for Remote Build Execution.
|
||||
import %workspace%/third_party/github.com/bazelbuild/bazel-toolchains/bazelrc/.bazelrc.notoolchain
|
||||
|
||||
# Increase the default number of jobs by 50% because our build has lots of
|
||||
# parallelism
|
||||
build:remote --jobs=150
|
||||
|
||||
# Point to our custom execution platform; see tools/BUILD.bazel
|
||||
# Toolchain and platform related flags
|
||||
build:remote --host_javabase=@rbe_ubuntu1604_angular//java:jdk
|
||||
build:remote --javabase=@rbe_ubuntu1604_angular//java:jdk
|
||||
build:remote --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_hostjdk8
|
||||
build:remote --java_toolchain=@bazel_tools//tools/jdk:toolchain_hostjdk8
|
||||
build:remote --crosstool_top=@rbe_ubuntu1604_angular//cc:toolchain
|
||||
build:remote --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1
|
||||
build:remote --extra_toolchains=@rbe_ubuntu1604_angular//config:cc-toolchain
|
||||
build:remote --extra_execution_platforms=//tools:rbe_ubuntu1604-angular
|
||||
build:remote --host_platform=//tools:rbe_ubuntu1604-angular
|
||||
build:remote --platforms=//tools:rbe_ubuntu1604-angular
|
||||
|
@ -167,7 +167,8 @@ jobs:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- *setup_circleci_bazel_config
|
||||
|
||||
# Enable remote/sibling docker which is needed by auto-selection of toolchain configs for RBE.
|
||||
- setup_remote_docker
|
||||
# Setup remote execution and run RBE-compatible tests.
|
||||
- *setup_bazel_remote_execution
|
||||
- run: yarn bazel test //... --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only
|
||||
@ -180,6 +181,8 @@ jobs:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- *setup_circleci_bazel_config
|
||||
# Enable remote/sibling docker which is needed by auto-selection of toolchain configs for RBE.
|
||||
- setup_remote_docker
|
||||
- *setup_bazel_remote_execution
|
||||
|
||||
# We need to explicitly specify the --symlink_prefix option because otherwise we would
|
||||
@ -292,11 +295,21 @@ jobs:
|
||||
|
||||
test_aio_local_ivy:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
||||
- image: *browsers_docker_image
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
# Build aio with Ivy (using local Angular packages)
|
||||
- run: yarn --cwd aio build-with-ivy --progress=false
|
||||
# Run PWA-score tests
|
||||
# (Run before unit and e2e tests, which destroy the `dist/` directory.)
|
||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||
# Run unit tests
|
||||
- run: yarn --cwd aio test --progress=false --watch=false
|
||||
# Run e2e tests
|
||||
- run: yarn --cwd aio e2e --configuration=ci
|
||||
|
||||
test_aio_tools:
|
||||
<<: *job_defaults
|
||||
@ -351,7 +364,7 @@ jobs:
|
||||
# Run examples tests with ivy. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
||||
# Since the parallelism is set to "3", there will be three parallel CircleCI containers
|
||||
# with either "0", "1" or "2" as node index. This can be passed to the "--shard" argument.
|
||||
- run: yarn --cwd aio example-e2e --setup --local --ivy --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL}
|
||||
- run: yarn --cwd aio example-e2e --setup --local --ivy --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL}
|
||||
|
||||
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
||||
aio_preview:
|
||||
@ -399,6 +412,8 @@ jobs:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- *setup_circleci_bazel_config
|
||||
# Enable remote/sibling docker which is needed by auto-selection of toolchain configs for RBE.
|
||||
- setup_remote_docker
|
||||
- *setup_bazel_remote_execution
|
||||
|
||||
- run: scripts/build-packages-dist.sh
|
||||
@ -425,6 +440,8 @@ jobs:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- *setup_circleci_bazel_config
|
||||
# Enable remote/sibling docker which is needed by auto-selection of toolchain configs for RBE.
|
||||
- setup_remote_docker
|
||||
- *setup_bazel_remote_execution
|
||||
|
||||
- run: scripts/build-ivy-npm-packages.sh
|
||||
@ -712,25 +729,23 @@ workflows:
|
||||
cron: "0 * * * *"
|
||||
filters: *publish_branches_filter
|
||||
|
||||
# This job is currently disabled due to a version skew problem.
|
||||
# More info is available here: https://github.com/angular/angular/issues/30101
|
||||
# aio_monitoring:
|
||||
# jobs:
|
||||
# - setup
|
||||
# - aio_monitoring_stable:
|
||||
# requires:
|
||||
# - setup
|
||||
# - aio_monitoring_next:
|
||||
# requires:
|
||||
# - setup
|
||||
# triggers:
|
||||
# - schedule:
|
||||
# # Runs AIO monitoring jobs at 00:00AM every day.
|
||||
# cron: "0 0 * * *"
|
||||
# filters:
|
||||
# branches:
|
||||
# only:
|
||||
# - master
|
||||
aio_monitoring:
|
||||
jobs:
|
||||
- setup
|
||||
- aio_monitoring_stable:
|
||||
requires:
|
||||
- setup
|
||||
- aio_monitoring_next:
|
||||
requires:
|
||||
- setup
|
||||
triggers:
|
||||
- schedule:
|
||||
# Runs AIO monitoring jobs at 10:00AM every day.
|
||||
cron: "0 10 * * *"
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
# TODO:
|
||||
# - don't build the g3 branch
|
||||
|
@ -20,6 +20,7 @@ steps:
|
||||
# Add Bazel CI config
|
||||
- copy .codefresh\bazel.rc %ProgramData%\bazel.bazelrc
|
||||
# Run tests
|
||||
- yarn bazel test //tools/ts-api-guardian:all //packages/language-service/test
|
||||
- yarn bazel test //tools/ts-api-guardian:all //packages/language-service/test //packages/compiler/test //packages/compiler-cli/test:ngc //packages/compiler-cli/test/ngtsc:ngtsc
|
||||
- yarn test-ivy-aot //packages/animations/test //packages/common/test //packages/forms/test //packages/http/test //packages/platform-browser/test //packages/platform-browser-dynamic/test //packages/router/test
|
||||
- yarn bazel test //tools/public_api_guard/...
|
||||
- yarn bazel test //packages/compiler-cli/integrationtest:integrationtest //packages/compiler-cli/test/compliance:compliance
|
||||
|
22
.devcontainer/recommended-Dockerfile
Normal file
22
.devcontainer/recommended-Dockerfile
Normal file
@ -0,0 +1,22 @@
|
||||
# Image metadata and config.
|
||||
FROM circleci/node:10-browsers
|
||||
|
||||
LABEL name="Angular dev environment" \
|
||||
description="This image can be used to create a dev environment for building Angular." \
|
||||
vendor="angular" \
|
||||
version="1.0"
|
||||
|
||||
EXPOSE 4000 4200 4433 5000 8080 9876
|
||||
|
||||
|
||||
# Switch to `root` (CircleCI images use `circleci` as the user).
|
||||
USER root
|
||||
|
||||
|
||||
# Configure `Node.js`/`npm` and install utilities.
|
||||
RUN npm config --global set user root
|
||||
RUN npm install --global yarn@1.13.0 # This needs to be in sync with what we use on CI.
|
||||
|
||||
|
||||
# Go! (And keep going.)
|
||||
CMD ["tail", "--follow", "/dev/null"]
|
16
.devcontainer/recommended-devcontainer.json
Normal file
16
.devcontainer/recommended-devcontainer.json
Normal file
@ -0,0 +1,16 @@
|
||||
// Reference: https://code.visualstudio.com/docs/remote/containers#_devcontainerjson-reference
|
||||
{
|
||||
"name": "Angular dev container",
|
||||
"dockerFile": "Dockerfile",
|
||||
"appPort": [4000, 4200, 4433, 5000, 8080, 9876],
|
||||
"postCreateCommand": "yarn install",
|
||||
"extensions": [
|
||||
"devondcarew.bazel-code",
|
||||
"gkalpak.aio-docs-utils",
|
||||
"ms-vscode.vscode-typescript-tslint-plugin",
|
||||
"xaver.clang-format",
|
||||
// The following extensions are useful when working on angular.io (i.e. inside the `aio/` directory).
|
||||
//"angular.ng-template",
|
||||
//"dbaeumer.vscode-eslint",
|
||||
],
|
||||
}
|
4
.github/CODEOWNERS
vendored
4
.github/CODEOWNERS
vendored
@ -218,6 +218,7 @@
|
||||
#
|
||||
# - gkalpak
|
||||
# - petebacondarwin
|
||||
# - jasonaden
|
||||
|
||||
|
||||
# ===========================================================
|
||||
@ -657,8 +658,10 @@
|
||||
# ================================================
|
||||
|
||||
/packages/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/common/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/examples/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/upgrade.md @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/upgrade-lazy-load-ajs/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/upgrade-module/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/upgrade-phonecat-1-typescript/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
@ -853,6 +856,7 @@ testing/** @angular/fw-test
|
||||
/.buildkite/** @angular/fw-dev-infra
|
||||
/.circleci/** @angular/fw-dev-infra
|
||||
/.codefresh/** @angular/fw-dev-infra
|
||||
/.devcontainer/** @angular/fw-dev-infra
|
||||
/.github/** @angular/fw-dev-infra
|
||||
/.vscode/** @angular/fw-dev-infra
|
||||
/docs/BAZEL.md @angular/fw-dev-infra
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -11,6 +11,9 @@ tools/gulp-tasks/cldr/cldr-data/
|
||||
pubspec.lock
|
||||
.c9
|
||||
.idea/
|
||||
.devcontainer/*
|
||||
!.devcontainer/recommended-devcontainer.json
|
||||
!.devcontainer/recommended-Dockerfile
|
||||
.settings/
|
||||
.vscode/launch.json
|
||||
.vscode/settings.json
|
||||
|
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
@ -8,5 +8,8 @@
|
||||
"gkalpak.aio-docs-utils",
|
||||
"ms-vscode.vscode-typescript-tslint-plugin",
|
||||
"xaver.clang-format",
|
||||
// The following extensions are useful when working on angular.io (i.e. inside the `aio/` directory).
|
||||
//"angular.ng-template",
|
||||
//"dbaeumer.vscode-eslint",
|
||||
],
|
||||
}
|
||||
|
285
CHANGELOG.md
285
CHANGELOG.md
@ -1,3 +1,285 @@
|
||||
<a name="8.0.0"></a>
|
||||
# [8.0.0](https://github.com/angular/angular/compare/8.0.0-rc.5...8.0.0) (2019-05-28)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add support for TypeScript 3.3 (and drop older versions) ([#29004](https://github.com/angular/angular/issues/29004)) ([75748d6](https://github.com/angular/angular/commit/75748d6))
|
||||
* **common:** add ability to watch for AngularJS URL updates through `onUrlChange` hook ([#30466](https://github.com/angular/angular/issues/30466)) ([8022d36](https://github.com/angular/angular/commit/8022d36))
|
||||
* **common:** stricter types for SlicePipe ([#30156](https://github.com/angular/angular/issues/30156)) ([722b2fa](https://github.com/angular/angular/commit/722b2fa))
|
||||
* **bazel:** use rbe_autoconfig() and new container. ([#29336](https://github.com/angular/angular/issues/29336)) ([e562acc](https://github.com/angular/angular/commit/e562acc))
|
||||
* **common:** add [@angular](https://github.com/angular)/common/upgrade package for $location-related APIs ([#30055](https://github.com/angular/angular/issues/30055)) ([152d99e](https://github.com/angular/angular/commit/152d99e))
|
||||
* **common:** add ability to retrieve the state from Location service ([#30055](https://github.com/angular/angular/issues/30055)) ([b44b143](https://github.com/angular/angular/commit/b44b143))
|
||||
* **common:** add ability to track all location changes ([#30055](https://github.com/angular/angular/issues/30055)) ([3a9cf3f](https://github.com/angular/angular/commit/3a9cf3f))
|
||||
* **common:** add APIs to read component pieces of URL ([#30055](https://github.com/angular/angular/issues/30055)) ([b635fe8](https://github.com/angular/angular/commit/b635fe8))
|
||||
* **common:** add MockPlatformLocation to enable more robust testing of Location services ([#30055](https://github.com/angular/angular/issues/30055)) ([d0672c2](https://github.com/angular/angular/commit/d0672c2))
|
||||
* **common:** add UrlCodec type for use with upgrade applications ([#30055](https://github.com/angular/angular/issues/30055)) ([ec455e1](https://github.com/angular/angular/commit/ec455e1))
|
||||
* **common:** provide replacement for AngularJS $location service ([#30055](https://github.com/angular/angular/issues/30055)) ([4277600](https://github.com/angular/angular/commit/4277600))
|
||||
* remove deprecated DOCUMENT token from platform-browser ([#28117](https://github.com/angular/angular/issues/28117)) ([3a9d247](https://github.com/angular/angular/commit/3a9d247))
|
||||
* **compiler:** support skipping leading trivia in template source-maps ([#30095](https://github.com/angular/angular/issues/30095)) ([304a12f](https://github.com/angular/angular/commit/304a12f))
|
||||
* **core:** add missing ARIA attributes to html sanitizer ([#29685](https://github.com/angular/angular/issues/29685)) ([909557d](https://github.com/angular/angular/commit/909557d)), closes [#26815](https://github.com/angular/angular/issues/26815)
|
||||
* **router:** deprecate loadChildren:string ([#30073](https://github.com/angular/angular/issues/30073)) ([c61df39](https://github.com/angular/angular/commit/c61df39))
|
||||
* **service-worker:** allow configuring when the SW is registered ([#21842](https://github.com/angular/angular/issues/21842)) ([4cfba58](https://github.com/angular/angular/commit/4cfba58)), closes [#20970](https://github.com/angular/angular/issues/20970)
|
||||
* **service-worker:** expose `SwRegistrationOptions` token to allow runtime config ([#21842](https://github.com/angular/angular/issues/21842)) ([39c0152](https://github.com/angular/angular/commit/39c0152))
|
||||
* **service-worker:** support bypassing SW with specific header/query param ([#30010](https://github.com/angular/angular/issues/30010)) ([6200732](https://github.com/angular/angular/commit/6200732)), closes [#21191](https://github.com/angular/angular/issues/21191)
|
||||
* **compiler-cli:** export tooling definitions ([#29929](https://github.com/angular/angular/issues/29929)) ([e1f51ea](https://github.com/angular/angular/commit/e1f51ea))
|
||||
* **compiler-cli:** lower some exported expressions ([#30038](https://github.com/angular/angular/issues/30038)) ([8e73f9b](https://github.com/angular/angular/commit/8e73f9b))
|
||||
* **core:** add schematics to move deprecated DOCUMENT import ([#29950](https://github.com/angular/angular/issues/29950)) ([645e305](https://github.com/angular/angular/commit/645e305))
|
||||
* **bazel:** update the build to use the new architect api ([#29720](https://github.com/angular/angular/issues/29720)) ([902a53a](https://github.com/angular/angular/commit/902a53a))
|
||||
* remove [@angular](https://github.com/angular)/http dependency from [@angular](https://github.com/angular)/platform-server ([#29408](https://github.com/angular/angular/issues/29408)) ([9745f55](https://github.com/angular/angular/commit/9745f55))
|
||||
* **compiler-cli:** ngcc - make logging more configurable ([#29591](https://github.com/angular/angular/issues/29591)) ([8d3d75e](https://github.com/angular/angular/commit/8d3d75e))
|
||||
* **core:** Add "AbstractType<T>" interface ([#29295](https://github.com/angular/angular/issues/29295)) ([afd4a4e](https://github.com/angular/angular/commit/afd4a4e)), closes [#26491](https://github.com/angular/angular/issues/26491)
|
||||
* **core:** template-var-assignment update schematic ([#29608](https://github.com/angular/angular/issues/29608)) ([7c8f4e3](https://github.com/angular/angular/commit/7c8f4e3))
|
||||
* **bazel:** Upgrade rules_nodejs and rules_sass ([#29388](https://github.com/angular/angular/issues/29388)) ([d6d081e](https://github.com/angular/angular/commit/d6d081e))
|
||||
* **service-worker:** support multiple apps on different subpaths of a domain ([#27080](https://github.com/angular/angular/issues/27080)) ([e721c08](https://github.com/angular/angular/commit/e721c08)), closes [#21388](https://github.com/angular/angular/issues/21388)
|
||||
* **bazel:** Eject Bazel ([#29167](https://github.com/angular/angular/issues/29167)) ([36a1550](https://github.com/angular/angular/commit/36a1550))
|
||||
* **bazel:** Hide Bazel files in Bazel builder ([#29110](https://github.com/angular/angular/issues/29110)) ([7060d90](https://github.com/angular/angular/commit/7060d90))
|
||||
* **forms:** clear (remove all) components from a FormArray ([#28918](https://github.com/angular/angular/issues/28918)) ([a68b1a1](https://github.com/angular/angular/commit/a68b1a1)), closes [#18531](https://github.com/angular/angular/issues/18531)
|
||||
* **platform-server:** wait on returned BEFORE_APP_SERIALIZED promises ([#29120](https://github.com/angular/angular/issues/29120)) ([7102ea8](https://github.com/angular/angular/commit/7102ea8))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** allow ts_library interop with list-typed inputs ([#30600](https://github.com/angular/angular/issues/30600)) ([bf38df4](https://github.com/angular/angular/commit/bf38df4))
|
||||
* **bazel:** Disable sandbox on Mac OS ([#30460](https://github.com/angular/angular/issues/30460)) ([3de26a8](https://github.com/angular/angular/commit/3de26a8))
|
||||
* **bazel:** ng test should run specific ts_web_test_suite ([#30526](https://github.com/angular/angular/issues/30526)) ([8bc4da8](https://github.com/angular/angular/commit/8bc4da8))
|
||||
* **core:** remove deprecated `TestBed.deprecatedOverrideProvider` API ([#30576](https://github.com/angular/angular/issues/30576)) ([5a46f94](https://github.com/angular/angular/commit/5a46f94))
|
||||
* **core:** require 'static' flag on queries in typings ([#30641](https://github.com/angular/angular/issues/30641)) ([c8af830](https://github.com/angular/angular/commit/c8af830))
|
||||
* **core:** temporarily remove [@deprecated](https://github.com/deprecated) jsdoc tag for a TextBed.get overload ([#30514](https://github.com/angular/angular/issues/30514)) ([561e01d](https://github.com/angular/angular/commit/561e01d)), closes [#29290](https://github.com/angular/angular/issues/29290) [#29905](https://github.com/angular/angular/issues/29905)
|
||||
* **router:** type cast correctly for IE 11 bug breaking URL Unification when comparing objects ([#30464](https://github.com/angular/angular/issues/30464)) ([32daa93](https://github.com/angular/angular/commit/32daa93))
|
||||
* **bazel:** Directly spawn native Bazel binary ([#30306](https://github.com/angular/angular/issues/30306)) ([d1fcc2b](https://github.com/angular/angular/commit/d1fcc2b))
|
||||
* **bazel:** pass correct arguments to http_server in Windows ([#30346](https://github.com/angular/angular/issues/30346)) ([71eba45](https://github.com/angular/angular/commit/71eba45)), closes [#29785](https://github.com/angular/angular/issues/29785)
|
||||
* **bazel:** Use existing npm/yarn lock files ([#30438](https://github.com/angular/angular/issues/30438)) ([3136d9f](https://github.com/angular/angular/commit/3136d9f))
|
||||
* **compiler:** ensure strict mode when evaluating in JIT ([#30122](https://github.com/angular/angular/issues/30122)) ([192f108](https://github.com/angular/angular/commit/192f108))
|
||||
* **core:** migrations not always migrating all files ([#30269](https://github.com/angular/angular/issues/30269)) ([e8ceae1](https://github.com/angular/angular/commit/e8ceae1))
|
||||
* **core:** static-query migration errors not printed properly ([#30458](https://github.com/angular/angular/issues/30458)) ([fde3f46](https://github.com/angular/angular/commit/fde3f46))
|
||||
* **core:** static-query migration fails with default parameter values ([#30269](https://github.com/angular/angular/issues/30269)) ([c3246e6](https://github.com/angular/angular/commit/c3246e6))
|
||||
* **core:** static-query migration should gracefully exit if AOT compiler throws ([#30269](https://github.com/angular/angular/issues/30269)) ([a71d8a8](https://github.com/angular/angular/commit/a71d8a8))
|
||||
* **core:** static-query migration should handle queries on accessors ([#30327](https://github.com/angular/angular/issues/30327)) ([dd299f9](https://github.com/angular/angular/commit/dd299f9))
|
||||
* **core:** static-query migration should not fallback to test strategy ([#30458](https://github.com/angular/angular/issues/30458)) ([0fa48e8](https://github.com/angular/angular/commit/0fa48e8))
|
||||
* **core:** static-query migration should not prompt if no queries are used ([#30254](https://github.com/angular/angular/issues/30254)) ([12fb639](https://github.com/angular/angular/commit/12fb639))
|
||||
* **core:** static-query usage migration strategy should detect ambiguous query usage ([#30215](https://github.com/angular/angular/issues/30215)) ([e295c6a](https://github.com/angular/angular/commit/e295c6a))
|
||||
* **router:** ensure navigations start with the current URL value incase redirect is skipped ([#30344](https://github.com/angular/angular/issues/30344)) ([9b88920](https://github.com/angular/angular/commit/9b88920)), closes [#30340](https://github.com/angular/angular/issues/30340) [#30160](https://github.com/angular/angular/issues/30160)
|
||||
* **router:** IE 11 bug can break URL unification when comparing objects ([#30393](https://github.com/angular/angular/issues/30393)) ([c383491](https://github.com/angular/angular/commit/c383491))
|
||||
* **bazel:** Bump ibazel to 0.10.1 for windows fixes ([#30196](https://github.com/angular/angular/issues/30196)) ([9f68c35](https://github.com/angular/angular/commit/9f68c35))
|
||||
* **compiler-cli:** log ngcc skipping messages as debug instead of info ([#30232](https://github.com/angular/angular/issues/30232)) ([548b003](https://github.com/angular/angular/commit/548b003))
|
||||
* **core:** fix interpolate identifier in AOT ([#30243](https://github.com/angular/angular/issues/30243)) ([3fe3a84](https://github.com/angular/angular/commit/3fe3a84))
|
||||
* **router:** ensure `history.state` is set in `eager` update mode ([#30154](https://github.com/angular/angular/issues/30154)) ([9720227](https://github.com/angular/angular/commit/9720227))
|
||||
* **router:** fix a problem with router not responding to back button ([#30160](https://github.com/angular/angular/issues/30160)) ([132f01c](https://github.com/angular/angular/commit/132f01c))
|
||||
* **language-service:** Remove tsserverlibrary from rollup globals ([#30123](https://github.com/angular/angular/issues/30123)) ([b706800](https://github.com/angular/angular/commit/b706800))
|
||||
* disable injectable-pipe migration ([#30180](https://github.com/angular/angular/issues/30180)) ([4b2fcfd](https://github.com/angular/angular/commit/4b2fcfd))
|
||||
* **bazel:** Exclude common/upgrade* in metadata.tsconfig.json ([#30133](https://github.com/angular/angular/issues/30133)) ([6711f22](https://github.com/angular/angular/commit/6711f22))
|
||||
* **bazel:** update peerDep ranges ([#30155](https://github.com/angular/angular/issues/30155)) ([6067583](https://github.com/angular/angular/commit/6067583))
|
||||
* **bazel:** make name param in ng add optional ([#30074](https://github.com/angular/angular/issues/30074)) ([0b5f480](https://github.com/angular/angular/commit/0b5f480))
|
||||
* **bazel:** Make sure only single copy of `[@angular](https://github.com/angular)/bazel` is installed ([#30072](https://github.com/angular/angular/issues/30072)) ([2905bf5](https://github.com/angular/angular/commit/2905bf5))
|
||||
* **bazel:** transitive npm deps in ng_module ([#30065](https://github.com/angular/angular/issues/30065)) ([61365a9](https://github.com/angular/angular/commit/61365a9))
|
||||
* **common:** add upgrade sub-package to ng_package rule for [@angular](https://github.com/angular)/common ([#30117](https://github.com/angular/angular/issues/30117)) ([6de4cbd](https://github.com/angular/angular/commit/6de4cbd)), closes [#30055](https://github.com/angular/angular/issues/30055) [#30116](https://github.com/angular/angular/issues/30116)
|
||||
* **common:** adjust MockPlatformLocation to set state to new object ([#30055](https://github.com/angular/angular/issues/30055)) ([825efa8](https://github.com/angular/angular/commit/825efa8))
|
||||
* **compiler:** Fix compiler crash due to isSkipSelf of null ([#30075](https://github.com/angular/angular/issues/30075)) ([28fd5ab](https://github.com/angular/angular/commit/28fd5ab))
|
||||
* **upgrade:** do not break if `onMicrotaskEmpty` emits while a `$digest` is in progress ([#29794](https://github.com/angular/angular/issues/29794)) ([0ddf2e7](https://github.com/angular/angular/commit/0ddf2e7)), closes [#24680](https://github.com/angular/angular/issues/24680) [/github.com/angular/angular/blob/78146c189/packages/core/src/util/ng_dev_mode.ts#L12](https://github.com//github.com/angular/angular/blob/78146c189/packages/core/src/util/ng_dev_mode.ts/issues/L12) [#24680](https://github.com/angular/angular/issues/24680)
|
||||
* **bazel:** do not typecheck core schematic files ([#29876](https://github.com/angular/angular/issues/29876)) ([2ba799d](https://github.com/angular/angular/commit/2ba799d))
|
||||
* **bazel:** restore ng build --prod ([#30005](https://github.com/angular/angular/issues/30005)) ([96a8289](https://github.com/angular/angular/commit/96a8289))
|
||||
* **common:** prevent repeated application of HttpParams mutations ([#29045](https://github.com/angular/angular/issues/29045)) ([8e8e89a](https://github.com/angular/angular/commit/8e8e89a)), closes [#20430](https://github.com/angular/angular/issues/20430)
|
||||
* **common:** async pipe will properly check when it recieves an NaN value from an observable ([#22305](https://github.com/angular/angular/issues/22305)) ([3f6bf6d](https://github.com/angular/angular/commit/3f6bf6d)), closes [#15721](https://github.com/angular/angular/issues/15721)
|
||||
* **core:** don't include a local `EventListener` in typings ([#29809](https://github.com/angular/angular/issues/29809)) ([4bde40f](https://github.com/angular/angular/commit/4bde40f)), closes [/github.com/angular/angular/blob/303eae918d997070a36b523ddc97e018f622c258/packages/core/src/debug/debug_node.ts#L32](https://github.com//github.com/angular/angular/blob/303eae918d997070a36b523ddc97e018f622c258/packages/core/src/debug/debug_node.ts/issues/L32) [#29806](https://github.com/angular/angular/issues/29806)
|
||||
* **core:** use shakeable global definitions ([#29929](https://github.com/angular/angular/issues/29929)) ([e5905bb](https://github.com/angular/angular/commit/e5905bb)), closes [/github.com/angular/angular-cli/blob/5fc1f2499cbe57f9a95e4b0dfced130eb3a8046d/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/common.ts#L279-L282](https://github.com//github.com/angular/angular-cli/blob/5fc1f2499cbe57f9a95e4b0dfced130eb3a8046d/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/common.ts/issues/L279-L282)
|
||||
* **language-service:** Use proper types instead of any ([#29942](https://github.com/angular/angular/issues/29942)) ([1a56cd5](https://github.com/angular/angular/commit/1a56cd5))
|
||||
* **bazel:** Install packages after `ng add` when invoked independently ([#29852](https://github.com/angular/angular/issues/29852)) ([bd2ce9c](https://github.com/angular/angular/commit/bd2ce9c))
|
||||
* **compiler-cli:** pass config path to ts.parseJsonConfigFileContent ([#29872](https://github.com/angular/angular/issues/29872)) ([86a3f90](https://github.com/angular/angular/commit/86a3f90)), closes [/github.com/Microsoft/TypeScript/blob/025d82633915b67003ea38ba40b9239a19721c13/src/compiler/emitter.ts#L56-L57](https://github.com//github.com/Microsoft/TypeScript/blob/025d82633915b67003ea38ba40b9239a19721c13/src/compiler/emitter.ts/issues/L56-L57)
|
||||
* **router:** support non-NgFactory promise in loadChildren typings ([#29832](https://github.com/angular/angular/issues/29832)) ([2bfb6a0](https://github.com/angular/angular/commit/2bfb6a0))
|
||||
* **bazel:** add configuration_env_vars = ["compile"] to generated [@npm](https://github.com/npm)//[@angular](https://github.com/angular)/bazel/bin:ngc-wrapped nodejs_binary ([#29694](https://github.com/angular/angular/issues/29694)) ([2e66ddf](https://github.com/angular/angular/commit/2e66ddf))
|
||||
* **bazel:** docs formatting ([#29817](https://github.com/angular/angular/issues/29817)) ([cc2e4b6](https://github.com/angular/angular/commit/cc2e4b6))
|
||||
* **bazel:** remove karma-jasmine from ts_web_test_suite ([#29695](https://github.com/angular/angular/issues/29695)) ([2bd9214](https://github.com/angular/angular/commit/2bd9214))
|
||||
* **bazel:** support running ng-add on minimal applications ([#29681](https://github.com/angular/angular/issues/29681)) ([9810c6c](https://github.com/angular/angular/commit/9810c6c)), closes [#29680](https://github.com/angular/angular/issues/29680)
|
||||
* **common:** add `@Injectable()` to common pipes ([#29834](https://github.com/angular/angular/issues/29834)) ([387fbb8](https://github.com/angular/angular/commit/387fbb8))
|
||||
* **compiler-cli:** ensure LogicalProjectPaths always start with a slash ([#29627](https://github.com/angular/angular/issues/29627)) ([e02684e](https://github.com/angular/angular/commit/e02684e))
|
||||
* **core:** add missing migration to npm package ([#29705](https://github.com/angular/angular/issues/29705)) ([96b76dc](https://github.com/angular/angular/commit/96b76dc))
|
||||
* **core:** call ngOnDestroy for tree-shakeable providers ([#28943](https://github.com/angular/angular/issues/28943)) ([30b0442](https://github.com/angular/angular/commit/30b0442)), closes [#28927](https://github.com/angular/angular/issues/28927)
|
||||
* **core:** Deprecate TestBed.get(...):any ([#29290](https://github.com/angular/angular/issues/29290)) ([609024f](https://github.com/angular/angular/commit/609024f)), closes [#13785](https://github.com/angular/angular/issues/13785) [#26491](https://github.com/angular/angular/issues/26491)
|
||||
* **core:** resolve ts compile issues due to lenient tsconfig ([#29843](https://github.com/angular/angular/issues/29843)) ([54058ba](https://github.com/angular/angular/commit/54058ba))
|
||||
* **platform-browser:** insert APP_ID in styles, contentAttr and hostAttr ([#17745](https://github.com/angular/angular/issues/17745)) ([712d60e](https://github.com/angular/angular/commit/712d60e))
|
||||
* **bazel:** use //:tsconfig.json as the default for ng_module ([#29670](https://github.com/angular/angular/issues/29670)) ([#29711](https://github.com/angular/angular/issues/29711)) ([9e33dc3](https://github.com/angular/angular/commit/9e33dc3))
|
||||
* **platform-browser:** insert APP_ID in styles, contentAttr and hostAttr ([#17745](https://github.com/angular/angular/issues/17745)) ([ca14509](https://github.com/angular/angular/commit/ca14509))
|
||||
* **bazel:** Update schematics to support routing ([#29548](https://github.com/angular/angular/issues/29548)) ([401b8ee](https://github.com/angular/angular/commit/401b8ee))
|
||||
* **bazel:** use //:tsconfig.json as the default for ng_module ([#29670](https://github.com/angular/angular/issues/29670)) ([b14537a](https://github.com/angular/angular/commit/b14537a))
|
||||
* **compiler-cli:** ngcc - cope with processing entry-points multiple times ([#29657](https://github.com/angular/angular/issues/29657)) ([6b39c9c](https://github.com/angular/angular/commit/6b39c9c))
|
||||
* **core:** static-query schematic should detect static queries in getters. ([#29609](https://github.com/angular/angular/issues/29609)) ([33016b8](https://github.com/angular/angular/commit/33016b8))
|
||||
* **common:** escape query selector used when anchor scrolling ([#29577](https://github.com/angular/angular/issues/29577)) ([7671c73](https://github.com/angular/angular/commit/7671c73)), closes [#28193](https://github.com/angular/angular/issues/28193)
|
||||
* **router:** adjust setting navigationTransition when a new navigation cancels an existing one ([#29636](https://github.com/angular/angular/issues/29636)) ([e884c0c](https://github.com/angular/angular/commit/e884c0c)), closes [#29389](https://github.com/angular/angular/issues/29389) [#29590](https://github.com/angular/angular/issues/29590)
|
||||
* **bazel:** allow ng_module users to set createExternalSymbolFactoryReexports ([#29459](https://github.com/angular/angular/issues/29459)) ([21be0fb](https://github.com/angular/angular/commit/21be0fb))
|
||||
* **bazel:** workaround problem reading summary files from node_modules ([#29459](https://github.com/angular/angular/issues/29459)) ([769d960](https://github.com/angular/angular/commit/769d960))
|
||||
* **compiler:** inherit param types when class has a constructor which takes no declared parameters and delegates up ([#29232](https://github.com/angular/angular/issues/29232)) ([0007564](https://github.com/angular/angular/commit/0007564))
|
||||
* **core:** parse incorrect ML open tag as text ([#29328](https://github.com/angular/angular/issues/29328)) ([dafbbf8](https://github.com/angular/angular/commit/dafbbf8)), closes [#29231](https://github.com/angular/angular/issues/29231)
|
||||
* **core:** static-query schematic should detect queries in "ngDoCheck" and "ngOnChanges" ([#29492](https://github.com/angular/angular/issues/29492)) ([09fab58](https://github.com/angular/angular/commit/09fab58))
|
||||
* **router:** support NgFactory promise in loadChildren typings ([#29392](https://github.com/angular/angular/issues/29392)) ([26a8c59](https://github.com/angular/angular/commit/26a8c59))
|
||||
* **bazel:** correct regexp test for self-references in metadata ([#29346](https://github.com/angular/angular/issues/29346)) ([9d090cb](https://github.com/angular/angular/commit/9d090cb))
|
||||
* **bazel:** don't produce self-references in metadata ([#29317](https://github.com/angular/angular/issues/29317)) ([3facdeb](https://github.com/angular/angular/commit/3facdeb)), closes [#29315](https://github.com/angular/angular/issues/29315)
|
||||
* **bazel:** fix strict null checks compile error in packages/bazel/src/schematics/ng-add/index.ts ([#29282](https://github.com/angular/angular/issues/29282)) ([9a7f560](https://github.com/angular/angular/commit/9a7f560))
|
||||
* **bazel:** Remove [@angular](https://github.com/angular)/upgrade from dev dependencies ([#29319](https://github.com/angular/angular/issues/29319)) ([1db8bf3](https://github.com/angular/angular/commit/1db8bf3))
|
||||
* **bazel:** Support new e2e project layout ([#29318](https://github.com/angular/angular/issues/29318)) ([8ef690c](https://github.com/angular/angular/commit/8ef690c))
|
||||
* **bazel:** turn off pure call tree shaking for ng_package ([#29210](https://github.com/angular/angular/issues/29210)) ([4990b93](https://github.com/angular/angular/commit/4990b93))
|
||||
* **compiler-cli:** incorrect metadata bundle for multiple unnamed re-exports ([#29360](https://github.com/angular/angular/issues/29360)) ([105cfaf](https://github.com/angular/angular/commit/105cfaf)), closes [/github.com/angular/material2/blob/master/tools/package-tools/build-release.ts#L78-L85](https://github.com//github.com/angular/material2/blob/master/tools/package-tools/build-release.ts/issues/L78-L85)
|
||||
* **core:** don't wrap `<tr>` and `<col>` elements into a required parent ([#29219](https://github.com/angular/angular/issues/29219)) ([f2dc32e](https://github.com/angular/angular/commit/f2dc32e))
|
||||
* **core:** parse incorrect ML open tag as text ([#29328](https://github.com/angular/angular/issues/29328)) ([4605df8](https://github.com/angular/angular/commit/4605df8)), closes [#29231](https://github.com/angular/angular/issues/29231)
|
||||
* **compiler-cli:** incorrect metadata bundle for multiple unnamed re-exports ([#29360](https://github.com/angular/angular/issues/29360)) ([cf8d934](https://github.com/angular/angular/commit/cf8d934)), closes [github.com/angular/material2/blob/master/tools/package-tools/build-release.ts#L78-L85](https://github.com/angular/material2/blob/master/tools/package-tools/build-release.ts#L78-L85)
|
||||
* **bazel:** add missing binary path for api-extractor ([#29202](https://github.com/angular/angular/issues/29202)) ([df354d1](https://github.com/angular/angular/commit/df354d1))
|
||||
* **bazel:** ng build should produce prod bundle ([#29136](https://github.com/angular/angular/issues/29136)) ([14ce8a9](https://github.com/angular/angular/commit/14ce8a9))
|
||||
* **compiler:** ensure template is updated if an output is transformed ([#29041](https://github.com/angular/angular/issues/29041)) ([c7e4931](https://github.com/angular/angular/commit/c7e4931))
|
||||
|
||||
|
||||
### DEPRECATIONS
|
||||
|
||||
* **core:** deprecate integration with the Web Tracing Framework (WTF) ([#30642](https://github.com/angular/angular/issues/30642)) ([b408445](https://github.com/angular/angular/commit/b408445))
|
||||
* **platform-webworker:** deprecate platform-webworker ([#30642](https://github.com/angular/angular/issues/30642)) ([361f181](https://github.com/angular/angular/commit/361f181))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **bazel:** @bazel/typescript is now a peerDependency of @angular/bazel so user's of @angular/bazel must add @bazel/typescript to their package.json
|
||||
* **bazel:** ng_module now depends on a minimum of build_bazel_rules_nodejs 0.27.12
|
||||
* **core:** In Angular version 8, it's required that all @ViewChild and @ContentChild
|
||||
queries have a 'static' flag specifying whether the query is 'static' or
|
||||
'dynamic'. The compiler previously sorted queries automatically, but in
|
||||
8.0 developers are required to explicitly specify which behavior is wanted.
|
||||
This is a temporary requirement as part of a migration; see
|
||||
https://v8.angular.io/guide/static-query-migration for more details.
|
||||
|
||||
@ViewChildren and @ContentChildren queries are always dynamic, and so are
|
||||
unaffected.
|
||||
|
||||
* `TestBed.get()` has two signatures, one which is typed and another which accepts and returns `any`. The signature for `any` is deprecated; all usage of `TestBed.get()` should go through the typed API. This mainly affects string tokens
|
||||
(which aren't supported) and abstract class tokens.
|
||||
|
||||
Before:
|
||||
|
||||
```ts
|
||||
TestBed.configureTestingModule({
|
||||
providers: [{provide: "stringToken", useValue: new Service()}],
|
||||
});
|
||||
|
||||
let service = TestBed.get("stringToken"); // type any
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```ts
|
||||
const SERVICE_TOKEN = new InjectionToken<Service>("SERVICE_TOKEN");
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
providers: [{provide: SERVICE_TOKEN, useValue: new Service()}],
|
||||
});
|
||||
|
||||
let service = TestBed.get(SERVICE_TOKEN); // type Service
|
||||
```
|
||||
|
||||
* **core:** Certain elements (like `<tr>` or `<col>`) require parent elements to be of a certain type by the HTML specification
|
||||
(ex. `<tr>` can only be inside `<tbody>` / `<thead>`). Before this change Angular template parser was auto-correcting
|
||||
"invalid" HTML using the following rules:
|
||||
- `<tr>` would be wrapped in `<tbody>` if not inside `<tbody>`, `<tfoot>` or `<thead>`;
|
||||
- `<col>` would be wrapped in `<colgroup>` if not inside `<colgroup>`.
|
||||
|
||||
This meachanism of automatic wrapping / auto-correcting was problematic for several reasons:
|
||||
- it is non-obvious and arbitrary (ex. there are more HTML elements that has rules for parent type);
|
||||
- it is incorrect for cases where `<tr>` / `<col>` are at the root of a component's content, ex.:
|
||||
|
||||
```html
|
||||
<projecting-tr-inside-tbody>
|
||||
<tr>...</tr>
|
||||
</projecting-tr-inside-tbody>
|
||||
```
|
||||
|
||||
In the above example the `<projecting-tr-inside-tbody>` component could be "surprised" to see additional
|
||||
`<tbody>` elements inserted by Angular HTML parser.
|
||||
|
||||
|
||||
* TypeScript 3.1 and 3.2 are no longer supported.
|
||||
|
||||
Please update your TypeScript version to 3.3
|
||||
|
||||
|
||||
<a name="8.0.0-rc.5"></a>
|
||||
# [8.0.0-rc.5](https://github.com/angular/angular/compare/8.0.0-rc.4...8.0.0-rc.5) (2019-05-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** allow ts_library interop with list-typed inputs ([#30600](https://github.com/angular/angular/issues/30600)) ([bf38df4](https://github.com/angular/angular/commit/bf38df4))
|
||||
* **bazel:** Disable sandbox on Mac OS ([#30460](https://github.com/angular/angular/issues/30460)) ([3de26a8](https://github.com/angular/angular/commit/3de26a8))
|
||||
* **bazel:** ng test should run specific ts_web_test_suite ([#30526](https://github.com/angular/angular/issues/30526)) ([8bc4da8](https://github.com/angular/angular/commit/8bc4da8))
|
||||
* **core:** remove deprecated `TestBed.deprecatedOverrideProvider` API ([#30576](https://github.com/angular/angular/issues/30576)) ([5a46f94](https://github.com/angular/angular/commit/5a46f94))
|
||||
* **core:** require 'static' flag on queries in typings ([#30641](https://github.com/angular/angular/issues/30641)) ([c8af830](https://github.com/angular/angular/commit/c8af830))
|
||||
* **core:** temporarily remove [@deprecated](https://github.com/deprecated) jsdoc tag for a TextBed.get overload ([#30514](https://github.com/angular/angular/issues/30514)) ([561e01d](https://github.com/angular/angular/commit/561e01d)), closes [#29290](https://github.com/angular/angular/issues/29290) [#29905](https://github.com/angular/angular/issues/29905)
|
||||
* **router:** type cast correctly for IE 11 bug breaking URL Unification when comparing objects ([#30464](https://github.com/angular/angular/issues/30464)) ([32daa93](https://github.com/angular/angular/commit/32daa93))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **common:** add ability to watch for AngularJS URL updates through `onUrlChange` hook ([#30466](https://github.com/angular/angular/issues/30466)) ([8022d36](https://github.com/angular/angular/commit/8022d36))
|
||||
* **common:** stricter types for SlicePipe ([#30156](https://github.com/angular/angular/issues/30156)) ([722b2fa](https://github.com/angular/angular/commit/722b2fa))
|
||||
|
||||
|
||||
### DEPRECATIONS
|
||||
|
||||
* **core:** deprecate integration with the Web Tracing Framework (WTF) ([#30642](https://github.com/angular/angular/issues/30642)) ([b408445](https://github.com/angular/angular/commit/b408445))
|
||||
* **platform-webworker:** deprecate platform-webworker ([#30642](https://github.com/angular/angular/issues/30642)) ([361f181](https://github.com/angular/angular/commit/361f181))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **core:** In Angular version 8, it's required that all @ViewChild and @ContentChild
|
||||
queries have a 'static' flag specifying whether the query is 'static' or
|
||||
'dynamic'. The compiler previously sorted queries automatically, but in
|
||||
8.0 developers are required to explicitly specify which behavior is wanted.
|
||||
This is a temporary requirement as part of a migration; see
|
||||
https://v8.angular.io/guide/static-query-migration for more details.
|
||||
|
||||
@ViewChildren and @ContentChildren queries are always dynamic, and so are
|
||||
unaffected.
|
||||
|
||||
|
||||
|
||||
<a name="8.0.0-rc.4"></a>
|
||||
# [8.0.0-rc.4](https://github.com/angular/angular/compare/8.0.0-rc.3...8.0.0-rc.4) (2019-05-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** Directly spawn native Bazel binary ([#30306](https://github.com/angular/angular/issues/30306)) ([d1fcc2b](https://github.com/angular/angular/commit/d1fcc2b))
|
||||
* **bazel:** pass correct arguments to http_server in Windows ([#30346](https://github.com/angular/angular/issues/30346)) ([71eba45](https://github.com/angular/angular/commit/71eba45)), closes [#29785](https://github.com/angular/angular/issues/29785)
|
||||
* **bazel:** Use existing npm/yarn lock files ([#30438](https://github.com/angular/angular/issues/30438)) ([3136d9f](https://github.com/angular/angular/commit/3136d9f))
|
||||
* **compiler:** ensure strict mode when evaluating in JIT ([#30122](https://github.com/angular/angular/issues/30122)) ([192f108](https://github.com/angular/angular/commit/192f108))
|
||||
* **core:** migrations not always migrating all files ([#30269](https://github.com/angular/angular/issues/30269)) ([e8ceae1](https://github.com/angular/angular/commit/e8ceae1))
|
||||
* **core:** static-query migration errors not printed properly ([#30458](https://github.com/angular/angular/issues/30458)) ([fde3f46](https://github.com/angular/angular/commit/fde3f46))
|
||||
* **core:** static-query migration fails with default parameter values ([#30269](https://github.com/angular/angular/issues/30269)) ([c3246e6](https://github.com/angular/angular/commit/c3246e6))
|
||||
* **core:** static-query migration should gracefully exit if AOT compiler throws ([#30269](https://github.com/angular/angular/issues/30269)) ([a71d8a8](https://github.com/angular/angular/commit/a71d8a8))
|
||||
* **core:** static-query migration should handle queries on accessors ([#30327](https://github.com/angular/angular/issues/30327)) ([dd299f9](https://github.com/angular/angular/commit/dd299f9))
|
||||
* **core:** static-query migration should not fallback to test strategy ([#30458](https://github.com/angular/angular/issues/30458)) ([0fa48e8](https://github.com/angular/angular/commit/0fa48e8))
|
||||
* **core:** static-query migration should not prompt if no queries are used ([#30254](https://github.com/angular/angular/issues/30254)) ([12fb639](https://github.com/angular/angular/commit/12fb639))
|
||||
* **core:** static-query usage migration strategy should detect ambiguous query usage ([#30215](https://github.com/angular/angular/issues/30215)) ([e295c6a](https://github.com/angular/angular/commit/e295c6a))
|
||||
* **router:** ensure navigations start with the current URL value incase redirect is skipped ([#30344](https://github.com/angular/angular/issues/30344)) ([9b88920](https://github.com/angular/angular/commit/9b88920)), closes [#30340](https://github.com/angular/angular/issues/30340) [#30160](https://github.com/angular/angular/issues/30160)
|
||||
* **router:** IE 11 bug can break URL unification when comparing objects ([#30393](https://github.com/angular/angular/issues/30393)) ([c383491](https://github.com/angular/angular/commit/c383491))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **bazel:** use rbe_autoconfig() and new container. ([#29336](https://github.com/angular/angular/issues/29336)) ([e562acc](https://github.com/angular/angular/commit/e562acc))
|
||||
|
||||
|
||||
|
||||
<a name="8.0.0-rc.3"></a>
|
||||
# [8.0.0-rc.3](https://github.com/angular/angular/compare/8.0.0-rc.2...8.0.0-rc.3) (2019-05-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** Bump ibazel to 0.10.1 for windows fixes ([#30196](https://github.com/angular/angular/issues/30196)) ([9f68c35](https://github.com/angular/angular/commit/9f68c35))
|
||||
* **compiler-cli:** log ngcc skipping messages as debug instead of info ([#30232](https://github.com/angular/angular/issues/30232)) ([548b003](https://github.com/angular/angular/commit/548b003))
|
||||
* **core:** fix interpolate identifier in AOT ([#30243](https://github.com/angular/angular/issues/30243)) ([3fe3a84](https://github.com/angular/angular/commit/3fe3a84))
|
||||
* **router:** ensure `history.state` is set in `eager` update mode ([#30154](https://github.com/angular/angular/issues/30154)) ([9720227](https://github.com/angular/angular/commit/9720227))
|
||||
* **router:** fix a problem with router not responding to back button ([#30160](https://github.com/angular/angular/issues/30160)) ([132f01c](https://github.com/angular/angular/commit/132f01c))
|
||||
|
||||
|
||||
|
||||
<a name="8.0.0-rc.2"></a>
|
||||
# [8.0.0-rc.2](https://github.com/angular/angular/compare/8.0.0-rc.1...8.0.0-rc.2) (2019-04-29)
|
||||
|
||||
@ -998,7 +1280,6 @@ To learn about the release highlights and our new CLI-powered update workflow fo
|
||||
|
||||
* **bazel:** protractor rule should include *.e2e-spec.js ([#25701](https://github.com/angular/angular/issues/25701)) ([ed6b68b](https://github.com/angular/angular/commit/ed6b68b))
|
||||
* **core:** size regression with closure compiler ([#25531](https://github.com/angular/angular/issues/25531)) ([ebcf762](https://github.com/angular/angular/commit/ebcf762))
|
||||
* **docs-infra:** show "suggest edits" only for /guide and /tutorial dirs ([#24378](https://github.com/angular/angular/issues/24378)) ([66b7870](https://github.com/angular/angular/commit/66b7870))
|
||||
* **upgrade:** trigger `$destroy` event on upgraded component element ([#25357](https://github.com/angular/angular/issues/25357)) ([82e0676](https://github.com/angular/angular/commit/82e0676)), closes [#25334](https://github.com/angular/angular/issues/25334)
|
||||
* **router:** warn if navigation triggered outside Angular zone ([#24959](https://github.com/angular/angular/issues/24959)) ([23a96dc](https://github.com/angular/angular/commit/23a96dc)), closes [#15770](https://github.com/angular/angular/issues/15770) [#15946](https://github.com/angular/angular/issues/15946) [#24728](https://github.com/angular/angular/issues/24728)
|
||||
|
||||
@ -1090,7 +1371,6 @@ Note: the 6.1.5 release on npm accidentally glitched-out midway, so we cut 6.1.6
|
||||
* **core:** Injector correctly honors the @Self flag ([#24520](https://github.com/angular/angular/issues/24520)) ([ccbda9d](https://github.com/angular/angular/commit/ccbda9d))
|
||||
* **core:** avoid eager providers re-initialization ([#23559](https://github.com/angular/angular/issues/23559)) ([0c6dc45](https://github.com/angular/angular/commit/0c6dc45))
|
||||
* **core:** call ngOnDestroy on all services that have it ([#23755](https://github.com/angular/angular/issues/23755)) ([fc03427](https://github.com/angular/angular/commit/fc03427)), closes [#22466](https://github.com/angular/angular/issues/22466) [#22240](https://github.com/angular/angular/issues/22240) [#14818](https://github.com/angular/angular/issues/14818)
|
||||
* **docs-infra:** fix table header layout in API pages ([#24919](https://github.com/angular/angular/issues/24919)) ([3cd9645](https://github.com/angular/angular/commit/3cd9645))
|
||||
* **elements:** always check to create strategy ([#23825](https://github.com/angular/angular/issues/23825)) ([b1cda36](https://github.com/angular/angular/commit/b1cda36))
|
||||
* **elements:** prevent closure renaming of platform properties ([#23843](https://github.com/angular/angular/issues/23843)) ([d4b8b24](https://github.com/angular/angular/commit/d4b8b24))
|
||||
* **forms:** properly handle special properties in FormGroup.get ([#22249](https://github.com/angular/angular/issues/22249)) ([9367e91](https://github.com/angular/angular/commit/9367e91)), closes [#17195](https://github.com/angular/angular/issues/17195)
|
||||
@ -1207,7 +1487,6 @@ For example:
|
||||
|
||||
* **animations:** always render end-state styles for orphaned DOM nodes ([#24236](https://github.com/angular/angular/issues/24236)) ([0139173](https://github.com/angular/angular/commit/0139173))
|
||||
* **bazel:** Allow ng_module to depend on targets w no deps ([#24446](https://github.com/angular/angular/issues/24446)) ([ea3669e](https://github.com/angular/angular/commit/ea3669e))
|
||||
* **docs-infra:** use script nomodule to load IE polyfills, skip other polyfills ([#24317](https://github.com/angular/angular/issues/24317)) ([e876535](https://github.com/angular/angular/commit/e876535)), closes [#23647](https://github.com/angular/angular/issues/23647)
|
||||
* **router:** fix lazy loading of aux routes ([#23459](https://github.com/angular/angular/issues/23459)) ([d20877b](https://github.com/angular/angular/commit/d20877b)), closes [#10981](https://github.com/angular/angular/issues/10981)
|
||||
* **service-worker:** fix `SwPush.unsubscribe()` ([#24162](https://github.com/angular/angular/issues/24162)) ([ea2987c](https://github.com/angular/angular/commit/ea2987c)), closes [#24095](https://github.com/angular/angular/issues/24095)
|
||||
|
||||
|
22
WORKSPACE
22
WORKSPACE
@ -96,7 +96,7 @@ web_test_repositories()
|
||||
|
||||
# Temporary work-around for https://github.com/angular/angular/issues/28681
|
||||
# TODO(gregmagolan): go back to @io_bazel_rules_webtesting browser_repositories
|
||||
load("@npm_bazel_karma//:browser_repositories.bzl", "browser_repositories")
|
||||
load("//:browser_repositories.bzl", "browser_repositories")
|
||||
|
||||
browser_repositories()
|
||||
|
||||
@ -114,3 +114,23 @@ sass_repositories()
|
||||
load("@io_bazel_skydoc//skylark:skylark.bzl", "skydoc_repositories")
|
||||
|
||||
skydoc_repositories()
|
||||
|
||||
load("@bazel_toolchains//rules:environments.bzl", "clang_env")
|
||||
load("@bazel_toolchains//rules:rbe_repo.bzl", "rbe_autoconfig")
|
||||
|
||||
rbe_autoconfig(
|
||||
name = "rbe_ubuntu1604_angular",
|
||||
# The sha256 of marketplace.gcr.io/google/rbe-ubuntu16-04 container that is
|
||||
# used by rbe_autoconfig() to pair toolchain configs in the @bazel_toolchains repo.
|
||||
base_container_digest = "sha256:677c1317f14c6fd5eba2fd8ec645bfdc5119f64b3e5e944e13c89e0525cc8ad1",
|
||||
# Note that if you change the `digest`, you might also need to update the
|
||||
# `base_container_digest` to make sure marketplace.gcr.io/google/rbe-ubuntu16-04-webtest:<digest>
|
||||
# and marketplace.gcr.io/google/rbe-ubuntu16-04:<base_container_digest> have
|
||||
# the same Clang and JDK installed.
|
||||
# Clang is needed because of the dependency on @com_google_protobuf.
|
||||
# Java is needed for the Bazel's test executor Java tool.
|
||||
digest = "sha256:74a8e9dca4781d5f277a7bd8e7ea7ed0f5906c79c9cd996205b6d32f090c62f3",
|
||||
env = clang_env(),
|
||||
registry = "marketplace.gcr.io",
|
||||
repository = "google/rbe-ubuntu16-04-webtest",
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
<h1 class="no-toc">CLI Command Reference</h1>
|
||||
# CLI Overview and Command Reference
|
||||
|
||||
The Angular CLI is a command-line interface tool that you use to initialize, develop, scaffold, and maintain Angular applications. You can use the tool directly in a command shell, or indirectly through an interactive UI such as [Angular Console](https://angularconsole.com).
|
||||
|
||||
|
3
aio/content/examples/.gitignore
vendored
3
aio/content/examples/.gitignore
vendored
@ -23,6 +23,9 @@
|
||||
**/bs-config.e2e.json
|
||||
**/bs-config.json
|
||||
**/package.json
|
||||
**/tsconfig.json
|
||||
**/tsconfig.app.json
|
||||
**/tsconfig.spec.json
|
||||
**/tslint.json
|
||||
**/karma-test-shim.js
|
||||
**/browser-test-shim.js
|
||||
|
@ -67,8 +67,8 @@ describe('AngularJS to Angular Quick Reference Tests', function () {
|
||||
testFavoriteHero('Magneta', 'No movie, sorry!');
|
||||
});
|
||||
|
||||
it('should display a movie for Mr. Nice', function () {
|
||||
testFavoriteHero('Mr. Nice', 'Excellent choice!');
|
||||
it('should display a movie for Dr Nice', function () {
|
||||
testFavoriteHero('Dr Nice', 'Excellent choice!');
|
||||
});
|
||||
|
||||
function testImagesAreDisplayed(isDisplayed: boolean) {
|
||||
|
@ -18,12 +18,12 @@ export class MovieService {
|
||||
approvalRating: .97
|
||||
},
|
||||
{
|
||||
hero: 'Mr. Nice',
|
||||
hero: 'Dr Nice',
|
||||
imageurl: 'assets/images/villain.png',
|
||||
movieId: 2,
|
||||
mpaa: 'pg-13',
|
||||
releaseDate: '2015-12-18T00:00:00',
|
||||
title: 'No More Mr. Nice Guy',
|
||||
title: 'No More Dr Nice',
|
||||
price: 14.95,
|
||||
starRating: 4.6,
|
||||
approvalRating: .94
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { Hero } from './hero';
|
||||
|
||||
export const HEROES: Hero[] = [
|
||||
{ id: 11, name: 'Mr. Nice' },
|
||||
{ id: 11, name: 'Dr Nice' },
|
||||
{ id: 12, name: 'Narco' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' },
|
||||
|
@ -31,7 +31,7 @@ describe('Architecture', () => {
|
||||
|
||||
function heroTests() {
|
||||
|
||||
const targetHero: Hero = { id: 2, name: 'Mr. Nice' };
|
||||
const targetHero: Hero = { id: 2, name: 'Dr Nice' };
|
||||
|
||||
it('has the right number of heroes', () => {
|
||||
let page = getPageElts();
|
||||
|
@ -5,7 +5,7 @@ import { Hero } from './hero';
|
||||
|
||||
const HEROES = [
|
||||
new Hero('Windstorm', 'Weather mastery'),
|
||||
new Hero('Mr. Nice', 'Killing them with kindness'),
|
||||
new Hero('Dr Nice', 'Killing them with kindness'),
|
||||
new Hero('Magneta', 'Manipulates metallic objects')
|
||||
];
|
||||
|
||||
|
@ -9,6 +9,6 @@ describe('feature-modules App', () => {
|
||||
|
||||
it('should display message saying app works', () => {
|
||||
page.navigateTo();
|
||||
expect(page.getParagraphText()).toEqual('app works!');
|
||||
expect(page.getTitleText()).toEqual('app works!');
|
||||
});
|
||||
});
|
||||
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"open": false,
|
||||
"logLevel": "silent",
|
||||
"port": 8080,
|
||||
"server": {
|
||||
"baseDir": "dist",
|
||||
"middleware": {
|
||||
"0": null
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
'use strict'; // necessary for es6 output in node
|
||||
|
||||
import { browser, element, by } from 'protractor';
|
||||
|
||||
describe('cli-quickstart App', () => {
|
||||
beforeEach(() => {
|
||||
return browser.get('/');
|
||||
});
|
||||
|
||||
it('should display message saying app works', () => {
|
||||
let pageTitle = element(by.css('app-root h1')).getText();
|
||||
expect(pageTitle).toEqual('Welcome to My First Angular App!!');
|
||||
});
|
||||
});
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"build": "build:cli",
|
||||
"run": "serve:cli"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
/* #docregion */
|
||||
h1 {
|
||||
color: #369;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-size: 250%;
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
<!--The content below is only a placeholder and can be replaced.-->
|
||||
<div style="text-align:center">
|
||||
<h1>
|
||||
Welcome to {{ title }}!
|
||||
</h1>
|
||||
<img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
|
||||
</div>
|
||||
<h2>Here are some links to help you start: </h2>
|
||||
<ul>
|
||||
<li>
|
||||
<h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
|
||||
</li>
|
||||
<li>
|
||||
<h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
|
||||
</li>
|
||||
<li>
|
||||
<h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
|
||||
</li>
|
||||
</ul>
|
@ -1,30 +0,0 @@
|
||||
import { TestBed, async } from '@angular/core/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
it('should create the app', async(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.debugElement.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
}));
|
||||
|
||||
it(`should have as title 'app'`, async(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.debugElement.componentInstance;
|
||||
expect(app.title).toMatch(/app/i);
|
||||
}));
|
||||
|
||||
it('should render title in a h1 tag', async(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.debugElement.nativeElement;
|
||||
expect(compiled.querySelector('h1').textContent).toMatch(/app/i);
|
||||
}));
|
||||
});
|
@ -1,16 +0,0 @@
|
||||
// #docregion import
|
||||
import { Component } from '@angular/core';
|
||||
// #enddocregion import
|
||||
|
||||
// #docregion metadata, component
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
// #enddocregion metadata
|
||||
// #docregion title, class
|
||||
export class AppComponent {
|
||||
title = 'My First Angular App!';
|
||||
}
|
||||
// #enddocregion title, class, component
|
@ -1,16 +0,0 @@
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
@ -1,9 +0,0 @@
|
||||
{
|
||||
"files":[
|
||||
"!**/*.d.ts",
|
||||
"!**/*.js",
|
||||
"!**/*.[0-9].*",
|
||||
"angular.json",
|
||||
"protractor.conf.js"
|
||||
]
|
||||
}
|
@ -13,7 +13,7 @@ describe('Component Communication Cookbook Tests', function () {
|
||||
describe('Parent-to-child communication', function() {
|
||||
// #docregion parent-to-child
|
||||
// ...
|
||||
let _heroNames = ['Mr. IQ', 'Magneta', 'Bombasto'];
|
||||
let _heroNames = ['Dr IQ', 'Magneta', 'Bombasto'];
|
||||
let _masterName = 'Master';
|
||||
|
||||
it('should pass properties to children properly', function () {
|
||||
@ -36,7 +36,7 @@ describe('Component Communication Cookbook Tests', function () {
|
||||
// ...
|
||||
it('should display trimmed, non-empty names', function () {
|
||||
let _nonEmptyNameIndex = 0;
|
||||
let _nonEmptyName = '"Mr. IQ"';
|
||||
let _nonEmptyName = '"Dr IQ"';
|
||||
let parent = element.all(by.tagName('app-name-parent')).get(0);
|
||||
let hero = parent.all(by.tagName('app-name-child')).get(_nonEmptyNameIndex);
|
||||
|
||||
|
@ -39,7 +39,7 @@ export class CountdownLocalVarParentComponent { }
|
||||
})
|
||||
export class CountdownViewChildParentComponent implements AfterViewInit {
|
||||
|
||||
@ViewChild(CountdownTimerComponent)
|
||||
@ViewChild(CountdownTimerComponent, {static: false})
|
||||
private timerComponent: CountdownTimerComponent;
|
||||
|
||||
seconds() { return 0; }
|
||||
|
@ -3,7 +3,7 @@ export class Hero {
|
||||
}
|
||||
|
||||
export const HEROES = [
|
||||
{name: 'Mr. IQ'},
|
||||
{name: 'Dr IQ'},
|
||||
{name: 'Magneta'},
|
||||
{name: 'Bombasto'}
|
||||
];
|
||||
|
@ -9,7 +9,7 @@ import { Component } from '@angular/core';
|
||||
`
|
||||
})
|
||||
export class NameParentComponent {
|
||||
// Displays 'Mr. IQ', '<no name set>', 'Bombasto'
|
||||
names = ['Mr. IQ', ' ', ' Bombasto '];
|
||||
// Displays 'Dr IQ', '<no name set>', 'Bombasto'
|
||||
names = ['Dr IQ', ' ', ' Bombasto '];
|
||||
}
|
||||
// #enddocregion
|
||||
|
@ -15,7 +15,7 @@ import { Component } from '@angular/core';
|
||||
export class VoteTakerComponent {
|
||||
agreed = 0;
|
||||
disagreed = 0;
|
||||
voters = ['Mr. IQ', 'Ms. Universe', 'Bombasto'];
|
||||
voters = ['Narco', 'Celeritas', 'Bombasto'];
|
||||
|
||||
onVoted(agreed: boolean) {
|
||||
agreed ? this.agreed++ : this.disagreed++;
|
||||
|
@ -23,8 +23,8 @@ describe('Dependency Injection Cookbook', function () {
|
||||
expect(sortedHeroes).toBeDefined();
|
||||
});
|
||||
|
||||
it('Mr. Nice should be in sorted heroes', function () {
|
||||
let sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Mr. Nice" and position()=2]')).get(0);
|
||||
it('Dr Nice should be in sorted heroes', function () {
|
||||
let sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Dr Nice" and position()=2]')).get(0);
|
||||
expect(sortedHero).toBeDefined();
|
||||
});
|
||||
|
||||
@ -60,7 +60,7 @@ describe('Dependency Injection Cookbook', function () {
|
||||
|
||||
it('should render Hero-of-the-Month runner-ups', function () {
|
||||
let runnersUp = element(by.id('rups1')).getText();
|
||||
expect(runnersUp).toContain('RubberMan, Mr. Nice');
|
||||
expect(runnersUp).toContain('RubberMan, Dr Nice');
|
||||
});
|
||||
|
||||
it('should render DateLogger log entry in Hero-of-the-Month', function () {
|
||||
|
@ -11,7 +11,7 @@ export class HeroService {
|
||||
private heroes: Array<Hero> = [
|
||||
new Hero(1, 'RubberMan', 'Hero of many talents', '123-456-7899'),
|
||||
new Hero(2, 'Magma', 'Hero of all trades', '555-555-5555'),
|
||||
new Hero(3, 'Mr. Nice', 'The name says it all', '111-222-3333')
|
||||
new Hero(3, 'Dr Nice', 'The name says it all', '111-222-3333')
|
||||
];
|
||||
|
||||
getHeroById(id: number): Hero {
|
||||
|
@ -29,10 +29,10 @@ export class StorageComponent implements OnInit {
|
||||
}
|
||||
|
||||
setSession() {
|
||||
this.sessionStorageService.set('hero', 'Mr. Nice - Session');
|
||||
this.sessionStorageService.set('hero', 'Dr Nice - Session');
|
||||
}
|
||||
|
||||
setLocal() {
|
||||
this.localStorageService.set('hero', 'Mr. Nice - Local');
|
||||
this.localStorageService.set('hero', 'Dr Nice - Local');
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ describe('Dependency Injection Tests', function () {
|
||||
});
|
||||
|
||||
it('Hero displays as expected', function () {
|
||||
expectedMsg = 'Mr. Nice';
|
||||
expectedMsg = 'Dr Nice';
|
||||
expect(element(by.css('#hero')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { Hero } from './hero';
|
||||
|
||||
export const HEROES: Hero[] = [
|
||||
{ id: 11, isSecret: false, name: 'Mr. Nice' },
|
||||
{ id: 11, isSecret: false, name: 'Dr Nice' },
|
||||
{ id: 12, isSecret: false, name: 'Narco' },
|
||||
{ id: 13, isSecret: false, name: 'Bombasto' },
|
||||
{ id: 14, isSecret: false, name: 'Celeritas' },
|
||||
|
@ -4,7 +4,7 @@ export class Hero {
|
||||
}
|
||||
|
||||
export const HEROES: Hero[] = [
|
||||
{ id: 11, name: 'Mr. Nice' },
|
||||
{ id: 11, name: 'Dr Nice' },
|
||||
{ id: 12, name: 'Narco' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' }
|
||||
|
@ -20,7 +20,7 @@ import { AdComponent } from './ad.component';
|
||||
export class AdBannerComponent implements OnInit, OnDestroy {
|
||||
@Input() ads: AdItem[];
|
||||
currentAdIndex = -1;
|
||||
@ViewChild(AdDirective) adHost: AdDirective;
|
||||
@ViewChild(AdDirective, {static: true}) adHost: AdDirective;
|
||||
interval: any;
|
||||
|
||||
constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
|
||||
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"projectType": "elements"
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ export class ItemDetailComponent {
|
||||
@Output() deleteRequest = new EventEmitter<Item>();
|
||||
|
||||
delete() {
|
||||
this.deleteRequest.emit(this.item.name);
|
||||
this.deleteRequest.emit(this.item);
|
||||
this.displayNone = this.displayNone ? '' : 'none';
|
||||
this.lineThrough = this.lineThrough ? '' : 'line-through';
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ describe('feature-modules App', () => {
|
||||
|
||||
it('should display message saying app works', () => {
|
||||
page.navigateTo();
|
||||
expect(page.getParagraphText()).toEqual('app works!');
|
||||
expect(page.getTitleText()).toEqual('app works!');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -36,7 +36,7 @@ describe('Http Tests', function() {
|
||||
describe('Heroes', () => {
|
||||
it('retrieves the list of heroes at startup', () => {
|
||||
expect(page.heroesListItems.count()).toBe(4);
|
||||
expect(page.heroesListItems.get(0).getText()).toContain('Mr. Nice');
|
||||
expect(page.heroesListItems.get(0).getText()).toContain('Dr Nice');
|
||||
checkLogForMessage('GET "api/heroes"');
|
||||
});
|
||||
|
||||
|
@ -3,7 +3,7 @@ import { InMemoryDbService } from 'angular-in-memory-web-api';
|
||||
export class InMemoryDataService implements InMemoryDbService {
|
||||
createDb() {
|
||||
const heroes = [
|
||||
{ id: 11, name: 'Mr. Nice' },
|
||||
{ id: 11, name: 'Dr Nice' },
|
||||
{ id: 12, name: 'Narco' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' },
|
||||
|
@ -15,7 +15,7 @@ describe('providers App', () => {
|
||||
|
||||
it('should display message saying app works', () => {
|
||||
page.navigateTo();
|
||||
expect(page.getParagraphText()).toEqual('Lazy loading feature modules');
|
||||
expect(page.getTitleText()).toEqual('Lazy loading feature modules');
|
||||
});
|
||||
|
||||
describe('Customers list', function() {
|
||||
|
@ -8,11 +8,11 @@ import { Routes, RouterModule } from '@angular/router';
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: 'customers',
|
||||
loadChildren: './customers/customers.module#CustomersModule'
|
||||
loadChildren: () => import('./customers/customers.module').then(mod => mod.CustomersModule)
|
||||
},
|
||||
{
|
||||
path: 'orders',
|
||||
loadChildren: './orders/orders.module#OrdersModule'
|
||||
loadChildren: () => import('./orders/orders.module').then(mod => mod.OrdersModule)
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
|
@ -34,7 +34,7 @@ export class AfterContentComponent implements AfterContentChecked, AfterContentI
|
||||
comment = '';
|
||||
|
||||
// Query for a CONTENT child of type `ChildComponent`
|
||||
@ContentChild(ChildComponent) contentChild: ChildComponent;
|
||||
@ContentChild(ChildComponent, {static: false}) contentChild: ChildComponent;
|
||||
|
||||
// #enddocregion hooks
|
||||
constructor(private logger: LoggerService) {
|
||||
|
@ -35,7 +35,7 @@ export class AfterViewComponent implements AfterViewChecked, AfterViewInit {
|
||||
private prevHero = '';
|
||||
|
||||
// Query for a VIEW child of type `ChildViewComponent`
|
||||
@ViewChild(ChildViewComponent) viewChild: ChildViewComponent;
|
||||
@ViewChild(ChildViewComponent, {static: false}) viewChild: ChildViewComponent;
|
||||
|
||||
// #enddocregion hooks
|
||||
constructor(private logger: LoggerService) {
|
||||
|
@ -81,7 +81,7 @@ export class DoCheckParentComponent {
|
||||
hero: Hero;
|
||||
power: string;
|
||||
title = 'DoCheck';
|
||||
@ViewChild(DoCheckComponent) childView: DoCheckComponent;
|
||||
@ViewChild(DoCheckComponent, {static: false}) childView: DoCheckComponent;
|
||||
|
||||
constructor() { this.reset(); }
|
||||
|
||||
|
@ -55,7 +55,7 @@ export class OnChangesParentComponent {
|
||||
hero: Hero;
|
||||
power: string;
|
||||
title = 'OnChanges';
|
||||
@ViewChild(OnChangesComponent) childView: OnChangesComponent;
|
||||
@ViewChild(OnChangesComponent, {static: false}) childView: OnChangesComponent;
|
||||
|
||||
constructor() {
|
||||
this.reset();
|
||||
|
@ -6,7 +6,7 @@ export class Hero {
|
||||
}
|
||||
|
||||
export const heroes: Hero[] = [
|
||||
{ id: 1, name: 'Mr. Nice', emotion: 'happy' },
|
||||
{ id: 1, name: 'Dr Nice', emotion: 'happy' },
|
||||
{ id: 2, name: 'Narco', emotion: 'sad' },
|
||||
{ id: 3, name: 'Windstorm', emotion: 'confused' },
|
||||
{ id: 4, name: 'Magneta' }
|
||||
|
@ -3,8 +3,8 @@ import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
export const routes: Routes = [
|
||||
{ path: '', redirectTo: 'contact', pathMatch: 'full'},
|
||||
{ path: 'items', loadChildren: './items/items.module#ItemsModule' },
|
||||
{ path: 'customers', loadChildren: './customers/customers.module#CustomersModule' }
|
||||
{ path: 'items', loadChildren: () => import('./items/items.module').then(mod => mod.ItemsModule) },
|
||||
{ path: 'customers', loadChildren: () => import('./customers/customers.module').then(mod => mod.CustomersModule) }
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
@ -11,8 +11,7 @@ import { Pipe, PipeTransform } from '@angular/core';
|
||||
*/
|
||||
@Pipe({name: 'exponentialStrength'})
|
||||
export class ExponentialStrengthPipe implements PipeTransform {
|
||||
transform(value: number, exponent: string): number {
|
||||
let exp = parseFloat(exponent);
|
||||
return Math.pow(value, isNaN(exp) ? 1 : exp);
|
||||
transform(value: number, exponent?: number): number {
|
||||
return Math.pow(value, isNaN(exponent) ? 1 : exponent);
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ describe('providers App', () => {
|
||||
|
||||
it('should display header that says Users list', () => {
|
||||
page.navigateTo();
|
||||
expect(page.getParagraphText()).toEqual('Users list');
|
||||
expect(page.getTitleText()).toEqual('Users list');
|
||||
});
|
||||
|
||||
|
||||
|
@ -20,7 +20,7 @@ const appRoutes: Routes = [
|
||||
// #docregion admin, admin-1
|
||||
{
|
||||
path: 'admin',
|
||||
loadChildren: './admin/admin.module#AdminModule',
|
||||
loadChildren: () => import('./admin/admin.module').then(mod => mod.AdminModule),
|
||||
// #enddocregion admin-1
|
||||
canLoad: [AuthGuard]
|
||||
// #docregion admin-1
|
||||
|
@ -21,12 +21,12 @@ const appRoutes: Routes = [
|
||||
},
|
||||
{
|
||||
path: 'admin',
|
||||
loadChildren: './admin/admin.module#AdminModule',
|
||||
loadChildren: () => import('./admin/admin.module').then(mod => mod.AdminModule),
|
||||
canLoad: [AuthGuard]
|
||||
},
|
||||
{
|
||||
path: 'crisis-center',
|
||||
loadChildren: './crisis-center/crisis-center.module#CrisisCenterModule'
|
||||
loadChildren: () => import('./crisis-center/crisis-center.module').then(mod => mod.CrisisCenterModule)
|
||||
},
|
||||
{ path: '', redirectTo: '/heroes', pathMatch: 'full' },
|
||||
{ path: '**', component: PageNotFoundComponent }
|
||||
|
@ -17,13 +17,13 @@ const appRoutes: Routes = [
|
||||
},
|
||||
{
|
||||
path: 'admin',
|
||||
loadChildren: './admin/admin.module#AdminModule',
|
||||
loadChildren: () => import('./admin/admin.module').then(mod => mod.AdminModule),
|
||||
canLoad: [AuthGuard]
|
||||
},
|
||||
// #docregion preload-v2
|
||||
{
|
||||
path: 'crisis-center',
|
||||
loadChildren: './crisis-center/crisis-center.module#CrisisCenterModule',
|
||||
loadChildren: () => import('./crisis-center/crisis-center.module').then(mod => mod.CrisisCenterModule),
|
||||
data: { preload: true }
|
||||
},
|
||||
// #enddocregion preload-v2
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Hero } from './hero';
|
||||
|
||||
export const HEROES: Hero[] = [
|
||||
{ id: 11, name: 'Mr. Nice' },
|
||||
{ id: 11, name: 'Dr Nice' },
|
||||
{ id: 12, name: 'Narco' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' },
|
||||
|
@ -11,7 +11,7 @@ describe('sw-example App', () => {
|
||||
|
||||
it('should display welcome message', () => {
|
||||
page.navigateTo();
|
||||
expect(page.getParagraphText()).toEqual('Welcome to Service Workers!');
|
||||
expect(page.getTitleText()).toEqual('Welcome to Service Workers!');
|
||||
});
|
||||
|
||||
it('should display the Angular logo', () => {
|
||||
|
@ -10,12 +10,12 @@ describe('Structural Directives', function () {
|
||||
|
||||
it('first div should show hero name with *ngIf', function () {
|
||||
const allDivs = element.all(by.tagName('div'));
|
||||
expect(allDivs.get(0).getText()).toEqual('Mr. Nice');
|
||||
expect(allDivs.get(0).getText()).toEqual('Dr Nice');
|
||||
});
|
||||
|
||||
it('first li should show hero name with *ngFor', function () {
|
||||
const allLis = element.all(by.tagName('li'));
|
||||
expect(allLis.get(0).getText()).toEqual('Mr. Nice');
|
||||
expect(allLis.get(0).getText()).toEqual('Dr Nice');
|
||||
});
|
||||
|
||||
it('ngSwitch have two <happy-hero> instances', function () {
|
||||
|
@ -6,7 +6,7 @@ export class Hero {
|
||||
}
|
||||
|
||||
export const heroes: Hero[] = [
|
||||
{ id: 1, name: 'Mr. Nice', emotion: 'happy'},
|
||||
{ id: 1, name: 'Dr Nice', emotion: 'happy'},
|
||||
{ id: 2, name: 'Narco', emotion: 'sad' },
|
||||
{ id: 3, name: 'Windstorm', emotion: 'confused' },
|
||||
{ id: 4, name: 'Magneta'}
|
||||
|
@ -13,7 +13,7 @@ import { Hero } from './hero';
|
||||
})
|
||||
export class HeroFormComponent {
|
||||
@Input() hero: Hero;
|
||||
@ViewChild('heroForm') form: NgForm;
|
||||
@ViewChild('heroForm', {static: false}) form: NgForm;
|
||||
|
||||
private _submitMessage = '';
|
||||
|
||||
|
@ -10,7 +10,7 @@ export class Hero {
|
||||
'http://www.imdb.com/title/tt0065832/',
|
||||
325
|
||||
),
|
||||
new Hero(1, 'Mr. Nice', 'happy'),
|
||||
new Hero(1, 'Dr Nice', 'happy'),
|
||||
new Hero(2, 'Narco', 'sad' ),
|
||||
new Hero(3, 'Windstorm', 'confused' ),
|
||||
new Hero(4, 'Magneta')
|
||||
|
@ -8,7 +8,7 @@ import { AboutComponent } from './about/about.component';
|
||||
RouterModule.forRoot([
|
||||
{ path: '', redirectTo: 'dashboard', pathMatch: 'full'},
|
||||
{ path: 'about', component: AboutComponent },
|
||||
{ path: 'heroes', loadChildren: './hero/hero.module#HeroModule'}
|
||||
{ path: 'heroes', loadChildren: () => import('./hero/hero.module').then(mod => mod.HeroModule)}
|
||||
])
|
||||
],
|
||||
exports: [ RouterModule ] // re-export the module declarations
|
||||
|
@ -9,7 +9,7 @@ const maxQuotes = Infinity; // 0;
|
||||
export class InMemoryDataService implements InMemoryDbService {
|
||||
createDb() {
|
||||
const heroes = [
|
||||
{ id: 11, name: 'Mr. Nice' },
|
||||
{ id: 11, name: 'Dr Nice' },
|
||||
{ id: 12, name: 'Narco' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' },
|
||||
|
@ -1 +1 @@
|
||||
export * from './fake-hero.service';
|
||||
export * from './test-hero.service';
|
||||
|
@ -6,7 +6,7 @@ import { Component, AfterViewInit, ViewChild } from '@angular/core';
|
||||
})
|
||||
export class CanvasComponent implements AfterViewInit {
|
||||
blobSize: number;
|
||||
@ViewChild('sampleCanvas') sampleCanvas;
|
||||
@ViewChild('sampleCanvas', {static: false}) sampleCanvas;
|
||||
|
||||
constructor() { }
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Hero } from './hero';
|
||||
|
||||
export const HEROES: Hero[] = [
|
||||
{ id: 11, name: 'Mr. Nice' },
|
||||
{ id: 11, name: 'Dr Nice' },
|
||||
{ id: 12, name: 'Narco' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' },
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Hero } from './hero';
|
||||
|
||||
export const HEROES: Hero[] = [
|
||||
{ id: 11, name: 'Mr. Nice' },
|
||||
{ id: 11, name: 'Dr Nice' },
|
||||
{ id: 12, name: 'Narco' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' },
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { Hero } from './hero';
|
||||
|
||||
export const HEROES: Hero[] = [
|
||||
{ id: 11, name: 'Mr. Nice' },
|
||||
{ id: 11, name: 'Dr Nice' },
|
||||
{ id: 12, name: 'Narco' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' },
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { Hero } from './hero';
|
||||
|
||||
export const HEROES: Hero[] = [
|
||||
{ id: 11, name: 'Mr. Nice' },
|
||||
{ id: 11, name: 'Dr Nice' },
|
||||
{ id: 12, name: 'Narco' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' },
|
||||
|
@ -9,7 +9,7 @@ import { Injectable } from '@angular/core';
|
||||
export class InMemoryDataService implements InMemoryDbService {
|
||||
createDb() {
|
||||
const heroes = [
|
||||
{ id: 11, name: 'Mr. Nice' },
|
||||
{ id: 11, name: 'Dr Nice' },
|
||||
{ id: 12, name: 'Narco' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' },
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { Hero } from './hero';
|
||||
|
||||
export const HEROES: Hero[] = [
|
||||
{ id: 11, name: 'Mr. Nice' },
|
||||
{ id: 11, name: 'Dr Nice' },
|
||||
{ id: 12, name: 'Narco' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' },
|
||||
|
@ -41,7 +41,6 @@
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-trailing-whitespace": true,
|
||||
"no-unused-expression": true,
|
||||
"no-use-before-declare": false,
|
||||
"no-var-keyword": true,
|
||||
"object-literal-sort-keys": false,
|
||||
"one-line": [
|
||||
|
@ -3,7 +3,7 @@ import { InMemoryDbService } from 'angular-in-memory-web-api';
|
||||
export class InMemoryDataService implements InMemoryDbService {
|
||||
createDb() {
|
||||
const heroes = [
|
||||
{ id: 11, name: 'Mr. Nice' },
|
||||
{ id: 11, name: 'Dr Nice' },
|
||||
{ id: 12, name: 'Narco' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' },
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Hero } from './hero';
|
||||
|
||||
export const HEROES: Hero[] = [
|
||||
{ id: 11, name: 'Mr. Nice' },
|
||||
{ id: 11, name: 'Dr Nice' },
|
||||
{ id: 12, name: 'Narco' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' },
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../out-tsc/app",
|
||||
"baseUrl": "./",
|
||||
@ -11,6 +11,6 @@
|
||||
"**/*.spec.ts"
|
||||
],
|
||||
"angularCompilerOptions": {
|
||||
"entryModule": "app/app.server.module#AppServerModule"
|
||||
"entryModule": "src/app/app.server.module#AppServerModule"
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
import { Component, OnInit, ElementRef } from '@angular/core';
|
||||
import { LazyLoaderService } from '../lazy-loader.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-angular-js',
|
||||
template: '<div ng-view></div>'
|
||||
})
|
||||
export class AngularJSComponent implements OnInit {
|
||||
constructor(private lazyLoader: LazyLoaderService, private elRef: ElementRef) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.lazyLoader.load(this.elRef.nativeElement);
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
import * as angular from 'angular';
|
||||
import 'angular-route';
|
||||
|
||||
const appName = 'myApp';
|
||||
|
||||
angular.module(appName, [
|
||||
'ngRoute'
|
||||
])
|
||||
.config(['$routeProvider', '$locationProvider',
|
||||
function config($routeProvider, $locationProvider) {
|
||||
$locationProvider.html5Mode(true);
|
||||
|
||||
$routeProvider.
|
||||
when('/users', {
|
||||
template: `
|
||||
<p>
|
||||
Users Page
|
||||
</p>
|
||||
`
|
||||
}).
|
||||
otherwise({
|
||||
template: ''
|
||||
});
|
||||
}]
|
||||
);
|
||||
|
||||
export function bootstrap(el: HTMLElement) {
|
||||
return angular.bootstrap(el, [appName]);
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
// #docplaster
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule, UrlSegment } from '@angular/router';
|
||||
import { AngularJSComponent } from './angular-js/angular-js.component';
|
||||
import { HomeComponent } from './home/home.component';
|
||||
import { App404Component } from './app404/app404.component';
|
||||
|
||||
// Match any URL that starts with `users`
|
||||
// #docregion matcher
|
||||
export function isAngularJSUrl(url: UrlSegment[]) {
|
||||
return url.length > 0 && url[0].path.startsWith('users') ? ({consumed: url}) : null;
|
||||
}
|
||||
// #enddocregion matcher
|
||||
|
||||
export const routes: Routes = [
|
||||
// Routes rendered by Angular
|
||||
{ path: '', component: HomeComponent },
|
||||
|
||||
// AngularJS routes
|
||||
{ matcher: isAngularJSUrl, component: AngularJSComponent },
|
||||
|
||||
// Catch-all route
|
||||
{ path: '**', component: App404Component }
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule { }
|
@ -0,0 +1,9 @@
|
||||
Lazy Loading AngularJS
|
||||
|
||||
<nav>
|
||||
<a routerLink="/">Home</a>
|
||||
<a routerLink="/users">Users</a>
|
||||
<a routerLink="/notfound">404 Page</a>
|
||||
</nav>
|
||||
|
||||
<router-outlet></router-outlet>
|
@ -0,0 +1,8 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
export class AppComponent { }
|
@ -0,0 +1,25 @@
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { AngularJSComponent } from './angular-js/angular-js.component';
|
||||
import { HomeComponent } from './home/home.component';
|
||||
import { App404Component } from './app404/app404.component';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
AngularJSComponent,
|
||||
HomeComponent,
|
||||
App404Component
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
AppRoutingModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
@ -0,0 +1,3 @@
|
||||
<p>
|
||||
Angular 404
|
||||
</p>
|
@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-app404',
|
||||
templateUrl: './app404.component.html',
|
||||
styleUrls: ['./app404.component.css']
|
||||
})
|
||||
export class App404Component implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
<p>
|
||||
Angular Home
|
||||
</p>
|
@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-home',
|
||||
templateUrl: './home.component.html',
|
||||
styleUrls: ['./home.component.css']
|
||||
})
|
||||
export class HomeComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class LazyLoaderService {
|
||||
bootstrapped = false;
|
||||
|
||||
load(el: HTMLElement): void {
|
||||
if (this.bootstrapped) {
|
||||
return;
|
||||
}
|
||||
|
||||
import('./angularjs-app').then(app => {
|
||||
try {
|
||||
app.bootstrap(el);
|
||||
this.bootstrapped = true;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>MyApp</title>
|
||||
<title>AngularJS Hybrid</title>
|
||||
<base href="/">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
@ -8,4 +8,5 @@ if (environment.production) {
|
||||
enableProdMode();
|
||||
}
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
platformBrowserDynamic().bootstrapModule(AppModule)
|
||||
.catch(err => console.error(err));
|
7
aio/content/examples/upgrade-lazy-load-ajs/zipper.json
Normal file
7
aio/content/examples/upgrade-lazy-load-ajs/zipper.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"files": [
|
||||
"!**/*.d.ts",
|
||||
"!**/*.js",
|
||||
"!**/*.[1,2].*"
|
||||
]
|
||||
}
|
@ -125,7 +125,7 @@ The third argument, `easing`, controls how the animation [accelerates and decele
|
||||
|
||||
* Run for 200ms, with no delay. Use a standard curve to start slow, accelerate in the middle, and then decelerate slowly at the end: `'0.2s ease-in-out'`
|
||||
|
||||
* Start immediately, run for 200ms. Use a acceleration curve to start slow and end at full velocity: `'0.2s ease-in'`
|
||||
* Start immediately, run for 200ms. Use an acceleration curve to start slow and end at full velocity: `'0.2s ease-in'`
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
@ -75,7 +75,7 @@ Notice how custom components like this mix seamlessly with native HTML in the sa
|
||||
|
||||
### Data binding
|
||||
|
||||
Without a framework, you would be responsible for pushing data values into the HTML controls and turning user responses into actions and value updates. Writing such push and pull logic by hand is tedious, error-prone, and a nightmare to read, as any experienced jQuery programmer can attest.
|
||||
Without a framework, you would be responsible for pushing data values into the HTML controls and turning user responses into actions and value updates. Writing such push and pull logic by hand is tedious, error-prone, and a nightmare to read, as any experienced front-end JavaScript programmer can attest.
|
||||
|
||||
Angular supports *two-way data binding*, a mechanism for coordinating the parts of a template with the parts of a component. Add binding markup to the template HTML to tell Angular how to connect both sides.
|
||||
|
||||
|
@ -15,7 +15,7 @@ There are three kinds of directives in Angular:
|
||||
1. Attribute directives—change the appearance or behavior of an element, component, or another directive.
|
||||
|
||||
*Components* are the most common of the three directives.
|
||||
You saw a component for the first time in the [Getting Started](guide/quickstart).
|
||||
You saw a component for the first time in the [Getting Started](start "Getting Started with Angular") tutorial.
|
||||
|
||||
*Structural Directives* change the structure of the view.
|
||||
Two examples are [NgFor](guide/template-syntax#ngFor) and [NgIf](guide/template-syntax#ngIf).
|
||||
|
595
aio/content/guide/cli-builder.md
Normal file
595
aio/content/guide/cli-builder.md
Normal file
@ -0,0 +1,595 @@
|
||||
# Angular CLI Builders
|
||||
|
||||
A number of Angular CLI commands run a complex process on your code, such as linting, building, or testing.
|
||||
The commands use an internal tool called Architect to run *CLI builders*, which apply another tool to accomplish the desired task.
|
||||
|
||||
With Angular version 8, the CLI Builder API is stable and available to developers who want to customize the Angular CLI by adding or modifying commands. For example, you could supply a builder to perform an entirely new task, or to change which third-party tool is used by an existing command.
|
||||
|
||||
This document explains how CLI builders integrate with the workspace configuration file, and shows how you can create your own builder.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
You can find the code from the examples used here in [this GitHub repository](https://github.com/mgechev/cli-builders-demo).
|
||||
|
||||
</div>
|
||||
|
||||
## CLI builders
|
||||
|
||||
The internal Architect tool delegates work to handler functions called [*builders*](guide/glossary#builder).
|
||||
A builder handler function receives two arguments; a set of input `options` (a JSON object), and a `context` (a `BuilderContext` object).
|
||||
|
||||
The separation of concerns here is the same as with [schematics](guide/glossary#schematic), which are used for other CLI commands that touch your code (such as `ng generate`).
|
||||
|
||||
* Options are given by the CLI user, context is provided by and provides access to the CLI Builder API, and the developer provides the behavior.
|
||||
|
||||
* The `BuilderContext` object provides access to the scheduling method, `BuilderContext.scheduleTarget()`. The scheduler executes the builder handler function with a given [target configuration](guide/glossary#target).
|
||||
|
||||
The builder handler function can be synchronous (return a value) or asynchronous (return a Promise), or it can watch and return multiple values (return an Observable).
|
||||
The return value or values must always be of type `BuilderOutput`.
|
||||
This object contains a Boolean `success` field and an optional `error` field that can contain an error message.
|
||||
|
||||
Angular provides some builders that are used by the CLI for commands such as `ng build`, `ng test`, and `ng lint`.
|
||||
Default target configurations for these and other built-in CLI builders can be found (and customized) in the "architect" section of the [workspace configuration file](guide/workspace-config), `angular.json`.
|
||||
You can also extend and customize Angular by creating your own builders, which you can run using the [`ng run` CLI command](cli/run).
|
||||
|
||||
### Builder project structure
|
||||
|
||||
A builder resides in a "project" folder that is similar in structure to an Angular workspace, with global configuration files at the top level, and more specific configuration in a source folder with the code files that define the behavior.
|
||||
For example, your `myBuilder` folder could contain the following files.
|
||||
|
||||
| FILES | PURPOSE |
|
||||
| :----------------------- | :------------------------------------------|
|
||||
| `src/my-builder.ts` | Main source file for the builder definition. |
|
||||
| `src/my-builder.spec.ts` | Source file for tests. |
|
||||
| `src/schema.json` | Definition of builder input options. |
|
||||
| `builders.json` | Testing configuration. |
|
||||
| `package.json` | Dependencies. See https://docs.npmjs.com/files/package.json. |
|
||||
| `tsconfig.json` | [TypeScript configuration](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html). |
|
||||
|
||||
You can publish the builder to `npm` (see [Publishing your Library](https://angular.io/guide/creating-libraries#publishing-your-library)). If you publish it as `@example/my-builder`, you can install it using the following command.
|
||||
|
||||
<code-example language="sh">
|
||||
|
||||
npm install @example/my-builder
|
||||
|
||||
</code-example>
|
||||
|
||||
## Creating a builder
|
||||
|
||||
As an example, let’s create a builder that executes a shell command.
|
||||
To create a builder, use the `createBuilder()` CLI Builder function, and return a `BuilderOutput` object.
|
||||
|
||||
```
|
||||
|
||||
import { BuilderOutput, createBuilder } from '@angular-devkit/architect';
|
||||
|
||||
export default createBuilder(_commandBuilder);
|
||||
|
||||
function _commandBuilder(
|
||||
options: JsonObject,
|
||||
context: BuilderContext,
|
||||
): Promise<BuilderOutput> {
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Now let’s add some logic to it.
|
||||
The following code retrieves the command and arguments from the user options, spawns the new process, and waits for the process to finish.
|
||||
If the process is successful (returns a code of 0), it resolves the return value.
|
||||
|
||||
```
|
||||
import { BuilderOutput, createBuilder } from '@angular-devkit/architect';
|
||||
import * as childProcess from 'child_process';
|
||||
|
||||
export default createBuilder(_commandBuilder);
|
||||
|
||||
function _commandBuilder(
|
||||
options: JsonObject,
|
||||
context: BuilderContext,
|
||||
): Promise<BuilderOutput> {
|
||||
const child = childProcess.spawn(options.command, options.args);
|
||||
return new Promise<BuilderOutput>(resolve => {
|
||||
child.on('close', code => {
|
||||
resolve({success: code === 0});
|
||||
});
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### Handling output
|
||||
|
||||
By default, the `spawn()` method outputs everything to the process standard output and error.
|
||||
To make it easier to test and debug, we can forward the output to the CLI Builder logger instead.
|
||||
This also allows the builder itself to be executed in a separate process, even if the standard output and error are deactivated (as in an [Electron app](https://electronjs.org/)).
|
||||
|
||||
We can retrieve a Logger instance from the context.
|
||||
|
||||
```
|
||||
import { BuilderOutput, createBuilder, BuilderContext } from '@angular-devkit/architect';
|
||||
import * as childProcess from 'child_process';
|
||||
|
||||
export default createBuilder(_commandBuilder);
|
||||
|
||||
function _commandBuilder(
|
||||
options: JsonObject,
|
||||
context: BuilderContext,
|
||||
): Promise<BuilderOutput> {
|
||||
const child = childProcess.spawn(options.command, options.args, {stdio: 'pipe'});
|
||||
child.stdout.on('data', (data) => {
|
||||
context.logger.info(data.toString());
|
||||
});
|
||||
child.stderr.on('data', (data) => {
|
||||
context.logger.error(data.toString());
|
||||
});
|
||||
|
||||
return new Promise<BuilderOutput>(resolve => {
|
||||
child.on('close', code => {
|
||||
resolve({success: code === 0});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Progress and status reporting
|
||||
|
||||
The CLI Builder API includes progress and status reporting tools, which can provide hints for certain functions and interfaces.
|
||||
|
||||
To report progress, use the `BuilderContext.reportProgress()` method, which takes a current value, (optional) total, and status string as arguments.
|
||||
The total can be any number; for example, if you know how many files you have to process, the total could be the number of files, and current should be the number processed so far.
|
||||
The status string is unmodified unless you pass in a new string value.
|
||||
|
||||
You can see an [example](https://github.com/angular/angular-cli/blob/ba21c855c0c8b778005df01d4851b5a2176edc6f/packages/angular_devkit/build_angular/src/tslint/index.ts#L107) of how the `tslint` builder reports progress.
|
||||
|
||||
In our example, the shell command either finishes or is still executing, so there’s no need for a progress report, but we can report status so that a parent builder that called our builder would know what’s going on.
|
||||
Use the `BuilderContext.reportStatus()` method to generate a status string of any length.
|
||||
(Note that there’s no guarantee that a long string will be shown entirely; it could be cut to fit the UI that displays it.)
|
||||
Pass an empty string to remove the status.
|
||||
|
||||
```
|
||||
import { BuilderOutput, createBuilder, BuilderContext } from '@angular-devkit/architect';
|
||||
import * as childProcess from 'child_process';
|
||||
|
||||
export default createBuilder(_commandBuilder);
|
||||
|
||||
function _commandBuilder(
|
||||
options: JsonObject,
|
||||
context: BuilderContext,
|
||||
): Promise<BuilderOutput> {
|
||||
context.reportStatus(`Executing "${options.command}"...`);
|
||||
const child = childProcess.spawn(options.command, options.args, {stdio: 'pipe'});
|
||||
|
||||
child.stdout.on('data', (data) => {
|
||||
context.logger.info(data.toString());
|
||||
});
|
||||
child.stderr.on('data', (data) => {
|
||||
context.logger.error(data.toString());
|
||||
});
|
||||
|
||||
return new Promise<BuilderOutput>(resolve => {
|
||||
context.reportStatus(`Done.`);
|
||||
child.on('close', code => {
|
||||
resolve({success: code === 0});
|
||||
});
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Builder input
|
||||
|
||||
You can invoke a builder indirectly through a CLI command, or directly with the Angular CLI `ng run` command.
|
||||
In either case, you must provide required inputs, but can allow other inputs to default to values that are pre-configured for a specific [*target*](guide/glossary#target), provide a pre-defined, named override configuration, and provide further override option values on the command line.
|
||||
|
||||
### Input validation
|
||||
|
||||
You define builder inputs in a JSON schema associated with that builder.
|
||||
The Architect tool collects the resolved input values into an `options` object, and validates their types against the schema before passing them to the builder function.
|
||||
(The Schematics library does the same kind of validation of user input).
|
||||
|
||||
For our example builder, we expect the `options` value to be a `JsonObject` with two keys: a `command` that is a string, and an `args` array of string values.
|
||||
|
||||
We can provide the following schema for type validation of these values.
|
||||
|
||||
<code-example format="." language="json" linenums="false">
|
||||
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"command": {
|
||||
"type": "string"
|
||||
},
|
||||
"args": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
This is a very simple example, but the use of a schema for validation can be very powerful.
|
||||
For more information, see the [JSON schemas website](http://json-schema.org/).
|
||||
|
||||
</div>
|
||||
|
||||
To link our builder implementation with its schema and name, we need to create a *builder definition* file, which we can point to in `package.json`.
|
||||
|
||||
Create a file named `builders.json` file that looks like this.
|
||||
|
||||
<code-example format="." language="json" linenums="false">
|
||||
|
||||
{
|
||||
"builders": {
|
||||
"command": {
|
||||
"implementation": "./command",
|
||||
"schema": "./command/schema.json",
|
||||
"description": "Runs any command line in the operating system."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code-example>
|
||||
|
||||
In the `package.json` file, add a `builders` key that tells the Architect tool where to find our builder definition file.
|
||||
|
||||
<code-example format="." language="json" linenums="false">
|
||||
|
||||
{
|
||||
"name": "@example/command-runner",
|
||||
"version": "1.0.0",
|
||||
"description": "Builder for Command Runner",
|
||||
"builders": "builders.json",
|
||||
"devDependencies": {
|
||||
"@angular-devkit/architect": "^1.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
</code-example>
|
||||
|
||||
The official name of our builder is now ` @example/command-runner:command`.
|
||||
The first part of this is the package name (resolved using node resolution), and the second part is the builder name (resolved using the `builder.json` file).
|
||||
|
||||
Using one of our `options` is very straightforward, we did this in the previous section when we accessed `options.command`.
|
||||
|
||||
<code-example format="." language="typescript" linenums="false">
|
||||
context.reportStatus(`Executing "${options.command}"...`);
|
||||
const child = childProcess.spawn(options.command, options.args, { stdio: 'pipe' });
|
||||
|
||||
</code-example>
|
||||
|
||||
### Target configuration
|
||||
|
||||
A builder must have a defined target that associates it with a specific input configuration and [project](guide/glossary#project).
|
||||
|
||||
Targets are defined in the `angular.json` [workspace configuration file](guide/workspace-config).
|
||||
A target specifies the builder to use, its default options configuration, and named alternative configurations.
|
||||
The Architect tool uses the target definition to resolve input options for a given run.
|
||||
|
||||
The `angular.json` file has a section for each project, and the "architect" section of each project configures targets for builders used by CLI commands such as 'build', 'test', and 'lint'.
|
||||
By default, for example, the `build` command runs the builder `@angular-devkit/build-angular:browser` to perform the build task, and passes in default option values as specified for the `build` target in `angular.json`.
|
||||
|
||||
<code-example format="." language="json" linenums="false">
|
||||
{
|
||||
"myApp": {
|
||||
...
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist/myApp",
|
||||
"index": "src/index.html",
|
||||
...
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
...
|
||||
}
|
||||
}
|
||||
},
|
||||
...
|
||||
|
||||
</code-example>
|
||||
|
||||
The command passes the builder the set of default options specified in the "options" section.
|
||||
If you pass the `--configuration=production` flag, it uses the override values specified in the `production` alternative configuration.
|
||||
You can specify further option overrides individually on the command line.
|
||||
You might also add more alternative configurations to the `build` target, to define other environments such as `stage` or `qa`.
|
||||
|
||||
#### Target strings
|
||||
|
||||
The generic `ng run` CLI command takes as its first argument a target string of the form *project:target[:configuration]*.
|
||||
|
||||
* *project*: The name of the Angular CLI project that the target is associated with.
|
||||
|
||||
* *target*: A named builder configuration from the `architect` section of the `angular.json` file.
|
||||
|
||||
* *configuration*: (optional) The name of a specific configuration override for the given target, as defined in the `angular.json` file.
|
||||
|
||||
If your builder calls another builder, it may need to read a passed target string.
|
||||
You can parse this string into an object by using the `targetFromTargetString()` utility function from `@angular-devkit/architect`.
|
||||
|
||||
## Schedule and run
|
||||
|
||||
Architect runs builders asynchronously.
|
||||
To invoke a builder, you schedule a task to be run when all configuration resolution is complete.
|
||||
|
||||
The builder function is not executed until the scheduler returns a `BuilderRun` control object.
|
||||
The CLI typically schedules tasks by calling the `BuilderContext.scheduleTarget()` function, and then resolves input options using the target definition in the `angular.json` file.
|
||||
|
||||
Architect resolves input options for a given target by taking the default options object, then overwriting values from the configuration used (if any), then further overwriting values from the overrides object passed to `BuilderContext.scheduleTarget()`.
|
||||
For the Angular CLI, the overrides object is built from command line arguments.
|
||||
|
||||
Architect validates the resulting options values against the schema of the builder.
|
||||
If inputs are valid, Architect creates the context and executes the builder.
|
||||
|
||||
For more information see [Workspace Configuration](guide/workspace-config).
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
You can also invoke a builder directly from another builder or test by calling `BuilderContext.scheduleBuilder()`.
|
||||
You pass an `options` object directly to the method, and those option values are validated against the schema of the builder without further adjustment.
|
||||
|
||||
Only the `BuilderContext.scheduleTarget()` method resolves the configuration and overrides through the `angular.json` file.
|
||||
|
||||
</div>
|
||||
|
||||
### Default architect configuration
|
||||
|
||||
Let’s create a simple `angular.json` file that puts target configurations into context.
|
||||
|
||||
We can publish the builder to npm (see [Publishing your Library](https://angular.io/guide/creating-libraries#publishing-your-library)), and install it using the following command:
|
||||
|
||||
<code-example language="sh">
|
||||
|
||||
npm install @example/command-runner
|
||||
|
||||
</code-example>
|
||||
|
||||
If we create a new project with `ng new builder-test`, the generated `angular.json` file looks something like this, with only default builder configurations.
|
||||
|
||||
<code-example format="." language="json" linenums="false">
|
||||
|
||||
{
|
||||
// ...
|
||||
"projects": {
|
||||
// ...
|
||||
"builder-test": {
|
||||
// ...
|
||||
"architect": {
|
||||
// ...
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
// ... more options...
|
||||
"outputPath": "dist/builder-test",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "src/tsconfig.app.json"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
// ... more options...
|
||||
"optimization": true,
|
||||
"aot": true,
|
||||
"buildOptimizer": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ...
|
||||
}
|
||||
|
||||
</code-example>
|
||||
|
||||
### Adding a target
|
||||
|
||||
Let's add a new target that will run our builder to execute a particular command.
|
||||
This target will tell the builder to run `touch` on a file, in order to update its modified date.
|
||||
|
||||
We need to update the `angular.json` file to add a target for this builder to the "architect" section of our new project.
|
||||
|
||||
* We'll add a new target section to the "architect" object for our project.
|
||||
|
||||
* The target named "touch" uses our builder, which we published to `@example/command-runner`. (See [Publishing your Library](https://angular.io/guide/creating-libraries#publishing-your-library))
|
||||
|
||||
* The options object provides default values for the two inputs that we defined; `command`, which is the Unix command to execute, and `args`, an array that contains the file to operate on.
|
||||
|
||||
* The configurations key is optional, we'll leave it out for now.
|
||||
|
||||
<code-example format="." language="json" linenums="false">
|
||||
|
||||
{
|
||||
"projects": {
|
||||
"builder-test": {
|
||||
"architect": {
|
||||
"builder-test": {
|
||||
"touch": {
|
||||
"builder": "@example/command-runner:command",
|
||||
"options": {
|
||||
"command": "touch",
|
||||
"args": [
|
||||
"src/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist/builder-test",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "src/tsconfig.app.json"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"optimization": true,
|
||||
"aot": true,
|
||||
"buildOptimizer": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code-example>
|
||||
|
||||
### Running the builder
|
||||
|
||||
To run our builder with the new target's default configuration, use the following CLI command in a Linux shell.
|
||||
|
||||
<code-example language="sh">
|
||||
|
||||
ng run builder-test:touch
|
||||
|
||||
</code-example>
|
||||
|
||||
This will run the `touch` command on the `src/main.ts` file.
|
||||
|
||||
You can use command-line arguments to override the configured defaults.
|
||||
For example, to run with a different `command` value, use the following CLI command.
|
||||
|
||||
<code-example language="sh">
|
||||
|
||||
ng run builder-test:touch --command=ls
|
||||
|
||||
</code-example>
|
||||
|
||||
This will call the `ls` command instead of the `touch` command.
|
||||
Because we did not override the *args* option, it will list information about the `src/main.ts` file (the default value provided for the target).
|
||||
|
||||
## Testing a builder
|
||||
|
||||
Use integration testing for your builder, so that you can use the Architect scheduler to create a context, as in this [example](https://github.com/mgechev/cli-builders-demo).
|
||||
|
||||
* In the builder source directory, we have created a new test file `index.spec.ts`. The code creates new instances of `JsonSchemaRegistry` (for schema validation), `TestingArchitectHost` (an in-memory implementation of `ArchitectHost`), and `Architect`.
|
||||
|
||||
* We've added a `builders.json` file next to the builder's [`package.json` file](https://github.com/mgechev/cli-builders-demo/blob/master/command-builder/builders.json), and modified the package file to point to it.
|
||||
|
||||
Here’s an example of a test that runs the command builder.
|
||||
The test uses the builder to run the `ls` command, then validates that it ran successfully and listed the proper files.
|
||||
|
||||
<code-example format="." language="typescript" linenums="false">
|
||||
|
||||
import { Architect, ArchitectHost } from '@angular-devkit/architect';
|
||||
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
|
||||
// Our builder forwards the STDOUT of the command to the logger.
|
||||
import { logging, schema } from '@angular-devkit/core';
|
||||
|
||||
describe('Command Runner Builder', () => {
|
||||
let architect: Architect;
|
||||
let architectHost: ArchitectHost;
|
||||
|
||||
beforeEach(async () => {
|
||||
const registry = new schema.CoreSchemaRegistry();
|
||||
registry.addPostTransform(schema.transforms.addUndefinedDefaults);
|
||||
|
||||
// TestingArchitectHost() takes workspace and current directories.
|
||||
// Since we don't use those, both are the same in this case.
|
||||
architectHost = new TestingArchitectHost(__dirname, __dirname);
|
||||
architect = new Architect(architectHost, registry);
|
||||
|
||||
// This will either take a Node package name, or a path to the directory
|
||||
// for the package.json file.
|
||||
await architectHost.addBuilderFromPackage('..');
|
||||
});
|
||||
|
||||
// This might not work in Windows.
|
||||
it('can run ls', async () => {
|
||||
// Create a logger that keeps an array of all messages that were logged.
|
||||
const logger = new logging.Logger('');
|
||||
const logs = [];
|
||||
logger.subscribe(ev => logs.push(ev.message));
|
||||
|
||||
// A "run" can have multiple outputs, and contains progress information.
|
||||
const run = await architect.scheduleBuilder('@example/command-runner:command', {
|
||||
command: 'ls',
|
||||
args: [__dirname],
|
||||
}, { logger }); // We pass the logger for checking later.
|
||||
|
||||
// The "result" member (of type BuilderOutput) is the next output.
|
||||
const output = await run.result;
|
||||
|
||||
// Stop the builder from running. This stops Architect from keeping
|
||||
// the builder-associated states in memory, since builders keep waiting
|
||||
// to be scheduled.
|
||||
await run.stop();
|
||||
|
||||
// Expect that it succeeded.
|
||||
expect(output.success).toBe(true);
|
||||
|
||||
// Expect that this file was listed. It should be since we're running
|
||||
// `ls $__dirname`.
|
||||
expect(logs).toContain('index.spec.ts');
|
||||
});
|
||||
});
|
||||
|
||||
</code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
When running this test in your repo, you need the [`ts-node`](https://github.com/TypeStrong/ts-node) package. You can avoid this by renaming `index.spec.ts` to `index.spec.js`.
|
||||
|
||||
</div>
|
||||
|
||||
### Watch mode
|
||||
|
||||
Architect expects builders to run once (by default) and return.
|
||||
This behavior is not entirely compatible with a builder that watches for changes (like Webpack, for example).
|
||||
Architect can support watch mode, but there are some things to look out for.
|
||||
|
||||
* To be used with watch mode, a builder handler function should return an Observable. Architect subscribes to the Observable until it completes and might reuse it if the builder is scheduled again with the same arguments.
|
||||
|
||||
* The builder should always emit a `BuilderOutput` object after each execution. Once it’s been executed, it can enter a watch mode, to be triggered by an external event. If an event triggers it to restart, the builder should execute the `BuilderContext.reportRunning()` function to tell Architect that it is running again. This prevents Architect from stopping the builder if another run is scheduled.
|
||||
|
||||
When your builder calls `BuilderRun.stop()` to exit watch mode, Architect unsubscribes from the builder’s Observable and calls the builder’s teardown logic to clean up.
|
||||
(This behavior also allows for long running builds to be stopped and cleaned up.)
|
||||
|
||||
In general, if your builder is watching an external event, you should separate your run into three phases.
|
||||
|
||||
1. **Running**
|
||||
For example, webpack compiles. This ends when webpack finishes and your builder emits a `BuilderOutput` object.
|
||||
|
||||
1. **Watching**
|
||||
Between two runs, watch an external event stream. For example, webpack watches the file system for any changes. This ends when webpack restarts building, and `BuilderContext.reportRunning()` is called. This goes back to step 1.
|
||||
|
||||
1. **Completion**
|
||||
Either the task is fully completed (for example, webpack was supposed to run a number of times), or the builder run was stopped (using `BuilderRun.stop()`). Your teardown logic is executed, and Architect unsubscribes from your builder’s Observable.
|
||||
|
||||
## Summary
|
||||
|
||||
The CLI Builder API provides a new way of changing the behavior of the Angular CLI by using builders to execute custom logic.
|
||||
|
||||
* Builders can be synchronous or asynchronous, execute once or watch for external events, and can schedule other builders or targets.
|
||||
|
||||
* Builders have option defaults specified in the `angular.json` configuration file, which can be overwritten by an alternate configuration for the target, and further overwritten by command line flags.
|
||||
|
||||
* We recommend that you use integration tests to test Architect builders. You can use unit tests to validate the logic that the builder executes.
|
||||
|
||||
* If your builder returns an Observable, it should clean up in the teardown logic of that Observable.
|
@ -87,6 +87,8 @@ If that form will need additional customization by the user, it might work best
|
||||
However, if the forms will always be the same and not need much customization by developers, then you could create a dynamic component that takes the configuration and generates the form.
|
||||
In general, the more complex the customization, the more useful the schematic approach.
|
||||
|
||||
{@a integrating-with-the-cli}
|
||||
|
||||
## Integrating with the CLI
|
||||
|
||||
A library can include [schematics](guide/glossary#schematic) that allow it to integrate with the Angular CLI.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user