mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
Compare commits
253 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 33639db911 | |||
| 2fe2104738 | |||
| 02378451a2 | |||
| 04e469ee16 | |||
| 8ab332b00b | |||
| 68be6f9896 | |||
| c39ed99bcc | |||
| ee14e43d26 | |||
| 9f2ed3096a | |||
| 0a43d090c6 | |||
| 1523ea59bd | |||
| a645573f97 | |||
| 2287cd6b1f | |||
| 3ea3128ac6 | |||
| ab45d5890a | |||
| 26533a0954 | |||
| 84377531cb | |||
| 91faaaccb7 | |||
| 153b42b01e | |||
| 163fdc35f6 | |||
| 9b867b39d6 | |||
| a76706d375 | |||
| fd0cb532dc | |||
| 413c238a05 | |||
| 9f987b635e | |||
| 158581b366 | |||
| 5d8b5eb97b | |||
| db29176075 | |||
| 403d889edf | |||
| 46edc48056 | |||
| 724dc93080 | |||
| 3fcfc5fcd1 | |||
| 10e4ac05b4 | |||
| a88bc643fc | |||
| 752af2ea48 | |||
| 882ff8fc37 | |||
| 1891455784 | |||
| 9e87fc88ff | |||
| 19b77b8a3b | |||
| db62b5f979 | |||
| 05b22a956e | |||
| 53ea4bbc93 | |||
| 271be8aaec | |||
| 9ab3fe732b | |||
| 8a425cc29a | |||
| 9d1131c58c | |||
| 1c3226d45d | |||
| 5080a16933 | |||
| e05cfdd367 | |||
| b363d96724 | |||
| b8f9aa3b5b | |||
| f2d88955bd | |||
| 7f3314a1e8 | |||
| 83a6ab1edc | |||
| 8d317dfa50 | |||
| f1d8717a88 | |||
| 323609d9a7 | |||
| 47a1af6ce3 | |||
| 06de803963 | |||
| a7adcbda54 | |||
| 7ab31c9929 | |||
| e02bea8e53 | |||
| 5fae8b3aa9 | |||
| 005e3c6458 | |||
| 651ba4e331 | |||
| 20db90a41d | |||
| 050cea9252 | |||
| 978f0810d9 | |||
| 888f0e4913 | |||
| 7ddda8a5b0 | |||
| 4dc861fa5a | |||
| 92900d561d | |||
| faf5205a66 | |||
| 6e45f2bee9 | |||
| 28112ca55c | |||
| a17ae55445 | |||
| 3cc9bee1f7 | |||
| 4552b4b554 | |||
| c68ca49d0b | |||
| dd28855455 | |||
| ff925af908 | |||
| ce7d5c4829 | |||
| 62457ca88b | |||
| 0319fc7656 | |||
| 7cb9e19297 | |||
| f51cf295b7 | |||
| bd5c7dd2df | |||
| 2da9a46e70 | |||
| b8e9b3d601 | |||
| 94d001396a | |||
| 92f833bde9 | |||
| 63f9e16309 | |||
| d34e36cc95 | |||
| de4f913662 | |||
| 96ad439d48 | |||
| 6959620002 | |||
| 43b4940c9d | |||
| e9889da457 | |||
| 450830cf1a | |||
| 7ef72d192b | |||
| 6817377590 | |||
| e8654f943c | |||
| b0bbc1f232 | |||
| b6064c2782 | |||
| e34c87e114 | |||
| a0b6548a94 | |||
| 40f38ce7df | |||
| d386fb3e86 | |||
| f868dcb9e8 | |||
| ad4f0fd85c | |||
| 8d0c1bdabf | |||
| 47244dbd00 | |||
| e5caf1189a | |||
| 37128ca1f7 | |||
| ce14f37a58 | |||
| 5c13c67d66 | |||
| 83565229fa | |||
| 1ac05001a1 | |||
| 67ea7b6098 | |||
| b2f3952946 | |||
| 3abf95dca9 | |||
| eb625b993e | |||
| a8e0db73ba | |||
| feda78e1c8 | |||
| 3091534af2 | |||
| 669c4f7ced | |||
| 3b6497b981 | |||
| 0e60dc5597 | |||
| e45da28ed5 | |||
| 5bb5069836 | |||
| ec416d0210 | |||
| e7f262d691 | |||
| 8ea0ee918d | |||
| 6f2b69d94e | |||
| 89835fe8fa | |||
| b0e114e51d | |||
| eccf9d68b8 | |||
| b8c71c45de | |||
| daab797f7d | |||
| 7c52fc690d | |||
| bf05c979a7 | |||
| ddc070e778 | |||
| d746804985 | |||
| 17fe000879 | |||
| 3870d5e629 | |||
| 112f7e9b58 | |||
| 2bc8b807c4 | |||
| 65d1ed38e0 | |||
| 75110f7487 | |||
| 2632510f87 | |||
| f61ac8a60e | |||
| 366be11150 | |||
| 899218de1f | |||
| 399f491894 | |||
| 910fa51e76 | |||
| f184578e2e | |||
| d76beda439 | |||
| 72e0c6b8be | |||
| bf1caa7ad1 | |||
| 4b26a05dbc | |||
| 70daf10b86 | |||
| 1bfc44d48a | |||
| 2a0a287121 | |||
| 523a451a68 | |||
| 13063c45d5 | |||
| 89c6d109e1 | |||
| 6c79598eb6 | |||
| 65abf7effa | |||
| d1840eed36 | |||
| cc329325ac | |||
| 32163ef355 | |||
| 97b4653cab | |||
| 291322fd53 | |||
| a94852c97d | |||
| 758c52b3bf | |||
| a4ea0bbe67 | |||
| 3fbf32534c | |||
| f5710c6902 | |||
| e8e3771002 | |||
| 8bc295ffc3 | |||
| f1a1a205d6 | |||
| b73d59e241 | |||
| 6669571884 | |||
| 84e09a06e3 | |||
| ef28295bf7 | |||
| fc2e3cc84d | |||
| 084b082f5c | |||
| dbc9547643 | |||
| 8144ea5cc9 | |||
| 91e2851f5d | |||
| 6c7e16ab08 | |||
| 54366c3590 | |||
| 252ef62e41 | |||
| 6b7ca5956a | |||
| 1e91958b69 | |||
| 9309a51368 | |||
| 44f245a0c3 | |||
| 298c9822f0 | |||
| 13f9120b92 | |||
| a92b5317bf | |||
| 61e98f8352 | |||
| f2fea8c94f | |||
| 3fcbdc5c25 | |||
| cd2bf969f4 | |||
| 279de9f0ff | |||
| 7d43ca9dfe | |||
| 4e29200dfc | |||
| 0992b678f0 | |||
| c83a389aea | |||
| f875b0d9b6 | |||
| 7f79e77c66 | |||
| 08a4c5b5df | |||
| b4e8399144 | |||
| d8c9f42689 | |||
| 8b36487cbc | |||
| 63b8c04372 | |||
| e30c6519d3 | |||
| ac53101fc6 | |||
| 161b278b6f | |||
| 3738233f16 | |||
| 38a3c31ada | |||
| 595062e415 | |||
| f341da8a43 | |||
| 44913944a9 | |||
| 5167eead45 | |||
| 736e0644b0 | |||
| e0322282e6 | |||
| 51301b9f4b | |||
| d3087be237 | |||
| aba1cb4672 | |||
| 726c5ef679 | |||
| d30911c4eb | |||
| e7f9e6fdac | |||
| 8a744d5246 | |||
| 6c9c70a0e4 | |||
| d2ea9b05d8 | |||
| 60b4135795 | |||
| a0fde29f80 | |||
| 09de939694 | |||
| 13847816d3 | |||
| 63a915b023 | |||
| fdbc61111d | |||
| f541e5f39d | |||
| 20b801e707 | |||
| bed8c1c814 | |||
| 6acddb9518 | |||
| 5e1c7e69e6 | |||
| 61cd1b685a | |||
| b05af6dd53 | |||
| cd4388e523 | |||
| 9269ad9626 | |||
| c1e0776d39 | |||
| 14f15ecd38 |
+1
-1
@@ -1,3 +1,3 @@
|
||||
3.5.1
|
||||
3.6.0
|
||||
# [NB: this comment has to be after the first line, see https://github.com/bazelbuild/bazelisk/issues/117]
|
||||
# When updating the Bazel version you also need to update the RBE toolchains version in package.bzl
|
||||
|
||||
@@ -6,10 +6,6 @@
|
||||
# https://docs.bazel.build/versions/master/guide.html#bazelrc-syntax-and-semantics
|
||||
try-import %workspace%/.circleci/bazel.common.rc
|
||||
|
||||
# Save downloaded repositories in a location that can be cached by CircleCI. This helps us
|
||||
# speeding up the analysis time significantly with Bazel managed node dependencies on the CI.
|
||||
build --repository_cache=C:/Users/circleci/bazel_repository_cache
|
||||
|
||||
# Manually set the local resources used in windows CI runs
|
||||
build --local_ram_resources=120000
|
||||
build --local_cpu_resources=32
|
||||
|
||||
+18
-11
@@ -22,16 +22,16 @@ version: 2.1
|
||||
# **NOTE 1 **: If you change the cache key prefix, also sync the cache_key_fallback to match.
|
||||
# **NOTE 2 **: Keep the static part of the cache key as prefix to enable correct fallbacks.
|
||||
# See https://circleci.com/docs/2.0/caching/#restoring-cache for how prefixes work in CircleCI.
|
||||
var_3: &cache_key v7-angular-node-12-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
||||
var_3: &cache_key v1-angular-node-12-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
||||
# We invalidate the cache if the Bazel version changes because otherwise the `bazelisk` cache
|
||||
# folder will contain all previously used versions and ultimately cause the cache restoring to
|
||||
# be slower due to its growing size.
|
||||
var_4: &cache_key_fallback v7-angular-node-12-{{ checksum ".bazelversion" }}
|
||||
var_4: &cache_key_fallback v1-angular-node-12-{{ checksum ".bazelversion" }}
|
||||
|
||||
# Cache key for the `components-repo-unit-tests` job. **Note** when updating the SHA in the
|
||||
# cache keys also update the SHA for the "COMPONENTS_REPO_COMMIT" environment variable.
|
||||
var_5: &components_repo_unit_tests_cache_key v9-angular-components-09e68db8ed5b1253f2fe38ff954ef0df019fc25a
|
||||
var_6: &components_repo_unit_tests_cache_key_fallback v9-angular-components-
|
||||
var_5: &components_repo_unit_tests_cache_key v1-angular-components-09e68db8ed5b1253f2fe38ff954ef0df019fc25a
|
||||
var_6: &components_repo_unit_tests_cache_key_fallback v1-angular-components-
|
||||
|
||||
# Workspace initially persisted by the `setup` job, and then enhanced by `build-npm-packages` and
|
||||
# `build-ivy-npm-packages`.
|
||||
@@ -748,19 +748,26 @@ jobs:
|
||||
steps:
|
||||
- setup_win
|
||||
- run:
|
||||
# Ran into a command parsing problem where `-browser:chromium-local` was converted to
|
||||
# `-browser: chromium-local` (a space was added) in https://circleci.com/gh/angular/angular/357511.
|
||||
# Probably a powershell command parsing thing. There's no problem using a yarn script though.
|
||||
command: yarn circleci-win-ve
|
||||
no_output_timeout: 45m
|
||||
name: Build all windows CI targets
|
||||
command: yarn bazel build --build_tag_filters=-ivy-only //packages/compiler-cli/... //tools/ts-api-guardian/...
|
||||
no_output_timeout: 15m
|
||||
- run:
|
||||
name: Test all windows CI targets
|
||||
command: yarn bazel test --test_tag_filters="-ivy-only,-browser:chromium-local" //packages/compiler-cli/... //tools/ts-api-guardian/...
|
||||
no_output_timeout: 15m
|
||||
|
||||
test_ivy_aot_win:
|
||||
executor: windows-executor
|
||||
steps:
|
||||
- setup_win
|
||||
- run:
|
||||
command: yarn circleci-win-ivy
|
||||
no_output_timeout: 45m
|
||||
name: Build all windows CI targets
|
||||
command: yarn bazel build --config=ivy --build_tag_filters=-no-ivy-aot,-fixme-ivy-aot //packages/compiler-cli/... //tools/ts-api-guardian/...
|
||||
no_output_timeout: 15m
|
||||
- run:
|
||||
name: Test all windows CI targets
|
||||
command: yarn bazel test --config=ivy --test_tag_filters="-no-ivy-aot,-fixme-ivy-aot,-browser:chromium-local" //packages/compiler-cli/... //tools/ts-api-guardian/...
|
||||
no_output_timeout: 15m
|
||||
|
||||
|
||||
workflows:
|
||||
|
||||
@@ -165,6 +165,12 @@ triage:
|
||||
-
|
||||
- "discussion"
|
||||
- "comp: *"
|
||||
-
|
||||
- "needs clarification"
|
||||
- "comp: *"
|
||||
-
|
||||
- "needs reproduction"
|
||||
- "comp: *"
|
||||
|
||||
# options for the triage PR plugin
|
||||
triagePR:
|
||||
@@ -181,7 +187,6 @@ triagePR:
|
||||
# arrays of labels that determine if a PR has been fully triaged
|
||||
l2TriageLabels:
|
||||
-
|
||||
- "type: *"
|
||||
- "effort*"
|
||||
- "risk*"
|
||||
- "comp: *"
|
||||
|
||||
@@ -10,6 +10,6 @@ jobs:
|
||||
if: github.repository == 'angular/angular'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: angular/dev-infra/github-actions/lock-closed@414834b2b24dd2df37c6ed00808387ee6fd91b66
|
||||
- uses: angular/dev-infra/github-actions/lock-closed@0fc6f4d839e93312ed0dd9a2be88d4c11e947a0b
|
||||
with:
|
||||
lock-bot-key: ${{ secrets.LOCK_BOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -48,3 +48,9 @@ baseline.json
|
||||
|
||||
# Ignore .history for the xyz.local-history VSCode extension
|
||||
.history
|
||||
|
||||
# CLDR data
|
||||
tools/gulp-tasks/cldr/cldr-data/
|
||||
|
||||
# Husky
|
||||
.husky/_
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
_
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname $0)/_/husky.sh"
|
||||
|
||||
yarn -s ng-dev commit-message pre-commit-validate --file $1;
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname $0)/_/husky.sh"
|
||||
|
||||
yarn -s ng-dev format staged;
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname $0)/_/husky.sh"
|
||||
|
||||
yarn -s ng-dev commit-message restore-commit-message-draft $1 $2;
|
||||
@@ -16,6 +16,8 @@ export const format: FormatConfig = {
|
||||
'!.yarn/**',
|
||||
// Do not format d.ts files as they are generated
|
||||
'!**/*.d.ts',
|
||||
// Do not format generated ng-dev script
|
||||
'!dev-infra/ng-dev.js',
|
||||
]
|
||||
},
|
||||
'buildifier': true
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ export const merge: DevInfraMergeConfig['merge'] = async api => {
|
||||
githubApiMerge: false,
|
||||
claSignedLabel: 'cla: yes',
|
||||
mergeReadyLabel: /^action: merge(-assistance)?/,
|
||||
caretakerNoteLabel: 'action: merge-assistance',
|
||||
caretakerNoteLabel: /^(action: merge-assistance)|(PullApprove: disable)/,
|
||||
commitMessageFixupLabel: 'commit message fixup',
|
||||
// We can pick any of the NPM packages as we are in a monorepo where all packages are
|
||||
// published together with the same version and branching.
|
||||
|
||||
+19
-2
@@ -103,6 +103,8 @@ meta:
|
||||
github_api_version: "shadow-cat-preview"
|
||||
|
||||
pullapprove_conditions:
|
||||
# For PRs which are still being worked on, either still in draft mode or indicated through WIP in
|
||||
# title or label, PullApprove stays in a pending state until its ready for review.
|
||||
- condition: "'WIP' not in title"
|
||||
unmet_status: pending
|
||||
explanation: "Waiting to send reviews as PR is WIP"
|
||||
@@ -112,6 +114,10 @@ pullapprove_conditions:
|
||||
- condition: "not draft"
|
||||
unmet_status: pending
|
||||
explanation: "Waiting to send reviews as PR is in draft"
|
||||
# Disable PullApprove on specific PRs by adding the `PullApprove: disable` label
|
||||
- condition: "'PullApprove: disable' not in labels"
|
||||
unmet_status: success
|
||||
explanation: "PullApprove skipped because of 'PullApprove: disable' label"
|
||||
|
||||
|
||||
groups:
|
||||
@@ -186,6 +192,7 @@ groups:
|
||||
- IgorMinar # Igor Minar
|
||||
- jbogarthyde # Judy Bogart
|
||||
- jelbourn # Jeremy Elbourn
|
||||
- jessicajaniuk # Jessica Janiuk
|
||||
- JiaLiPassion # Jia Li
|
||||
- JoostK # Joost Koehoorn
|
||||
- josephperrott # Joey Perrott
|
||||
@@ -323,6 +330,8 @@ groups:
|
||||
'aio/content/guide/component-interaction.md',
|
||||
'aio/content/examples/component-interaction/**',
|
||||
'aio/content/images/guide/component-interaction/**',
|
||||
'aio/content/guide/component-overview.md',
|
||||
'aio/content/examples/component-overview/**',
|
||||
'aio/content/guide/component-styles.md',
|
||||
'aio/content/guide/view-encapsulation.md',
|
||||
'aio/content/examples/component-styles/**',
|
||||
@@ -341,6 +350,7 @@ groups:
|
||||
'aio/content/guide/dynamic-component-loader.md',
|
||||
'aio/content/examples/dynamic-component-loader/**',
|
||||
'aio/content/images/guide/dynamic-component-loader/**',
|
||||
'aio/content/guide/example-apps-list.md',
|
||||
'aio/content/guide/entry-components.md',
|
||||
'aio/content/guide/feature-modules.md',
|
||||
'aio/content/examples/feature-modules/**',
|
||||
@@ -368,6 +378,7 @@ groups:
|
||||
'aio/content/guide/built-in-template-functions.md',
|
||||
'aio/content/examples/built-in-template-functions/**',
|
||||
'aio/content/guide/event-binding.md',
|
||||
'aio/content/guide/event-binding-concepts.md',
|
||||
'aio/content/examples/event-binding/**',
|
||||
'aio/content/guide/interpolation.md',
|
||||
'aio/content/examples/interpolation/**',
|
||||
@@ -377,6 +388,7 @@ groups:
|
||||
'aio/content/examples/binding-syntax/**',
|
||||
'aio/content/guide/property-binding.md',
|
||||
'aio/content/examples/property-binding/**',
|
||||
'aio/content/guide/property-binding-best-practices.md',
|
||||
'aio/content/guide/attribute-binding.md',
|
||||
'aio/content/examples/attribute-binding/**',
|
||||
'aio/content/guide/two-way-binding.md',
|
||||
@@ -405,6 +417,7 @@ groups:
|
||||
'aio/content/guide/structural-directives.md',
|
||||
'aio/content/examples/structural-directives/**',
|
||||
'aio/content/guide/svg-in-templates.md',
|
||||
'aio/content/guide/style-precedence.md',
|
||||
'aio/content/images/guide/structural-directives/**',
|
||||
'aio/content/guide/template-statements.md',
|
||||
'aio/content/guide/user-input.md',
|
||||
@@ -418,6 +431,7 @@ groups:
|
||||
- atscott
|
||||
- ~kara # do not request reviews from Kara, but allow her to approve PRs
|
||||
- mhevery
|
||||
- jessicajaniuk
|
||||
# OOO as of 2020-09-28 - pkozlowski-opensource
|
||||
|
||||
|
||||
@@ -644,7 +658,7 @@ groups:
|
||||
- *can-be-global-docs-approved
|
||||
- >
|
||||
contains_any_globs(files.exclude('packages/compiler-cli/**'), [
|
||||
'**/testing/**',
|
||||
'packages/**/testing/**',
|
||||
'aio/content/guide/testing.md',
|
||||
'aio/content/guide/test-debugging.md',
|
||||
'aio/content/guide/testing-attribute-directives.md',
|
||||
@@ -945,7 +959,7 @@ groups:
|
||||
'aio/content/guide/migration-localize.md',
|
||||
'aio/content/guide/migration-module-with-providers.md',
|
||||
'aio/content/guide/static-query-migration.md',
|
||||
'aio/content/guide/updating-to-version-10.md',
|
||||
'aio/content/guide/updating-to-version-11.md',
|
||||
'aio/content/guide/ivy-compatibility.md',
|
||||
'aio/content/guide/ivy-compatibility-examples.md'
|
||||
])
|
||||
@@ -1011,6 +1025,7 @@ groups:
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
- alan-agius4
|
||||
- clydin
|
||||
- IgorMinar
|
||||
- mgechev
|
||||
@@ -1103,6 +1118,7 @@ groups:
|
||||
'.circleci/**',
|
||||
'.devcontainer/**',
|
||||
'.github/**',
|
||||
'.husky/**',
|
||||
'.ng-dev/**',
|
||||
'.vscode/**',
|
||||
'.yarn/**',
|
||||
@@ -1120,6 +1136,7 @@ groups:
|
||||
'docs/SAVED_REPLIES.md',
|
||||
'docs/TOOLS.md',
|
||||
'docs/TRIAGE_AND_LABELS.md',
|
||||
'docs/images/**',
|
||||
'goldens/*',
|
||||
'modules/*',
|
||||
'packages/*',
|
||||
|
||||
+236
-283
@@ -1,53 +1,255 @@
|
||||
<a name="11.0.0-next.6"></a>
|
||||
# 11.0.0-next.6 (2020-10-14)
|
||||
<a name="11.0.2"></a>
|
||||
## 11.0.2 (2020-11-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **router:** migration incorrectly replacing deprecated key ([#39763](https://github.com/angular/angular/issues/39763)) ([0237845](https://github.com/angular/angular/commit/0237845)), closes [#38762](https://github.com/angular/angular/issues/38762) [#39755](https://github.com/angular/angular/issues/39755)
|
||||
|
||||
|
||||
|
||||
<a name="11.0.1"></a>
|
||||
## 11.0.1 (2020-11-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler-cli:** incorrectly type checking calls to implicit template variables ([#39686](https://github.com/angular/angular/issues/39686)) ([e05cfdd](https://github.com/angular/angular/commit/e05cfdd)), closes [#39634](https://github.com/angular/angular/issues/39634)
|
||||
* **compiler-cli:** setComponentScope should only list used components/pipes ([#39662](https://github.com/angular/angular/issues/39662)) ([8d317df](https://github.com/angular/angular/commit/8d317df))
|
||||
* **core:** handle !important in style property value ([#39603](https://github.com/angular/angular/issues/39603)) ([978f081](https://github.com/angular/angular/commit/978f081)), closes [#35323](https://github.com/angular/angular/issues/35323)
|
||||
* **core:** not inserting ViewContainerRef nodes when inside root of a component ([#39599](https://github.com/angular/angular/issues/39599)) ([20db90a](https://github.com/angular/angular/commit/20db90a)), closes [#39556](https://github.com/angular/angular/issues/39556)
|
||||
* **core:** remove deprecated wtfZoneSpec from NgZone ([#37864](https://github.com/angular/angular/issues/37864)) ([e02bea8](https://github.com/angular/angular/commit/e02bea8)), closes [#33949](https://github.com/angular/angular/issues/33949)
|
||||
* **forms:** more precise control cleanup ([#39623](https://github.com/angular/angular/issues/39623)) ([050cea9](https://github.com/angular/angular/commit/050cea9))
|
||||
* **http:** queue jsonp <script> tag onLoad event handler in microtask ([#39512](https://github.com/angular/angular/issues/39512)) ([10e4ac0](https://github.com/angular/angular/commit/10e4ac0)), closes [#39496](https://github.com/angular/angular/issues/39496)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **compiler:** optimize computation of i18n message ids ([#39694](https://github.com/angular/angular/issues/39694)) ([1891455](https://github.com/angular/angular/commit/1891455))
|
||||
* **compiler:** use raw bytes to represent utf-8 encoded strings ([#39694](https://github.com/angular/angular/issues/39694)) ([882ff8f](https://github.com/angular/angular/commit/882ff8f))
|
||||
* **compiler-cli:** reduce filesystem hits during resource resolution ([#39604](https://github.com/angular/angular/issues/39604)) ([a7adcbd](https://github.com/angular/angular/commit/a7adcbd))
|
||||
|
||||
|
||||
|
||||
<a name="11.0.0"></a>
|
||||
# 11.0.0 (2020-11-11)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** only providing stamping information if the `--stamp` flag is used ([#39392](https://github.com/angular/angular/issues/39392)) ([84e09a0](https://github.com/angular/angular/commit/84e09a0))
|
||||
* **common:** do not round up fractions of a millisecond in `DatePipe` ([#38009](https://github.com/angular/angular/issues/38009)) ([26f2820](https://github.com/angular/angular/commit/26f2820)), closes [#37989](https://github.com/angular/angular/issues/37989)
|
||||
* **common:** mark locale data arrays as readonly ([#30397](https://github.com/angular/angular/issues/30397)) ([6acea54](https://github.com/angular/angular/commit/6acea54)), closes [#27003](https://github.com/angular/angular/issues/27003)
|
||||
* **common:** add `params` and `reportProgress` options to `HttpClient.put()` overload ([#37873](https://github.com/angular/angular/issues/37873)) ([dd8d8c8](https://github.com/angular/angular/commit/dd8d8c8)), closes [#23600](https://github.com/angular/angular/issues/23600)
|
||||
* **common:** correct and simplify typing of `KeyValuePipe` ([#37447](https://github.com/angular/angular/issues/37447)) ([4dfe0fa](https://github.com/angular/angular/commit/4dfe0fa))
|
||||
* **common:** correct and simplify typing of `AsyncPipe` ([#37447](https://github.com/angular/angular/issues/37447)) ([5f815c0](https://github.com/angular/angular/commit/5f815c0))
|
||||
* **common:** correct and simplify typing of `I18nPluralPipe` ([#37447](https://github.com/angular/angular/issues/37447)) ([3b919ef](https://github.com/angular/angular/commit/3b919ef))
|
||||
* **common:** correct typing and implementation of `SlicePipe` ([#37447](https://github.com/angular/angular/issues/37447)) ([4744c22](https://github.com/angular/angular/commit/4744c22))
|
||||
* **common:** let case conversion pipes accept type unions with `null` ([#37447](https://github.com/angular/angular/issues/37447)) ([c7d5555](https://github.com/angular/angular/commit/c7d5555)), closes [#36259](https://github.com/angular/angular/issues/36259)
|
||||
* **common:** add boolean to valid json for testing ([#37893](https://github.com/angular/angular/issues/37893)) ([3c474ec](https://github.com/angular/angular/commit/3c474ec)), closes [#20690](https://github.com/angular/angular/issues/20690)
|
||||
* **common:** update locales using new CLDR data ([#39343](https://github.com/angular/angular/issues/39343)) ([3738233](https://github.com/angular/angular/commit/3738233))
|
||||
* **common:** change the week-numbering year format from `r` -> `Y` ([#39495](https://github.com/angular/angular/issues/39495)) ([feda78e](https://github.com/angular/angular/commit/feda78e))
|
||||
* **compiler:** source span for microsyntax text att should be key span ([#38766](https://github.com/angular/angular/issues/38766)) ([8f349b2](https://github.com/angular/angular/commit/8f349b2))
|
||||
* **compiler:** promote constants in templates to Trusted Types ([#39211](https://github.com/angular/angular/issues/39211)) ([6e18d2d](https://github.com/angular/angular/commit/6e18d2d))
|
||||
* **compiler:** do not throw away render3 AST on errors ([#39413](https://github.com/angular/angular/issues/39413)) ([d76beda](https://github.com/angular/angular/commit/d76beda))
|
||||
* **compiler:** treat i18n attributes with no bindings as static attributes ([#39408](https://github.com/angular/angular/issues/39408)) ([bf1caa7](https://github.com/angular/angular/commit/bf1caa7)), closes [#38231](https://github.com/angular/angular/issues/38231)
|
||||
* **compiler:** preserve `this.$event` and `this.$any` accesses in expressions ([#39323](https://github.com/angular/angular/issues/39323)) ([a8e0db7](https://github.com/angular/angular/commit/a8e0db7)), closes [#30278](https://github.com/angular/angular/issues/30278)
|
||||
* **compiler:** ensure that i18n message-parts have the correct source-span ([#39486](https://github.com/angular/angular/issues/39486)) ([63f9e16](https://github.com/angular/angular/commit/63f9e16))
|
||||
* **compiler:** skipping leading whitespace should not break placeholder source-spans ([#39486](https://github.com/angular/angular/issues/39486)) ([b8e9b3d](https://github.com/angular/angular/commit/b8e9b3d)), closes [#39195](https://github.com/angular/angular/issues/39195)
|
||||
* **compiler-cli:** compute source-mappings for localized strings ([#38645](https://github.com/angular/angular/issues/38645)) ([7e0b3fd](https://github.com/angular/angular/commit/7e0b3fd))
|
||||
* **compiler-cli:** generate `let` statements in ES2015+ mode ([#38775](https://github.com/angular/angular/issues/38775)) ([123bff7](https://github.com/angular/angular/commit/123bff7))
|
||||
* **compiler-cli:** perform DOM schema checks even in basic mode in g3 ([#38943](https://github.com/angular/angular/issues/38943)) ([40975e0](https://github.com/angular/angular/commit/40975e0))
|
||||
* **compiler-cli:** type checking of expressions within ICUs ([#39072](https://github.com/angular/angular/issues/39072)) ([0a16e60](https://github.com/angular/angular/commit/0a16e60)), closes [#39064](https://github.com/angular/angular/issues/39064)
|
||||
* **core:** migrate relative link resolution with single quotes ([#39102](https://github.com/angular/angular/issues/39102)) ([049b453](https://github.com/angular/angular/commit/049b453)), closes [#39082](https://github.com/angular/angular/issues/39082)
|
||||
* **compiler-cli:** generating invalid `setClassMetadata` call in ES5 for class with custom decorator ([#39527](https://github.com/angular/angular/issues/39527)) ([b0bbc1f](https://github.com/angular/angular/commit/b0bbc1f)), closes [#39509](https://github.com/angular/angular/issues/39509)
|
||||
* **compiler-cli:** report missing pipes when `fullTemplateTypeCheck` is disabled ([#39320](https://github.com/angular/angular/issues/39320)) ([67ea7b6](https://github.com/angular/angular/commit/67ea7b6)), closes [#38195](https://github.com/angular/angular/issues/38195)
|
||||
* **compiler-cli:** avoid duplicate diagnostics about unknown pipes ([#39517](https://github.com/angular/angular/issues/39517)) ([c68ca49](https://github.com/angular/angular/commit/c68ca49))
|
||||
* **compiler-cli:** do not drop non-Angular decorators when downleveling ([#39577](https://github.com/angular/angular/issues/39577)) ([f51cf29](https://github.com/angular/angular/commit/f51cf29)), closes [#39574](https://github.com/angular/angular/issues/39574)
|
||||
* **core:** remove `CollectionChangeRecord` symbol ([#38668](https://github.com/angular/angular/issues/38668)) ([fdea180](https://github.com/angular/angular/commit/fdea180))
|
||||
* **core:** ensure `TestBed` is not instantiated before override provider ([#38717](https://github.com/angular/angular/issues/38717)) ([c8f056b](https://github.com/angular/angular/commit/c8f056b))
|
||||
* **core:** use single quotes for relative link resolution migration to align with style guide ([#39070](https://github.com/angular/angular/issues/39070)) ([8894706](https://github.com/angular/angular/commit/8894706))
|
||||
* **core:** migrate relative link resolution with single quotes ([#39102](https://github.com/angular/angular/issues/39102)) ([049b453](https://github.com/angular/angular/commit/049b453))
|
||||
* **core:** use Trusted Types policy in inert DOM builder ([#39208](https://github.com/angular/angular/issues/39208)) ([7d49299](https://github.com/angular/angular/commit/7d49299))
|
||||
* **core:** use Trusted Types policy in named_array_type ([#39209](https://github.com/angular/angular/issues/39209)) ([f6d5cdf](https://github.com/angular/angular/commit/f6d5cdf))
|
||||
* **router:** Allow undefined inputs on routerLink ([#39151](https://github.com/angular/angular/issues/39151)) ([b0b4953](https://github.com/angular/angular/commit/b0b4953))
|
||||
* **router:** create schematic for preserveQueryParams ([#38762](https://github.com/angular/angular/issues/38762)) ([93ee05d](https://github.com/angular/angular/commit/93ee05d))
|
||||
* **router:** remove preserveQueryParams symbol ([#38762](https://github.com/angular/angular/issues/38762)) ([783a5bd](https://github.com/angular/angular/commit/783a5bd))
|
||||
* **core:** use Trusted Types policy in `createNamedArrayType()` ([#39209](https://github.com/angular/angular/issues/39209)) ([f6d5cdf](https://github.com/angular/angular/commit/f6d5cdf))
|
||||
* **core:** guard reading of global `ngDevMode` for undefined. ([#36055](https://github.com/angular/angular/issues/36055)) ([f541e5f](https://github.com/angular/angular/commit/f541e5f))
|
||||
* **core:** do not error when `ngDevMode` is undeclared ([#39415](https://github.com/angular/angular/issues/39415)) ([cc32932](https://github.com/angular/angular/commit/cc32932))
|
||||
* **core:** store ICU state in `LView` rather than in `TView` ([#39233](https://github.com/angular/angular/issues/39233)) ([0992b67](https://github.com/angular/angular/commit/0992b67)), closes [#37021](https://github.com/angular/angular/issues/37021) [#38144](https://github.com/angular/angular/issues/38144) [#38073](https://github.com/angular/angular/issues/38073)
|
||||
* **core:** `markDirty()` should only mark flags when really scheduling tick. ([#39316](https://github.com/angular/angular/issues/39316)) ([3b6497b](https://github.com/angular/angular/commit/3b6497b)), closes [#39296](https://github.com/angular/angular/issues/39296)
|
||||
* **core:** access injected parent values using `SkipSelf` ([#39464](https://github.com/angular/angular/issues/39464)) ([7cb9e19](https://github.com/angular/angular/commit/7cb9e19))
|
||||
* **elements:** update the view of an `OnPush` component when inputs change ([#39452](https://github.com/angular/angular/issues/39452)) ([dd28855](https://github.com/angular/angular/commit/dd28855)), closes [#38948](https://github.com/angular/angular/issues/38948)
|
||||
* **forms:** ensure to emit `statusChanges` on subsequent value update/validations ([#38354](https://github.com/angular/angular/issues/38354)) ([d9fea85](https://github.com/angular/angular/commit/d9fea85)), closes [#20424](https://github.com/angular/angular/issues/20424) [#14542](https://github.com/angular/angular/issues/14542)
|
||||
* **forms:** type `NG_VALUE_ACCESSOR` injection token as array ([#29723](https://github.com/angular/angular/issues/29723)) ([2b1b718](https://github.com/angular/angular/commit/2b1b718)), closes [#29351](https://github.com/angular/angular/issues/29351)
|
||||
* **forms:** improve types of directive constructor arguments ([#38944](https://github.com/angular/angular/issues/38944)) ([246de9a](https://github.com/angular/angular/commit/246de9a))
|
||||
* **forms:** include `null` in `.parent` of abstract control ([#32671](https://github.com/angular/angular/issues/32671)) ([f4f1bcc](https://github.com/angular/angular/commit/f4f1bcc)), closes [#16999](https://github.com/angular/angular/issues/16999)
|
||||
* **forms:** remove validators while cleaning up a control ([#39234](https://github.com/angular/angular/issues/39234)) ([43b4940](https://github.com/angular/angular/commit/43b4940))
|
||||
* **language-service:** hybrid visitor returns parent node of `BoundAttribute` ([#38995](https://github.com/angular/angular/issues/38995)) ([323be39](https://github.com/angular/angular/commit/323be39))
|
||||
* **language-service:** [Ivy] hybrid visitor should not locate let keyword ([#39061](https://github.com/angular/angular/issues/39061)) ([70e13dc](https://github.com/angular/angular/commit/70e13dc))
|
||||
* **language-service:** [Ivy] create compiler only when program changes ([#39231](https://github.com/angular/angular/issues/39231)) ([8f1317f](https://github.com/angular/angular/commit/8f1317f))
|
||||
* **localize:** render placeholder types in extracted XLIFF files ([#39398](https://github.com/angular/angular/issues/39398)) ([32163ef](https://github.com/angular/angular/commit/32163ef)), closes [#38791](https://github.com/angular/angular/issues/38791)
|
||||
* **localize:** serialize all the message locations to XLIFF ([#39411](https://github.com/angular/angular/issues/39411)) ([f5710c6](https://github.com/angular/angular/commit/f5710c6)), closes [#39330](https://github.com/angular/angular/issues/39330)
|
||||
* **ngcc:** ensure that "inline exports" can be interpreted correctly ([#39267](https://github.com/angular/angular/issues/39267)) ([822b838](https://github.com/angular/angular/commit/822b838))
|
||||
* **ngcc:** capture UMD/CommonJS inner class implementation node correctly ([#39346](https://github.com/angular/angular/issues/39346)) ([fc2e3cc](https://github.com/angular/angular/commit/fc2e3cc))
|
||||
* **platform-server:** resolve absolute URL from `baseUrl` ([#39334](https://github.com/angular/angular/issues/39334)) ([b4e8399](https://github.com/angular/angular/commit/b4e8399))
|
||||
* **platform-webworker:** remove @angular/platform-webworker and @angular/platform-webworker-dynamic ([#38846](https://github.com/angular/angular/issues/38846)) ([93c3d8f](https://github.com/angular/angular/commit/93c3d8f))
|
||||
* **router:** fix arguments order for call to `shouldReuseRoute` ([#26949](https://github.com/angular/angular/issues/26949)) ([3817e5f](https://github.com/angular/angular/commit/3817e5f)), closes [#16192](https://github.com/angular/angular/issues/16192)
|
||||
* **router:** support lazy loading for empty path named outlets ([#38379](https://github.com/angular/angular/issues/38379)) ([926ffcd](https://github.com/angular/angular/commit/926ffcd)), closes [#12842](https://github.com/angular/angular/issues/12842)
|
||||
* **router:** set `relativeLinkResolution` to `corrected` by default ([#25609](https://github.com/angular/angular/issues/25609)) ([837889f](https://github.com/angular/angular/commit/837889f))
|
||||
* **router:** properly assign `ExtraOptions` to `Router` in `RouterTestingModule` ([#39096](https://github.com/angular/angular/issues/39096)) ([d8c0534](https://github.com/angular/angular/commit/d8c0534)), closes [#23347](https://github.com/angular/angular/issues/23347)
|
||||
* **router:** allow undefined inputs on `routerLink` ([#39151](https://github.com/angular/angular/issues/39151)) ([b0b4953](https://github.com/angular/angular/commit/b0b4953))
|
||||
* **router:** create schematic for `preserveQueryParams` ([#38762](https://github.com/angular/angular/issues/38762)) ([93ee05d](https://github.com/angular/angular/commit/93ee05d))
|
||||
* **router:** remove `preserveQueryParams` symbol ([#38762](https://github.com/angular/angular/issues/38762)) ([783a5bd](https://github.com/angular/angular/commit/783a5bd))
|
||||
* **router:** fix incorrect type signature for `createUrlTree` ([#39347](https://github.com/angular/angular/issues/39347)) ([161b278](https://github.com/angular/angular/commit/161b278))
|
||||
* **router:** ensure all outlets are used when commands have a prefix ([#39456](https://github.com/angular/angular/issues/39456)) ([b2f3952](https://github.com/angular/angular/commit/b2f3952))
|
||||
* **service-worker:** fix condition to check for a cache-busted request ([#36847](https://github.com/angular/angular/issues/36847)) ([5be4edf](https://github.com/angular/angular/commit/5be4edf))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **core:** add automated migration to replace async with waitForAsync ([#39212](https://github.com/angular/angular/issues/39212)) ([5ce71e0](https://github.com/angular/angular/commit/5ce71e0))
|
||||
* **core:** add automated migration to replace ViewEncapsulation.Native ([#38882](https://github.com/angular/angular/issues/38882)) ([0e733f3](https://github.com/angular/angular/commit/0e733f3))
|
||||
* **core:** add initialNavigation schematic ([#36926](https://github.com/angular/angular/issues/36926)) ([0ec7043](https://github.com/angular/angular/commit/0ec7043))
|
||||
* **core:** add Trusted Types workaround for Function constructor ([#39209](https://github.com/angular/angular/issues/39209)) ([5913e5c](https://github.com/angular/angular/commit/5913e5c))
|
||||
* **common:** add ISO week-numbering year formats support to `formatDate` ([#38828](https://github.com/angular/angular/issues/38828)) ([984ed39](https://github.com/angular/angular/commit/984ed39))
|
||||
* **common:** stricter types for `DatePipe` ([#37447](https://github.com/angular/angular/issues/37447)) ([daf8b7f](https://github.com/angular/angular/commit/daf8b7f))
|
||||
* **common:** stricter types for number pipes ([#37447](https://github.com/angular/angular/issues/37447)) ([7b2aac9](https://github.com/angular/angular/commit/7b2aac9))
|
||||
* **compiler:** parse and recover on incomplete opening HTML tags ([#38681](https://github.com/angular/angular/issues/38681)) ([6ae3b68](https://github.com/angular/angular/commit/6ae3b68)), closes [#38596](https://github.com/angular/angular/issues/38596)
|
||||
* **compiler:** add `keySpan` to `Variable` node ([#38965](https://github.com/angular/angular/issues/38965)) ([239968d](https://github.com/angular/angular/commit/239968d))
|
||||
* **compiler-cli:** `TemplateTypeChecker` operation to get `Symbol` from a template node ([#38618](https://github.com/angular/angular/issues/38618)) ([c4556db](https://github.com/angular/angular/commit/c4556db))
|
||||
* **compiler-cli:** add ability to get `Symbol` of `Template`s and `Element`s in component template ([#38618](https://github.com/angular/angular/issues/38618)) ([cf2e8b9](https://github.com/angular/angular/commit/cf2e8b9))
|
||||
* **compiler-cli:** add ability to get `Symbol` of AST expression in component template ([#38618](https://github.com/angular/angular/issues/38618)) ([f56ece4](https://github.com/angular/angular/commit/f56ece4))
|
||||
* **compiler-cli:** add ability to get symbol of reference or variable ([#38618](https://github.com/angular/angular/issues/38618)) ([19598b4](https://github.com/angular/angular/commit/19598b4))
|
||||
* **compiler-cli:** define interfaces to be used for `TemplateTypeChecker` ([#38618](https://github.com/angular/angular/issues/38618)) ([9e77bd3](https://github.com/angular/angular/commit/9e77bd3))
|
||||
* **compiler-cli:** support getting resource dependencies for a source file ([#38048](https://github.com/angular/angular/issues/38048)) ([5dbf357](https://github.com/angular/angular/commit/5dbf357))
|
||||
* **core:** add automated migration to replace `async` with `waitForAsync` ([#39212](https://github.com/angular/angular/issues/39212)) ([5ce71e0](https://github.com/angular/angular/commit/5ce71e0))
|
||||
* **core:** add automated migration to replace `ViewEncapsulation.Native` ([#38882](https://github.com/angular/angular/issues/38882)) ([0e733f3](https://github.com/angular/angular/commit/0e733f3))
|
||||
* **core:** add `initialNavigation` schematic ([#36926](https://github.com/angular/angular/issues/36926)) ([0ec7043](https://github.com/angular/angular/commit/0ec7043))
|
||||
* **core:** add Trusted Types workaround for `Function` constructor ([#39209](https://github.com/angular/angular/issues/39209)) ([5913e5c](https://github.com/angular/angular/commit/5913e5c))
|
||||
* **core:** create internal Trusted Types module ([#39207](https://github.com/angular/angular/issues/39207)) ([0875fd2](https://github.com/angular/angular/commit/0875fd2))
|
||||
* **core:** depend on type definitions for Trusted Types ([#39207](https://github.com/angular/angular/issues/39207)) ([c4266fb](https://github.com/angular/angular/commit/c4266fb))
|
||||
* **core:** remove ViewEncapsulation.Native ([#38882](https://github.com/angular/angular/issues/38882)) ([4a1c12c](https://github.com/angular/angular/commit/4a1c12c))
|
||||
* **language-service:** [Ivy] getSemanticDiagnostics for external templates ([#39065](https://github.com/angular/angular/issues/39065)) ([63624a2](https://github.com/angular/angular/commit/63624a2))
|
||||
* **language-service:** Add getTypeDefinitionAtPosition (go to type definition) ([#39145](https://github.com/angular/angular/issues/39145)) ([a84976f](https://github.com/angular/angular/commit/a84976f))
|
||||
* **language-service:** Add module name to directive quick info ([#39121](https://github.com/angular/angular/issues/39121)) ([4604fe9](https://github.com/angular/angular/commit/4604fe9))
|
||||
* **router:** add new initialNavigation options to replace legacy ([#37480](https://github.com/angular/angular/issues/37480)) ([c4becca](https://github.com/angular/angular/commit/c4becca))
|
||||
* **core:** remove `ViewEncapsulation.Native` ([#38882](https://github.com/angular/angular/issues/38882)) ([4a1c12c](https://github.com/angular/angular/commit/4a1c12c))
|
||||
* **forms:** add migration for `AbstractControl.parent` accesses ([#39009](https://github.com/angular/angular/issues/39009)) ([aeec223](https://github.com/angular/angular/commit/aeec223)), closes [#32671](https://github.com/angular/angular/issues/32671)
|
||||
* **language-service:** add `getDefinitionAndBoundSpan` (go to definition) ([#39101](https://github.com/angular/angular/issues/39101)) ([3975dd9](https://github.com/angular/angular/commit/3975dd9))
|
||||
* **language-service:** add quick info for inline templates in ivy ([#39060](https://github.com/angular/angular/issues/39060)) ([904adb7](https://github.com/angular/angular/commit/904adb7))
|
||||
* **language-service:** [Ivy] `getSemanticDiagnostics` for external templates ([#39065](https://github.com/angular/angular/issues/39065)) ([63624a2](https://github.com/angular/angular/commit/63624a2))
|
||||
* **language-service:** add `getTypeDefinitionAtPosition` (go to type definition) ([#39145](https://github.com/angular/angular/issues/39145)) ([a84976f](https://github.com/angular/angular/commit/a84976f))
|
||||
* **language-service:** add module name to directive quick info ([#39121](https://github.com/angular/angular/issues/39121)) ([4604fe9](https://github.com/angular/angular/commit/4604fe9))
|
||||
* **router:** add migration to update calls to `navigateByUrl` and `createUrlTree` with invalid parameters ([#38825](https://github.com/angular/angular/issues/38825)) ([7849fdd](https://github.com/angular/angular/commit/7849fdd))
|
||||
* **router:** add `relativeLinkResolution` migration to update default value ([#38698](https://github.com/angular/angular/issues/38698)) ([15ea811](https://github.com/angular/angular/commit/15ea811))
|
||||
* **router:** add new `initialNavigation` options to replace legacy ([#37480](https://github.com/angular/angular/issues/37480)) ([c4becca](https://github.com/angular/angular/commit/c4becca))
|
||||
* **service-worker:** add `UnrecoverableStateError` ([#36847](https://github.com/angular/angular/issues/36847)) ([036a2fa](https://github.com/angular/angular/commit/036a2fa)), closes [#36539](https://github.com/angular/angular/issues/36539)
|
||||
* **service-worker:** add the option to prefer network for navigation requests ([#38565](https://github.com/angular/angular/issues/38565)) ([a206852](https://github.com/angular/angular/commit/a206852)), closes [#38194](https://github.com/angular/angular/issues/38194)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **compiler-cli:** only emit directive/pipe references that are used ([#38539](https://github.com/angular/angular/issues/38539)) ([077f516](https://github.com/angular/angular/commit/077f516))
|
||||
* **compiler-cli:** optimize computation of type-check scope information ([#38539](https://github.com/angular/angular/issues/38539)) ([297c060](https://github.com/angular/angular/commit/297c060))
|
||||
* **compiler-cli:** only generate template context declaration when used ([#39321](https://github.com/angular/angular/issues/39321)) ([1ac0500](https://github.com/angular/angular/commit/1ac0500))
|
||||
* **core:** do not recurse into modules that have already been registered ([#39514](https://github.com/angular/angular/issues/39514)) ([5c13c67](https://github.com/angular/angular/commit/5c13c67)), closes [#39487](https://github.com/angular/angular/issues/39487)
|
||||
* **router:** use `ngDevMode` to tree-shake error messages in router ([#38674](https://github.com/angular/angular/issues/38674)) ([db21c4f](https://github.com/angular/angular/commit/db21c4f))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **router:** * The `initialNavigation` property for the options in
|
||||
`RouterModule.forRoot` no longer supports `legacy_disabled`,
|
||||
`legacy_enabled`, `true`, or `false` as valid values.
|
||||
`legacy_enabled` (the old default) is instead `enabledNonBlocking`
|
||||
* `enabled` is deprecated as a valid value for the
|
||||
`RouterModule.forRoot` `initialNavigation` option. `enabledBlocking`
|
||||
has been introduced to replace it
|
||||
* **router:** preserveQueryParams has been removed, use
|
||||
queryParamsHandling="preserve" instead
|
||||
* **router:** If you were accessing the `RouterLink` values of `queryParams`,
|
||||
`fragment` or `queryParamsHandling` you might need to relax the typing to also
|
||||
accept `undefined` and `null`. ([#39151](https://github.com/angular/angular/issues/39151))
|
||||
* **core:** * `ViewEncapsulation.Native` has been removed. Use `ViewEncapsulation.ShadowDom` instead. Existing
|
||||
usages will be updated automatically by `ng update`.
|
||||
* **compiler-cli:** Expressions within ICUs are now type-checked again, fixing a regression
|
||||
in Ivy. This may cause compilation failures if errors are found in
|
||||
expressions that appear within an ICU. Please correct these expressions
|
||||
to resolve the type-check errors.
|
||||
* **common:**
|
||||
- **[6acea54](https://github.com/angular/angular/commit/6acea54f62fe7e62e9b36458b30d98501277236f):**
|
||||
The locale data API has been marked as returning readonly arrays, rather than mutable arrays, since these arrays are shared across calls to the API.
|
||||
If you were mutating them (e.g. calling `sort()`, `push()`, `splice()`, etc.) then your code will no longer compile.
|
||||
If you need to mutate the array, you should now make a copy (e.g. by calling `slice()`) and mutate the copy.
|
||||
- **[26f2820](https://github.com/angular/angular/commit/26f28200bf3a909024184c61111f4cd20ac41edd):**
|
||||
When passing a date-time formatted string to the `DatePipe` in a format that contains fractions of a millisecond, the milliseconds will now always be rounded down rather than to the nearest millisecond.
|
||||
Most applications will not be affected by this change.
|
||||
If this is not the desired behaviour then consider pre-processing the string to round the millisecond part before passing it to the `DatePipe`.
|
||||
- **[4744c22](https://github.com/angular/angular/commit/4744c229dbd372746a38ebbcdae2245f945ebcc4):**
|
||||
The `slice` pipe now returns `null` for the `undefined` input value, which is consistent with the behavior of most pipes.
|
||||
If you rely on `undefined` being the result in that case, you now need to check for it explicitly.
|
||||
- **[4dfe0fa](https://github.com/angular/angular/commit/4dfe0fa068007c28ca3b4a1476ed4ba1d2d86064):**
|
||||
The typing of the `keyvalue` pipe has been fixed to report that for input objects that have `number` keys, the result will contain the string representation of the keys.
|
||||
This was already the case and the types have simply been updated to reflect this.
|
||||
Please update the consumers of the pipe output if they were relying on the incorrect types.
|
||||
Note that this does not affect use cases where the input values are `Map`s, so if you need to preserve `number`s, this is an effective way.
|
||||
- **[7b2aac9](https://github.com/angular/angular/commit/7b2aac97df63717fd2dfbb81903d12221ae29ba1):**
|
||||
The signatures of the number pipes now explicitly state which types are accepted.
|
||||
This should only cause issues in corner cases, as any other values would result in runtime exceptions.
|
||||
- **[daf8b7f](https://github.com/angular/angular/commit/daf8b7f10038c7ecf7ea78bc6fe39766c85224a6):**
|
||||
The signature of the `date` pipe now explicitly states which types are accepted.
|
||||
This should only cause issues in corner cases, as any other values would result in runtime exceptions.
|
||||
- **[5f815c0](https://github.com/angular/angular/commit/5f815c05650c15e414fe72cddaa2b690a7962273):**
|
||||
The `async` pipe no longer claims to return `undefined` for an input that was typed as `undefined`.
|
||||
Note that the code actually returned `null` on `undefined` inputs.
|
||||
In the unlikely case you were relying on this, please fix the typing of the consumers of the pipe output.
|
||||
- **[c7d5555](https://github.com/angular/angular/commit/c7d5555dfb14f5deca4a2d947fe82a68453e5f09):**
|
||||
The case conversion pipes no longer let falsy values through.
|
||||
They now map both `null` and `undefined` to `null` and raise an exception on invalid input (`0`, `false`, `NaN`) just like most "common pipes".
|
||||
If your code required falsy values to pass through, you need to handle them explicitly.
|
||||
* **compiler:**
|
||||
- **[736e064](https://github.com/angular/angular/commit/736e0644b02bc4606a7ae0c974d1b06e993708f6):**
|
||||
TypeScript 3.9 is no longer supported, please upgrade to TypeScript 4.0.
|
||||
* **compiler-cli:**
|
||||
- **[0a16e60](https://github.com/angular/angular/commit/0a16e60afae27c7af023cf617de05297dddf5135):**
|
||||
Expressions within ICUs are now type-checked again, fixing a regression in Ivy.
|
||||
This may cause compilation failures if errors are found in expressions that appear within an ICU.
|
||||
Please correct these expressions to resolve the type-check errors.
|
||||
* **core:**
|
||||
- **[fdea180](https://github.com/angular/angular/commit/fdea1804d6d46d33c71640972ff45a8d5cc82f8b):**
|
||||
`CollectionChangeRecord` has been removed, use `IterableChangeRecord` instead.
|
||||
- **[c8f056b](https://github.com/angular/angular/commit/c8f056beb696d176530ee4e86f64964c3b834c9a):**
|
||||
If you call `TestBed.overrideProvider` after TestBed initialization, provider overrides are not applied.
|
||||
This behavior is consistent with other override methods (such as `TestBed.overrideDirective`, etc) but they throw an error to indicate that, when the check was missing in the `TestBed.overrideProvider` function.
|
||||
Now calling `TestBed.overrideProvider` after `TestBed` initialization also triggers an error, thus there is a chance that some tests (where `TestBed.overrideProvider` is called after `TestBed` initialization) will start to fail and require updates to move `TestBed.overrideProvider` calls before `TestBed` initialization is completed.
|
||||
- **[4ca1c73](https://github.com/angular/angular/commit/4ca1c736bb020de166b6a1fbfb9fe264602ccd5c):**
|
||||
In v10, IE 9, 10, and IE mobile support was deprecated.
|
||||
In v11, Angular framework removes IE 9, 10, and IE mobile support completely.
|
||||
Supporting outdated browsers like these increases bundle size, code complexity, and test load, and also requires time and effort that could be spent on improvements to the framework.
|
||||
For example, fixing issues can be more difficult, as a straightforward fix for modern browsers could break old ones that have quirks due to not receiving updates from vendors.
|
||||
- **[4a1c12c](https://github.com/angular/angular/commit/4a1c12c773f14dbfc5db61087f415d56f60127cf):**
|
||||
`ViewEncapsulation.Native` has been removed. Use `ViewEncapsulation.ShadowDom` instead.
|
||||
Existing usages will be updated automatically by `ng update`.
|
||||
* **forms:**
|
||||
- **[d9fea85](https://github.com/angular/angular/commit/d9fea857db0638149f200ca86c7852c01c9787f4):**
|
||||
Previously if `FormControl`, `FormGroup` and `FormArray` class instances had async validators defined at initialization time, the status change event was not emitted once async validators completed.
|
||||
After this change the status event is emitted into the `statusChanges` observable.
|
||||
If your code relies on the old behavior, you can filter/ignore this additional status change event.
|
||||
- **[246de9a](https://github.com/angular/angular/commit/246de9aaad2a85c39f4e624ba25e444d716fe486):**
|
||||
Directives in the `@angular/forms` package used to have `any[]` as a type of `validators` and `asyncValidators` arguments in constructors.
|
||||
Now these arguments are properly typed, so if your code relies on directive constructor types it may require some updates to improve type safety.
|
||||
- **[f4f1bcc](https://github.com/angular/angular/commit/f4f1bcc99711be277205dcd8ef6fc5a1873cb227):**
|
||||
Type of `AbstractFormControl.parent` now includes `null`.
|
||||
`null` is now included in the types of `.parent`.
|
||||
If you don't already have a check for this case, the TypeScript compiler might complain.
|
||||
A v11 migration exists which adds the non-null assertion operator where necessary.
|
||||
In an unlikely case your code was testing the parent against `undefined` with strict equality, you'll need to change this to `=== null` instead, since the parent is now explicitly initialized with `null` instead of being left `undefined`.
|
||||
* **platform-server:**
|
||||
- **[b4e8399](https://github.com/angular/angular/commit/b4e8399144ae4b6d4f0da9ff2a8e1fa73643f766):**
|
||||
If you use `useAbsoluteUrl` to setup `platform-server`, you now need to also specify `baseUrl`.
|
||||
We are intentionally making this a breaking change in a minor release, because if `useAbsoluteUrl` is set to `true` then the behavior of the application could be unpredictable, resulting in issues that are hard to discover but could be affecting production environments.
|
||||
* **platform-webworker:**
|
||||
- **[93c3d8f](https://github.com/angular/angular/commit/93c3d8f9fd79014bf700a1447503f5ee6f170bf9):**
|
||||
@angular/platform-webworker and @angular/platform-webworker-dynamic have been removed as they were deprecated in v8.
|
||||
* **router:**
|
||||
- **[3817e5f](https://github.com/angular/angular/commit/3817e5f1dfeb9de26fa2ea4068a37565f435214f):**
|
||||
This change corrects the argument order when calling `RouteReuseStrategy#shouldReuseRoute`.
|
||||
Previously, when evaluating child routes, they would be called with the future and current arguments would be swapped.
|
||||
If your `RouteReuseStrategy` relies specifically on only the future or current snapshot state, you may need to update the `shouldReuseRoute` implementation's use of "future" and "current" `ActivatedRouteSnapshot`s.
|
||||
- **[e4f4d18](https://github.com/angular/angular/commit/e4f4d18e7e73a7c755d3b79cf599e0e04270000d):**
|
||||
While the new parameter types allow a variable of type `NavigationExtras` to be passed in, they will not allow object literals, as they may only specify known properties.
|
||||
They will also not accept types that do not have properties in common with the ones in the `Pick`.
|
||||
To fix this error, only specify properties from the `NavigationExtras` which are actually used in the respective function calls or use a type assertion on the object or variable: `as NavigationExtras`.
|
||||
- **[837889f](https://github.com/angular/angular/commit/837889f0a47521d3de5c445ac3ffeedfe47fc109):**
|
||||
This commit changes the default value of `relativeLinkResolution` from `'legacy'` to `'default'`.
|
||||
If your application previously used the default by not specifying a value in the `ExtraOptions` and uses relative links when navigating from children of empty path routes, you will need to update your `RouterModule` to specifically specify `'legacy'` for `relativeLinkResolution`.
|
||||
See https://angular.io/api/router/ExtraOptions#relativeLinkResolution for more details.
|
||||
- **[c4becca](https://github.com/angular/angular/commit/c4becca0e4238640461c43567a6d3e16b8c5d3f3):**
|
||||
The `initialNavigation` property for the options in `RouterModule.forRoot` no longer supports `legacy_disabled`, `legacy_enabled`, `true`, or `false` as valid values.
|
||||
`legacy_enabled` (the old default) is instead `enabledNonBlocking`.
|
||||
- **[c4becca](https://github.com/angular/angular/commit/c4becca0e4238640461c43567a6d3e16b8c5d3f3):**
|
||||
`enabled` is deprecated as a valid value for the `RouterModule.forRoot` `initialNavigation` option.
|
||||
`enabledBlocking` has been introduced to replace it.
|
||||
- **[783a5bd](https://github.com/angular/angular/commit/783a5bd7bbae35562e21aaa27771c54091fb9812):**
|
||||
`preserveQueryParams` has been removed, use `queryParamsHandling: "preserve"` instead.
|
||||
- **[b0b4953](https://github.com/angular/angular/commit/b0b4953fd654aeda2f358b0af1ab32d20b368930):**
|
||||
If you were accessing the `RouterLink` values of `queryParams`, `fragment` or `queryParamsHandling` you might need to relax the typing to also accept `undefined` and `null`.
|
||||
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* **compiler:** remove support for TypeScript 3.9 ([#39313](https://github.com/angular/angular/issues/39313)) ([736e064](https://github.com/angular/angular/commit/736e0644b02bc4606a7ae0c974d1b06e993708f6))
|
||||
* **router:** adjust type of parameter in `navigateByUrl` and `createUrlTree` to be more accurate ([#38227](https://github.com/angular/angular/issues/38227)) ([e4f4d18](https://github.com/angular/angular/commit/e4f4d18)), closes [#18798](https://github.com/angular/angular/issues/18798)
|
||||
|
||||
|
||||
|
||||
<a name="10.1.6"></a>
|
||||
@@ -75,44 +277,6 @@ to resolve the type-check errors.
|
||||
* **ngcc:** do not rescan program source files when referenced from multiple root files ([#39254](https://github.com/angular/angular/issues/39254)) ([5221df8](https://github.com/angular/angular/commit/5221df8)), closes [#39240](https://github.com/angular/angular/issues/39240)
|
||||
|
||||
|
||||
<a name="11.0.0-next.5"></a>
|
||||
# 11.0.0-next.5 (2020-10-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **common:** add boolean to valid json for testing ([#37893](https://github.com/angular/angular/issues/37893)) ([3c474ec](https://github.com/angular/angular/commit/3c474ec)), closes [#20690](https://github.com/angular/angular/issues/20690)
|
||||
* **core:** use single quotes for relative link resolution migration to align with style guide ([#39070](https://github.com/angular/angular/issues/39070)) ([8894706](https://github.com/angular/angular/commit/8894706))
|
||||
* **forms:** improve types of directive constructor arguments ([#38944](https://github.com/angular/angular/issues/38944)) ([246de9a](https://github.com/angular/angular/commit/246de9a))
|
||||
* **forms:** include null in .parent of abstract control ([#32671](https://github.com/angular/angular/issues/32671)) ([f4f1bcc](https://github.com/angular/angular/commit/f4f1bcc)), closes [#16999](https://github.com/angular/angular/issues/16999)
|
||||
* **language-service:** [Ivy] hybrid visitor should not locate let keyword ([#39061](https://github.com/angular/angular/issues/39061)) ([70e13dc](https://github.com/angular/angular/commit/70e13dc))
|
||||
* **router:** properly assign ExtraOptions to Router in RouterTestingModule ([#39096](https://github.com/angular/angular/issues/39096)) ([d8c0534](https://github.com/angular/angular/commit/d8c0534)), closes [#23347](https://github.com/angular/angular/issues/23347)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **compiler-cli:** support getting resource dependencies for a source file ([#38048](https://github.com/angular/angular/issues/38048)) ([5dbf357](https://github.com/angular/angular/commit/5dbf357))
|
||||
* **forms:** add migration for AbstractControl.parent accesses ([#39009](https://github.com/angular/angular/issues/39009)) ([aeec223](https://github.com/angular/angular/commit/aeec223)), closes [#32671](https://github.com/angular/angular/issues/32671)
|
||||
* **language-service:** Add getDefinitionAndBoundSpan (go to definition) ([#39101](https://github.com/angular/angular/issues/39101)) ([3975dd9](https://github.com/angular/angular/commit/3975dd9))
|
||||
* **language-service:** add quick info for inline templates in ivy ([#39060](https://github.com/angular/angular/issues/39060)) ([904adb7](https://github.com/angular/angular/commit/904adb7))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **forms:** Directives in the `@angular/forms` package used to have `any[]` as a type of `validators` and
|
||||
`asyncValidators` arguments in constructors. Now these arguments are properly typed, so if your
|
||||
code relies on directive constructor types it may require some updates to improve type safety.
|
||||
* **forms:** Type of AbstractFormControl.parent now includes null
|
||||
|
||||
`null` is now included in the types of .parent. If you don't already have a check for this case,
|
||||
the TypeScript compiler might compain. A v11 migration exists which adds the not-null assertion
|
||||
operator where necessary.
|
||||
|
||||
In an unlikely case your code was testing the parnet against undefined with sitrct equality,
|
||||
you'll need to change this to `=== null` instead, since the parent is not explicily initialized
|
||||
with `null` instead of being left `undefined`.
|
||||
|
||||
|
||||
|
||||
<a name="10.1.5"></a>
|
||||
## 10.1.5 (2020-10-07)
|
||||
@@ -125,92 +289,6 @@ with `null` instead of being left `undefined`.
|
||||
|
||||
|
||||
|
||||
<a name="11.0.0-next.4"></a>
|
||||
# 11.0.0-next.4 (2020-09-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **common:** correct and simplify typing of `KeyValuePipe` ([#37447](https://github.com/angular/angular/issues/37447)) ([4dfe0fa](https://github.com/angular/angular/commit/4dfe0fa))
|
||||
* **common:** correct and simplify typing of AsyncPipe ([#37447](https://github.com/angular/angular/issues/37447)) ([5f815c0](https://github.com/angular/angular/commit/5f815c0))
|
||||
* **common:** correct and simplify typing of I18nPluralPipe ([#37447](https://github.com/angular/angular/issues/37447)) ([3b919ef](https://github.com/angular/angular/commit/3b919ef))
|
||||
* **common:** correct typing and implementation of `SlicePipe` ([#37447](https://github.com/angular/angular/issues/37447)) ([4744c22](https://github.com/angular/angular/commit/4744c22))
|
||||
* **common:** let case conversion pipes accept type unions with `null` ([#36259](https://github.com/angular/angular/issues/36259)) ([#37447](https://github.com/angular/angular/issues/37447)) ([c7d5555](https://github.com/angular/angular/commit/c7d5555))
|
||||
* **compiler-cli:** perform DOM schema checks even in basic mode in g3 ([#38943](https://github.com/angular/angular/issues/38943)) ([40975e0](https://github.com/angular/angular/commit/40975e0))
|
||||
* **language-service:** hybrid visitor returns parent node of BoundAttribute ([#38995](https://github.com/angular/angular/issues/38995)) ([323be39](https://github.com/angular/angular/commit/323be39))
|
||||
* **packaging:** remove polyfills needed to run tests on IE9 and IE 10 ([#38931](https://github.com/angular/angular/issues/38931)) ([4ca1c73](https://github.com/angular/angular/commit/4ca1c73))
|
||||
* **platform-webworker:** remove platform-webworker and platform-webworker-dynamic ([#38846](https://github.com/angular/angular/issues/38846)) ([93c3d8f](https://github.com/angular/angular/commit/93c3d8f))
|
||||
* **router:** make relativeLinkResolution corrected by default ([#25609](https://github.com/angular/angular/issues/25609)) ([837889f](https://github.com/angular/angular/commit/837889f)), closes [#22394](https://github.com/angular/angular/issues/22394)
|
||||
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* **router:** Adjust type of parameter in navigateByUrl and createUrlTree to be more accurate ([#38227](https://github.com/angular/angular/issues/38227)) ([e4f4d18](https://github.com/angular/angular/commit/e4f4d18)), closes [#18798](https://github.com/angular/angular/issues/18798)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **common:** stricter types for DatePipe ([#37447](https://github.com/angular/angular/issues/37447)) ([daf8b7f](https://github.com/angular/angular/commit/daf8b7f))
|
||||
* **common:** stricter types for number pipes ([#37447](https://github.com/angular/angular/issues/37447)) ([7b2aac9](https://github.com/angular/angular/commit/7b2aac9))
|
||||
* **compiler:** Add keySpan to Variable Node ([#38965](https://github.com/angular/angular/issues/38965)) ([239968d](https://github.com/angular/angular/commit/239968d))
|
||||
* **router:** Add `relativeLinkResolution` migration to update default value ([#38698](https://github.com/angular/angular/issues/38698)) ([15ea811](https://github.com/angular/angular/commit/15ea811))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **packaging:** In v10, IE 9, 10, and IE mobile support was deprecated. In v11, Angular framework removes IE 9,
|
||||
10, and IE mobile support completely.
|
||||
Supporting outdated browsers like these increases bundle size, code complexity, and test load,
|
||||
and also requires time and effort that could be spent on improvements to the framework.
|
||||
For example, fixing issues can be more difficult, as a straightforward fix for modern browsers
|
||||
could break old ones that have quirks due to not receiving updates from vendors.
|
||||
* **platform-webworker:** @angular/platform-webworker and @angular/platform-webworker-dynamic
|
||||
have been removed as they were deprecated in v8
|
||||
* **common:** The `slice` pipe now returns `null` for the `undefined` input value,
|
||||
which is consistent with the behavior of most pipes. If you rely on
|
||||
`undefined` being the result in that case, you now need to check for it
|
||||
explicitly.
|
||||
* **common:** The typing of the `keyvalue` pipe has been fixed to report that for
|
||||
input objects that have `number` keys, the result will contain the
|
||||
string representation of the keys. This was already the case and the
|
||||
code has simply been updated to reflect this. Please update the
|
||||
consumers of the pipe output if they were relying on the incorrect
|
||||
types. Note that this does not affect use cases where the input values
|
||||
are `Map`s, so if you need to preserve `number`s, this is an effective
|
||||
way.
|
||||
* **common:** The signatures of the number pipes now explicitly state which types are
|
||||
accepted. This should only cause issues in corner cases, as any other
|
||||
values would result in runtime exceptions.
|
||||
* **common:** The signature of the `date` pipe now explicitly states which types are
|
||||
accepted. This should only cause issues in corner cases, as any other
|
||||
values would result in runtime exceptions.
|
||||
* **common:** The async pipe no longer claims to return `undefined` for an input that
|
||||
was typed as `undefined`. Note that the code actually returned `null` on
|
||||
`undefined` inputs. In the unlikely case you were relying on this,
|
||||
please fix the typing of the consumers of the pipe output.
|
||||
* **common:** The case conversion pipes no longer let falsy values through. They now
|
||||
map both `null` and `undefined` to `null` and raise an exception on
|
||||
invalid input (`0`, `false`, `NaN`) just like most "common pipes". If
|
||||
your code required falsy values to pass through, you need to handle them
|
||||
explicitly.
|
||||
* **router:** While the new parameter types allow a variable of type
|
||||
`NavigationExtras` to be passed in, they will not allow object literals,
|
||||
as they may only specify known properties. They will also not accept
|
||||
types that do not have properties in common with the ones in the `Pick`.
|
||||
To fix this error, only specify properties from the `NavigationExtras` which are
|
||||
actually used in the respective function calls or use a type assertion
|
||||
on the object or variable: `as NavigationExtras`.
|
||||
* **router:** This commit changes the default value of
|
||||
`relativeLinkResolution` from `'legacy'` to `'default'`. If your
|
||||
application previously used the default by not specifying a value in the
|
||||
`ExtraOptions` and uses relative links when navigating from children of
|
||||
empty path routes, you will need to update your `RouterModule` to
|
||||
specifically specify `'legacy'` for `relativeLinkResolution`.
|
||||
See https://angular.io/api/router/ExtraOptions#relativeLinkResolution
|
||||
for more details.
|
||||
|
||||
|
||||
|
||||
<a name="10.1.4"></a>
|
||||
## 10.1.4 (2020-09-30)
|
||||
|
||||
@@ -221,38 +299,6 @@ for more details.
|
||||
|
||||
|
||||
|
||||
<a name="11.0.0-next.3"></a>
|
||||
# 11.0.0-next.3 (2020-09-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **common:** add `params` and `reportProgress` options to `HttpClient.put()` overload ([#37873](https://github.com/angular/angular/issues/37873)) ([dd8d8c8](https://github.com/angular/angular/commit/dd8d8c8)), closes [#23600](https://github.com/angular/angular/issues/23600)
|
||||
* **compiler-cli:** generate `let` statements in ES2015+ mode ([#38775](https://github.com/angular/angular/issues/38775)) ([123bff7](https://github.com/angular/angular/commit/123bff7))
|
||||
* **core:** ensure TestBed is not instantiated before override provider ([#38717](https://github.com/angular/angular/issues/38717)) ([c8f056b](https://github.com/angular/angular/commit/c8f056b))
|
||||
* **forms:** type NG_VALUE_ACCESSOR injection token as array ([#29723](https://github.com/angular/angular/issues/29723)) ([2b1b718](https://github.com/angular/angular/commit/2b1b718)), closes [#29351](https://github.com/angular/angular/issues/29351)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **common:** Add ISO week-numbering year formats support to formatDate ([#38828](https://github.com/angular/angular/issues/38828)) ([984ed39](https://github.com/angular/angular/commit/984ed39))
|
||||
* **compiler:** Parse and recover on incomplete opening HTML tags ([#38681](https://github.com/angular/angular/issues/38681)) ([6ae3b68](https://github.com/angular/angular/commit/6ae3b68)), closes [#38596](https://github.com/angular/angular/issues/38596)
|
||||
* **router:** add migration to update calls to navigateByUrl and createUrlTree with invalid parameters ([#38825](https://github.com/angular/angular/issues/38825)) ([7849fdd](https://github.com/angular/angular/commit/7849fdd)), closes [#38227](https://github.com/angular/angular/issues/38227)
|
||||
* **service-worker:** add the option to prefer network for navigation requests ([#38565](https://github.com/angular/angular/issues/38565)) ([a206852](https://github.com/angular/angular/commit/a206852)), closes [#38194](https://github.com/angular/angular/issues/38194)
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **core:** If you call `TestBed.overrideProvider` after TestBed initialization, provider overrides are not applied. This
|
||||
behavior is consistent with other override methods (such as `TestBed.overrideDirective`, etc) but they
|
||||
throw an error to indicate that, when the check was missing in the `TestBed.overrideProvider` function.
|
||||
Now calling `TestBed.overrideProvider` after TestBed initialization also triggers an
|
||||
error, thus there is a chance that some tests (where `TestBed.overrideProvider` is
|
||||
called after TestBed initialization) will start to fail and require updates to move `TestBed.overrideProvider` calls
|
||||
before TestBed initialization is completed.
|
||||
|
||||
|
||||
|
||||
<a name="10.1.3"></a>
|
||||
## 10.1.3 (2020-09-23)
|
||||
|
||||
@@ -269,56 +315,6 @@ before TestBed initialization is completed.
|
||||
|
||||
|
||||
|
||||
<a name="11.0.0-next.2"></a>
|
||||
# 11.0.0-next.2 (2020-09-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **common:** do not round up fractions of a millisecond in `DatePipe` ([#38009](https://github.com/angular/angular/issues/38009)) ([26f2820](https://github.com/angular/angular/commit/26f2820)), closes [/www.ecma-international.org/ecma-262/5.1/#sec-15](https://github.com//www.ecma-international.org/ecma-262/5.1//issues/sec-15) [#37989](https://github.com/angular/angular/issues/37989)
|
||||
* **common:** mark locale data arrays as readonly ([#30397](https://github.com/angular/angular/issues/30397)) ([6acea54](https://github.com/angular/angular/commit/6acea54)), closes [#27003](https://github.com/angular/angular/issues/27003)
|
||||
* **compiler:** source span for microsyntax text att should be key span ([#38766](https://github.com/angular/angular/issues/38766)) ([8f349b2](https://github.com/angular/angular/commit/8f349b2))
|
||||
* **router:** Fix arguments order for call to shouldReuseRoute ([#26949](https://github.com/angular/angular/issues/26949)) ([3817e5f](https://github.com/angular/angular/commit/3817e5f)), closes [#16192](https://github.com/angular/angular/issues/16192) [#16192](https://github.com/angular/angular/issues/16192)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **compiler-cli:** `TemplateTypeChecker` operation to get `Symbol` from a template node ([#38618](https://github.com/angular/angular/issues/38618)) ([c4556db](https://github.com/angular/angular/commit/c4556db))
|
||||
* **compiler-cli:** Add ability to get `Symbol` of `Template`s and `Element`s in component template ([#38618](https://github.com/angular/angular/issues/38618)) ([cf2e8b9](https://github.com/angular/angular/commit/cf2e8b9))
|
||||
* **compiler-cli:** Add ability to get `Symbol` of AST expression in component template ([#38618](https://github.com/angular/angular/issues/38618)) ([f56ece4](https://github.com/angular/angular/commit/f56ece4))
|
||||
* **compiler-cli:** add ability to get symbol of reference or variable ([#38618](https://github.com/angular/angular/issues/38618)) ([19598b4](https://github.com/angular/angular/commit/19598b4))
|
||||
* **compiler-cli:** define interfaces to be used for TemplateTypeChecker ([#38618](https://github.com/angular/angular/issues/38618)) ([9e77bd3](https://github.com/angular/angular/commit/9e77bd3))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **compiler-cli:** only emit directive/pipe references that are used ([#38539](https://github.com/angular/angular/issues/38539)) ([077f516](https://github.com/angular/angular/commit/077f516))
|
||||
* **compiler-cli:** optimize computation of type-check scope information ([#38539](https://github.com/angular/angular/issues/38539)) ([297c060](https://github.com/angular/angular/commit/297c060))
|
||||
* **router:** use `ngDevMode` to tree-shake error messages in router ([#38674](https://github.com/angular/angular/issues/38674)) ([db21c4f](https://github.com/angular/angular/commit/db21c4f))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **router:** This change corrects the argument order when calling
|
||||
RouteReuseStrategy#shouldReuseRoute. Previously, when evaluating child
|
||||
routes, they would be called with the future and current arguments would
|
||||
be swapped. If your RouteReuseStrategy relies specifically on only the future
|
||||
or current snapshot state, you may need to update the shouldReuseRoute
|
||||
implementation's use of "future" and "current" ActivateRouteSnapshots.
|
||||
* **common:** The locale data API has been marked as returning readonly arrays, rather
|
||||
than mutable arrays, since these arrays are shared across calls to the
|
||||
API. If you were mutating them (e.g. calling `sort()`, `push()`, `splice()`, etc)
|
||||
then your code will not longer compile. If you need to mutate the array, you
|
||||
should now take a copy (e.g. by calling `slice()`) and mutate the copy.
|
||||
* **common:** When passing a date-time formatted string to the `DatePipe` in a format that contains
|
||||
fractions of a millisecond, the milliseconds will now always be rounded down rather than
|
||||
to the nearest millisecond.
|
||||
|
||||
Most applications will not be affected by this change. If this is not the desired behaviour
|
||||
then consider pre-processing the string to round the millisecond part before passing
|
||||
it to the `DatePipe`.
|
||||
|
||||
|
||||
|
||||
<a name="10.1.2"></a>
|
||||
## 10.1.2 (2020-09-16)
|
||||
@@ -342,24 +338,6 @@ it to the `DatePipe`.
|
||||
|
||||
|
||||
|
||||
<a name="11.0.0-next.1"></a>
|
||||
# 11.0.0-next.1 (2020-09-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler-cli:** compute source-mappings for localized strings ([#38645](https://github.com/angular/angular/issues/38645)) ([7e0b3fd](https://github.com/angular/angular/commit/7e0b3fd)), closes [#38588](https://github.com/angular/angular/issues/38588)
|
||||
* **core:** remove CollectionChangeRecord symbol ([#38668](https://github.com/angular/angular/issues/38668)) ([fdea180](https://github.com/angular/angular/commit/fdea180))
|
||||
* **router:** support lazy loading for empty path named outlets ([#38379](https://github.com/angular/angular/issues/38379)) ([926ffcd](https://github.com/angular/angular/commit/926ffcd)), closes [#12842](https://github.com/angular/angular/issues/12842)
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **core:** CollectionChangeRecord has been removed, use IterableChangeRecord
|
||||
instead
|
||||
|
||||
|
||||
|
||||
<a name="10.1.1"></a>
|
||||
## 10.1.1 (2020-09-09)
|
||||
|
||||
@@ -385,31 +363,6 @@ instead
|
||||
|
||||
|
||||
|
||||
<a name="11.0.0-next.0"></a>
|
||||
# 11.0.0-next.0 (2020-09-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **forms:** ensure to emit `statusChanges` on subsequent value update/validations ([#38354](https://github.com/angular/angular/issues/38354)) ([d9fea85](https://github.com/angular/angular/commit/d9fea85)), closes [#20424](https://github.com/angular/angular/issues/20424) [#14542](https://github.com/angular/angular/issues/14542)
|
||||
* **service-worker:** fix condition to check for a cache-busted request ([#36847](https://github.com/angular/angular/issues/36847)) ([5be4edf](https://github.com/angular/angular/commit/5be4edf))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **service-worker:** add `UnrecoverableStateError` ([#36847](https://github.com/angular/angular/issues/36847)) ([036a2fa](https://github.com/angular/angular/commit/036a2fa)), closes [#36539](https://github.com/angular/angular/issues/36539)
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **forms:** Previously if FormControl, FormGroup and FormArray class instances had async validators
|
||||
defined at initialization time, the status change event was not emitted once async validator
|
||||
completed. After this change the status event is emitted into the `statusChanges` observable.
|
||||
If your code relies on the old behavior, you can filter/ignore this additional status change
|
||||
event.
|
||||
|
||||
|
||||
|
||||
<a name="10.1.0"></a>
|
||||
# 10.1.0 (2020-09-02)
|
||||
|
||||
|
||||
+9
-9
@@ -209,7 +209,7 @@ To ensure consistency throughout the source code, keep these rules in mind as yo
|
||||
|
||||
## <a name="commit"></a> Commit Message Format
|
||||
|
||||
*This specification is inspired and supersedes the [AngularJS commit message format][commit-message-format].*
|
||||
*This specification is inspired by and supersedes the [AngularJS commit message format][commit-message-format].*
|
||||
|
||||
We have very precise rules over how our Git commit messages must be formatted.
|
||||
This format leads to **easier to read commit history**.
|
||||
@@ -227,15 +227,15 @@ Each commit message consists of a **header**, a **body**, and a **footer**.
|
||||
|
||||
The `header` is mandatory and must conform to the [Commit Message Header](#commit-header) format.
|
||||
|
||||
The `body` is mandatory for all commits except for those of scope "docs".
|
||||
When the body is required it must be at least 20 characters long.
|
||||
The `body` is mandatory for all commits except for those of type "docs".
|
||||
When the body is present it must be at least 20 characters long and must conform to the [Commit Message Body](#commit-body) format.
|
||||
|
||||
The `footer` is optional.
|
||||
The `footer` is optional. The [Commit Message Footer](#commit-footer) format describes what the footer is used for and the structure it must have.
|
||||
|
||||
Any line of the commit message cannot be longer than 100 characters.
|
||||
|
||||
|
||||
#### <a href="commit-header"></a>Commit Message Header
|
||||
#### <a name="commit-header"></a>Commit Message Header
|
||||
|
||||
```
|
||||
<type>(<scope>): <short summary>
|
||||
@@ -248,7 +248,7 @@ Any line of the commit message cannot be longer than 100 characters.
|
||||
│ upgrade|zone.js|packaging|changelog|dev-infra|docs-infra|migrations|
|
||||
│ ngcc|ve
|
||||
│
|
||||
└─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
|
||||
└─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|test
|
||||
```
|
||||
|
||||
The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is optional.
|
||||
@@ -309,7 +309,7 @@ There are currently a few exceptions to the "use package name" rule:
|
||||
|
||||
* `ve`: used for changes specific to ViewEngine (legacy compiler/renderer).
|
||||
|
||||
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all packages (e.g. `style: add missing semicolons`) and for docs changes that are not related to a specific package (e.g. `docs: fix typo in tutorial`).
|
||||
* none/empty string: useful for `test` and `refactor` changes that are done across all packages (e.g. `test: add missing unit tests`) and for docs changes that are not related to a specific package (e.g. `docs: fix typo in tutorial`).
|
||||
|
||||
|
||||
##### Summary
|
||||
@@ -321,7 +321,7 @@ Use the summary field to provide a succinct description of the change:
|
||||
* no dot (.) at the end
|
||||
|
||||
|
||||
#### Commit Message Body
|
||||
#### <a name="commit-body"></a>Commit Message Body
|
||||
|
||||
Just as in the summary, use the imperative, present tense: "fix" not "fixed" nor "fixes".
|
||||
|
||||
@@ -329,7 +329,7 @@ Explain the motivation for the change in the commit message body. This commit me
|
||||
You can include a comparison of the previous behavior with the new behavior in order to illustrate the impact of the change.
|
||||
|
||||
|
||||
#### Commit Message Footer
|
||||
#### <a name="commit-footer"></a>Commit Message Footer
|
||||
|
||||
The footer can contain information about breaking changes and is also the place to reference GitHub issues, Jira tickets, and other PRs that this commit closes or is related to.
|
||||
|
||||
|
||||
@@ -1,27 +1,151 @@
|
||||
[](https://circleci.com/gh/angular/workflows/angular/tree/master)
|
||||
[](https://discord.gg/angular)
|
||||
[](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://www.npmjs.com/@angular/core)
|
||||
<h1 align="center">Angular - One framework. Mobile & desktop.</h1>
|
||||
|
||||
<p align="center">
|
||||
<img src="aio/src/assets/images/logos/angular/angular.png" alt="angular-logo" width="120px" height="120px"/>
|
||||
<br>
|
||||
<i>Angular is a development platform for building mobile and desktop web applications
|
||||
<br> using Typescript/JavaScript and other languages.</i>
|
||||
<br>
|
||||
</p>
|
||||
|
||||
# Angular
|
||||
<p align="center">
|
||||
<a href="https://www.angular.io"><strong>www.angular.io</strong></a>
|
||||
<br>
|
||||
</p>
|
||||
|
||||
Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages.
|
||||
<p align="center">
|
||||
<a href="CONTRIBUTING.md">Contributing Guidelines</a>
|
||||
·
|
||||
<a href="https://github.com/angular/angular/issues">Submit an Issue</a>
|
||||
·
|
||||
<a href="https://blog.angular.io/">Blog</a>
|
||||
<br>
|
||||
<br>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://circleci.com/gh/angular/workflows/angular/tree/master">
|
||||
<img src="https://img.shields.io/circleci/build/github/angular/angular/master.svg?logo=circleci&logoColor=fff&label=CircleCI" alt="CI status" />
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/@angular/core">
|
||||
<img src="https://img.shields.io/npm/v/@angular/core.svg?logo=npm&logoColor=fff&label=NPM+package&color=limegreen" alt="Angular on npm" />
|
||||
</a>
|
||||
<a href="https://discord.gg/angular">
|
||||
<img src="https://img.shields.io/discord/463752820026376202.svg?logo=discord&logoColor=fff&label=Discord&color=7389d8" alt="Discord conversation" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
## Documentation
|
||||
|
||||
Get started with Angular, learn the fundamentals and explore advanced topics on our documentation website.
|
||||
|
||||
- [Getting Started][quickstart]
|
||||
- [Architecture][architecture]
|
||||
- [Components and Templates][componentstemplates]
|
||||
- [Forms][forms]
|
||||
- [API][api]
|
||||
|
||||
### Advanced
|
||||
|
||||
- [Angular Elements][angularelements]
|
||||
- [Server Side Rendering][ssr]
|
||||
- [Schematics][schematics]
|
||||
- [Lazy Loading][lazyloading]
|
||||
|
||||
## Development Setup
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Install [Node.js] which includes [Node Package Manager][npm]
|
||||
|
||||
### Setting Up a Project
|
||||
|
||||
Install the Angular CLI globally:
|
||||
|
||||
```
|
||||
npm install -g @angular/cli
|
||||
```
|
||||
|
||||
Create workspace:
|
||||
|
||||
```
|
||||
ng new [PROJECT NAME]
|
||||
```
|
||||
|
||||
Run the application:
|
||||
|
||||
```
|
||||
cd [PROJECT NAME]
|
||||
ng serve
|
||||
```
|
||||
|
||||
## Quickstart
|
||||
|
||||
[Get started in 5 minutes][quickstart].
|
||||
|
||||
## Ecosystem
|
||||
|
||||
<p>
|
||||
<img src="/docs/images/angular-ecosystem-logos.png" alt="angular ecosystem logos" width="500px" height="auto">
|
||||
</p>
|
||||
|
||||
- [Angular Command Line (CLI)][cli]
|
||||
- [Angular Material][angularmaterial]
|
||||
|
||||
## Changelog
|
||||
|
||||
[Learn about the latest improvements][changelog].
|
||||
|
||||
## Want to help?
|
||||
## Upgrading
|
||||
|
||||
Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our
|
||||
guidelines for [contributing][contributing] and then check out one of our issues in the [hotlist: community-help](https://github.com/angular/angular/labels/hotlist%3A%20community-help).
|
||||
Check out our [upgrade guide](https://update.angular.io/) to find out the best way to upgrade your project.
|
||||
|
||||
[contributing]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md
|
||||
## Contributing
|
||||
|
||||
### Contributing Guidelines
|
||||
|
||||
Read through our [contributing guidelines][contributing] to learn about our submission process, coding rules and more.
|
||||
|
||||
### Want to Help?
|
||||
|
||||
Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our guidelines for [contributing][contributing] and then check out one of our issues in the [hotlist: community-help](https://github.com/angular/angular/labels/hotlist%3A%20community-help).
|
||||
|
||||
### Code of Conduct
|
||||
|
||||
Help us keep Angular open and inclusive. Please read and follow our [Code of Conduct][codeofconduct].
|
||||
|
||||
## Community
|
||||
|
||||
Join the conversation and help the community.
|
||||
|
||||
- [Twitter][twitter]
|
||||
- [Gitter][gitter]
|
||||
- Find a Local [Meetup][meetup]
|
||||
|
||||
[](https://www.github.com/angular/angular)
|
||||
|
||||
**Love Angular? Give our repo a star :star: :arrow_up:.**
|
||||
|
||||
[contributing]: CONTRIBUTING.md
|
||||
[quickstart]: https://angular.io/start
|
||||
[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md
|
||||
[changelog]: CHANGELOG.md
|
||||
[ng]: https://angular.io
|
||||
[documentation]: https://angular.io/docs
|
||||
[angularmaterial]: https://material.angular.io/
|
||||
[cli]: https://cli.angular.io/
|
||||
[architecture]: https://angular.io/guide/architecture
|
||||
[componentstemplates]: https://angular.io/guide/displaying-data
|
||||
[forms]: https://angular.io/guide/forms-overview
|
||||
[api]: https://angular.io/api
|
||||
[angularelements]: https://angular.io/guide/elements
|
||||
[ssr]: https://angular.io/guide/universal
|
||||
[schematics]: https://angular.io/guide/schematics
|
||||
[lazyloading]: https://angular.io/guide/lazy-loading-ngmodules
|
||||
[node.js]: https://nodejs.org/
|
||||
[npm]: https://www.npmjs.com/get-npm
|
||||
[codeofconduct]: CODE_OF_CONDUCT.md
|
||||
[twitter]: https://www.twitter.com/angular
|
||||
[gitter]: https://gitter.im/angular/angular
|
||||
[meetup]: https://www.meetup.com/find/?keywords=angular"
|
||||
|
||||
@@ -81,14 +81,14 @@ rbe_autoconfig(
|
||||
# Need to specify a base container digest in order to ensure that we can use the checked-in
|
||||
# platform configurations for the "ubuntu16_04" image. Otherwise the autoconfig rule would
|
||||
# need to pull the image and run it in order determine the toolchain configuration. See:
|
||||
# https://github.com/bazelbuild/bazel-toolchains/blob/3.5.1/configs/ubuntu16_04_clang/versions.bzl
|
||||
# https://github.com/bazelbuild/bazel-toolchains/blob/3.6.0/configs/ubuntu16_04_clang/versions.bzl
|
||||
base_container_digest = "sha256:f6568d8168b14aafd1b707019927a63c2d37113a03bcee188218f99bd0327ea1",
|
||||
# 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:f743114235a43355bf8324e2ba0fa6a597236fe06f7bc99aaa9ac703631c306b",
|
||||
digest = "sha256:dddaaddbe07a61c2517f9b08c4977fc23c4968fcb6c0b8b5971e955d2de7a961",
|
||||
env = clang_env(),
|
||||
registry = "marketplace.gcr.io",
|
||||
# We can't use the default "ubuntu16_04" RBE image provided by the autoconfig because we need
|
||||
|
||||
+2
-1
@@ -36,8 +36,9 @@ Here are the most important tasks you might need to use:
|
||||
|
||||
* `yarn boilerplate:add` - generate all the boilerplate code for the examples, so that they can be run locally.
|
||||
* `yarn boilerplate:add:viewengine` - same as `boilerplate:add` but also turns on `ViewEngine` (pre-Ivy) mode.
|
||||
|
||||
* `yarn boilerplate:remove` - remove all the boilerplate code that was added via `yarn boilerplate:add`.
|
||||
* `yarn create-example` - create a new example directory containing initial source files.
|
||||
|
||||
* `yarn generate-stackblitz` - generate the stackblitz files that are used by the `live-example` tags in the docs.
|
||||
* `yarn generate-zips` - generate the zip files from the examples. Zip available via the `live-example` tags in the docs.
|
||||
|
||||
|
||||
@@ -6,4 +6,4 @@ TODO (gkalpak): Add docs. Mention:
|
||||
Relevant files: `aio/aio-builds-setup/scripts/test.sh`
|
||||
- Deploying from CI.
|
||||
Relevant files: `.circleci/config.yml`, `scripts/ci/deploy.sh`, `aio/scripts/build-artifacts.sh`,
|
||||
`aio/scripts/deploy-to-firebase.sh`
|
||||
`aio/scripts/deploy-to-firebase.js`
|
||||
|
||||
+12
-1
@@ -37,7 +37,6 @@
|
||||
"outputHashing": "all",
|
||||
"sourceMap": true,
|
||||
"statsJson": true,
|
||||
"extractCss": true,
|
||||
"extractLicenses": true,
|
||||
"namedChunks": true,
|
||||
"vendorChunk": false,
|
||||
@@ -81,6 +80,15 @@
|
||||
],
|
||||
"serviceWorker": true
|
||||
},
|
||||
"rc": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.rc.ts"
|
||||
}
|
||||
],
|
||||
"serviceWorker": true
|
||||
},
|
||||
"stable": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
@@ -116,6 +124,9 @@
|
||||
"next": {
|
||||
"browserTarget": "site:build:next"
|
||||
},
|
||||
"rc": {
|
||||
"browserTarget": "site:build:rc"
|
||||
},
|
||||
"stable": {
|
||||
"browserTarget": "site:build:stable"
|
||||
},
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
**/karma-test-shim.js
|
||||
**/browser-test-shim.js
|
||||
**/node_modules
|
||||
**/yarn.lock
|
||||
**/package-lock.json
|
||||
|
||||
# built files
|
||||
*.map
|
||||
|
||||
@@ -12,7 +12,7 @@ describe('Accessibility example e2e tests', () => {
|
||||
|
||||
it('should take a number and change progressbar width', () => {
|
||||
element(by.css('input')).sendKeys('16');
|
||||
expect(element(by.css('input')).getAttribute('value')).toEqual('016');
|
||||
expect(element(by.css('input')).getAttribute('value')).toEqual('16');
|
||||
expect(element(by.css('app-example-progressbar div')).getCssValue('width')).toBe('48px');
|
||||
});
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<label>
|
||||
Enter an example progress value
|
||||
<input type="number" min="0" max="100"
|
||||
[value]="progress" (input)="progress = $event.target.value">
|
||||
[value]="progress" (input)="setProgress($event)">
|
||||
</label>
|
||||
|
||||
<!-- The user of the progressbar sets an aria-label to communicate what the progress means. -->
|
||||
|
||||
@@ -7,4 +7,8 @@ import { Component } from '@angular/core';
|
||||
})
|
||||
export class AppComponent {
|
||||
progress = 0;
|
||||
|
||||
setProgress($event: Event) {
|
||||
this.progress = +($event.target as HTMLInputElement).value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
<h2>Attribute binding</h2>
|
||||
<!-- #docregion attrib-binding-colspan -->
|
||||
<table border=1>
|
||||
<!-- #docregion colspan -->
|
||||
<!-- expression calculates colspan=2 -->
|
||||
<tr><td [attr.colspan]="1 + 1">One-Two</td></tr>
|
||||
<!-- #enddocregion colspan -->
|
||||
|
||||
<!-- ERROR: There is no `colspan` property to set!
|
||||
<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
|
||||
@@ -32,31 +34,31 @@
|
||||
<!-- #docregion basic-specificity -->
|
||||
<h3>Basic specificity</h3>
|
||||
|
||||
<!-- The `class.special` binding will override any value for the `special` class in `classExpr`. -->
|
||||
<div [class.special]="isSpecial" [class]="classExpr">Some text.</div>
|
||||
<!-- The `class.special` binding overrides any value for the `special` class in `classExpression`. -->
|
||||
<div [class.special]="isSpecial" [class]="classExpression">Some text.</div>
|
||||
|
||||
<!-- The `style.color` binding will override any value for the `color` property in `styleExpr`. -->
|
||||
<div [style.color]="color" [style]="styleExpr">Some text.</div>
|
||||
<!-- The `style.color` binding overrides any value for the `color` property in `styleExpression`. -->
|
||||
<div [style.color]="color" [style]="styleExpression">Some text.</div>
|
||||
<!-- #enddocregion basic-specificity -->
|
||||
|
||||
<!-- #docregion source-specificity -->
|
||||
<h3>Source specificity</h3>
|
||||
|
||||
<!-- The `class.special` template binding will override any host binding to the `special` class set by `dirWithClassBinding` or `comp-with-host-binding`.-->
|
||||
<!-- The `class.special` template binding overrides any host binding to the `special` class set by `dirWithClassBinding` or `comp-with-host-binding`.-->
|
||||
<comp-with-host-binding [class.special]="isSpecial" dirWithClassBinding>Some text.</comp-with-host-binding>
|
||||
|
||||
<!-- The `style.color` template binding will override any host binding to the `color` property set by `dirWithStyleBinding` or `comp-with-host-binding`. -->
|
||||
<!-- The `style.color` template binding overrides any host binding to the `color` property set by `dirWithStyleBinding` or `comp-with-host-binding`. -->
|
||||
<comp-with-host-binding [style.color]="color" dirWithStyleBinding>Some text.</comp-with-host-binding>
|
||||
<!-- #enddocregion source-specificity -->
|
||||
|
||||
<!-- #docregion dynamic-priority -->
|
||||
<h3>Dynamic vs static</h3>
|
||||
|
||||
<!-- If `classExpr` has a value for the `special` class, this value will override the `class="special"` below -->
|
||||
<div class="special" [class]="classExpr">Some text.</div>
|
||||
<!-- If `classExpression` has a value for the `special` class, this value overrides the `class="special"` below -->
|
||||
<div class="special" [class]="classExpression">Some text.</div>
|
||||
|
||||
<!-- If `styleExpr` has a value for the `color` property, this value will override the `style="color: blue"` below -->
|
||||
<div style="color: blue" [style]="styleExpr">Some text.</div>
|
||||
<!-- If `styleExpression` has a value for the `color` property, this value overrides the `style="color: blue"` below -->
|
||||
<div style="color: blue" [style]="styleExpression">Some text.</div>
|
||||
|
||||
<!-- #enddocregion dynamic-priority -->
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ export class AppComponent {
|
||||
actionName = 'Go for it';
|
||||
isSpecial = true;
|
||||
canSave = true;
|
||||
classExpr = 'special clearance';
|
||||
styleExpr = 'color: red';
|
||||
classExpression = 'special clearance';
|
||||
styleExpression = 'color: red';
|
||||
color = 'blue';
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ export class CompWithHostBindingComponent {
|
||||
@HostBinding('style.color')
|
||||
color = 'green';
|
||||
|
||||
// #docregion hostbinding
|
||||
@HostBinding('style.width')
|
||||
width = '200px';
|
||||
// #enddocregion hostbinding
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!-- #docregion v2, -->
|
||||
<h1>My First Attribute Directive</h1>
|
||||
|
||||
<h4>Pick a highlight color</h4>
|
||||
<h2>Pick a highlight color</h2>
|
||||
<div>
|
||||
<input type="radio" name="colors" (click)="color='lightgreen'">Green
|
||||
<input type="radio" name="colors" (click)="color='yellow'">Yellow
|
||||
@@ -17,8 +17,22 @@
|
||||
</p>
|
||||
<!-- #enddocregion defaultColor, -->
|
||||
|
||||
<hr>
|
||||
<p><i>Mouse over the following lines to see fixed highlights</i></p>
|
||||
<hr />
|
||||
<h2>Mouse over the following lines to see fixed highlights</h2>
|
||||
|
||||
<p [appHighlight]="'yellow'">Highlighted in yellow</p>
|
||||
<p appHighlight="orange">Highlighted in orange</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<h2>ngNonBindable</h2>
|
||||
<!-- #docregion ngNonBindable -->
|
||||
<p>Use ngNonBindable to stop evaluation.</p>
|
||||
<p ngNonBindable>This should not evaluate: {{ 1 + 1 }}</p>
|
||||
<!-- #enddocregion ngNonBindable -->
|
||||
|
||||
<!-- #docregion ngNonBindable-with-directive -->
|
||||
<h3>ngNonBindable with a directive</h3>
|
||||
<div ngNonBindable [appHighlight]="'yellow'">This should not evaluate: {{ 1 +1 }}, but will highlight yellow.
|
||||
</div>
|
||||
<!-- #enddocregion ngNonBindable-with-directive -->
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* tslint:disable:forin */
|
||||
// #docregion
|
||||
import { Component, Input, OnChanges, SimpleChange } from '@angular/core';
|
||||
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-version-child',
|
||||
@@ -17,7 +17,7 @@ export class VersionChildComponent implements OnChanges {
|
||||
@Input() minor: number;
|
||||
changeLog: string[] = [];
|
||||
|
||||
ngOnChanges(changes: {[propKey: string]: SimpleChange}) {
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
const log: string[] = [];
|
||||
for (const propName in changes) {
|
||||
const changedProp = changes[propName];
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { browser, element, by } from 'protractor';
|
||||
|
||||
describe('Component Overview', () => {
|
||||
|
||||
beforeAll(() => {
|
||||
browser.get('');
|
||||
});
|
||||
|
||||
it('should display component overview works ', () => {
|
||||
expect(element(by.css('p')).getText()).toEqual('component-overview works!');
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
<app-component-overview></app-component-overview>
|
||||
@@ -0,0 +1,31 @@
|
||||
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', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
});
|
||||
|
||||
it(`should have as title 'component-overview'`, () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app.title).toEqual('component-overview');
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement;
|
||||
expect(compiled.querySelector('.content span').textContent).toContain('component-overview app is running!');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'component-overview';
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { ComponentOverviewComponent } from './component-overview/component-overview.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
ComponentOverviewComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// #docplaster
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
// #docregion template
|
||||
@Component({
|
||||
selector: 'app-component-overview',
|
||||
template: '<h1>Hello World!</h1>',
|
||||
})
|
||||
// #enddocregion template
|
||||
|
||||
export class ComponentOverviewComponent {
|
||||
|
||||
}
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// #docplaster
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
// #docregion templatebacktick
|
||||
@Component({
|
||||
selector: 'app-component-overview',
|
||||
template: `<h1>Hello World!</h1>
|
||||
<p>This template definition spans
|
||||
multiple lines.</p>`
|
||||
})
|
||||
// #enddocregion templatebacktick
|
||||
|
||||
export class ComponentOverviewComponent {
|
||||
|
||||
}
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// #docplaster
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
// #docregion styles
|
||||
@Component({
|
||||
selector: 'app-component-overview',
|
||||
template: '<h1>Hello World!</h1>',
|
||||
styles: ['h1 { font-weight: normal; }']
|
||||
})
|
||||
// #enddocregion styles
|
||||
|
||||
export class ComponentOverviewComponent {
|
||||
|
||||
}
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
<p>component-overview works!</p>
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ComponentOverviewComponent } from './component-overview.component';
|
||||
|
||||
describe('ComponentOverviewComponent', () => {
|
||||
let component: ComponentOverviewComponent;
|
||||
let fixture: ComponentFixture<ComponentOverviewComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ComponentOverviewComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ComponentOverviewComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// #docplaster
|
||||
// #docregion import
|
||||
import { Component } from '@angular/core';
|
||||
// #enddocregion import
|
||||
|
||||
// #docregion decorator, decorator-skeleton, selector, templateUrl
|
||||
@Component({
|
||||
// #enddocregion decorator-skeleton
|
||||
selector: 'app-component-overview',
|
||||
// #enddocregion selector
|
||||
templateUrl: './component-overview.component.html',
|
||||
// #enddocregion templateUrl
|
||||
styleUrls: ['./component-overview.component.css']
|
||||
// #docregion decorator-skeleton, selector, templateUrl
|
||||
})
|
||||
// #enddocregion decorator, decorator-skeleton, selector, templateUrl
|
||||
|
||||
// #docregion class
|
||||
export class ComponentOverviewComponent {
|
||||
|
||||
}
|
||||
// #enddocregion class
|
||||
@@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>ComponentOverview</title>
|
||||
<base href="/">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,12 @@
|
||||
import { enableProdMode } from '@angular/core';
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
import { AppModule } from './app/app.module';
|
||||
import { environment } from './environments/environment';
|
||||
|
||||
if (environment.production) {
|
||||
enableProdMode();
|
||||
}
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule)
|
||||
.catch(err => console.error(err));
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"description": "Component Overview",
|
||||
"files":[
|
||||
"!**/*.d.ts",
|
||||
"!**/*.js"
|
||||
],
|
||||
"tags":["overview", "component"]
|
||||
}
|
||||
@@ -7,9 +7,15 @@ import { Component } from '@angular/core';
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
export class AppComponent {
|
||||
// #docregion item-image
|
||||
itemImageUrl = '../assets/phone.png';
|
||||
// #enddocregion item-image
|
||||
// #docregion boolean
|
||||
isUnchanged = true;
|
||||
// #enddocregion boolean
|
||||
// #docregion directive-property
|
||||
classes = 'special';
|
||||
// #enddocregion directive-property
|
||||
// #docregion parent-data-type
|
||||
parentItem = 'lamp';
|
||||
// #enddocregion parent-data-type
|
||||
|
||||
@@ -23,13 +23,13 @@ describe('retry-on-error', () => {
|
||||
docRegionDefault(mockConsole, ajax);
|
||||
expect(mockConsole.log.calls.allArgs()).toEqual([
|
||||
['Subscribed to AJAX'],
|
||||
['Error occured.'],
|
||||
['Error occurred.'],
|
||||
['Subscribed to AJAX'],
|
||||
['Error occured.'],
|
||||
['Error occurred.'],
|
||||
['Subscribed to AJAX'],
|
||||
['Error occured.'],
|
||||
['Error occurred.'],
|
||||
['Subscribed to AJAX'],
|
||||
['Error occured.'],
|
||||
['Error occurred.'],
|
||||
['data: ', []],
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -17,7 +17,7 @@ export function docRegionDefault(console, ajax) {
|
||||
const apiData = ajax('/api/data').pipe(
|
||||
map((res: any) => {
|
||||
if (!res.response) {
|
||||
console.log('Error occured.');
|
||||
console.log('Error occurred.');
|
||||
throw new Error('Value expected!');
|
||||
}
|
||||
return res.response;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
h3 {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
pre, .wrapper {
|
||||
background-color: rgb(240, 250, 250);
|
||||
padding: 1rem;
|
||||
border: 1px solid #444;
|
||||
}
|
||||
|
||||
input {
|
||||
margin: .5rem;
|
||||
padding: .5rem;
|
||||
}
|
||||
|
||||
@@ -39,8 +39,7 @@
|
||||
<h2>Reference variables, forms, and NgForm</h2>
|
||||
<!-- #docregion ngForm -->
|
||||
<form #itemForm="ngForm" (ngSubmit)="onSubmit(itemForm)">
|
||||
<label for="name"
|
||||
>Name <input class="form-control" name="name" ngModel required />
|
||||
<label for="name">Name <input class="form-control" name="name" ngModel required />
|
||||
</label>
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
@@ -53,3 +52,60 @@
|
||||
|
||||
|
||||
<p>JSON: {{ itemForm.form.value | json }}</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<h2>Template Reference Variable Scope</h2>
|
||||
|
||||
<p>This section demonstrates in which situations you can access local template reference variables (<code>#ref</code>).</p>
|
||||
|
||||
<h3>Accessing in a child template</h3>
|
||||
<!-- Accessing a template reference variable from an inner template
|
||||
works as the context is inherited. Try changing the text in the
|
||||
input to see how it is immediately reflected through the template
|
||||
reference variable. -->
|
||||
|
||||
<div class="example">
|
||||
<!-- #docregion template-ref-vars-scope1 -->
|
||||
<input #ref1 type="text" [(ngModel)]="firstExample" />
|
||||
<span *ngIf="true">Value: {{ ref1.value }}</span>
|
||||
<!-- #enddocregion template-ref-vars-scope1 -->
|
||||
</div>
|
||||
|
||||
<!-- In this case there's a "hidden" ng-template around the
|
||||
span and the definition of the variable is outside of it. Thus, you access a template variable from a parent template (which is logical as the context is inherited). -->
|
||||
|
||||
<p>Here's the desugared syntax:</p>
|
||||
<pre><code [innerText]="desugared1"></code></pre>
|
||||
|
||||
<h3>Accessing from outside parent template. (Doesn't work.)</h3>
|
||||
<!-- Accessing the template reference variable from outside the parent template does
|
||||
not work. The value to the right is empty and changing the
|
||||
value of the input will have no effect. -->
|
||||
|
||||
<div class="example">
|
||||
<!-- #docregion template-ref-vars-scope2 -->
|
||||
<input *ngIf="true" #ref2 type="text" [(ngModel)]="secondExample" />
|
||||
<!-- <span>Value: {{ ref2?.value }}</span> -->
|
||||
<!-- uncomment the above and the app breaks -->
|
||||
<!-- #enddocregion template-ref-vars-scope2 -->
|
||||
</div>
|
||||
|
||||
<p>Here's the desugared syntax:</p>
|
||||
<pre><code [innerText]="desugared2"></code></pre>
|
||||
|
||||
<h3>*ngFor and template reference variable scope</h3>
|
||||
|
||||
<!-- The template is instantiated twice because *ngFor iterates
|
||||
over the two items in the array, so it's impossible to define what ref2 is referencing. -->
|
||||
|
||||
<pre><code [innerText]="ngForExample"></code></pre>
|
||||
|
||||
<h3>Accessing a on an <code>ng-template</code></h3>
|
||||
|
||||
See the console output to see that when you declare the variable on an <code>ng-template</code>, the variable refers to a <code>TemplateRef</code> instance, which represents the template.
|
||||
|
||||
<!-- #docregion template-ref -->
|
||||
<ng-template #ref3></ng-template>
|
||||
<button (click)="log(ref3)">Log type of #ref</button>
|
||||
<!-- #enddocregion template-ref -->
|
||||
|
||||
@@ -8,7 +8,38 @@ import { NgForm } from '@angular/forms';
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
export class AppComponent {
|
||||
@ViewChild('itemForm') form: NgForm;
|
||||
|
||||
public firstExample = 'Hello, World!';
|
||||
public secondExample = 'Hello, World!';
|
||||
|
||||
public ref2 = '';
|
||||
|
||||
public desugared1 = `
|
||||
<input #ref1 type="text" [(ngModel)]="firstExample" /><!-- A new template! -->
|
||||
<ng-template [ngIf]="true">
|
||||
<!-- … and it works -->
|
||||
<span>Value: {{ ref1.value }}</span>
|
||||
</ng-template>`
|
||||
;
|
||||
|
||||
public desugared2 = `<ng-template [ngIf]="true">
|
||||
<!-- The reference, ref2, is defined within a template -->
|
||||
<input #ref2 type="text" [(ngModel)]="secondExample" />
|
||||
</ng-template>
|
||||
|
||||
<!-- Attempting to access ref2 from outside the above template doesn't work. -->
|
||||
<span>Value: {{ ref2?.value }}</span>`;
|
||||
|
||||
public ngForExample = `<ng-container *ngFor="let i of [1,2]">
|
||||
<input #ref type="text" [value]="i" />
|
||||
</ng-container>
|
||||
|
||||
<!-- The template is instantiated twice because *ngFor iterates
|
||||
over the two items in the array, so it's impossible to define what ref2 is referencing.-->
|
||||
|
||||
{{ ref.value }}`;
|
||||
|
||||
@ViewChild('itemForm', { static: false }) form: NgForm;
|
||||
|
||||
get submitMessage() { return this._submitMessage; }
|
||||
private _submitMessage = ''; // tslint:disable-line: variable-name
|
||||
@@ -25,4 +56,7 @@ export class AppComponent {
|
||||
console.warn(`Faxing ${value} ...`);
|
||||
}
|
||||
|
||||
log(ref3: any) {
|
||||
console.warn(ref3.constructor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Component, ContentChildren, Directive, EventEmitter,
|
||||
HostBinding, HostListener,
|
||||
OnInit, OnChanges, OnDestroy,
|
||||
Pipe, PipeTransform,
|
||||
SimpleChange } from '@angular/core';
|
||||
SimpleChanges } from '@angular/core';
|
||||
|
||||
import { of } from 'rxjs';
|
||||
import { delay } from 'rxjs/operators';
|
||||
@@ -309,7 +309,7 @@ export class MyIfChildComponent implements OnInit, OnChanges, OnDestroy {
|
||||
this.changeLog.push('ngOnDestroy called');
|
||||
}
|
||||
|
||||
ngOnChanges(changes: {[propertyName: string]: SimpleChange}) {
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
for (const propName in changes) {
|
||||
this.ngOnChangesCounter += 1;
|
||||
const prop = changes[propName];
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<h1 id="two-way">Two-way Binding</h1>
|
||||
<div id="two-way-1">
|
||||
<!-- #docregion two-way-1 -->
|
||||
<!-- #docregion two-way-syntax -->
|
||||
<app-sizer [(size)]="fontSizePx"></app-sizer>
|
||||
<!-- #enddocregion two-way-syntax-->
|
||||
<div [style.font-size.px]="fontSizePx">Resizable Text</div>
|
||||
<!-- #enddocregion two-way-1 -->
|
||||
<label>FontSize (px): <input [(ngModel)]="fontSizePx"></label>
|
||||
|
||||
@@ -5,9 +5,9 @@ import { Component, Input, Output, EventEmitter } from '@angular/core';
|
||||
templateUrl: './sizer.component.html',
|
||||
styleUrls: ['./sizer.component.css']
|
||||
})
|
||||
// #docregion sizer-component
|
||||
export class SizerComponent {
|
||||
|
||||
|
||||
@Input() size: number | string;
|
||||
@Output() sizeChange = new EventEmitter<number>();
|
||||
|
||||
@@ -18,5 +18,5 @@ export class SizerComponent {
|
||||
this.size = Math.min(40, Math.max(8, +this.size + delta));
|
||||
this.sizeChange.emit(this.size);
|
||||
}
|
||||
|
||||
}
|
||||
// #enddocregion sizer-component
|
||||
|
||||
@@ -70,7 +70,7 @@ When authoring Angular components, you should re-use these native elements direc
|
||||
For example, instead of creating a custom element for a new variety of button, you can create a component that uses an attribute selector with a native `<button>` element.
|
||||
This most commonly applies to `<button>` and `<a>`, but can be used with many other types of element.
|
||||
|
||||
You can see examples of this pattern in Angular Material: [`MatButton`](https://github.com/angular/components/blob/master/src/material/button/button.ts#L66-L68), [`MatTabNav`](https://github.com/angular/components/blob/master/src/material/tabs/tab-nav-bar/tab-nav-bar.ts#L67), [`MatTable`](https://github.com/angular/components/blob/master/src/material/table/table.ts#L17).
|
||||
You can see examples of this pattern in Angular Material: [`MatButton`](https://github.com/angular/components/blob/50d3f29b6dc717b512dbd0234ce76f4ab7e9762a/src/material/button/button.ts#L67-L69), [`MatTabNav`](https://github.com/angular/components/blob/50d3f29b6dc717b512dbd0234ce76f4ab7e9762a/src/material/tabs/tab-nav-bar/tab-nav-bar.ts#L139), [`MatTable`](https://github.com/angular/components/blob/50d3f29b6dc717b512dbd0234ce76f4ab7e9762a/src/material/table/table.ts#L22).
|
||||
|
||||
### Using containers for native elements
|
||||
|
||||
|
||||
@@ -190,7 +190,7 @@ When you use the CLI command `ng new --strict`, it is set to `true` in the gener
|
||||
|
||||
### `strictTemplates`
|
||||
|
||||
When `true`, enables [strict template type checking](guide/template-typecheck#strict-mode) in Angular version 9. Strict mode is only available when using [Ivy](guide/ivy).
|
||||
When `true`, enables [strict template type checking](guide/template-typecheck#strict-mode). Strict mode is only available when using [Ivy](guide/ivy) (Angular version 9 and later).
|
||||
|
||||
Additional strictness flags allow you to enable and disable specific types of strict template type checking. See [troubleshooting template errors](guide/template-typecheck#troubleshooting-template-errors).
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ This example from the `HeroListComponent` template uses three of these forms.
|
||||
|
||||
<code-example path="architecture/src/app/hero-list.component.1.html" header="src/app/hero-list.component.html (binding)" region="binding"></code-example>
|
||||
|
||||
* The `{{hero.name}}` [*interpolation*](guide/displaying-data#interpolation)
|
||||
* The `{{hero.name}}` [*interpolation*](guide/interpolation)
|
||||
displays the component's `hero.name` property value within the `<li>` element.
|
||||
|
||||
* The `[hero]` [*property binding*](guide/property-binding) passes the value of
|
||||
@@ -166,8 +166,8 @@ The example template uses two built-in structural directives to add application
|
||||
|
||||
<code-example path="architecture/src/app/hero-list.component.1.html" header="src/app/hero-list.component.html (structural)" region="structural"></code-example>
|
||||
|
||||
* [`*ngFor`](guide/displaying-data#ngFor) is an iterative; it tells Angular to stamp out one `<li>` per hero in the `heroes` list.
|
||||
* [`*ngIf`](guide/displaying-data#ngIf) is a conditional; it includes the `HeroDetail` component only if a selected hero exists.
|
||||
* [`*ngFor`](guide/structural-directives#inside-ngfor) is an iterative; it tells Angular to stamp out one `<li>` per hero in the `heroes` list.
|
||||
* [`*ngIf`](guide/structural-directives#ngif-case-study) is a conditional; it includes the `HeroDetail` component only if a selected hero exists.
|
||||
|
||||
#### Attribute directives
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ about the features and tools that can help you develop and deliver Angular appli
|
||||
|
||||
## Application architecture
|
||||
|
||||
* The [Components and templates](guide/displaying-data) guide explains how to connect the application data in your [components](guide/glossary#component) to your page-display [templates](guide/glossary#template), to create a complete interactive application.
|
||||
* The **Main Concepts** section located in the table of contents contains several topics that explain how to connect the application data in your [components](guide/glossary#component) to your page-display [templates](guide/glossary#template), to create a complete interactive application.
|
||||
|
||||
* The [NgModules](guide/ngmodules) guide provides in-depth information on the modular structure of an Angular application.
|
||||
|
||||
@@ -21,7 +21,7 @@ about the features and tools that can help you develop and deliver Angular appli
|
||||
|
||||
## Responsive programming
|
||||
|
||||
The **Components and Templates** guide provides guidance and details of the [template syntax](guide/template-syntax) that you use to display your component data when and where you want it within a view, and to collect input from users that you can respond to.
|
||||
The [template syntax](guide/template-syntax) and related topics contain details about how to display your component data when and where you want it within a view, and how to collect input from users that you can respond to.
|
||||
|
||||
Additional pages and sections describe some basic programming techniques for Angular apps.
|
||||
|
||||
@@ -52,8 +52,6 @@ For some platforms and applications, you might also want to use the PWA (Progres
|
||||
|
||||
## Support for the development cycle
|
||||
|
||||
The **Development Workflow** section describes the tools and processes you use to compile, test, and deploy Angular applications.
|
||||
|
||||
* [CLI Command Reference](cli): The Angular CLI is a command-line tool that you use to create projects, generate application and library code, and perform a variety of ongoing development tasks such as testing, bundling, and deployment.
|
||||
|
||||
* [Compilation](guide/aot-compiler): Angular provides just-in-time (JIT) compilation for the development environment, and ahead-of-time (AOT) compilation for the production environment.
|
||||
@@ -68,7 +66,6 @@ The **Development Workflow** section describes the tools and processes you use t
|
||||
|
||||
* [Accessibility](guide/accessibility): Make your app accessible to all users.
|
||||
|
||||
|
||||
## File structure, configuration, and dependencies
|
||||
|
||||
* [Workspace and file structure](guide/file-structure): Understand the structure of Angular workspace and project folders.
|
||||
|
||||
@@ -5,7 +5,7 @@ Angular is written in TypeScript.
|
||||
It implements core and optional functionality as a set of TypeScript libraries that you import into your apps.
|
||||
|
||||
The architecture of an Angular application relies on certain fundamental concepts.
|
||||
The basic building blocks are *NgModules*, which provide a compilation context for *components*. NgModules collect related code into functional sets; an Angular app is defined by a set of NgModules. An app always has at least a *root module* that enables bootstrapping, and typically has many more *feature modules*.
|
||||
The basic building blocks of the Angular framework are Angular components that are organized into *NgModules*. NgModules collect related code into functional sets; an Angular app is defined by a set of NgModules. An app always has at least a *root module* that enables bootstrapping, and typically has many more *feature modules*.
|
||||
|
||||
* Components define *views*, which are sets of screen elements that Angular can choose among and modify according to your program logic and data.
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Attribute, class, and style bindings
|
||||
|
||||
The template syntax provides specialized one-way bindings for scenarios less well-suited to property binding.
|
||||
Attribute binding in Angular helps you set values for attributes directly.
|
||||
With attribute binding, you can improve accessibility, style your application dynamically, and manage multiple CSS classes or styles simultaneously.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
@@ -8,23 +9,36 @@ See the <live-example></live-example> for a working example containing the code
|
||||
|
||||
</div>
|
||||
|
||||
## Binding to an attribute
|
||||
|
||||
## Attribute binding
|
||||
It is recommended that you set an element property with a [property binding](guide/property-binding) whenever possible.
|
||||
However, sometimes you don't have an element property to bind.
|
||||
In those situations, you can use attribute binding.
|
||||
|
||||
Set the value of an attribute directly with an **attribute binding**. This is the only exception to the rule that a binding sets a target property and the only binding that creates and sets an attribute.
|
||||
For example, [ARIA](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) and
|
||||
[SVG](https://developer.mozilla.org/en-US/docs/Web/SVG) are purely attributes.
|
||||
Neither ARIA nor SVG correspond to element properties and don't set element properties.
|
||||
In these cases, you must use attribute binding because there are no corresponding property targets.
|
||||
|
||||
Usually, setting an element property with a [property binding](guide/property-binding)
|
||||
is preferable to setting the attribute with a string. However, sometimes
|
||||
there is no element property to bind, so attribute binding is the solution.
|
||||
|
||||
Consider the [ARIA](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) and
|
||||
[SVG](https://developer.mozilla.org/en-US/docs/Web/SVG). They are purely attributes, don't correspond to element properties, and don't set element properties. In these cases, there are no property targets to bind to.
|
||||
## Syntax
|
||||
|
||||
Attribute binding syntax resembles property binding, but
|
||||
instead of an element property between brackets, start with the prefix `attr`,
|
||||
followed by a dot (`.`), and the name of the attribute.
|
||||
You then set the attribute value, using an expression that resolves to a string,
|
||||
or remove the attribute when the expression resolves to `null`.
|
||||
Attribute binding syntax resembles [property binding](guide/property-binding), but instead of an element property between brackets, you precede the name of the attribute with the prefix `attr`, followed by a dot.
|
||||
Then, you set the attribute value with an expression that resolves to a string.
|
||||
|
||||
<code-example language="html">
|
||||
|
||||
<p [attr.attribute-you-are-targeting]="expression"></p>
|
||||
|
||||
</code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
When the expression resolves to `null`, Angular removes the attribute altogether.
|
||||
|
||||
</div>
|
||||
|
||||
## Binding ARIA attributes
|
||||
|
||||
One of the primary use cases for attribute binding
|
||||
is to set ARIA attributes, as in this example:
|
||||
@@ -33,32 +47,30 @@ is to set ARIA attributes, as in this example:
|
||||
|
||||
{@a colspan}
|
||||
|
||||
## Binding to `colspan`
|
||||
|
||||
Another common use case for attribute binding is with the `colspan` attribute in tables.
|
||||
Binding to the `colspan` attribute helps you keep your tables programmatically dynamic.
|
||||
Depending on the amount of data that your application populates a table with, the number of columns that a row spans could change.
|
||||
|
||||
To use attribute binding with the `<td>` attribute `colspan`:
|
||||
|
||||
1. Specify the `colspan` attribute by using the following syntax: `[attr.colspan]`.
|
||||
1. Set `[attr.colspan]` equal to an expression.
|
||||
|
||||
In the following example, we bind the `colspan` attribute to the expression `1 + 1`.
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="colspan" header="src/app/app.component.html"></code-example>
|
||||
|
||||
This binding causes the `<tr>` to span two columns.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
#### `colspan` and `colSpan`
|
||||
Sometimes there are differences between the name of property and an attribute.
|
||||
|
||||
Notice the difference between the `colspan` attribute and the `colSpan` property.
|
||||
|
||||
If you wrote something like this:
|
||||
|
||||
<code-example language="html">
|
||||
<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
|
||||
</code-example>
|
||||
|
||||
You'd get this error:
|
||||
|
||||
<code-example language="bash">
|
||||
Template parse errors:
|
||||
Can't bind to 'colspan' since it isn't a known native property
|
||||
</code-example>
|
||||
|
||||
As the message says, the `<td>` element does not have a `colspan` property. This is true
|
||||
because `colspan` is an attribute—`colSpan`, with a capital `S`, is the
|
||||
corresponding property. Interpolation and property binding can set only *properties*, not attributes.
|
||||
|
||||
Instead, you'd use property binding and write it like this:
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="colSpan" header="src/app/app.component.html"></code-example>
|
||||
`colspan` is an attribute of `<tr>`, while `colSpan` with a capital "S" is a property.
|
||||
When using attribute binding, use `colspan` with a lowercase "s".
|
||||
For more information on how to bind to the `colSpan` property, see the [`colspan` and `colSpan`](guide/property-binding#colspan) section of [Property Binding](guide/property-binding).
|
||||
|
||||
</div>
|
||||
|
||||
@@ -66,28 +78,32 @@ Instead, you'd use property binding and write it like this:
|
||||
|
||||
{@a class-binding}
|
||||
|
||||
## Class binding
|
||||
## Binding to the `class` attribute
|
||||
|
||||
Here's how to set the `class` attribute without a binding in plain HTML:
|
||||
You can use class binding to add and remove CSS class names from an element's `class` attribute.
|
||||
|
||||
```html
|
||||
<!-- standard class attribute setting -->
|
||||
<div class="foo bar">Some text</div>
|
||||
```
|
||||
### Binding to a single CSS `class`
|
||||
|
||||
You can also add and remove CSS class names from an element's `class` attribute with a **class binding**.
|
||||
To create a single class binding, use the prefix `class` followed by a dot and the name of the CSS class—for example, `[class.sale]="onSale"`.
|
||||
Angular adds the class when the bound expression, `onSale` is truthy, and it removes the class when the expression is falsy—with the exception of `undefined`.
|
||||
See [styling delegation](guide/style-precedence#styling-delegation) for more information.
|
||||
|
||||
To create a single class binding, start with the prefix `class` followed by a dot (`.`) and the name of the CSS class (for example, `[class.foo]="hasFoo"`).
|
||||
Angular adds the class when the bound expression is truthy, and it removes the class when the expression is falsy (with the exception of `undefined`, see [styling delegation](#styling-delegation)).
|
||||
### Binding to multiple CSS classes
|
||||
|
||||
To create a binding to multiple classes, use a generic `[class]` binding without the dot (for example, `[class]="classExpr"`).
|
||||
The expression can be a space-delimited string of class names, or you can format it as an object with class names as the keys and truthy/falsy expressions as the values.
|
||||
With object format, Angular will add a class only if its associated value is truthy.
|
||||
To bind to multiple classes, use `[class]` set to an expression—for example, `[class]="classExpression"`.
|
||||
The expression can be a space-delimited string of class names, or an object with class names as the keys and truthy or falsy expressions as the values.
|
||||
With an object format, Angular adds a class only if its associated value is truthy.
|
||||
|
||||
It's important to note that with any object-like expression (`object`, `Array`, `Map`, `Set`, etc), the identity of the object must change for the class list to be updated.
|
||||
Updating the property without changing object identity will have no effect.
|
||||
<div class="alert is-important">
|
||||
|
||||
If there are multiple bindings to the same class name, conflicts are resolved using [styling precedence](#styling-precedence).
|
||||
With any object-like expression—such as `object`, `Array`, `Map`, or `Set`—the identity of the object must change for Angular to update the class list.
|
||||
Updating the property without changing object identity has no effect.
|
||||
|
||||
</div>
|
||||
|
||||
If there are multiple bindings to the same class name, Angular uses [styling precedence](guide/style-precedence) to determine which binding to use.
|
||||
|
||||
The following table summarizes class binding syntax.
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
@@ -118,13 +134,13 @@ If there are multiple bindings to the same class name, conflicts are resolved us
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Single class binding</td>
|
||||
<td><code>[class.foo]="hasFoo"</code></td>
|
||||
<td><code>[class.sale]="onSale"</code></td>
|
||||
<td><code>boolean | undefined | null</code></td>
|
||||
<td><code>true</code>, <code>false</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=3>Multi-class binding</td>
|
||||
<td rowspan=3><code>[class]="classExpr"</code></td>
|
||||
<td rowspan=3><code>[class]="classExpression"</code></td>
|
||||
<td><code>string</code></td>
|
||||
<td><code>"my-class-1 my-class-2 my-class-3"</code></td>
|
||||
</tr>
|
||||
@@ -138,44 +154,44 @@ If there are multiple bindings to the same class name, conflicts are resolved us
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
The [NgClass](guide/built-in-directives/#ngclass) directive can be used as an alternative to direct `[class]` bindings.
|
||||
However, using the above class binding syntax without `NgClass` is preferred because due to improvements in class binding in Angular, `NgClass` no longer provides significant value, and might eventually be removed in the future.
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
## Style binding
|
||||
{@a style-binding}
|
||||
|
||||
Here's how to set the `style` attribute without a binding in plain HTML:
|
||||
## Binding to the style attribute
|
||||
|
||||
```html
|
||||
<!-- standard style attribute setting -->
|
||||
<div style="color: blue">Some text</div>
|
||||
```
|
||||
You can use style binding to set styles dynamically.
|
||||
|
||||
You can also set styles dynamically with a **style binding**.
|
||||
### Binding to a single style
|
||||
|
||||
To create a single style binding, start with the prefix `style` followed by a dot (`.`) and the name of the CSS style property (for example, `[style.width]="width"`).
|
||||
The property will be set to the value of the bound expression, which is normally a string.
|
||||
To create a single style binding, use the prefix `style` followed by a dot and the name of the CSS style property—for example, `[style.width]="width"`.
|
||||
Angular sets the property to the value of the bound expression, which is usually a string.
|
||||
Optionally, you can add a unit extension like `em` or `%`, which requires a number type.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Note that a _style property_ name can be written in either
|
||||
[dash-case](guide/glossary#dash-case), as shown above, or
|
||||
[camelCase](guide/glossary#camelcase), such as `fontSize`.
|
||||
You can write a style property name in either [dash-case](guide/glossary#dash-case), or
|
||||
[camelCase](guide/glossary#camelcase).
|
||||
|
||||
</div>
|
||||
|
||||
If there are multiple styles you'd like to toggle, you can bind to the `[style]` property directly without the dot (for example, `[style]="styleExpr"`).
|
||||
The expression attached to the `[style]` binding is most often a string list of styles like `"width: 100px; height: 100px;"`.
|
||||
### Binding to multiple styles
|
||||
|
||||
You can also format the expression as an object with style names as the keys and style values as the values, like `{width: '100px', height: '100px'}`.
|
||||
It's important to note that with any object-like expression (`object`, `Array`, `Map`, `Set`, etc), the identity of the object must change for the class list to be updated.
|
||||
Updating the property without changing object identity will have no effect.
|
||||
To toggle multiple styles, bind to the `[style]` attribute—for example, `[style]="styleExpression"`.
|
||||
The expression is often a string list of styles such as `"width: 100px; height: 100px;"`.
|
||||
|
||||
If there are multiple bindings to the same style property, conflicts are resolved using [styling precedence rules](#styling-precedence).
|
||||
You can also format the expression as an object with style names as the keys and style values as the values, such as `{width: '100px', height: '100px'}`.
|
||||
|
||||
<div class="alert is-important">
|
||||
|
||||
With any object-like expression—such as `object`, `Array`, `Map`, or `Set`—the identity of the object must change for Angular to update the class list.
|
||||
Updating the property without changing object identity has no effect.
|
||||
|
||||
</div>
|
||||
|
||||
If there are multiple bindings to the same style attribute, Angular uses [styling precedence](guide/style-precedence) to determine which binding to use.
|
||||
|
||||
The following table summarizes style binding syntax.
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
@@ -219,7 +235,7 @@ If there are multiple bindings to the same style property, conflicts are resolve
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=3>Multi-style binding</td>
|
||||
<td rowspan=3><code>[style]="styleExpr"</code></td>
|
||||
<td rowspan=3><code>[style]="styleExpression"</code></td>
|
||||
<td><code>string</code></td>
|
||||
<td><code>"width: 100px; height: 100px"</code></td>
|
||||
</tr>
|
||||
@@ -232,72 +248,3 @@ If there are multiple bindings to the same style property, conflicts are resolve
|
||||
<td><code>['width', '100px']</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
The [NgStyle](guide/built-in-directives/#ngstyle) directive can be used as an alternative to direct `[style]` bindings.
|
||||
However, using the above style binding syntax without `NgStyle` is preferred because due to improvements in style binding in Angular, `NgStyle` no longer provides significant value, and might eventually be removed in the future.
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a styling-precedence}
|
||||
|
||||
## Styling Precedence
|
||||
|
||||
A single HTML element can have its CSS class list and style values bound to multiple sources (for example, host bindings from multiple directives).
|
||||
|
||||
When there are multiple bindings to the same class name or style property, Angular uses a set of precedence rules to resolve conflicts and determine which classes or styles are ultimately applied to the element.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
<h4>Styling precedence (highest to lowest)</h4>
|
||||
|
||||
1. Template bindings
|
||||
1. Property binding (for example, `<div [class.foo]="hasFoo">` or `<div [style.color]="color">`)
|
||||
1. Map binding (for example, `<div [class]="classExpr">` or `<div [style]="styleExpr">`)
|
||||
1. Static value (for example, `<div class="foo">` or `<div style="color: blue">`)
|
||||
1. Directive host bindings
|
||||
1. Property binding (for example, `host: {'[class.foo]': 'hasFoo'}` or `host: {'[style.color]': 'color'}`)
|
||||
1. Map binding (for example, `host: {'[class]': 'classExpr'}` or `host: {'[style]': 'styleExpr'}`)
|
||||
1. Static value (for example, `host: {'class': 'foo'}` or `host: {'style': 'color: blue'}`)
|
||||
1. Component host bindings
|
||||
1. Property binding (for example, `host: {'[class.foo]': 'hasFoo'}` or `host: {'[style.color]': 'color'}`)
|
||||
1. Map binding (for example, `host: {'[class]': 'classExpr'}` or `host: {'[style]': 'styleExpr'}`)
|
||||
1. Static value (for example, `host: {'class': 'foo'}` or `host: {'style': 'color: blue'}`)
|
||||
|
||||
</div>
|
||||
|
||||
The more specific a class or style binding is, the higher its precedence.
|
||||
|
||||
A binding to a specific class (for example, `[class.foo]`) will take precedence over a generic `[class]` binding, and a binding to a specific style (for example, `[style.bar]`) will take precedence over a generic `[style]` binding.
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="basic-specificity" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Specificity rules also apply when it comes to bindings that originate from different sources.
|
||||
It's possible for an element to have bindings in the template where it's declared, from host bindings on matched directives, and from host bindings on matched components.
|
||||
|
||||
Template bindings are the most specific because they apply to the element directly and exclusively, so they have the highest precedence.
|
||||
|
||||
Directive host bindings are considered less specific because directives can be used in multiple locations, so they have a lower precedence than template bindings.
|
||||
|
||||
Directives often augment component behavior, so host bindings from components have the lowest precedence.
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="source-specificity" header="src/app/app.component.html"></code-example>
|
||||
|
||||
In addition, bindings take precedence over static attributes.
|
||||
|
||||
In the following case, `class` and `[class]` have similar specificity, but the `[class]` binding will take precedence because it is dynamic.
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="dynamic-priority" header="src/app/app.component.html"></code-example>
|
||||
|
||||
{@a styling-delegation}
|
||||
### Delegating to styles with lower precedence
|
||||
|
||||
It is possible for higher precedence styles to "delegate" to lower precedence styles using `undefined` values.
|
||||
Whereas setting a style property to `null` ensures the style is removed, setting it to `undefined` will cause Angular to fall back to the next-highest precedence binding to that style.
|
||||
|
||||
For example, consider the following template:
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="style-delegation" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Imagine that the `dirWithHostBinding` directive and the `comp-with-host-binding` component both have a `[style.width]` host binding.
|
||||
In that case, if `dirWithHostBinding` sets its binding to `undefined`, the `width` property will fall back to the value of the `comp-with-host-binding` host binding.
|
||||
However, if `dirWithHostBinding` sets its binding to `null`, the `width` property will be removed entirely.
|
||||
|
||||
@@ -195,12 +195,12 @@ Add a `highlightColor` property to the directive class like this:
|
||||
|
||||
{@a input}
|
||||
|
||||
### Binding to an _@Input_ property
|
||||
### Binding to an `@Input()` property
|
||||
|
||||
Notice the `@Input` decorator. It adds metadata to the class that makes the directive's `highlightColor` property available for binding.
|
||||
Notice the `@Input()` decorator. It adds metadata to the class that makes the directive's `highlightColor` property available for binding.
|
||||
|
||||
It's called an *input* property because data flows from the binding expression _into_ the directive.
|
||||
Without that input metadata, Angular rejects the binding; see [below](guide/attribute-directives#why-input "Why add @Input?") for more about that.
|
||||
Without that `@Input()` metadata, Angular rejects the binding; see [below](guide/attribute-directives#why-input "Why add @Input?") for more information.
|
||||
|
||||
Try it by adding the following directive binding variations to the `AppComponent` template:
|
||||
|
||||
@@ -235,7 +235,7 @@ This is disagreeable. The word, `appHighlight`, is a terrible property name and
|
||||
|
||||
Fortunately you can name the directive property whatever you want _and_ **_alias it_** for binding purposes.
|
||||
|
||||
Restore the original property name and specify the selector as the alias in the argument to `@Input`.
|
||||
Restore the original property name and specify the selector as the alias in the argument to `@Input()`.
|
||||
|
||||
<code-example path="attribute-directives/src/app/highlight.directive.ts" header="src/app/highlight.directive.ts (color property with alias)" region="color"></code-example>
|
||||
|
||||
@@ -303,7 +303,7 @@ and fall back to "violet" as the default color.
|
||||
<code-example path="attribute-directives/src/app/app.component.html" header="src/app/app.component.html (defaultColor)" region="defaultColor"></code-example>
|
||||
|
||||
Angular knows that the `defaultColor` binding belongs to the `HighlightDirective`
|
||||
because you made it _public_ with the `@Input` decorator.
|
||||
because you made it _public_ with the `@Input()` decorator.
|
||||
|
||||
Here's how the harness should work when you're done coding.
|
||||
|
||||
@@ -311,6 +311,27 @@ Here's how the harness should work when you're done coding.
|
||||
<img src="generated/images/guide/attribute-directives/highlight-directive-final-anim.gif" alt="Final Highlight">
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
{@a ngNonBindable}
|
||||
|
||||
## `ngNonBindable`
|
||||
|
||||
With the built-in template primitive `ngNonBindable`, Angular won't
|
||||
evaluate expressions in elements. For example:
|
||||
|
||||
<code-example path="attribute-directives/src/app/app.component.html" linenums="false" header="src/app/app.component.html" region="ngNonBindable"></code-example>
|
||||
|
||||
The expression `{{ 1 + 1 }}` will render just as it does in your code editor,
|
||||
and will not display `2`. This is helpful when you want to render code in the browser.
|
||||
|
||||
When you apply `ngNonBindable` to an element, it stops any binding starting at that element, including child elements. However, `ngNonBindable` still allows
|
||||
directives to work to the element where you apply `ngNonBindable`. In the following example, the `appHighlight` directive will still be active but Angular will not evaluate the expression `{{ 1 + 1 }}`.
|
||||
|
||||
<code-example path="attribute-directives/src/app/app.component.html" linenums="false" header="src/app/app.component.html" region="ngNonBindable-with-directive"></code-example>
|
||||
|
||||
Additionally, if you apply `ngNonBindable` to a parent element, interpolation and binding of any sort, such as property binding, or event binding, is disabled for its children.
|
||||
|
||||
## Summary
|
||||
|
||||
This page covered how to:
|
||||
@@ -319,6 +340,7 @@ This page covered how to:
|
||||
* [Apply the directive](guide/attribute-directives#apply-directive) to an element in a template.
|
||||
* [Respond to **events**](guide/attribute-directives#respond-to-user) that change the directive's behavior.
|
||||
* [**Bind** values to the directive](guide/attribute-directives#bindings).
|
||||
* [Prevent expression evaluation](guide/attribute-directives#ngNonBindable).
|
||||
|
||||
The final source code follows:
|
||||
|
||||
@@ -337,9 +359,9 @@ You can also experience and download the <live-example title="Attribute Directiv
|
||||
|
||||
{@a why-input}
|
||||
|
||||
### Appendix: Why add _@Input_?
|
||||
### Appendix: Why add `@Input()`?
|
||||
|
||||
In this demo, the `highlightColor` property is an ***input*** property of
|
||||
In this demo, the `highlightColor` property is an `@Input()` property of
|
||||
the `HighlightDirective`. You've seen it applied without an alias:
|
||||
|
||||
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts (color)" region="color"></code-example>
|
||||
@@ -348,33 +370,33 @@ You've seen it with an alias:
|
||||
|
||||
<code-example path="attribute-directives/src/app/highlight.directive.ts" header="src/app/highlight.directive.ts (color)" region="color"></code-example>
|
||||
|
||||
Either way, the `@Input` decorator tells Angular that this property is
|
||||
Either way, the `@Input()` decorator tells Angular that this property is
|
||||
_public_ and available for binding by a parent component.
|
||||
Without `@Input`, Angular refuses to bind to the property.
|
||||
Without `@Input()`, Angular refuses to bind to the property.
|
||||
|
||||
You've bound template HTML to component properties before and never used `@Input`.
|
||||
You've bound template HTML to component properties before and never used `@Input()`.
|
||||
What's different?
|
||||
|
||||
The difference is a matter of trust.
|
||||
Angular treats a component's template as _belonging_ to the component.
|
||||
The component and its template trust each other implicitly.
|
||||
Therefore, the component's own template may bind to _any_ property of that component,
|
||||
with or without the `@Input` decorator.
|
||||
with or without the `@Input()` decorator.
|
||||
|
||||
But a component or directive shouldn't blindly trust _other_ components and directives.
|
||||
The properties of a component or directive are hidden from binding by default.
|
||||
They are _private_ from an Angular binding perspective.
|
||||
When adorned with the `@Input` decorator, the property becomes _public_ from an Angular binding perspective.
|
||||
When adorned with the `@Input()` decorator, the property becomes _public_ from an Angular binding perspective.
|
||||
Only then can it be bound by some other component or directive.
|
||||
|
||||
You can tell if `@Input` is needed by the position of the property name in a binding.
|
||||
You can tell if `@Input()` is needed by the position of the property name in a binding.
|
||||
|
||||
* When it appears in the template expression to the ***right*** of the equals (=),
|
||||
it belongs to the template's component and does not require the `@Input` decorator.
|
||||
it belongs to the template's component and does not require the `@Input()` decorator.
|
||||
|
||||
* When it appears in **square brackets** ([ ]) to the **left** of the equals (=),
|
||||
the property belongs to some _other_ component or directive;
|
||||
that property must be adorned with the `@Input` decorator.
|
||||
that property must be adorned with the `@Input()` decorator.
|
||||
|
||||
Now apply that reasoning to the following example:
|
||||
|
||||
@@ -382,8 +404,8 @@ Now apply that reasoning to the following example:
|
||||
|
||||
* The `color` property in the expression on the right belongs to the template's component.
|
||||
The template and its component trust each other.
|
||||
The `color` property doesn't require the `@Input` decorator.
|
||||
The `color` property doesn't require the `@Input()` decorator.
|
||||
|
||||
* The `appHighlight` property on the left refers to an _aliased_ property of the `HighlightDirective`,
|
||||
not a property of the template's component. There are trust issues.
|
||||
Therefore, the directive property must carry the `@Input` decorator.
|
||||
not a property of the template's component.
|
||||
For security, the directive property must carry the `@Input()` decorator.
|
||||
|
||||
@@ -80,7 +80,7 @@ Angular supports most recent browsers. This includes the following specific vers
|
||||
</td>
|
||||
|
||||
<td>
|
||||
X (10.0), Pie (9.0), Oreo (8.0), Nougat (7.0)
|
||||
Q (10.0), Pie (9.0), Oreo (8.0), Nougat (7.0)
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ which explains the following:
|
||||
* Using [`<ng-container>`](guide/structural-directives#ngcontainer "<ng-container>")
|
||||
to group elements when there is no suitable host element for the directive.
|
||||
* How to write your own structural directive.
|
||||
* That you can only apply [one structural directive](guide/structural-directives#one-per-element "one per host element") to an element.
|
||||
* Why you [can only apply one structural directive](guide/structural-directives#one-per-element "one per host element") to an element.
|
||||
|
||||
</div>
|
||||
|
||||
@@ -281,7 +281,7 @@ You define a block of HTML that defines how a single item should be displayed
|
||||
and then you tell Angular to use that block as a template for rendering each item in the list.
|
||||
The text assigned to `*ngFor` is the instruction that guides the repeater process.
|
||||
|
||||
The following example shows `NgFor` applied to a simple `<div>`. (Don't forget the asterisk (`*`) in front of `ngFor`.)
|
||||
The following example shows `NgFor` applied to a simple `<div>`.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgFor-1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
# Angular Components Overview
|
||||
|
||||
Components are the main building block for Angular applications. Each component consists of:
|
||||
|
||||
* An HTML template that declares what renders on the page
|
||||
* A Typescript class that defines behavior
|
||||
* A CSS selector that defines how the component is used in a template
|
||||
* Optionally, CSS styles applied to the template
|
||||
|
||||
This topic describes how to create and configure an Angular component.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
To view or download the example code used in this topic, see the <live-example></live-example>.
|
||||
|
||||
</div>
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To create a component, verify that you have met the following prerequisites:
|
||||
|
||||
1. Install the Angular CLI.
|
||||
1. Create an Angular project.
|
||||
If you don't have a project, you can create one using `ng new <project-name>`, where `<project-name>` is the name of your Angular application.
|
||||
|
||||
## Creating a component
|
||||
|
||||
The easiest way to create a component is with the Angular CLI. You can also create a component manually.
|
||||
|
||||
### Creating a component using the Angular CLI
|
||||
|
||||
To create a component using the Angular CLI:
|
||||
|
||||
1. From a terminal window, navigate to the directory containing your application.
|
||||
1. Run the `ng generate component <component-name>` command, where `<component-name>` is the name of your new component.
|
||||
|
||||
By default, this command creates the following:
|
||||
|
||||
* A folder named after the component
|
||||
* A component file, `<component-name>.component.ts`
|
||||
* A template file, `<component-name>.component.html`
|
||||
* A CSS file, `<component-name>.component.css`
|
||||
* A testing specification file, `<component-name>.component.spec.ts`
|
||||
|
||||
Where `<component-name>` is the name of your component.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
You can change how `ng generate component` creates new components.
|
||||
For more information, see [ng generate component](cli/generate#component-command) in the Angular CLI documentation.
|
||||
|
||||
</div>
|
||||
|
||||
### Creating a component manually
|
||||
|
||||
Although the Angular CLI is the easiest way to create an Angular component, you can also create a component manually.
|
||||
This section describes how to create the core component file within an existing Angular project.
|
||||
|
||||
To create a new component manually:
|
||||
|
||||
1. Navigate to your Angular project directory.
|
||||
1. Create a new file, `<component-name>.component.ts`.
|
||||
1. At the top of the file, add the following import statement.
|
||||
|
||||
<code-example
|
||||
path="component-overview/src/app/component-overview/component-overview.component.ts"
|
||||
region="import">
|
||||
</code-example>
|
||||
|
||||
1. After the `import` statement, add a `@Component` decorator.
|
||||
|
||||
<code-example
|
||||
path="component-overview/src/app/component-overview/component-overview.component.ts"
|
||||
region="decorator-skeleton">
|
||||
</code-example>
|
||||
|
||||
1. Choose a CSS selector for the component.
|
||||
|
||||
<code-example
|
||||
path="component-overview/src/app/component-overview/component-overview.component.ts"
|
||||
region="selector">
|
||||
</code-example>
|
||||
|
||||
For more information on choosing a selector, see [Specifying a component's selector](#specifying-a-components-css-selector).
|
||||
|
||||
1. Define the HTML template that the component uses to display information.
|
||||
In most cases, this template is a separate HTML file.
|
||||
|
||||
<code-example
|
||||
path="component-overview/src/app/component-overview/component-overview.component.ts"
|
||||
region="templateUrl">
|
||||
</code-example>
|
||||
|
||||
For more information on defining a component's template, see [Defining a component's template](#defining-a-components-template).
|
||||
|
||||
1. Select the styles for the component's template.
|
||||
In most cases, you define the styles for your component's template in a separate file.
|
||||
|
||||
<code-example
|
||||
path="component-overview/src/app/component-overview/component-overview.component.ts"
|
||||
region="decorator">
|
||||
</code-example>
|
||||
|
||||
1. Add a `class` statement that includes the code for the component.
|
||||
|
||||
<code-example
|
||||
path="component-overview/src/app/component-overview/component-overview.component.ts"
|
||||
region="class">
|
||||
</code-example>
|
||||
|
||||
## Specifying a component's CSS selector
|
||||
|
||||
Every component requires a CSS _selector_. A selector instructs Angular to instantiate this component wherever it finds the corresponding tag in template HTML. For example, consider a component `hello-world.component.ts` that defines its selector as `app-hello-world`. This selector instructs Angular to instantiate this component any time the tag `<app-hello-world>` appears in a template.
|
||||
|
||||
Specify a component's selector by adding a `selector` statement to the `@Component` decorator.
|
||||
|
||||
<code-example
|
||||
path="component-overview/src/app/component-overview/component-overview.component.ts"
|
||||
region="selector">
|
||||
</code-example>
|
||||
|
||||
## Defining a component's template
|
||||
|
||||
A template is a block of HTML that tells Angular how to render the component in your application.
|
||||
You can define a template for your component in one of two ways: by referencing an external file, or directly within the component.
|
||||
|
||||
To define a template as an external file, add a `templateUrl` property to the `@Component` decorator.
|
||||
|
||||
<code-example
|
||||
path="component-overview/src/app/component-overview/component-overview.component.ts"
|
||||
region="templateUrl">
|
||||
</code-example>
|
||||
|
||||
To define a template within the component, add a `template` property to the `@Component` decorator that contains the HTML you want to use.
|
||||
|
||||
<code-example
|
||||
path="component-overview/src/app/component-overview/component-overview.component.1.ts"
|
||||
region="template">
|
||||
</code-example>
|
||||
|
||||
If you want your template to span multiple lines, you can use backticks (<code> ` </code>).
|
||||
For example:
|
||||
|
||||
<code-example
|
||||
path="component-overview/src/app/component-overview/component-overview.component.2.ts"
|
||||
region="templatebacktick">
|
||||
</code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
An Angular component requires a template defined using `template` or `templateUrl`. You cannot have both statements in a component.
|
||||
|
||||
</div>
|
||||
|
||||
## Declaring a component's styles
|
||||
|
||||
You can declare component styles uses for its template in one of two ways: by referencing an external file, or directly within the component.
|
||||
|
||||
To declare the styles for a component in a separate file, add a `stylesUrls` property to the `@Component` decorator.
|
||||
|
||||
<code-example
|
||||
path="component-overview/src/app/component-overview/component-overview.component.ts"
|
||||
region="decorator">
|
||||
</code-example>
|
||||
|
||||
To select the styles within the component, add a `styles` property to the `@Component` decorator that contains the styles you want to use.
|
||||
|
||||
<code-example
|
||||
path="component-overview/src/app/component-overview/component-overview.component.3.ts"
|
||||
region="styles">
|
||||
</code-example>
|
||||
|
||||
The `styles` property takes an array of strings that contain the CSS rule declarations.
|
||||
|
||||
|
||||
## Next steps
|
||||
|
||||
* For an architectural overview of components, see [Introduction to components and templates](guide/architecture-components).
|
||||
* For additional options you can use when creating a component, see [Component](api/core/Component) in the API Reference.
|
||||
* For more information on styling components, see [Component styles](guide/component-styles).
|
||||
* For more information on templates, see [Template syntax](guide/template-syntax).
|
||||
|
||||
@@ -1,91 +1,15 @@
|
||||
# Dependency injection in action
|
||||
|
||||
This section explores many of the features of dependency injection (DI) in Angular.
|
||||
{@a toc}
|
||||
|
||||
See the <live-example name="dependency-injection-in-action"></live-example>
|
||||
of the code in this cookbook.
|
||||
|
||||
{@a nested-dependencies}
|
||||
|
||||
## Nested service dependencies
|
||||
|
||||
The _consumer_ of an injected service doesn't need to know how to create that service.
|
||||
It's the job of the DI framework to create and cache dependencies. The consumer just
|
||||
needs to let the DI framework know which dependencies it needs.
|
||||
|
||||
Sometimes a service depends on other services, which may depend on yet other services.
|
||||
The dependency injection framework resolves these nested dependencies in the correct order.
|
||||
At each step, the consumer of dependencies declares what it requires in its
|
||||
constructor, and lets the framework provide them.
|
||||
|
||||
The following example shows that `AppComponent` declares its dependence on `LoggerService` and `UserContext`.
|
||||
|
||||
<code-example path="dependency-injection-in-action/src/app/app.component.ts" region="ctor" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
|
||||
`UserContext` in turn depends on both `LoggerService` and
|
||||
`UserService`, another service that gathers information about a particular user.
|
||||
|
||||
|
||||
<code-example path="dependency-injection-in-action/src/app/user-context.service.ts" region="injectables" header="user-context.service.ts (injection)"></code-example>
|
||||
|
||||
|
||||
When Angular creates `AppComponent`, the DI framework creates an instance of `LoggerService` and starts to create `UserContextService`.
|
||||
`UserContextService` also needs `LoggerService`, which the framework already has, so the framework can provide the same instance. `UserContextService` also needs `UserService`, which the framework has yet to create. `UserService` has no further dependencies, so the framework can simply use `new` to instantiate the class and provide the instance to the `UserContextService` constructor.
|
||||
|
||||
The parent `AppComponent` doesn't need to know about the dependencies of dependencies.
|
||||
Declare what's needed in the constructor (in this case `LoggerService` and `UserContextService`)
|
||||
and the framework resolves the nested dependencies.
|
||||
|
||||
When all dependencies are in place, `AppComponent` displays the user information.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/dependency-injection-in-action/logged-in-user.png" alt="Logged In User">
|
||||
</div>
|
||||
|
||||
{@a service-scope}
|
||||
|
||||
## Limit service scope to a component subtree
|
||||
|
||||
An Angular application has multiple injectors, arranged in a tree hierarchy that parallels the component tree.
|
||||
Each injector creates a singleton instance of a dependency.
|
||||
That same instance is injected wherever that injector provides that service.
|
||||
A particular service can be provided and created at any level of the injector hierarchy,
|
||||
which means that there can be multiple instances of a service if it is provided by multiple injectors.
|
||||
|
||||
Dependencies provided by the root injector can be injected into *any* component *anywhere* in the application.
|
||||
In some cases, you might want to restrict service availability to a particular region of the application.
|
||||
For instance, you might want to let users explicitly opt in to use a service,
|
||||
rather than letting the root injector provide it automatically.
|
||||
|
||||
You can limit the scope of an injected service to a *branch* of the application hierarchy
|
||||
by providing that service *at the sub-root component for that branch*.
|
||||
This example shows how to make a different instance of `HeroService` available to `HeroesBaseComponent`
|
||||
by adding it to the `providers` array of the `@Component()` decorator of the sub-component.
|
||||
|
||||
<code-example path="dependency-injection-in-action/src/app/sorted-heroes.component.ts" region="injection" header="src/app/sorted-heroes.component.ts (HeroesBaseComponent excerpt)">
|
||||
|
||||
</code-example>
|
||||
|
||||
When Angular creates `HeroesBaseComponent`, it also creates a new instance of `HeroService`
|
||||
that is visible only to that component and its children, if any.
|
||||
|
||||
You could also provide `HeroService` to a different component elsewhere in the application.
|
||||
That would result in a different instance of the service, living in a different injector.
|
||||
This guide explores many of the features of dependency injection (DI) in Angular.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Examples of such scoped `HeroService` singletons appear throughout the accompanying sample code,
|
||||
including `HeroBiosComponent`, `HeroOfTheMonthComponent`, and `HeroesBaseComponent`.
|
||||
Each of these components has its own `HeroService` instance managing its own independent collection of heroes.
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
{@a multiple-service-instances}
|
||||
|
||||
|
||||
## Multiple service instances (sandboxing)
|
||||
|
||||
Sometimes you want multiple instances of a service at *the same level* of the component hierarchy.
|
||||
@@ -272,7 +196,7 @@ Although developers strive to avoid it, many visual effects and third-party tool
|
||||
require DOM access.
|
||||
As a result, you might need to access a component's DOM element.
|
||||
|
||||
To illustrate, here's a simplified version of `HighlightDirective` from
|
||||
To illustrate, here's a minimal version of `HighlightDirective` from
|
||||
the [Attribute Directives](guide/attribute-directives) page.
|
||||
|
||||
<code-example path="dependency-injection-in-action/src/app/highlight.directive.ts" header="src/app/highlight.directive.ts">
|
||||
@@ -297,46 +221,6 @@ The following image shows the effect of mousing over the `<hero-bios-and-contact
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/dependency-injection-in-action/highlight.png" alt="Highlighted bios">
|
||||
</div>
|
||||
|
||||
{@a providers}
|
||||
|
||||
|
||||
## Define dependencies with providers
|
||||
|
||||
This section demonstrates how to write providers that deliver dependent services.
|
||||
|
||||
In order to get a service from a dependency injector, you have to give it a [token](guide/glossary#token).
|
||||
Angular usually handles this transaction by specifying a constructor parameter and its type.
|
||||
The parameter type serves as the injector lookup token.
|
||||
Angular passes this token to the injector and assigns the result to the parameter.
|
||||
|
||||
The following is a typical example.
|
||||
|
||||
|
||||
<code-example path="dependency-injection-in-action/src/app/hero-bios.component.ts" region="ctor" header="src/app/hero-bios.component.ts (component constructor injection)"></code-example>
|
||||
|
||||
|
||||
Angular asks the injector for the service associated with `LoggerService`
|
||||
and assigns the returned value to the `logger` parameter.
|
||||
|
||||
If the injector has already cached an instance of the service associated with the token,
|
||||
it provides that instance.
|
||||
If it doesn't, it needs to make one using the provider associated with the token.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
If the injector doesn't have a provider for a requested token, it delegates the request
|
||||
to its parent injector, where the process repeats until there are no more injectors.
|
||||
If the search fails, the injector throws an error—unless the request was [optional](guide/dependency-injection-in-action#optional).
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
A new injector has no providers.
|
||||
Angular initializes the injectors it creates with a set of preferred providers.
|
||||
You have to configure providers for your own app-specific dependencies.
|
||||
|
||||
|
||||
{@a defining-providers}
|
||||
|
||||
|
||||
@@ -700,53 +584,3 @@ appear *above* the class definition.
|
||||
Break the circularity with `forwardRef`.
|
||||
|
||||
<code-example path="dependency-injection-in-action/src/app/parent-finder.component.ts" region="alex-providers" header="parent-finder.component.ts (AlexComponent providers)"></code-example>
|
||||
|
||||
|
||||
<!--- Waiting for good examples
|
||||
|
||||
{@a directive-level-providers}
|
||||
|
||||
{@a element-level-providers}
|
||||
|
||||
## Element-level providers
|
||||
|
||||
A component is a specialization of directive, and the `@Component()` decorator inherits the `providers` property from `@Directive`. The injector is at the element level, so a provider configured with any element-level injector is available to any component, directive, or pipe attached to the same element.
|
||||
|
||||
Here's a live example that implements a custom form control, taking advantage of an injector that is shared by a component and a directive on the same element.
|
||||
|
||||
https://stackblitz.com/edit/basic-form-control
|
||||
|
||||
The component, `custom-control`, configures a provider for the DI token `NG_VALUE_ACCESSOR`.
|
||||
In the template, the `FormControlName` directive is instantiated along with the custom component.
|
||||
It can inject the `NG_VALUE_ACCESSOR` dependency because they share the same injector.
|
||||
(Notice that this example also makes use of `forwardRef()` to resolve a circularity in the definitions.)
|
||||
|
||||
### Sharing a service among components
|
||||
|
||||
__NEED TO TURN THIS INTO FULL EXTERNAL EXAMPLE__
|
||||
|
||||
Suppose you want to share the same `HeroCacheService` among multiple components. One way to do this is to create a directive.
|
||||
|
||||
```
|
||||
<ng-container heroCache>
|
||||
<hero-overview></hero-overview>
|
||||
<hero-details></hero-details>
|
||||
</ng-container>
|
||||
```
|
||||
|
||||
Use the `@Directive()` decorator to configure the provider for the service:
|
||||
|
||||
```
|
||||
@Directive(providers:[HeroCacheService])
|
||||
|
||||
class heroCache{...}
|
||||
```
|
||||
|
||||
Because the injectors for both the overview and details components are children of the injector created from the `heroCache` directive, they can inject things it provides.
|
||||
If the `heroCache` directive provides the `HeroCacheService`, the two components end up sharing them.
|
||||
|
||||
If you want to show only one of them, use the directive to make sure __??of what??__.
|
||||
|
||||
`<hero-overview heroCache></hero-overview>`
|
||||
|
||||
--->
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# Navigate the component tree with DI
|
||||
|
||||
<div class="callout is-critical">
|
||||
<header>Marked for archiving</header>
|
||||
|
||||
To ensure that you have the best experience possible, this topic is marked for archiving until we determine
|
||||
that it clearly conveys the most accurate information possible.
|
||||
|
||||
In the meantime, this topic might be helpful: [Hierarchical injectors](guide/hierarchical-dependency-injection).
|
||||
|
||||
If you think this content should not be archived, please file a [GitHub issue](https://github.com/angular/angular/issues/new?template=3-docs-bug.md).
|
||||
|
||||
</div>
|
||||
|
||||
Application components often need to share information.
|
||||
You can often use loosely coupled techniques for sharing information,
|
||||
such as data binding and service sharing,
|
||||
@@ -170,7 +182,7 @@ Here's *Barry*.
|
||||
|
||||
|
||||
*Barry*'s `providers` array looks just like [*Alex*'s](#alex-providers).
|
||||
If you're going to keep writing [*alias providers*](guide/dependency-injection-in-action#useexisting) like this you should create a [helper function](#provideparent).
|
||||
If you're going to keep writing [*alias providers*](guide/dependency-injection-in-action#useexisting) like this you should create a helper function.
|
||||
|
||||
For now, focus on *Barry*'s constructor.
|
||||
|
||||
@@ -196,7 +208,7 @@ which *is* what parent means.
|
||||
|
||||
2. Angular throws a cyclic dependency error if you omit the `@SkipSelf` decorator.
|
||||
|
||||
`Cannot instantiate cyclic dependency! (BethComponent -> Parent -> BethComponent)`
|
||||
`NG0200: Circular dependency in DI detected for BethComponent. Dependency path: BethComponent -> Parent -> BethComponent`
|
||||
|
||||
Here's *Alice*, *Barry*, and family in action.
|
||||
|
||||
@@ -244,36 +256,3 @@ It doesn't in this example *only* to demonstrate that the code will compile and
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{@a provideparent}
|
||||
|
||||
|
||||
### `provideParent()` helper function
|
||||
|
||||
Writing variations of the same parent *alias provider* gets old quickly,
|
||||
especially this awful mouthful with a [*forwardRef*](guide/dependency-injection-in-action#forwardref).
|
||||
|
||||
<code-example path="dependency-injection-in-action/src/app/parent-finder.component.ts" region="alex-providers" header="dependency-injection-in-action/src/app/parent-finder.component.ts"></code-example>
|
||||
|
||||
You can extract that logic into a helper function like the following.
|
||||
|
||||
<code-example path="dependency-injection-in-action/src/app/parent-finder.component.ts" region="provide-the-parent" header="dependency-injection-in-action/src/app/parent-finder.component.ts"></code-example>
|
||||
|
||||
Now you can add a simpler, more meaningful parent provider to your components.
|
||||
|
||||
<code-example path="dependency-injection-in-action/src/app/parent-finder.component.ts" region="alice-providers" header="dependency-injection-in-action/src/app/parent-finder.component.ts"></code-example>
|
||||
|
||||
|
||||
You can do better. The current version of the helper function can only alias the `Parent` class interface.
|
||||
The application might have a variety of parent types, each with its own class interface token.
|
||||
|
||||
Here's a revised version that defaults to `parent` but also accepts an optional second parameter for a different parent class interface.
|
||||
|
||||
<code-example path="dependency-injection-in-action/src/app/parent-finder.component.ts" region="provide-parent" header="dependency-injection-in-action/src/app/parent-finder.component.ts"></code-example>
|
||||
|
||||
|
||||
And here's how you could use it with a different parent type.
|
||||
|
||||
<code-example path="dependency-injection-in-action/src/app/parent-finder.component.ts" region="beth-providers" header="dependency-injection-in-action/src/app/parent-finder.component.ts"></code-example>
|
||||
|
||||
@@ -30,12 +30,12 @@ v6 - v9
|
||||
v7 - v10
|
||||
v8 - v11
|
||||
v9 - v12
|
||||
v10 - v13
|
||||
-->
|
||||
|
||||
|
||||
| Area | API or Feature | May be removed in |
|
||||
| ----------------------------- | --------------------------------------------------------------------------- | ----------------- |
|
||||
| `@angular/bazel` | [`Bazel builder and schematics`](#bazelbuilder) | v10 |
|
||||
| `@angular/common` | [`ReflectiveInjector`](#reflectiveinjector) | <!--v8--> v11 |
|
||||
| `@angular/common` | [`CurrencyPipe` - `DEFAULT_CURRENCY_CODE`](api/common/CurrencyPipe#currency-code-deprecation) | <!--v9--> v11 |
|
||||
| `@angular/core` | [`DefaultIterableDiffer`](#core) | <!--v7--> v11 |
|
||||
@@ -91,10 +91,7 @@ Tip: In the [API reference section](api) of this doc site, deprecated APIs are i
|
||||
| [`entryComponents`](api/core/NgModule#entryComponents) | none | v9 | See [`entryComponents`](#entryComponents) |
|
||||
| [`ANALYZE_FOR_ENTRY_COMPONENTS`](api/core/ANALYZE_FOR_ENTRY_COMPONENTS) | none | v9 | See [`ANALYZE_FOR_ENTRY_COMPONENTS`](#entryComponents) |
|
||||
| [`WrappedValue`](api/core/WrappedValue) | none | v10 | See [removing `WrappedValue`](#wrapped-value) |
|
||||
|
||||
|
||||
|
||||
|
||||
| [`async`](api/core/testing/async) | [`waitForAsync`](api/core/testing/waitForAsync) | v11 | The `async` function from `@angular/core/testing` has been renamed to `waitForAsync` in order to avoid confusion with the native JavaScript `async` syntax. The existing function is deprecated and will be removed in a future version. |
|
||||
|
||||
{@a testing}
|
||||
### @angular/core/testing
|
||||
@@ -437,46 +434,27 @@ This section contains a complete list all of the currently deprecated CLI flags.
|
||||
|
||||
| API/Option | May be removed in | Notes |
|
||||
| ------------------------------- | ----------------- |-------------------------------------------------------------------------------- |
|
||||
| `i18nFile` | <!--v9--> v11 | Specified in the project locale configuration in version 9 and later. |
|
||||
| `i18nFormat` | <!--v9--> v11 | Format is now automatically detected. |
|
||||
| `i18nLocale` | <!--v9--> v11 | New [localization option](/guide/i18n#localize-config) in version 9 and later. |
|
||||
| `lazyModules` | <!--v9--> v11 | Used with deprecated SystemJsNgModuleLoader. |
|
||||
| `rebaseRootRelativeCssUrls` | <!--v8--> v11 | Intended only to assist with specific migration issues. |
|
||||
| `scripts[].lazy` | <!--v8--> v11 | Renamed to `scripts[].inject`. |
|
||||
| `styles[].lazy` | <!--v8--> v11 | Renamed to `styles[].inject`. |
|
||||
| `i18nFormat` | <!--v9--> v11 | Renamed to `format` to simplify the user experience. |
|
||||
| `i18nLocale` | <!--v9--> v11 | Redundant with project’s source locale. |
|
||||
| `scripts[].lazy` | <!--v8--> v11 | Renamed to `scripts[].inject`. |
|
||||
| `styles[].lazy` | <!--v8--> v11 | Renamed to `styles[].inject`. |
|
||||
| `i18nFile` | <!--v9--> v11 | Specified in the project locale configuration in version 9 and later. |
|
||||
| `i18nFormat` | <!--v9--> v11 | Format is now automatically detected. |
|
||||
| `i18nLocale` | <!--v9--> v11 | New [localization option](/guide/i18n#localize-config) in version 9 and later. |
|
||||
| `lazyModules` | <!--v9--> v11 | Used with deprecated SystemJsNgModuleLoader. |
|
||||
|
||||
### @angular-devkit/core
|
||||
|
||||
| API/Option | May be removed in | Notes |
|
||||
| ------------------------------- | ----------------- |-------------------------------------------------------------------------------- |
|
||||
| `ModuleNotFoundException` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Not Yarn PnP compatible and not used in the Angular CLI. Use Node.js [require.resolve](https://nodejs.org/api/modules.html#modules_require_resolve_request_options).|
|
||||
| `resolve` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Not Yarn PnP compatible and not used in the Angular CLI. Use Node.js [require.resolve](https://nodejs.org/api/modules.html#modules_require_resolve_request_options).|
|
||||
| `setResolveHook` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Not Yarn PnP compatible and not used in the Angular CLI. Use Node.js [require.resolve](https://nodejs.org/api/modules.html#modules_require_resolve_request_options).|
|
||||
| `ResolveOptions` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Not Yarn PnP compatible and not used in the Angular CLI. Use Node.js [require.resolve](https://nodejs.org/api/modules.html#modules_require_resolve_request_options).|
|
||||
| `terminal` | <!--v8--> v10 | Unused implementation of terminal codes (color). |
|
||||
| `isObservable` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Use `isObservable` function from the `rxjs` package.|
|
||||
| `extractCss` | <!--v11--> v13 | No longer required to disable CSS extraction during development. |
|
||||
| `i18nFormat` | <!--v9--> v12 | Format is now automatically detected. |
|
||||
| `i18nLocale` | <!--v9--> v12 | New [localization option](/guide/i18n#localize-config) in version 9 and later. |
|
||||
| `lazyModules` | <!--v9--> v12 | Used with deprecated SystemJsNgModuleLoader. |
|
||||
| `hmrWarning` | <!--v11--> v13 | No longer has an effect. |
|
||||
| `servePathDefaultWarning` | <!--v11--> v13 | No longer has an effect. |
|
||||
|
||||
### @ngtools/webpack
|
||||
|
||||
| API/Option | May be removed in | Notes |
|
||||
| ------------------------------- | ----------------- |-------------------------------------------------------------------------------- |
|
||||
| `discoverLazyRoutes` | <!--v9--> TBD | Used with deprecated SystemJsNgModuleLoader. |
|
||||
| `additionalLazyModules` | <!--v9--> TBD | Used with deprecated SystemJsNgModuleLoader. |
|
||||
| `additionalLazyModuleResources` | <!--v9--> TBD | Used with deprecated SystemJsNgModuleLoader. |
|
||||
| `discoverLazyRoutes` | <!--v9--> v12 | Used with deprecated SystemJsNgModuleLoader. |
|
||||
| `additionalLazyModules` | <!--v9--> v12 | Used with deprecated SystemJsNgModuleLoader. |
|
||||
| `additionalLazyModuleResources` | <!--v9--> v12 | Used with deprecated SystemJsNgModuleLoader. |
|
||||
|
||||
### @schematics/angular
|
||||
|
||||
| API/Option | May be removed in | Notes |
|
||||
| ------------------------------- | ----------------- |-------------------------------------------------------------------------------- |
|
||||
| `entryComponent` | <!--v9--> TBD | No longer needed with Ivy. |
|
||||
| `entryComponent` | <!--v9--> v12 | No longer needed with Ivy. |
|
||||
| `lintFix` | <!--v11--> v12 | Deprecated as part of TSLint deprecation. |
|
||||
|
||||
{@a removed}
|
||||
## Removed APIs
|
||||
|
||||
@@ -1,312 +0,0 @@
|
||||
# Displaying data in views
|
||||
|
||||
Angular [components](guide/glossary#component) form the data structure of your application.
|
||||
The HTML [template](guide/glossary#template) associated with a component provides the means to display that data in the context of a web page.
|
||||
Together, a component's class and template form a [view](guide/glossary#view) of your application data.
|
||||
|
||||
The process of combining data values with their representation on the page is called [data binding](guide/glossary#data-binding).
|
||||
You display your data to a user (and collect data from the user) by *binding* controls in the HTML template to the data properties of the component class.
|
||||
|
||||
In addition, you can add logic to the template by including [directives](guide/glossary#directive), which tell Angular how to modify the page as it is rendered.
|
||||
|
||||
Angular defines a *template language* that expands HTML notation with syntax that allows you to define various kinds of data binding and logical directives.
|
||||
When the page is rendered, Angular interprets the template syntax to update the HTML according to your logic and current data state.
|
||||
Before you read the complete [template syntax guide](guide/template-syntax), the exercises on this page give you a quick demonstration of how template syntax works.
|
||||
|
||||
In this demo, you'll create a component with a list of heroes.
|
||||
You'll display the list of hero names and conditionally show a message below the list.
|
||||
The final UI looks like this:
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/displaying-data/final.png" alt="Final UI">
|
||||
</div>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The <live-example></live-example> demonstrates all of the syntax and code snippets described in this page.
|
||||
|
||||
</div>
|
||||
|
||||
{@a interpolation}
|
||||
|
||||
## Showing component properties with interpolation
|
||||
The easiest way to display a component property is to bind the property name through interpolation.
|
||||
With interpolation, you put the property name in the view template, enclosed in double curly braces: `{{myHero}}`.
|
||||
|
||||
Use the CLI command [`ng new displaying-data`](cli/new) to create a workspace and app named `displaying-data`.
|
||||
|
||||
Delete the <code>app.component.html</code> file. It is not needed for this example.
|
||||
|
||||
Then modify the <code>app.component.ts</code> file by
|
||||
changing the template and the body of the component.
|
||||
|
||||
When you're done, it should look like this:
|
||||
|
||||
<code-example path="displaying-data/src/app/app.component.1.ts" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
You added two properties to the formerly empty component: `title` and `myHero`.
|
||||
|
||||
The template displays the two component properties using double curly brace
|
||||
interpolation:
|
||||
|
||||
<code-example path="displaying-data/src/app/app.component.1.ts" header="src/app/app.component.ts (template)" region="template"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The template is a multi-line string within ECMAScript 2015 backticks (<code>\`</code>).
|
||||
The backtick (<code>\`</code>)—which is *not* the same character as a single
|
||||
quote (`'`)—allows you to compose a string over several lines, which makes the
|
||||
HTML more readable.
|
||||
|
||||
</div>
|
||||
|
||||
Angular automatically pulls the value of the `title` and `myHero` properties from the component and
|
||||
inserts those values into the browser. Angular updates the display
|
||||
when these properties change.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
More precisely, the redisplay occurs after some kind of asynchronous event related to
|
||||
the view, such as a keystroke, a timer completion, or a response to an HTTP request.
|
||||
|
||||
</div>
|
||||
|
||||
Notice that you don't call **new** to create an instance of the `AppComponent` class.
|
||||
Angular is creating an instance for you. How?
|
||||
|
||||
The CSS `selector` in the `@Component` decorator specifies an element named `<app-root>`.
|
||||
That element is a placeholder in the body of your `index.html` file:
|
||||
|
||||
<code-example path="displaying-data/src/index.html" header="src/index.html (body)" region="body"></code-example>
|
||||
|
||||
When you bootstrap with the `AppComponent` class (in <code>main.ts</code>), Angular looks for a `<app-root>`
|
||||
in the `index.html`, finds it, instantiates an instance of `AppComponent`, and renders it
|
||||
inside the `<app-root>` tag.
|
||||
|
||||
Now run the app. It should display the title and hero name:
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/displaying-data/title-and-hero.png" alt="Title and Hero">
|
||||
</div>
|
||||
|
||||
The next few sections review some of the coding choices in the app.
|
||||
|
||||
|
||||
## Choosing the template source
|
||||
|
||||
The `@Component` metadata tells Angular where to find the component's template.
|
||||
You can store your component's template in one of two places.
|
||||
|
||||
* You can define the template *inline* using the `template` property of the `@Component` decorator. An inline template is useful for a small demo or test.
|
||||
* Alternatively, you can define the template in a separate HTML file and link to that file in the `templateUrl` property of the `@Component` decorator. This configuration is typical for anything more complex than a small test or demo, and is the default when you generate a new component.
|
||||
|
||||
In either style, the template data bindings have the same access to the component's properties.
|
||||
Here the app uses inline HTML because the template is small and the demo is simpler without the additional HTML file.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
By default, the Angular CLI command [`ng generate component`](cli/generate) generates components with a template file.
|
||||
You can override that by adding the "-t" (short for `inlineTemplate=true`) option:
|
||||
|
||||
<code-example hideCopy language="sh" class="code-shell">
|
||||
ng generate component hero -t
|
||||
</code-example>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
## Initialization
|
||||
|
||||
The following example uses variable assignment to initialize the components.
|
||||
|
||||
<code-example path="displaying-data/src/app/app-ctor.component.1.ts" region="class"></code-example>
|
||||
|
||||
You could instead declare and initialize the properties using a constructor.
|
||||
This app uses more terse "variable assignment" style simply for brevity.
|
||||
|
||||
|
||||
{@a ngFor}
|
||||
|
||||
## Add logic to loop through data
|
||||
|
||||
The `*ngFor` directive (predefined by Angular) lets you loop through data. The following example uses the directive to show all of the values in an array property.
|
||||
|
||||
To display a list of heroes, begin by adding an array of hero names to the component and redefine `myHero` to be the first name in the array.
|
||||
|
||||
|
||||
<code-example path="displaying-data/src/app/app.component.2.ts" header="src/app/app.component.ts (class)" region="class"></code-example>
|
||||
|
||||
|
||||
Now use the Angular `ngFor` directive in the template to display each item in the `heroes` list.
|
||||
|
||||
|
||||
<code-example path="displaying-data/src/app/app.component.2.ts" header="src/app/app.component.ts (template)" region="template"></code-example>
|
||||
|
||||
|
||||
This UI uses the HTML unordered list with `<ul>` and `<li>` tags. The `*ngFor`
|
||||
in the `<li>` element is the Angular "repeater" directive.
|
||||
It marks that `<li>` element (and its children) as the "repeater template":
|
||||
|
||||
|
||||
<code-example path="displaying-data/src/app/app.component.2.ts" header="src/app/app.component.ts (li)" region="li"></code-example>
|
||||
|
||||
<div class="alert is-important">
|
||||
|
||||
Don't forget the leading asterisk (\*) in `*ngFor`. It is an essential part of the syntax.
|
||||
Read more about `ngFor` and `*` in the [ngFor section](guide/built-in-directives#ngfor) of the [Built-in directives](guide/built-in-directives) page.
|
||||
|
||||
</div>
|
||||
|
||||
Notice the `hero` in the `ngFor` double-quoted instruction;
|
||||
it is an example of a template input variable. Read
|
||||
more about template input variables in the [microsyntax](guide/built-in-directives#microsyntax) section of
|
||||
the [Built-in directives](guide/built-in-directives) page.
|
||||
|
||||
Angular duplicates the `<li>` for each item in the list, setting the `hero` variable
|
||||
to the item (the hero) in the current iteration. Angular uses that variable as the
|
||||
context for the interpolation in the double curly braces.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
In this case, `ngFor` is displaying an array, but `ngFor` can
|
||||
repeat items for any [iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) object.
|
||||
|
||||
</div>
|
||||
|
||||
Now the heroes appear in an unordered list.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/displaying-data/hero-names-list.png" alt="After ngfor">
|
||||
</div>
|
||||
|
||||
|
||||
## Creating a class for the data
|
||||
|
||||
The app's code defines the data directly inside the component, which isn't best practice.
|
||||
In a simple demo, however, it's fine.
|
||||
|
||||
At the moment, the binding is to an array of strings.
|
||||
In real applications, most bindings are to more specialized objects.
|
||||
|
||||
To convert this binding to use specialized objects, turn the array
|
||||
of hero names into an array of `Hero` objects. For that you'll need a `Hero` class:
|
||||
|
||||
<code-example language="sh" class="code-shell">
|
||||
ng generate class hero
|
||||
</code-example>
|
||||
|
||||
This command creates the following code.
|
||||
|
||||
|
||||
<code-example path="displaying-data/src/app/hero.ts" header="src/app/hero.ts"></code-example>
|
||||
|
||||
You've defined a class with a constructor and two properties: `id` and `name`.
|
||||
|
||||
It might not look like the class has properties, but it does.
|
||||
The declaration of the constructor parameters takes advantage of a TypeScript shortcut.
|
||||
|
||||
Consider the first parameter:
|
||||
|
||||
|
||||
<code-example path="displaying-data/src/app/hero.ts" header="src/app/hero.ts (id)" region="id"></code-example>
|
||||
|
||||
That brief syntax does a lot:
|
||||
|
||||
* Declares a constructor parameter and its type.
|
||||
* Declares a public property of the same name.
|
||||
* Initializes that property with the corresponding argument when creating an instance of the class.
|
||||
|
||||
|
||||
### Using the Hero class
|
||||
|
||||
After importing the `Hero` class, the `AppComponent.heroes` property can return a _typed_ array
|
||||
of `Hero` objects:
|
||||
|
||||
|
||||
<code-example path="displaying-data/src/app/app.component.3.ts" header="src/app/app.component.ts (heroes)" region="heroes"></code-example>
|
||||
|
||||
|
||||
|
||||
Next, update the template.
|
||||
At the moment it displays the hero's `id` and `name`.
|
||||
Fix that to display only the hero's `name` property.
|
||||
|
||||
|
||||
<code-example path="displaying-data/src/app/app.component.3.ts" header="src/app/app.component.ts (template)" region="template"></code-example>
|
||||
|
||||
|
||||
The display looks the same, but the code is clearer.
|
||||
|
||||
{@a ngIf}
|
||||
|
||||
## Conditional display with NgIf
|
||||
|
||||
Sometimes an app needs to display a view or a portion of a view only under specific circumstances.
|
||||
|
||||
Let's change the example to display a message if there are more than three heroes.
|
||||
|
||||
The Angular `ngIf` directive inserts or removes an element based on a _truthy/falsy_ condition.
|
||||
To see it in action, add the following paragraph at the bottom of the template:
|
||||
|
||||
|
||||
<code-example path="displaying-data/src/app/app.component.ts" header="src/app/app.component.ts (message)" region="message"></code-example>
|
||||
|
||||
|
||||
<div class="alert is-important">
|
||||
|
||||
Don't forget the leading asterisk (\*) in `*ngIf`. It is an essential part of the syntax.
|
||||
Read more about `ngIf` and `*` in the [ngIf section](guide/built-in-directives#ngIf) of the [Built-in directives](guide/built-in-directives) page.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
The template expression inside the double quotes,
|
||||
`*ngIf="heroes.length > 3"`, looks and behaves much like TypeScript.
|
||||
When the component's list of heroes has more than three items, Angular adds the paragraph
|
||||
to the DOM and the message appears.
|
||||
If there are three or fewer items, Angular omits the paragraph, so no message appears.
|
||||
|
||||
For more information, see [template expression operators](guide/interpolation#template-expressions).
|
||||
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Angular isn't showing and hiding the message. It is adding and removing the paragraph element from the DOM. That improves performance, especially in larger projects when conditionally including or excluding
|
||||
big chunks of HTML with many data bindings.
|
||||
|
||||
</div>
|
||||
|
||||
Try it out. Because the array has four items, the message should appear.
|
||||
Go back into <code>app.component.ts</code> and delete or comment out one of the elements from the heroes array.
|
||||
The browser should refresh automatically and the message should disappear.
|
||||
|
||||
|
||||
## Summary
|
||||
Now you know how to use:
|
||||
|
||||
* **Interpolation** with double curly braces to display a component property.
|
||||
* **ngFor** to display an array of items.
|
||||
* A TypeScript class to shape the **model data** for your component and display properties of that model.
|
||||
* **ngIf** to conditionally display a chunk of HTML based on a boolean expression.
|
||||
|
||||
Here's the final code:
|
||||
|
||||
<code-tabs>
|
||||
|
||||
<code-pane header="src/app/app.component.ts" path="displaying-data/src/app/app.component.ts" region="final">
|
||||
|
||||
</code-pane>
|
||||
|
||||
<code-pane header="src/app/hero.ts" path="displaying-data/src/app/hero.ts">
|
||||
|
||||
</code-pane>
|
||||
|
||||
<code-pane header="src/app/app.module.ts" path="displaying-data/src/app/app.module.ts">
|
||||
|
||||
</code-pane>
|
||||
|
||||
<code-pane header="main.ts" path="displaying-data/src/main.ts">
|
||||
|
||||
</code-pane>
|
||||
|
||||
</code-tabs>
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
# How event binding works
|
||||
|
||||
In an event binding, Angular configures an event handler for the target event.
|
||||
You can use event binding with your own custom events.
|
||||
|
||||
When the component or directive raises the event, the handler executes the template statement.
|
||||
The template statement performs an action in response to the event.
|
||||
|
||||
## Handling events
|
||||
|
||||
A common way to handle events is to pass the event object, `$event`, to the method handling the event.
|
||||
The `$event` object often contains information the method needs, such as a user's name or an image URL.
|
||||
|
||||
The target event determines the shape of the `$event` object.
|
||||
If the target event is a native DOM element event, then `$event` is a [DOM event object](https://developer.mozilla.org/en-US/docs/Web/Events), with properties such as `target` and `target.value`.
|
||||
|
||||
In the following example the code sets the `<input>` `value` property by binding to the `name` property.
|
||||
|
||||
|
||||
<code-example path="event-binding/src/app/app.component.html" region="event-binding-3" header="src/app/app.component.html"></code-example>
|
||||
|
||||
With this example, the following actions occur:
|
||||
|
||||
1. The code binds to the `input` event of the `<input>` element, which allows the code to listen for changes.
|
||||
1. When the user makes changes, the component raises the `input` event.
|
||||
1. The binding executes the statement within a context that includes the DOM event object, `$event`.
|
||||
1. Angular retrieves the changed text by following the path `$event.target.value` and updates the `name` property.
|
||||
|
||||
If the event belongs to a directive or component, `$event` has the shape that the directive or component produces.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Event binding `(event)`
|
||||
# Event binding
|
||||
|
||||
Event binding allows you to listen for certain events such as
|
||||
keystrokes, mouse movements, clicks, and touches.
|
||||
Event binding allows you to listen for and respond to user actions such as keystrokes, mouse movements, clicks, and touches.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
@@ -9,100 +8,59 @@ See the <live-example></live-example> for a working example containing the code
|
||||
|
||||
</div>
|
||||
|
||||
Angular event binding syntax consists of a **target event** name
|
||||
within parentheses on the left of an equal sign, and a quoted
|
||||
template statement on the right.
|
||||
The following event binding listens for the button's click events, calling
|
||||
the component's `onSave()` method whenever a click occurs:
|
||||
## Binding to events
|
||||
|
||||
To bind to an event you use the Angular event binding syntax.
|
||||
This syntax consists of a target event name within parentheses to the left of an equal sign, and a quoted template statement to the right.
|
||||
In the following example, the target event name is `click` and the template statement is `onSave()`.
|
||||
|
||||
<code-example language="html" header="Event binding syntax">
|
||||
<button (click)="onSave()">Save</button>
|
||||
</code-example>
|
||||
|
||||
The event binding listens for the button's click events and calls the component's `onSave()` method whenever a click occurs.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src='generated/images/guide/template-syntax/syntax-diagram.svg' alt="Syntax diagram">
|
||||
</div>
|
||||
|
||||
## Target event
|
||||
|
||||
As above, the target is the button's click event.
|
||||
|
||||
<code-example path="event-binding/src/app/app.component.html" region="event-binding-1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Alternatively, use the `on-` prefix, known as the canonical form:
|
||||
|
||||
<code-example path="event-binding/src/app/app.component.html" region="event-binding-2" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Element events may be the more common targets, but Angular looks first to see if the name matches an event property
|
||||
of a known directive, as it does in the following example:
|
||||
|
||||
<code-example path="event-binding/src/app/app.component.html" region="custom-directive" header="src/app/app.component.html"></code-example>
|
||||
|
||||
If the name fails to match an element event or an output property of a known directive,
|
||||
Angular reports an “unknown directive” error.
|
||||
|
||||
## *$event* and event handling statements
|
||||
|
||||
In an event binding, Angular sets up an event handler for the target event.
|
||||
|
||||
When the event is raised, the handler executes the template statement.
|
||||
The template statement typically involves a receiver, which performs an action
|
||||
in response to the event, such as storing a value from the HTML control
|
||||
into a model.
|
||||
|
||||
The binding conveys information about the event. This information can include data values such as an event object, string, or number named `$event`.
|
||||
|
||||
The target event determines the shape of the `$event` object.
|
||||
If the target event is a native DOM element event, then `$event` is a
|
||||
[DOM event object](https://developer.mozilla.org/en-US/docs/Web/Events),
|
||||
with properties such as `target` and `target.value`.
|
||||
|
||||
Consider this example:
|
||||
|
||||
<code-example path="event-binding/src/app/app.component.html" region="event-binding-3" header="src/app/app.component.html"></code-example>
|
||||
|
||||
This code sets the `<input>` `value` property by binding to the `name` property.
|
||||
To listen for changes to the value, the code binds to the `input`
|
||||
event of the `<input>` element.
|
||||
When the user makes changes, the `input` event is raised, and the binding executes
|
||||
the statement within a context that includes the DOM event object, `$event`.
|
||||
|
||||
To update the `name` property, the changed text is retrieved by following the path `$event.target.value`.
|
||||
|
||||
If the event belongs to a directive—recall that components
|
||||
are directives—`$event` has whatever shape the directive produces.
|
||||
|
||||
## Custom events with `EventEmitter`
|
||||
|
||||
Directives typically raise custom events with an Angular [EventEmitter](api/core/EventEmitter).
|
||||
The directive creates an `EventEmitter` and exposes it as a property.
|
||||
The directive calls `EventEmitter.emit(payload)` to fire an event, passing in a message payload, which can be anything.
|
||||
Parent directives listen for the event by binding to this property and accessing the payload through the `$event` object.
|
||||
[Directives](guide/built-in-directives) typically raise custom events with an Angular [EventEmitter](api/core/EventEmitter) as follows.
|
||||
|
||||
1. The directive creates an `EventEmitter` and exposes it as a property.
|
||||
1. The directive then calls `EventEmitter.emit(data)` to emit an event, passing in message data, which can be anything.
|
||||
1. Parent directives listen for the event by binding to this property and accessing the data through the `$event` object.
|
||||
|
||||
Consider an `ItemDetailComponent` that presents item information and responds to user actions.
|
||||
Although the `ItemDetailComponent` has a delete button, it doesn't know how to delete the hero. It can only raise an event reporting the user's delete request.
|
||||
Although the `ItemDetailComponent` has a delete button, it doesn't contain the functionality to delete the hero.
|
||||
It can only raise an event reporting the user's delete request.
|
||||
|
||||
Here are the pertinent excerpts from that `ItemDetailComponent`:
|
||||
|
||||
<code-example path="event-binding/src/app/item-detail/item-detail.component.html" header="src/app/item-detail/item-detail.component.html (template)" region="line-through"></code-example>
|
||||
|
||||
The component defines a `deleteRequest` property that returns an `EventEmitter`.
|
||||
When the user clicks **Delete**, the component invokes the `delete()` method, telling the `EventEmitter` to emit an `Item` object.
|
||||
|
||||
<code-example path="event-binding/src/app/item-detail/item-detail.component.ts" header="src/app/item-detail/item-detail.component.ts (deleteRequest)" region="deleteRequest"></code-example>
|
||||
|
||||
The component defines a `deleteRequest` property that returns an `EventEmitter`.
|
||||
When the user clicks *delete*, the component invokes the `delete()` method,
|
||||
telling the `EventEmitter` to emit an `Item` object.
|
||||
|
||||
Now imagine a hosting parent component that binds to the `deleteRequest` event
|
||||
of the `ItemDetailComponent`.
|
||||
The hosting parent component binds to the `deleteRequest` event of the `ItemDetailComponent` as follows.
|
||||
|
||||
<code-example path="event-binding/src/app/app.component.html" header="src/app/app.component.html (event-binding-to-component)" region="event-binding-to-component"></code-example>
|
||||
|
||||
When the `deleteRequest` event fires, Angular calls the parent component's
|
||||
`deleteItem()` method, passing the *item-to-delete* (emitted by `ItemDetail`)
|
||||
in the `$event` variable.
|
||||
When the `deleteRequest` event fires, Angular calls the parent component's `deleteItem()` method with the item.
|
||||
|
||||
## Template statements have side effects
|
||||
### Determining an event target
|
||||
|
||||
Though [template expressions](guide/interpolation#template-expressions) shouldn't have [side effects](guide/property-binding#avoid-side-effects), template
|
||||
statements usually do. The `deleteItem()` method does have
|
||||
a side effect: it deletes an item.
|
||||
To determine an event target, Angular checks if the name of the target event matches an event property of a known directive.
|
||||
In the following example, Angular checks to see if `myClick` is an event on the custom `ClickDirective`.
|
||||
|
||||
Deleting an item updates the model, and depending on your code, triggers
|
||||
other changes including queries and saving to a remote server.
|
||||
These changes propagate through the system and ultimately display in this and other views.
|
||||
<code-example path="event-binding/src/app/app.component.html" region="custom-directive" header="src/app/app.component.html"></code-example>
|
||||
|
||||
If the target event name, `myClick` fails to match an element event or an output property of `ClickDirective`, Angular reports an "unknown directive" error.
|
||||
|
||||
<hr />
|
||||
|
||||
## What's next
|
||||
|
||||
For more information on how event binding works, see [How event binding works](guide/event-binding-concepts).
|
||||
|
||||
@@ -0,0 +1,476 @@
|
||||
# Example applications
|
||||
|
||||
The following is a list of the example applications in the [Angular documentation](docs).
|
||||
|
||||
## Fundamentals
|
||||
|
||||
These examples demonstrate minimal, fundamental concepts.
|
||||
|
||||
### Getting started application
|
||||
|
||||
<live-example name="getting-started"></live-example>
|
||||
|
||||
Introductory application demonstrating Angular features.
|
||||
For more information, see [Getting started](start).
|
||||
|
||||
|
||||
### Launching your app
|
||||
|
||||
<live-example name="bootstrapping"></live-example>
|
||||
|
||||
Demonstrates the Angular bootstrapping process.
|
||||
For more information, see [Launching your app with a root module](guide/bootstrapping).
|
||||
|
||||
### Structure of Angular applications
|
||||
|
||||
<live-example name="architecture"></live-example>
|
||||
|
||||
Demonstrates the fundamental architecture of Angular applications.
|
||||
For more information, see [Introduction to Angular concepts](guide/architecture).
|
||||
|
||||
### Setting the document title
|
||||
|
||||
<live-example name="set-document-title"></live-example>
|
||||
|
||||
Demonstrates customizing the document title in the browser.
|
||||
For more information, see [Set the document title](guide/set-document-title).
|
||||
|
||||
|
||||
## Tour of Heroes tutorial application
|
||||
|
||||
The Tour of Heroes is a comprehensive tutorial that guides you through the process of building an application with many of Angular's most popular features.
|
||||
|
||||
### Tour of Heroes: completed application
|
||||
|
||||
<live-example name="toh-pt6"></live-example>
|
||||
|
||||
Completed Tour of Heroes example application.
|
||||
For more information, see [Tour of Heroes app and tutorial](tutorial).
|
||||
|
||||
### Tour of Heroes: Creating an application
|
||||
|
||||
<live-example name="toh-pt0"></live-example>
|
||||
|
||||
Initial Tour of Heroes example application for beginning the tutorial.
|
||||
For more information, see [Create a new project](tutorial/toh-pt0).
|
||||
|
||||
### Tour of Heroes: The hero editor
|
||||
|
||||
<live-example name="toh-pt1"></live-example>
|
||||
|
||||
First step of the Tour of Heroes example application.
|
||||
For more information, see [The hero editor](tutorial/toh-pt1).
|
||||
|
||||
### Tour of Heroes: Display a selection list
|
||||
|
||||
<live-example name="toh-pt2"></live-example>
|
||||
|
||||
Second step of the Tour of Heroes example application.
|
||||
For more information, see [Display a selection list](tutorial/toh-pt2).
|
||||
|
||||
### Tour of Heroes: Create a feature component
|
||||
|
||||
<live-example name="toh-pt3"></live-example>
|
||||
|
||||
Third step of the Tour of Heroes example application.
|
||||
For more information, see [Create a feature component](tutorial/toh-pt3).
|
||||
|
||||
### Tour of Heroes: Add services
|
||||
|
||||
<live-example name="toh-pt4"></live-example>
|
||||
|
||||
Fourth step of the Tour of Heroes example application.
|
||||
For more information, see [Add services](tutorial/toh-pt4).
|
||||
|
||||
### Tour of Heroes: Add in-app navigation with routing
|
||||
|
||||
<live-example name="toh-pt5"></live-example>
|
||||
|
||||
Fifth step of the Tour of Heroes example application.
|
||||
For more information, see [Add in-app navigation with routing](tutorial/toh-pt5).
|
||||
|
||||
### Tour of Heroes: Get data from a server
|
||||
|
||||
<live-example name="toh-pt6"></live-example>
|
||||
|
||||
Sixth and final step of the Tour of Heroes example application.
|
||||
For more information, see [Get data from a server](tutorial/toh-pt6).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Working with templates
|
||||
|
||||
These examples demonstrate features of Angular templates.
|
||||
|
||||
### Accessibility
|
||||
|
||||
<live-example name="accessibility"></live-example>
|
||||
|
||||
Demonstrates building Angular applications in a more accessible way.
|
||||
For more information, see [Accessibility](guide/accessibility).
|
||||
|
||||
### Animations
|
||||
|
||||
<live-example name="animations"></live-example>
|
||||
|
||||
Demonstrates Angular's animation features.
|
||||
For more information, see [Introduction to Angular animations](guide/animations).
|
||||
|
||||
### Attribute, class, and style bindings
|
||||
|
||||
<live-example name="attribute-binding"></live-example>
|
||||
|
||||
Demonstrates Angular attribute, class, and style bindings.
|
||||
For more information, see [Attribute, class, and style bindings](guide/attribute-binding).
|
||||
|
||||
### Attribute directives
|
||||
|
||||
<live-example name="attribute-directives"></live-example>
|
||||
|
||||
Demonstrates Angular attribute directives.
|
||||
For more information, see [Attribute directives](guide/attribute-directives).
|
||||
|
||||
### Binding syntax
|
||||
|
||||
<live-example name="binding-syntax"></live-example>
|
||||
|
||||
Demonstrates Angular's binding syntax.
|
||||
For more information, see [Binding syntax: an overview](guide/binding-syntax).
|
||||
|
||||
### Built-in directives
|
||||
|
||||
<live-example name="built-in-directives"></live-example>
|
||||
|
||||
Demonstrates Angular built-in directives.
|
||||
For more information, see [Built-in directives](guide/built-in-directives).
|
||||
|
||||
### Built-in template functions
|
||||
|
||||
<live-example name="built-in-template-functions"></live-example>
|
||||
|
||||
Demonstrates Angular built-in template functions.
|
||||
For more information, see the [`$any()` type cast function section](guide/template-expression-operators#the-any-type-cast-function) of [Template expression operators](guide/template-expression-operators).
|
||||
|
||||
### Interpolation
|
||||
|
||||
<live-example name="interpolation"></live-example>
|
||||
|
||||
Demonstrates Angular interpolation.
|
||||
For more information, see [Interpolation and template expressions](guide/interpolation).
|
||||
|
||||
### Template expression operators
|
||||
|
||||
<live-example name="template-expression-operators"></live-example>
|
||||
|
||||
Demonstrates expression operators in Angular templates.
|
||||
For more information, see [Template expression operators](guide/template-expression-operators).
|
||||
|
||||
### Template reference variables
|
||||
|
||||
<live-example name="template-reference-variables"></live-example>
|
||||
|
||||
Demonstrates Angular's template reference variables.
|
||||
For more information, see [Template reference variables](guide/template-reference-variables).
|
||||
|
||||
### `<ngcontainer>`
|
||||
|
||||
<live-example name="ngcontainer"></live-example>
|
||||
|
||||
Demonstrates `<ngcontainer>`.
|
||||
For more information, see the [ngtemplate section](guide/structural-directives#ngcontainer) of [Structural directives](guide/structural-directives) .
|
||||
|
||||
### Pipes
|
||||
|
||||
<live-example name="pipes"></live-example>
|
||||
|
||||
Demonstrates Angular pipes.
|
||||
For more information, see [Transforming Data Using Pipes](guide/pipes).
|
||||
|
||||
### Property binding
|
||||
|
||||
<live-example name="property-binding"></live-example>
|
||||
|
||||
Demonstrates property binding in Angular.
|
||||
For more information, see [Property binding](guide/property-binding).
|
||||
|
||||
### Structural directives
|
||||
|
||||
<live-example name="structural-directives"></live-example>
|
||||
|
||||
Demonstrates Angular structural directives.
|
||||
For more information, see [Structural directives](guide/structural-directives).
|
||||
|
||||
|
||||
### Two-way binding
|
||||
|
||||
<live-example name="two-way-binding"></live-example>
|
||||
|
||||
Demonstrates two-way data binding in Angular applications.
|
||||
For more information, see [Two-way binding](guide/two-way-binding).
|
||||
|
||||
### Template syntax
|
||||
|
||||
<live-example name="template-syntax"></live-example>
|
||||
|
||||
Comprehensive demonstration of Angular's template syntax.
|
||||
For more information, see [Template reference variables](guide/template-syntax).
|
||||
|
||||
### User input
|
||||
|
||||
<live-example name="user-input"></live-example>
|
||||
|
||||
Demonstrates responding to user actions.
|
||||
For more information, see [User input](guide/user-input).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Working with components
|
||||
|
||||
These examples demonstrate features of Angular components.
|
||||
|
||||
### Component interaction
|
||||
|
||||
<live-example name="component-interaction"></live-example>
|
||||
|
||||
Demonstrates how Angular shares data between components.
|
||||
For more information, see [Component interaction](guide/component-interaction).
|
||||
|
||||
### Component styles
|
||||
|
||||
<live-example name="component-styles"></live-example>
|
||||
|
||||
Demonstrates styling in Angular apps.
|
||||
For more information, see [Component styles](guide/component-styles).
|
||||
|
||||
### Dynamic component loader
|
||||
|
||||
<live-example name="dynamic-component-loader"></live-example>
|
||||
|
||||
Demonstrates how to dynamically load components.
|
||||
For more information, see [Dynamic component loader](guide/dynamic-component-loader).
|
||||
|
||||
### Elements
|
||||
|
||||
<live-example name="elements"></live-example>
|
||||
|
||||
Demonstrates using Angular custom elements.
|
||||
For more information, see [Angular elements overview](guide/elements).
|
||||
|
||||
### Event binding
|
||||
|
||||
<live-example name="event-binding"></live-example>
|
||||
|
||||
Demonstrates binding to events in Angular.
|
||||
For more information, see [Event binding](guide/event-binding).
|
||||
|
||||
### `@Input()` and `@Output()`
|
||||
|
||||
<live-example name="inputs-outputs"></live-example>
|
||||
|
||||
Demonstrates `@Input()` and `@Output()` in components and directives.
|
||||
For more information, see [`@Input()` and `@Output()` properties](guide/inputs-outputs).
|
||||
|
||||
|
||||
### Lifecycle hooks
|
||||
|
||||
<live-example name="lifecycle-hooks"></live-example>
|
||||
|
||||
Demonstrates Angular lifecycle hooks such as `ngOnInit()` and `ngOnChanges()`.
|
||||
For more information, see [Hooking into the component lifecycle](guide/lifecycle-hooks).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Dependency injection
|
||||
|
||||
### Dependency injection fundamentals
|
||||
|
||||
<live-example name="dependency-injection"></live-example>
|
||||
|
||||
Demonstrates fundamentals of Angular dependency injection.
|
||||
For more information, see [Dependency injection](guide/dependency-injection).
|
||||
|
||||
### Dependency injection features
|
||||
|
||||
<live-example name="dependency-injection-in-action"></live-example>
|
||||
|
||||
Demonstrates many of the features of Angular dependency injection.
|
||||
For more information, see [Dependency injection in action](guide/dependency-injection).
|
||||
|
||||
### Providing dependencies in NgModules
|
||||
|
||||
<live-example name="providers"></live-example>
|
||||
|
||||
Demonstrates providing services in NgModules.
|
||||
For more information, see [Providing dependencies in modules](guide/providers).
|
||||
|
||||
|
||||
### Hierarchical dependency injection
|
||||
|
||||
<live-example name="hierarchical-dependency-injection"></live-example>
|
||||
|
||||
Demonstrates Angular injector trees and resolution modifiers.
|
||||
For more information, see [Hierarchical injectors](guide/hierarchical-dependency-injection).
|
||||
|
||||
### Dependency injection with `providers` and `viewProviders`
|
||||
|
||||
<live-example name="providers-viewproviders"></live-example>
|
||||
|
||||
Demonstrates how `providers` and `viewproviders` affect dependency injection.
|
||||
For more information, see the [Providing services in `@Component()`](guide/hierarchical-dependency-injection#providing-services-in-component) section of [Hierarchical injectors](guide/hierarchical-dependency-injection).
|
||||
|
||||
|
||||
### Resolution modifiers and dependency injection
|
||||
|
||||
<live-example name="resolution-modifiers"></live-example>
|
||||
|
||||
Demonstrates Angular's resolution modifiers, such as `@Self()`.
|
||||
For more information, see the [Modifying service visibility](guide/hierarchical-dependency-injection#modifying-service-visibility) section of [Hierarchical injectors](guide/hierarchical-dependency-injection).
|
||||
|
||||
|
||||
|
||||
## Forms
|
||||
|
||||
### Forms overview
|
||||
|
||||
<live-example name="forms-overview"></live-example>
|
||||
|
||||
Demonstrates foundational concepts of Angular forms.
|
||||
For more information, see [Introduction to forms in Angular](guide/forms-overview).
|
||||
|
||||
### Reactive forms
|
||||
|
||||
<live-example name="reactive-forms"></live-example>
|
||||
|
||||
Demonstrates Angular's reactive forms.
|
||||
For more information, see [Reactive forms](guide/reactive-forms).
|
||||
|
||||
### Template-driven forms
|
||||
|
||||
<live-example name="forms"></live-example>
|
||||
|
||||
Demonstrates Angular template-driven forms.
|
||||
For more information, see [Building a template-driven form](guide/forms).
|
||||
|
||||
### Form validation
|
||||
|
||||
<live-example name="form-validation"></live-example>
|
||||
|
||||
Demonstrates validating forms in Angular.
|
||||
For more information, see [Validating form input](guide/form-validation).
|
||||
|
||||
### Dynamic forms
|
||||
|
||||
<live-example name="dynamic-form"></live-example>
|
||||
|
||||
Demonstrates creating dynamic forms.
|
||||
For more information, see [Building dynamic forms](guide/dynamic-form).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## NgModules
|
||||
|
||||
### NgModules
|
||||
|
||||
<live-example name="ngmodules"></live-example>
|
||||
|
||||
Demonstrates fundamentals of NgModules.
|
||||
For more information, see [NgModules](guide/ngmodules).
|
||||
|
||||
### Feature modules
|
||||
|
||||
<live-example name="feature-modules"></live-example>
|
||||
|
||||
Demonstrates using feature modules in Angular.
|
||||
For more information, see [Feature modules](guide/feature-modules).
|
||||
|
||||
### Lazy loading NgModules
|
||||
|
||||
<live-example name="lazy-loading-ngmodules"></live-example>
|
||||
|
||||
Demonstrates lazy loading NgModules.
|
||||
For more information, see [Lazy-loading feature modules](guide/lazy-loading-ngmodules).
|
||||
|
||||
|
||||
## Routing
|
||||
|
||||
### Router
|
||||
|
||||
<live-example name="router"></live-example>
|
||||
|
||||
Demonstrates Angular's routing features.
|
||||
For more information, see [Router](guide/router).
|
||||
|
||||
### Router tutorial
|
||||
|
||||
<live-example name="router-tutorial"></live-example>
|
||||
|
||||
Demonstrates Angular's fundamental routing techniques.
|
||||
For more information, see [Using Angular routes in a single-page application](guide/router-tutorial).
|
||||
|
||||
|
||||
|
||||
### Style guide for Documentation contributions
|
||||
|
||||
<live-example name="docs-style-guide"></live-example>
|
||||
|
||||
Demonstrates Angular documentation style guidelines.
|
||||
For more information, see [Angular documentation style guide](guide/docs-style-guide).
|
||||
|
||||
|
||||
## Server communication
|
||||
|
||||
### `HttpClient`
|
||||
|
||||
<live-example name="http"></live-example>
|
||||
|
||||
Demonstrates server interaction using HTTP.
|
||||
For more information, see [Communicating with backend services using HTTP](guide/http).
|
||||
|
||||
|
||||
## Workflow
|
||||
|
||||
### Security
|
||||
|
||||
<live-example name="security"></live-example>
|
||||
|
||||
Demonstrates security concepts in Angular applications.
|
||||
For more information, see [Security](guide/security).
|
||||
|
||||
|
||||
### Testing
|
||||
|
||||
For the sample app that the testing guides describe, see the <live-example noDownload name="testing">sample app</live-example>.
|
||||
|
||||
For the tests featured in the testing guides, see <live-example name="testing" stackblitz="specs" noDownload>tests</live-example>.
|
||||
|
||||
Demonstrates techniques for testing Angular.
|
||||
For more information, see [Testing](guide/testing).
|
||||
|
||||
|
||||
|
||||
|
||||
## Hybrid Angular applications
|
||||
|
||||
### AngularJS to Angular concepts: Quick reference
|
||||
|
||||
<live-example name="ajs-quick-reference"></live-example>
|
||||
|
||||
Demonstrates Angular for those with an AngularJS background.
|
||||
For more information, see [AngularJS to Angular concepts: Quick reference](guide/ajs-quick-reference).
|
||||
|
||||
@@ -957,11 +957,11 @@ as happens in the `search()` method.
|
||||
Rather than forward every `searchText` value directly to the injected `PackageSearchService`,
|
||||
the code in `ngOnInit()` pipes search values through three operators, so that a search value reaches the service only if it's a new value and the user has stopped typing.
|
||||
|
||||
* `debounceTime(500)`&emdash;Wait for the user to stop typing (1/2 second in this case).
|
||||
* `debounceTime(500)`—Wait for the user to stop typing (1/2 second in this case).
|
||||
|
||||
* `distinctUntilChanged()`&emdash;Wait until the search text changes.
|
||||
* `distinctUntilChanged()`—Wait until the search text changes.
|
||||
|
||||
* `switchMap()`&emdash;Send the search request to the service.
|
||||
* `switchMap()`—Send the search request to the service.
|
||||
|
||||
The code sets `packages$` to this re-composed `Observable` of search results.
|
||||
The template subscribes to `packages$` with the [AsyncPipe](api/common/AsyncPipe)
|
||||
|
||||
+11
-17
@@ -327,7 +327,7 @@ You can also nest different clauses together, such as the `plural` and `select`
|
||||
|
||||
## Work with translation files
|
||||
|
||||
After preparing a template for translation, use the Angular CLI `xi18n` command to extract the marked text in the template into a _source language_ file.
|
||||
After preparing a template for translation, use the Angular CLI `extract-i18n` command to extract the marked text in the template into a _source language_ file.
|
||||
The marked text includes text marked with `i18n` and attributes marked with `i18n-`*attribute* as described in the previous section.
|
||||
Follow these steps:
|
||||
|
||||
@@ -344,12 +344,12 @@ You can optionally change the location, format, and name.
|
||||
To extract the source language file, open a terminal window, change to the root directory of your app project, and run the following CLI command:
|
||||
|
||||
<code-example language="sh" class="code-shell">
|
||||
ng xi18n
|
||||
ng extract-i18n
|
||||
</code-example>
|
||||
|
||||
The `xi18n` command creates a source language file named `messages.xlf` in your project's root directory using the [XML Localization Interchange File Format (XLIFF, version 1.2)](https://en.wikipedia.org/wiki/XLIFF "Wikipedia page about XLIFF").
|
||||
The `extract-i18n` command creates a source language file named `messages.xlf` in your project's root directory using the [XML Localization Interchange File Format (XLIFF, version 1.2)](https://en.wikipedia.org/wiki/XLIFF "Wikipedia page about XLIFF").
|
||||
|
||||
Use the following `xi18n` command options to change the source language file location, format, and file name:
|
||||
Use the following `extract-i18n` command options to change the source language file location, format, and file name:
|
||||
|
||||
* `--output-path`: Change the location.
|
||||
* `--format`: Change the format.
|
||||
@@ -358,25 +358,19 @@ Use the following `xi18n` command options to change the source language file loc
|
||||
Note: The `--i18n-locale` option is deprecated.
|
||||
Angular 9 uses the source locale configured in your app's [workspace configuration](guide/workspace-config "Angular workspace configuration") file (`angular.json`).
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The ng xi18n extraction mechanism uses the ViewEngine compiler, which is not able to cope with some code syntax that the Ivy compiler can handle. A fix for this issue is currently under development. To follow or contribute to this fix see [PR 32912](https://github.com/angular/angular/pull/32912).
|
||||
|
||||
</div>
|
||||
|
||||
#### Change the source language file location
|
||||
|
||||
To create a file in the `src/locale` directory, specify the output path as an option, as shown in the following example:
|
||||
|
||||
<code-example language="sh" class="code-shell">
|
||||
ng xi18n --output-path src/locale
|
||||
ng extract-i18n --output-path src/locale
|
||||
</code-example>
|
||||
|
||||
{@a other-formats}
|
||||
|
||||
#### Change the source language file format
|
||||
|
||||
The `xi18n` command can read and write files in three translation formats:
|
||||
The `extract-i18n` command can read and write files in three translation formats:
|
||||
|
||||
* XLIFF 1.2 (default)
|
||||
* XLIFF 2
|
||||
@@ -385,9 +379,9 @@ The `xi18n` command can read and write files in three translation formats:
|
||||
Specify the translation format explicitly with the `--format` command option, as shown in the following examples:
|
||||
|
||||
<code-example language="sh" class="code-shell">
|
||||
ng xi18n --format=xlf
|
||||
ng xi18n --format=xlf2
|
||||
ng xi18n --format=xmb
|
||||
ng extract-i18n --format=xlf
|
||||
ng extract-i18n --format=xlf2
|
||||
ng extract-i18n --format=xmb
|
||||
</code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
@@ -403,14 +397,14 @@ To change the name of the source language file generated by the extraction tool,
|
||||
the `--outFile` command option:
|
||||
|
||||
<code-example language="sh" class="code-shell">
|
||||
ng xi18n --out-file source.xlf
|
||||
ng extract-i18n --out-file source.xlf
|
||||
</code-example>
|
||||
|
||||
{@a localization-folder}
|
||||
|
||||
### Create a translation file for each language
|
||||
|
||||
The `ng xi18n` command (with no options) generates a source language file named `messages.xlf` in the project `src` folder.
|
||||
The `ng extract-i18n` command (with no options) generates a source language file named `messages.xlf` in the project `src` folder.
|
||||
Create *translation* files for each language by copying the source language file.
|
||||
To avoid confusion with multiple translations, you should organize the language translation files by locale in a dedicated `locale` folder under `src/`.
|
||||
Use a filename extension that matches the associated locale, such as `messages.fr.xlf`.
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
# `@Input()` and `@Output()` properties
|
||||
# Sharing data between child and parent directives and components
|
||||
|
||||
`@Input()` and `@Output()` allow Angular to share data between the parent context
|
||||
and child directives or components. An `@Input()` property is writable
|
||||
while an `@Output()` property is observable.
|
||||
A common pattern in Angular is sharing data between a parent component and one or more child components.
|
||||
You can implement this pattern by using the `@Input()` and `@Output()` directives.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
@@ -10,7 +9,7 @@ See the <live-example></live-example> for a working example containing the code
|
||||
|
||||
</div>
|
||||
|
||||
Consider this example of a child/parent relationship:
|
||||
Consider the following hierarchy:
|
||||
|
||||
```html
|
||||
<parent-component>
|
||||
@@ -19,80 +18,52 @@ Consider this example of a child/parent relationship:
|
||||
|
||||
```
|
||||
|
||||
Here, the `<child-component>` selector, or child directive, is embedded
|
||||
within a `<parent-component>`, which serves as the child's context.
|
||||
The `<parent-component>` serves as the context for the `<child-component>`.
|
||||
|
||||
`@Input()` and `@Output()` act as
|
||||
the API, or application programming interface, of the child
|
||||
component in that they allow the child to
|
||||
communicate with the parent. Think of `@Input()` and `@Output()` like ports
|
||||
or doorways—`@Input()` is the doorway into the component allowing data
|
||||
to flow in while `@Output()` is the doorway out of the component, allowing the
|
||||
child component to send data out.
|
||||
`@Input()` and `@Output()` give a child component a way to communicate with its parent component.
|
||||
`@Input()` allows a parent component to update data in the child component.
|
||||
Conversely, `@Output() allows the child to send data to a parent component.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
#### `@Input()` and `@Output()` are independent
|
||||
|
||||
Though `@Input()` and `@Output()` often appear together in apps, you can use
|
||||
them separately. If the nested
|
||||
component is such that it only needs to send data to its parent, you wouldn't
|
||||
need an `@Input()`, only an `@Output()`. The reverse is also true in that if the
|
||||
child only needs to receive data from the parent, you'd only need `@Input()`.
|
||||
|
||||
</div>
|
||||
|
||||
{@a input}
|
||||
|
||||
## How to use `@Input()`
|
||||
|
||||
Use the `@Input()` decorator in a child component or directive to let Angular know
|
||||
that a property in that component can receive its value from its parent component.
|
||||
It helps to remember that the data flow is from the perspective of the
|
||||
child component. So an `@Input()` allows data to be input _into_ the
|
||||
child component from the parent component.
|
||||
## Sending data to a child component
|
||||
|
||||
The `@Input()` decorator in a child component or directive signifies that the property can receive its value from its parent component.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/inputs-outputs/input.svg" alt="Input data flow diagram">
|
||||
</div>
|
||||
|
||||
To illustrate the use of `@Input()`, edit these parts of your app:
|
||||
To use `@Input()`, you must configure the parent and child.
|
||||
|
||||
* The child component class and template
|
||||
* The parent component class and template
|
||||
### Configuring the child component
|
||||
|
||||
|
||||
### In the child
|
||||
|
||||
To use the `@Input()` decorator in a child component class, first import
|
||||
`Input` and then decorate the property with `@Input()`:
|
||||
To use the `@Input()` decorator in a child component class, first import `Input` and then decorate the property with `@Input()`, as in the following example.
|
||||
|
||||
<code-example path="inputs-outputs/src/app/item-detail/item-detail.component.ts" region="use-input" header="src/app/item-detail/item-detail.component.ts"></code-example>
|
||||
|
||||
|
||||
In this case, `@Input()` decorates the property <code class="no-auto-link">item</code>, which has
|
||||
a type of `string`, however, `@Input()` properties can have any type, such as
|
||||
`number`, `string`, `boolean`, or `object`. The value for `item` will come from the parent component, which the next section covers.
|
||||
In this case, `@Input()` decorates the property <code class="no-auto-link">item</code>, which has a type of `string`, however, `@Input()` properties can have any type, such as `number`, `string`, `boolean`, or `object`.
|
||||
The value for `item` comes from the parent component.
|
||||
|
||||
Next, in the child component template, add the following:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/item-detail/item-detail.component.html" region="property-in-template" header="src/app/item-detail/item-detail.component.html"></code-example>
|
||||
|
||||
|
||||
|
||||
### In the parent
|
||||
### Configuring the parent component
|
||||
|
||||
The next step is to bind the property in the parent component's template.
|
||||
In this example, the parent component template is `app.component.html`.
|
||||
|
||||
First, use the child's selector, here `<app-item-detail>`, as a directive within the
|
||||
parent component template. Then, use [property binding](guide/property-binding)
|
||||
to bind the property in the child to the property of the parent.
|
||||
1. Use the child's selector, here `<app-item-detail>`, as a directive within the
|
||||
parent component template.
|
||||
|
||||
2. Use [property binding](guide/property-binding) to bind the `item` property in the child to the `currentItem` property of the parent.
|
||||
|
||||
<code-example path="inputs-outputs/src/app/app.component.html" region="input-parent" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Next, in the parent component class, `app.component.ts`, designate a value for `currentItem`:
|
||||
3. In the parent component class, designate a value for `currentItem`:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/app.component.ts" region="parent-property" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
@@ -104,239 +75,127 @@ The following diagram shows this structure:
|
||||
<img src="generated/images/guide/inputs-outputs/input-diagram-target-source.svg" alt="Property binding diagram">
|
||||
</div>
|
||||
|
||||
The target in the square brackets, `[]`, is the property you decorate
|
||||
with `@Input()` in the child component. The binding source, the part
|
||||
to the right of the equal sign, is the data that the parent
|
||||
component passes to the nested component.
|
||||
The target in the square brackets, `[]`, is the property you decorate with `@Input()` in the child component.
|
||||
The binding source, the part to the right of the equal sign, is the data that the parent component passes to the nested component.
|
||||
|
||||
The key takeaway is that when binding to a child component's property in a parent component—that is, what's
|
||||
in square brackets—you must
|
||||
decorate the property with `@Input()` in the child component.
|
||||
### Watching for `@Input()` changes
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
### `OnChanges` and `@Input()`
|
||||
|
||||
To watch for changes on an `@Input()` property, use
|
||||
`OnChanges`, one of Angular's [lifecycle hooks](guide/lifecycle-hooks#onchanges).
|
||||
`OnChanges` is specifically designed to work with properties that have the
|
||||
`@Input()` decorator. See the [`OnChanges`](guide/lifecycle-hooks#onchanges) section of the [Lifecycle Hooks](guide/lifecycle-hooks) guide for more details and examples.
|
||||
|
||||
</div>
|
||||
To watch for changes on an `@Input()` property, you can use `OnChanges`, one of Angular's [lifecycle hooks](guide/lifecycle-hooks).
|
||||
See the [`OnChanges`](guide/lifecycle-hooks#onchanges) section of the [Lifecycle Hooks](guide/lifecycle-hooks) guide for more details and examples.
|
||||
|
||||
{@a output}
|
||||
|
||||
## How to use `@Output()`
|
||||
|
||||
Use the `@Output()` decorator in the child component or directive to allow data to flow from
|
||||
the child _out_ to the parent.
|
||||
|
||||
An `@Output()` property should normally be initialized to an Angular [`EventEmitter`](api/core/EventEmitter) with values flowing out of the component as [events](guide/event-binding).
|
||||
## Sending data to a parent component
|
||||
|
||||
The `@Output()` decorator in a child component or directive allows data to flow from the child to the parent.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/inputs-outputs/output.svg" alt="Output diagram">
|
||||
</div>
|
||||
|
||||
Just like with `@Input()`, you can use `@Output()`
|
||||
on a property of the child component but its type should be
|
||||
`EventEmitter`.
|
||||
`@Output()` marks a property in a child component as a doorway through which data can travel from the child to the parent.
|
||||
|
||||
`@Output()` marks a property in a child component as a doorway
|
||||
through which data can travel from the child to the parent.
|
||||
The child component then has to raise an event so the
|
||||
parent knows something has changed. To raise an event,
|
||||
`@Output()` works hand in hand with `EventEmitter`,
|
||||
which is a class in `@angular/core` that you
|
||||
use to emit custom events.
|
||||
The child component uses the `@Output()` property to raise an event to notify the parent of the change.
|
||||
To raise an event, an `@Output()` must have the type of `EventEmitter`, which is a class in `@angular/core` that you use to emit custom events.
|
||||
|
||||
When you use `@Output()`, edit these parts of your app:
|
||||
The following example shows how to set up an `@Output()` in a child component that pushes data from an HTML `<input>` to an array in the parent component.
|
||||
|
||||
* The child component class and template
|
||||
* The parent component class and template
|
||||
To use `@Output()`, you must configure the parent and child.
|
||||
|
||||
### Configuring the child component
|
||||
|
||||
The following example shows how to set up an `@Output()` in a child
|
||||
component that pushes data you enter in an HTML `<input>` to an array in the
|
||||
parent component.
|
||||
The following example features an `<input>` where a user can enter a value and click a `<button>` that raises an event. The `EventEmitter` then relays the data to the parent component.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
1. Import `Output` and `EventEmitter` in the child component class:
|
||||
|
||||
The HTML element `<input>` and the Angular decorator `@Input()`
|
||||
are different. This documentation is about component communication in Angular as it pertains to `@Input()` and `@Output()`. For more information on the HTML element `<input>`, see the [W3C Recommendation](https://www.w3.org/TR/html5/sec-forms.html#the-input-element).
|
||||
```js
|
||||
import { Output, EventEmitter } from '@angular/core';
|
||||
|
||||
</div>
|
||||
```
|
||||
|
||||
## In the child
|
||||
1. In the component class, decorate a property with `@Output()`.
|
||||
The following example `newItemEvent` `@Output()` has a type of `EventEmitter`, which means it's an event.
|
||||
|
||||
This example features an `<input>` where a user can enter a value and click a `<button>` that raises an event. The `EventEmitter` then relays the data to the parent component.
|
||||
<code-example path="inputs-outputs/src/app/item-output/item-output.component.ts" region="item-output" header="src/app/item-output/item-output.component.ts"></code-example>
|
||||
|
||||
First, be sure to import `Output` and `EventEmitter`
|
||||
in the child component class:
|
||||
The different parts of the above declaration are as follows:
|
||||
|
||||
```js
|
||||
import { Output, EventEmitter } from '@angular/core';
|
||||
* `@Output()`—a decorator function marking the property as a way for data to go from the child to the parent
|
||||
* `newItemEvent`—the name of the `@Output()`
|
||||
* `EventEmitter<string>`—the `@Output()`'s type
|
||||
* `new EventEmitter<string>()`—tells Angular to create a new event emitter and that the data it emits is of type string.
|
||||
|
||||
```
|
||||
For more information on `EventEmitter`, see the [EventEmitter API documentation](api/core/EventEmitter).
|
||||
|
||||
Next, still in the child, decorate a property with `@Output()` in the component class.
|
||||
The following example `@Output()` is called `newItemEvent` and its type is
|
||||
`EventEmitter`, which means it's an event.
|
||||
1. Create an `addNewItem()` method in the same component class:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/item-output/item-output.component.ts" region="item-output-class" header="src/app/item-output/item-output.component.ts"></code-example>
|
||||
|
||||
<code-example path="inputs-outputs/src/app/item-output/item-output.component.ts" region="item-output" header="src/app/item-output/item-output.component.ts"></code-example>
|
||||
The `addNewItem()` function uses the `@Output()`, `newItemEvent`, to raise an event with the value the user types into the `<input>`.
|
||||
|
||||
The different parts of the above declaration are as follows:
|
||||
### Configuring the child's template
|
||||
|
||||
* `@Output()`—a decorator function marking the property as a way for data to go from the child to the parent
|
||||
* `newItemEvent`—the name of the `@Output()`
|
||||
* `EventEmitter<string>`—the `@Output()`'s type
|
||||
* `new EventEmitter<string>()`—tells Angular to create a new event emitter and that the data it emits is of type string. The type could be any type, such as `number`, `boolean`, and so on. For more information on `EventEmitter`, see the [EventEmitter API documentation](api/core/EventEmitter).
|
||||
|
||||
Next, create an `addNewItem()` method in the same component class:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/item-output/item-output.component.ts" region="item-output-class" header="src/app/item-output/item-output.component.ts"></code-example>
|
||||
|
||||
The `addNewItem()` function uses the `@Output()`, `newItemEvent`,
|
||||
to raise an event in which it emits the value the user
|
||||
types into the `<input>`. In other words, when
|
||||
the user clicks the add button in the UI, the child lets the parent know
|
||||
about the event and gives that data to the parent.
|
||||
|
||||
### In the child's template
|
||||
|
||||
The child's template has two controls. The first is an HTML `<input>` with a
|
||||
[template reference variable](guide/template-reference-variables) , `#newItem`,
|
||||
where the user types in an item name. Whatever the user types
|
||||
into the `<input>` gets stored in the `value` property of the `#newItem` variable.
|
||||
The child's template has two controls.
|
||||
The first is an HTML `<input>` with a [template reference variable](guide/template-reference-variables) , `#newItem`, where the user types in an item name.
|
||||
The `value` property of the `#newItem` variable stores what the user types into the `<input>`.
|
||||
|
||||
<code-example path="inputs-outputs/src/app/item-output/item-output.component.html" region="child-output" header="src/app/item-output/item-output.component.html"></code-example>
|
||||
|
||||
The second element is a `<button>`
|
||||
with an [event binding](guide/event-binding). You know it's
|
||||
an event binding because the part to the left of the equal
|
||||
sign is in parentheses, `(click)`.
|
||||
The second element is a `<button>` with a `click` [event binding](guide/event-binding).
|
||||
|
||||
The `(click)` event is bound to the `addNewItem()` method in the child component class which
|
||||
takes as its argument whatever the value of `#newItem.value` property is.
|
||||
The `(click)` event is bound to the `addNewItem()` method in the child component class.
|
||||
The `addNewItem()` method takes as its argument the value of the `#newItem.value` property.
|
||||
|
||||
Now the child component has an `@Output()`
|
||||
for sending data to the parent and a method for raising an event.
|
||||
The next step is in the parent.
|
||||
### Configuring the parent component
|
||||
|
||||
## In the parent
|
||||
|
||||
In this example, the parent component is `AppComponent`, but you could use
|
||||
any component in which you could nest the child.
|
||||
|
||||
The `AppComponent` in this example features a list of `items`
|
||||
in an array and a method for adding more items to the array.
|
||||
The `AppComponent` in this example features a list of `items` in an array and a method for adding more items to the array.
|
||||
|
||||
<code-example path="inputs-outputs/src/app/app.component.ts" region="add-new-item" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
The `addItem()` method takes an argument in the form of a string
|
||||
and then pushes, or adds, that string to the `items` array.
|
||||
The `addItem()` method takes an argument in the form of a string and then adds that string to the `items` array.
|
||||
|
||||
### In the parent's template
|
||||
### Configuring the parent's template
|
||||
|
||||
Next, in the parent's template, bind the parent's
|
||||
method to the child's event. Put the child selector, here `<app-item-output>`,
|
||||
within the parent component's
|
||||
template, `app.component.html`.
|
||||
1. In the parent's template, bind the parent's method to the child's event.
|
||||
|
||||
<code-example path="inputs-outputs/src/app/app.component.html" region="output-parent" header="src/app/app.component.html"></code-example>
|
||||
1. Put the child selector, here `<app-item-output>`, within the parent component's template, `app.component.html`.
|
||||
|
||||
The event binding, `(newItemEvent)='addItem($event)'`, tells
|
||||
Angular to connect the event in the child, `newItemEvent`, to
|
||||
the method in the parent, `addItem()`, and that the event that the child
|
||||
is notifying the parent about is to be the argument of `addItem()`.
|
||||
In other words, this is where the actual hand off of data takes place.
|
||||
The `$event` contains the data that the user types into the `<input>`
|
||||
in the child template UI.
|
||||
<code-example path="inputs-outputs/src/app/app.component.html" region="output-parent" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Now, in order to see the `@Output()` working, add the following to the parent's template:
|
||||
The event binding, `(newItemEvent)='addItem($event)'`, connects the event in the child, `newItemEvent`, to the method in the parent, `addItem()`.
|
||||
|
||||
```html
|
||||
<ul>
|
||||
<li *ngFor="let item of items">{{item}}</li>
|
||||
</ul>
|
||||
The `$event` contains the data that the user types into the `<input>` in the child template UI.
|
||||
|
||||
To see the `@Output()` working, you can add the following to the parent's template:
|
||||
|
||||
```html
|
||||
<ul>
|
||||
<li *ngFor="let item of items">{{item}}</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
The `*ngFor` iterates over the items in the `items` array. When you enter a value in the child's `<input>` and click the button, the child emits the event and the parent's `addItem()` method pushes the value to the `items` array and it renders in the list.
|
||||
The `*ngFor` iterates over the items in the `items` array.
|
||||
When you enter a value in the child's `<input>` and click the button, the child emits the event and the parent's `addItem()` method pushes the value to the `items` array and new item renders in the list.
|
||||
|
||||
|
||||
## `@Input()` and `@Output()` together
|
||||
## Using `@Input()` and `@Output()` together
|
||||
|
||||
You can use `@Input()` and `@Output()` on the same child component as in the following:
|
||||
You can use `@Input()` and `@Output()` on the same child component as follows:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/app.component.html" region="together" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The target, `item`, which is an `@Input()` property in the child component class, receives its value from the parent's property, `currentItem`. When you click delete, the child component raises an event, `deleteRequest`, which is the argument for the parent's `crossOffItem()` method.
|
||||
The target, `item`, which is an `@Input()` property in the child component class, receives its value from the parent's property, `currentItem`.
|
||||
When you click delete, the child component raises an event, `deleteRequest`, which is the argument for the parent's `crossOffItem()` method.
|
||||
|
||||
The following diagram is of an `@Input()` and an `@Output()` on the same
|
||||
child component and shows the different parts of each:
|
||||
The following diagram shows the different parts of the `@Input()` and `@Output()` on the `<app-input-output>` child component.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/inputs-outputs/input-output-diagram.svg" alt="Input/Output diagram">
|
||||
</div>
|
||||
|
||||
As the diagram shows, use inputs and outputs together in the same manner as using them separately. Here, the child selector is `<app-input-output>` with `item` and `deleteRequest` being `@Input()` and `@Output()`
|
||||
properties in the child component class. The property `currentItem` and the method `crossOffItem()` are both in the parent component class.
|
||||
The child selector is `<app-input-output>` with `item` and `deleteRequest` being `@Input()` and `@Output()`
|
||||
properties in the child component class.
|
||||
The property `currentItem` and the method `crossOffItem()` are both in the parent component class.
|
||||
|
||||
To combine property and event bindings using the banana-in-a-box
|
||||
syntax, `[()]`, see [Two-way Binding](guide/two-way-binding).
|
||||
|
||||
## `@Input()` and `@Output()` declarations
|
||||
|
||||
Instead of using the `@Input()` and `@Output()` decorators
|
||||
to declare inputs and outputs, you can identify
|
||||
members in the `inputs` and `outputs` arrays
|
||||
of the directive metadata, as in this example:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/in-the-metadata/in-the-metadata.component.ts" region="metadata" header="src/app/in-the-metadata/in-the-metadata.component.ts"></code-example>
|
||||
|
||||
While declaring `inputs` and `outputs` in the `@Directive` and `@Component`
|
||||
metadata is possible, it is a better practice to use the `@Input()` and `@Output()`
|
||||
class decorators instead, as follows:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/input-output/input-output.component.ts" region="input-output" header="src/app/input-output/input-output.component.ts"></code-example>
|
||||
|
||||
See the [Decorate input and output properties](guide/styleguide#decorate-input-and-output-properties) section of the
|
||||
[Style Guide](guide/styleguide) for details.
|
||||
|
||||
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
If you get a template parse error when trying to use inputs or outputs, but you know that the
|
||||
properties do indeed exist, double check
|
||||
that your properties are annotated with `@Input()` / `@Output()` or that you've declared
|
||||
them in an `inputs`/`outputs` array:
|
||||
|
||||
<code-example language="bash">
|
||||
Uncaught Error: Template parse errors:
|
||||
Can't bind to 'item' since it isn't a known property of 'app-item-detail'
|
||||
</code-example>
|
||||
|
||||
</div>
|
||||
|
||||
{@a aliasing-io}
|
||||
|
||||
## Aliasing inputs and outputs
|
||||
|
||||
Sometimes the public name of an input/output property should be different from the internal name. While it is a best practice to avoid this situation, Angular does
|
||||
offer a solution.
|
||||
|
||||
### Aliasing in the metadata
|
||||
|
||||
Alias inputs and outputs in the metadata using a colon-delimited (`:`) string with
|
||||
the directive property name on the left and the public alias on the right:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/aliasing/aliasing.component.ts" region="alias" header="src/app/aliasing/aliasing.component.ts"></code-example>
|
||||
|
||||
|
||||
### Aliasing with the `@Input()`/`@Output()` decorator
|
||||
|
||||
You can specify the alias for the property name by passing the alias name to the `@Input()`/`@Output()` decorator. The internal name remains as usual.
|
||||
|
||||
<code-example path="inputs-outputs/src/app/aliasing/aliasing.component.ts" region="alias-input-output" header="src/app/aliasing/aliasing.component.ts"></code-example>
|
||||
|
||||
@@ -2,18 +2,15 @@
|
||||
|
||||
The Angular team has worked hard to ensure Ivy is as backwards-compatible with the previous rendering engine ("View Engine") as possible.
|
||||
However, in rare cases, minor changes were necessary to ensure that the Angular's behavior was predictable and consistent, correcting issues in the View Engine implementation.
|
||||
In order to smooth the transition, we have provided [automated migrations](guide/updating-to-version-10#migrations) wherever possible so your application and library code is migrated automatically by the CLI.
|
||||
In order to smooth the transition, we have provided automated migrations wherever possible so your application and library code is migrated automatically by the CLI.
|
||||
That said, some applications will likely need to apply some manual updates.
|
||||
|
||||
{@a debugging}
|
||||
## How to debug errors with Ivy
|
||||
|
||||
In version 10, [a few deprecated APIs have been removed](guide/updating-to-version-10#removals) and there are a [few breaking changes](guide/updating-to-version-10#breaking-changes) unrelated to Ivy.
|
||||
If you're seeing errors after updating to version 9, you'll first want to rule those changes out.
|
||||
If you're seeing errors, first temporarily [turn off Ivy](guide/ivy#opting-out-of-angular-ivy) in your `tsconfig.json` and re-start your app.
|
||||
|
||||
To do so, temporarily [turn off Ivy](guide/ivy#opting-out-of-angular-ivy) in your `tsconfig.json` and re-start your app.
|
||||
|
||||
If you're still seeing the errors, they are not specific to Ivy. In this case, you may want to consult the [general version 10 guide](guide/updating-to-version-10). If you've opted into any of the new, stricter type-checking settings, you may also want to check out the [template type-checking guide](guide/template-typecheck).
|
||||
If you're still seeing the errors, they are not specific to Ivy. In this case, you may want to consult the [general update guide](guide/updating-to-version-11). If you've opted into any of the new, stricter type-checking settings, you may also want to check out the [template type-checking guide](guide/template-typecheck).
|
||||
|
||||
If the errors are gone, switch back to Ivy by removing the changes to the `tsconfig.json` and review the list of expected changes below.
|
||||
|
||||
|
||||
@@ -64,36 +64,9 @@ In the marketplace, search for Angular Language Service extension, and click the
|
||||
|
||||
### WebStorm
|
||||
|
||||
In [WebStorm](https://www.jetbrains.com/webstorm/), you must install the language service package as a project dependency.
|
||||
|
||||
1. Add the following to your `devDependencies` in your project's `package.json`
|
||||
|
||||
<code-example language="json" header="package.json">
|
||||
devDependencies {
|
||||
"@angular/language-service": "^6.0.0"
|
||||
}
|
||||
</code-example>
|
||||
|
||||
2. In the terminal window at the root of your project, install the `devDependencies` with `npm` or `yarn`:
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
*OR*
|
||||
|
||||
```sh
|
||||
yarn
|
||||
```
|
||||
|
||||
*OR*
|
||||
|
||||
```sh
|
||||
yarn install
|
||||
```
|
||||
|
||||
When Angular sees this dev dependency, it provides the language service in the WebStorm environment.
|
||||
WebStorm then gives you colorization inside the template and autocomplete in addition to the Angular Language Service.
|
||||
In [WebStorm](https://www.jetbrains.com/webstorm/), enable the plugin [Angular and AngularJS](https://plugins.jetbrains.com/plugin/6971-angular-and-angularjs).
|
||||
|
||||
Since WebStorm 2019.1, the `@angular/language-service` is not required anymore and should be removed from your `package.json`.
|
||||
|
||||
### Sublime Text
|
||||
|
||||
|
||||
@@ -305,11 +305,6 @@ Use the `ngOnInit()` method to perform the following initialization tasks.
|
||||
An `ngOnInit()` is a good place for a component to fetch its initial data.
|
||||
For an example, see the [Tour of Heroes tutorial](tutorial/toh-pt4#oninit).
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
In [Flaw: Constructor does Real Work](http://misko.hevery.com/code-reviewers-guide/flaw-constructor-does-real-work/), Misko Hevery, Angular team lead, explains why you should avoid complex constructor logic.
|
||||
|
||||
</div>
|
||||
|
||||
* Set up the component after Angular sets the input properties.
|
||||
Constructors should do no more than set the initial local variables to simple values.
|
||||
|
||||
@@ -8,7 +8,7 @@ Angular makes use of observables as an interface to handle a variety of common a
|
||||
|
||||
## Transmitting data between components
|
||||
|
||||
Angular provides an `EventEmitter` class that is used when publishing values from a component through the [`@Output()` decorator](guide/inputs-outputs#how-to-use-output).
|
||||
Angular provides an `EventEmitter` class that is used when publishing values from a component through the [`@Output()` decorator](guide/inputs-outputs#output).
|
||||
`EventEmitter` extends [RxJS `Subject`](https://rxjs.dev/api/index/class/Subject), adding an `emit()` method so it can send arbitrary values.
|
||||
When you call `emit()`, it passes the emitted value to the `next()` method of any subscribed observer.
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
# Property binding best practices
|
||||
|
||||
By following a few guidelines, you can use property binding in a way that helps you minimize bugs and keep your code readable.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example name="property-binding"></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
## Avoid side effects
|
||||
|
||||
Evaluation of a template expression should have no visible side effects.
|
||||
Use the syntax for template expressions to help avoid side effects.
|
||||
In general, the correct syntax prevents you from assigning a value to anything in a property binding expression.
|
||||
The syntax also prevents you from using increment and decrement operators.
|
||||
|
||||
### An example of producing side effects
|
||||
|
||||
If you had an expression that changed the value of something else that you were binding to, that change of value would be a side effect.
|
||||
Angular might or might not display the changed value.
|
||||
If Angular does detect the change, it throws an error.
|
||||
|
||||
As a best practice, use only properties and methods that return values.
|
||||
|
||||
## Return the proper type
|
||||
|
||||
A template expression should evaluate to the type of value that the target property expects.
|
||||
For example, return a string if the target property expects a string, a number if it expects a number, or an object if it expects an object.
|
||||
|
||||
### Passing in a string
|
||||
|
||||
In the following example, the `childItem` property of the `ItemDetailComponent` expects a string.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="model-property-binding" header="src/app/app.component.html"></code-example>
|
||||
|
||||
You can confirm this expectation by looking in the `ItemDetailComponent` where the `@Input()` type is `string`:
|
||||
|
||||
<code-example path="property-binding/src/app/item-detail/item-detail.component.ts" region="input-type" header="src/app/item-detail/item-detail.component.ts (setting the @Input() type)"></code-example>
|
||||
|
||||
The `parentItem` in `AppComponent` is a string, which means that the expression, `parentItem` within `[childItem]="parentItem"`, evaluates to a string.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.ts" region="parent-data-type" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
If `parentItem` were some other type, you would need to specify `childItem` `@Input()` as that type as well.
|
||||
|
||||
### Passing in an object
|
||||
|
||||
In this example, `ItemListComponent` is a child component of `AppComponent` and the `items` property expects an array of objects.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="pass-object" header="src/app/app.component.html"></code-example>
|
||||
|
||||
In the `ItemListComponent` the `@Input()`, `items`, has a type of `Item[]`.
|
||||
|
||||
<code-example path="property-binding/src/app/item-list/item-list.component.ts" region="item-input" header="src/app/item-list.component.ts"></code-example>
|
||||
|
||||
Notice that `Item` is an object that it has two properties; an `id` and a `name`.
|
||||
|
||||
<code-example path="property-binding/src/app/item.ts" region="item-class" header="src/app/item.ts"></code-example>
|
||||
|
||||
In `app.component.ts`, `currentItems` is an array of objects in the same shape as the `Item` object in `items.ts`, with an `id` and a `name`.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.ts" region="pass-object" header="src/app.component.ts"></code-example>
|
||||
|
||||
By supplying an object in the same shape, you satisfy the expectations of `items` when Angular evaluates the expression `currentItems`.
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
# Property binding `[property]`
|
||||
# Property binding
|
||||
|
||||
Use property binding to _set_ properties of target elements or
|
||||
directive `@Input()` decorators.
|
||||
Property binding in Angular helps you set values for properties of HTML elements or directives.
|
||||
With property binding, you can do things such as toggle button functionality, set paths programmatically, and share values between components.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
@@ -10,36 +10,86 @@ See the <live-example></live-example> for a working example containing the code
|
||||
|
||||
</div>
|
||||
|
||||
## One-way in
|
||||
## Prerequisites
|
||||
|
||||
Property binding flows a value in one direction,
|
||||
from a component's property into a target element property.
|
||||
To get the most out of property binding, you should be familiar with the following:
|
||||
|
||||
You can't use property
|
||||
binding to read or pull values out of target elements. Similarly, you cannot use
|
||||
property binding to call a method on the target element.
|
||||
If the element raises events, you can listen to them with an [event binding](guide/event-binding).
|
||||
* [Basics of components](guide/architecture-components)
|
||||
* [Basics of templates](guide/glossary#template)
|
||||
* [Binding syntax](guide/binding-syntax)
|
||||
|
||||
If you must read a target element property or call one of its methods,
|
||||
see the API reference for [ViewChild](api/core/ViewChild) and
|
||||
[ContentChild](api/core/ContentChild).
|
||||
<hr />
|
||||
|
||||
## Examples
|
||||
## Understanding the flow of data
|
||||
|
||||
The most common property binding sets an element property to a component
|
||||
property value. An example is
|
||||
binding the `src` property of an image element to a component's `itemImageUrl` property:
|
||||
Property binding moves a value in one direction, from a component's property into a target element property.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For more information on listening for events, see [Event binding](guide/event-binding).
|
||||
|
||||
</div>
|
||||
|
||||
To read a target element property or call one of its methods, see the API reference for [ViewChild](api/core/ViewChild) and [ContentChild](api/core/ContentChild).
|
||||
|
||||
## Binding to a property
|
||||
|
||||
To bind to an element's property, enclose it in square brackets, `[]`, which identifies the property as a target property.
|
||||
A target property is the DOM property to which you want to assign a value.
|
||||
For example, the target property in the following code is the image element's `src` property.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="property-binding" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Here's an example of binding to the `colSpan` property. Notice that it's not `colspan`,
|
||||
which is the attribute, spelled with a lowercase `s`.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="colSpan" header="src/app/app.component.html"></code-example>
|
||||
In most cases, the target name is the name of a property, even when it appears to be the name of an attribute.
|
||||
In this example, `src` is the name of the `<img>` element property.
|
||||
|
||||
For more details, see the [MDN HTMLTableCellElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement) documentation.
|
||||
The brackets, `[]`, cause Angular to evaluate the right-hand side of the assignment as a dynamic expression.
|
||||
Without the brackets, Angular treats the the right-hand side as a string literal and sets the property to that static value.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="no-evaluation" header="src/app.component.html"></code-example>
|
||||
|
||||
Omitting the brackets renders the string `parentItem`, not the value of `parentItem`.
|
||||
|
||||
## Setting an element property to a component property value
|
||||
|
||||
To bind the `src` property of an `<img>` element to a component's property, place the target, `src`, in square brackets followed by an equal sign and then the property.
|
||||
The property here is `itemImageUrl`.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="property-binding" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Declare the `itemImageUrl` property in the class, in this case `AppComponent`.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.ts" region="item-image" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
{@a colspan}
|
||||
|
||||
#### `colspan` and `colSpan`
|
||||
|
||||
A common point of confusion is between the attribute, `colspan`, and the property, `colSpan`.
|
||||
Notice that these two names differ by only a single letter.
|
||||
|
||||
If you wrote something like this:
|
||||
|
||||
<code-example language="html">
|
||||
<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
|
||||
</code-example>
|
||||
|
||||
You'd get this error:
|
||||
|
||||
<code-example language="bash">
|
||||
Template parse errors:
|
||||
Can't bind to 'colspan' since it isn't a known native property
|
||||
</code-example>
|
||||
|
||||
As the message says, the `<td>` element does not have a `colspan` property. This is true
|
||||
because `colspan` is an attribute—`colSpan`, with a capital `S`, is the
|
||||
corresponding property. Interpolation and property binding can set only *properties*, not attributes.
|
||||
|
||||
Instead, you'd use property binding and write it like this:
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="colSpan" header="src/app/app.component.html"></code-example>
|
||||
|
||||
For more information about `colSpan` and `colspan`, see the [Attribute binding](guide/attribute-binding#colspan) guide.
|
||||
|
||||
Another example is disabling a button when the component says that it `isUnchanged`:
|
||||
|
||||
@@ -54,175 +104,100 @@ for parent and child components to communicate:
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="model-property-binding" header="src/app/app.component.html"></code-example>
|
||||
|
||||
## Binding targets
|
||||
|
||||
An element property between enclosing square brackets identifies the target property.
|
||||
The target property in the following code is the image element's `src` property.
|
||||
## Toggling button functionality
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="property-binding" header="src/app/app.component.html"></code-example>
|
||||
To disable a button's functionality depending on a Boolean value, bind the DOM `disabled` property to a property in the class that is `true` or `false`.
|
||||
|
||||
There's also the `bind-` prefix alternative:
|
||||
<code-example path="property-binding/src/app/app.component.html" region="disabled-button" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="bind-prefix" header="src/app/app.component.html"></code-example>
|
||||
Because the value of the property `isUnchanged` is `true` in the `AppComponent`, Angular disables the button.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.ts" region="boolean" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
|
||||
In most cases, the target name is the name of a property, even
|
||||
when it appears to be the name of an attribute.
|
||||
So in this case, `src` is the name of the `<img>` element property.
|
||||
## Setting a directive property
|
||||
|
||||
Element properties may be the more common targets,
|
||||
but Angular looks first to see if the name is a property of a known directive,
|
||||
as it is in the following example:
|
||||
To set a property of a directive, place the directive within square brackets , such as `[ngClass]`, followed by an equal sign and the property.
|
||||
Here, the property is `classes`.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="class-binding" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Technically, Angular is matching the name to a directive `@Input()`,
|
||||
one of the property names listed in the directive's `inputs` array
|
||||
or a property decorated with `@Input()`.
|
||||
Such inputs map to the directive's own properties.
|
||||
To use the property, you must declare it in the class, which in this example is `AppComponent`.
|
||||
The value of `classes` is `special`.
|
||||
|
||||
If the name fails to match a property of a known directive or element, Angular reports an “unknown directive” error.
|
||||
<code-example path="property-binding/src/app/app.component.ts" region="directive-property" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
Angular applies the class `special` to the `<p>` element so that you can use `special` to apply CSS styles.
|
||||
|
||||
Though the target name is usually the name of a property,
|
||||
there is an automatic attribute-to-property mapping in Angular for
|
||||
several common attributes. These include `class`/`className`, `innerHtml`/`innerHTML`, and
|
||||
`tabindex`/`tabIndex`.
|
||||
## Bind values between components
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
## Avoid side effects
|
||||
|
||||
Evaluation of a template expression should have no visible side effects.
|
||||
The expression language itself, or the way you write template expressions,
|
||||
helps to a certain extent;
|
||||
you can't assign a value to anything in a property binding expression
|
||||
nor use the increment and decrement operators.
|
||||
|
||||
For example, you could have an expression that invoked a property or method that had
|
||||
side effects. The expression could call something like `getFoo()` where only you
|
||||
know what `getFoo()` does. If `getFoo()` changes something
|
||||
and you happen to be binding to that something,
|
||||
Angular may or may not display the changed value. Angular may detect the
|
||||
change and throw a warning error.
|
||||
As a best practice, stick to properties and to methods that return
|
||||
values and avoid side effects.
|
||||
|
||||
## Return the proper type
|
||||
|
||||
The template expression should evaluate to the type of value
|
||||
that the target property expects.
|
||||
Return a string if the target property expects a string, a number if it
|
||||
expects a number, an object if it expects an object, and so on.
|
||||
|
||||
In the following example, the `childItem` property of the `ItemDetailComponent` expects a string, which is exactly what you're sending in the property binding:
|
||||
To set the model property of a custom component, place the target, here `childItem`, between square brackets `[]` followed by an equal sign and the property.
|
||||
Here, the property is `parentItem`.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="model-property-binding" header="src/app/app.component.html"></code-example>
|
||||
|
||||
You can confirm this by looking in the `ItemDetailComponent` where the `@Input` type is set to a string:
|
||||
<code-example path="property-binding/src/app/item-detail/item-detail.component.ts" region="input-type" header="src/app/item-detail/item-detail.component.ts (setting the @Input() type)"></code-example>
|
||||
To use the target and the property, you must declare them in their respective classes.
|
||||
|
||||
Declare the target of `childItem` in its component class, in this case `ItemDetailComponent`.
|
||||
|
||||
For example, the following code declares the target of `childItem` in its component class, in this case `ItemDetailComponent`.
|
||||
|
||||
Then, the code contains an `@Input()` decorator with the `childItem` property so data can flow into it.
|
||||
|
||||
<code-example path="property-binding/src/app/item-detail/item-detail.component.ts" region="input-type" header="src/app/item-detail/item-detail.component.ts"></code-example>
|
||||
|
||||
Next, the code declares the property of `parentItem` in its component class, in this case `AppComponent`.
|
||||
In this example the type of `childItem` is `string`, so `parentItem` needs to be a string.
|
||||
Here, `parentItem` has the string value of `lamp`.
|
||||
|
||||
As you can see here, the `parentItem` in `AppComponent` is a string, which the `ItemDetailComponent` expects:
|
||||
<code-example path="property-binding/src/app/app.component.ts" region="parent-data-type" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
### Passing in an object
|
||||
With this configuration, the view of `<app-item-detail>` uses the value of `lamp` for `childItem`.
|
||||
|
||||
The previous simple example showed passing in a string. To pass in an object,
|
||||
the syntax and thinking are the same.
|
||||
## Property binding and security
|
||||
|
||||
In this scenario, `ItemListComponent` is nested within `AppComponent` and the `items` property expects an array of objects.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="pass-object" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The `items` property is declared in the `ItemListComponent` with a type of `Item` and decorated with `@Input()`:
|
||||
|
||||
<code-example path="property-binding/src/app/item-list/item-list.component.ts" region="item-input" header="src/app/item-list.component.ts"></code-example>
|
||||
|
||||
In this sample app, an `Item` is an object that has two properties; an `id` and a `name`.
|
||||
|
||||
<code-example path="property-binding/src/app/item.ts" region="item-class" header="src/app/item.ts"></code-example>
|
||||
|
||||
While a list of items exists in another file, `mock-items.ts`, you can
|
||||
specify a different item in `app.component.ts` so that the new item will render:
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.ts" region="pass-object" header="src/app.component.ts"></code-example>
|
||||
|
||||
You just have to make sure, in this case, that you're supplying an array of objects because that's the type of `Item` and is what the nested component, `ItemListComponent`, expects.
|
||||
|
||||
In this example, `AppComponent` specifies a different `item` object
|
||||
(`currentItems`) and passes it to the nested `ItemListComponent`. `ItemListComponent` was able to use `currentItems` because it matches what an `Item` object is according to `item.ts`. The `item.ts` file is where
|
||||
`ItemListComponent` gets its definition of an `item`.
|
||||
|
||||
## Remember the brackets
|
||||
|
||||
The brackets, `[]`, tell Angular to evaluate the template expression.
|
||||
If you omit the brackets, Angular treats the string as a constant
|
||||
and *initializes the target property* with that string:
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="no-evaluation" header="src/app.component.html"></code-example>
|
||||
|
||||
|
||||
Omitting the brackets will render the string
|
||||
`parentItem`, not the value of `parentItem`.
|
||||
|
||||
## One-time string initialization
|
||||
|
||||
You *should* omit the brackets when all of the following are true:
|
||||
|
||||
* The target property accepts a string value.
|
||||
* The string is a fixed value that you can put directly into the template.
|
||||
* This initial value never changes.
|
||||
|
||||
You routinely initialize attributes this way in standard HTML, and it works
|
||||
just as well for directive and component property initialization.
|
||||
The following example initializes the `prefix` property of the `StringInitComponent` to a fixed string,
|
||||
not a template expression. Angular sets it and forgets about it.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="string-init" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The `[item]` binding, on the other hand, remains a live binding to the component's `currentItems` property.
|
||||
|
||||
## Property binding vs. interpolation
|
||||
|
||||
You often have a choice between interpolation and property binding.
|
||||
The following binding pairs do the same thing:
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="property-binding-interpolation" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Interpolation is a convenient alternative to property binding in
|
||||
many cases. When rendering data values as strings, there is no
|
||||
technical reason to prefer one form to the other, though readability
|
||||
tends to favor interpolation. However, *when setting an element
|
||||
property to a non-string data value, you must use property binding*.
|
||||
|
||||
## Content security
|
||||
|
||||
Imagine the following malicious content.
|
||||
Property binding can help keep content secure.
|
||||
For example, consider the following malicious content.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.ts" region="malicious-content" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
In the component template, the content might be used with interpolation:
|
||||
The component template interpolates the content as follows:
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="malicious-interpolated" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Fortunately, Angular data binding is on alert for dangerous HTML. In the above case,
|
||||
the HTML displays as is, and the Javascript does not execute. Angular **does not**
|
||||
allow HTML with script tags to leak into the browser, neither with interpolation
|
||||
nor property binding.
|
||||
|
||||
In the following example, however, Angular [sanitizes](guide/security#sanitization-and-security-contexts)
|
||||
the values before displaying them.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="malicious-content" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Interpolation handles the `<script>` tags differently than
|
||||
property binding but both approaches render the
|
||||
content harmlessly. The following is the browser output
|
||||
of the `evilTitle` examples.
|
||||
The browser doesn't process the HTML and instead displays it raw, as follows.
|
||||
|
||||
<code-example language="bash">
|
||||
"Template <script>alert("evil never sleeps")</script> Syntax" is the interpolated evil title.
|
||||
</code-example>
|
||||
|
||||
|
||||
Angular does not allow HTML with `<script>` tags, neither with [interpolation](guide/interpolation) nor property binding, which prevents the JavaScript from running.
|
||||
|
||||
In the following example, however, Angular [sanitizes](guide/security#sanitization-and-security-contexts) the values before displaying them.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="malicious-content" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Interpolation handles the `<script>` tags differently than property binding, but both approaches render the content harmlessly.
|
||||
The following is the browser output of the sanitized `evilTitle` example.
|
||||
|
||||
<code-example language="bash">
|
||||
"Template Syntax" is the property bound evil title.
|
||||
</code-example>
|
||||
|
||||
## Property binding and interpolation
|
||||
|
||||
Often [interpolation](guide/interpolation) and property binding can achieve the same results.
|
||||
The following binding pairs do the same thing.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="property-binding-interpolation" header="src/app/app.component.html"></code-example>
|
||||
|
||||
You can use either form when rendering data values as strings, though interpolation is preferable for readability.
|
||||
However, when setting an element property to a non-string data value, you must use property binding.
|
||||
|
||||
<hr />
|
||||
|
||||
## What's next
|
||||
|
||||
* [Property binding best practices](guide/property-binding-best-practices)
|
||||
|
||||
@@ -101,7 +101,8 @@ The following table provides the status for Angular versions under support.
|
||||
|
||||
Version | Status | Released | Active Ends | LTS Ends
|
||||
------- | ------ | ------------ | ------------ | ------------
|
||||
^10.0.0 | Active | Jun 24, 2020 | Dec 24, 2020 | Dec 24, 2021
|
||||
^11.0.0 | Active | Nov 11, 2020 | May 11, 2021 | May 11, 2022
|
||||
^10.0.0 | LTS | Jun 24, 2020 | Dec 24, 2020 | Dec 24, 2021
|
||||
^9.0.0 | LTS | Feb 06, 2020 | Aug 06, 2020 | Aug 06, 2021
|
||||
^8.0.0 | LTS | May 28, 2019 | Nov 28, 2019 | Nov 28, 2020
|
||||
|
||||
|
||||
@@ -6,13 +6,17 @@ The projects below are not associated with a particular Angular version. We'll r
|
||||
|
||||
## In Progress
|
||||
|
||||
### Operation Bye Bye Backlog (aka Operation Byelog)
|
||||
### Faster apps by inlining critical styles in Universal applications
|
||||
|
||||
We are actively investing up to 50% of our engineering capacity on triaging issues and PRs until we have a clear understanding of broader community needs. After that, we'll commit up to 20% of our engineering capacity to keep up with new submissions promptly.
|
||||
Loading external stylesheets is a blocking operation, which means that the browser can’t start rendering your application until it loads all the referenced CSS. Having render-blocking resources in the header of a page can significantly impact its load performance, for example, its [first contentful paint](https://web.dev/first-contentful-paint/). To make apps faster, we’ve been collaborating with the Google Chrome team on inlining critical CSS and loading the rest of the styles asynchronously.
|
||||
|
||||
### Support TypeScript 4.0
|
||||
### Improve debugging with better Angular error messages
|
||||
|
||||
We're working on adding support for TypeScript 4.0 ahead of its stable release. We always want Angular to stay up-to-date with the latest version of TypeScript so that developers get the best the language has to offer.
|
||||
Error messages often bring limited actionable information to help developers resolve them. We’ve been working on making error messages more discoverable by adding associated codes, developing guides, and other materials to ensure a smoother debugging experience.
|
||||
|
||||
### Revamp performance dashboards to detect regressions
|
||||
|
||||
We have a set of benchmarks that we run against every code change to ensure Angular aligns with our performance standards. To ensure the framework’s runtime does not regress after a code change, we need to refine some of the existing infrastructure the dashboards step on.
|
||||
|
||||
### Update our e2e testing strategy
|
||||
|
||||
@@ -20,74 +24,78 @@ To ensure we provide a future-proof e2e testing strategy, we want to evaluate th
|
||||
|
||||
### Angular libraries use Ivy
|
||||
|
||||
We are investing in the design and development of Ivy library distribution plan, which will include an update of the library package format to use Ivy compilation, unblock the deprecation of the View Engine library format, and [ngcc](guide/glossary#ngcc).
|
||||
Earlier in 2020, we shared an [RFC](https://github.com/angular/angular/issues/38366) for Ivy library distribution. After invaluable feedback from the community, we developed a design of the project. We are now investing in the development of Ivy library distribution, including an update of the library package format to use Ivy compilation, unblock the deprecation of the View Engine library format, and [ngcc](https://angular.io/guide/glossary#ngcc).
|
||||
|
||||
### Evaluate future RxJS changes (v7 and beyond)
|
||||
### Ensure smooth adoption for future RxJS changes (v7 and beyond)
|
||||
|
||||
We want to ensure Angular developers are taking advantage of the latest capabilities of RxJS and have a smooth transition to the next major releases of the framework. For this purpose, we will explore and document the scope of the changes in v7 and beyond of RxJS and plan an update strategy.
|
||||
|
||||
### Angular language service uses Ivy
|
||||
### Transition the Angular language service to Ivy
|
||||
|
||||
Today the language service still uses the View Engine compiler and type checking, even for Ivy applications. We want to use the Ivy template parser and improved type checking for the Angular Language service to match application behavior. This migration will also be a step towards unblocking the removal of View Engine, which will simplify Angular, reduce the npm package size, and improve the framework's maintainability.
|
||||
The goal of this project is to improve the experience and remove legacy dependency by transitioning the language service to Ivy. Today the language service still uses the View Engine compiler and type checking, even for Ivy applications. We want to use the Ivy template parser and improved type checking for the Angular Language service to match application behavior. This migration will also be a step towards unblocking the removal of View Engine, which will simplify Angular, reduce the npm package size, and improve the framework's maintainability.
|
||||
|
||||
### Expand component harnesses best practices
|
||||
|
||||
Angular CDK introduced the concept of [component test harnesses](https://material.angular.io/cdk/test-harnesses) to Angular in version 9. Test harnesses allow component authors to create supported APIs for testing component interactions. We're continuing to improve this harness infrastructure and clarifying the best practices around using harnesses. We're also working to drive more harness adoption inside of Google.
|
||||
|
||||
### Support native [Trusted Types](https://web.dev/trusted-types/) in Angular
|
||||
### Increased security with native [Trusted Types](https://web.dev/trusted-types/) in Angular
|
||||
|
||||
In collaboration with Google's security team, we're adding support for the new Trusted Types API. This web platform API will help developers build more secure web applications.
|
||||
|
||||
### Integrate [MDC Web](https://material.io/develop/web/) into Angular Material
|
||||
### Enhanced Angular Material components by integrating [MDC Web](https://material.io/develop/web/)
|
||||
|
||||
MDC Web is a library created by Google's Material Design team that provides reusable primitives for building Material Design components. The Angular team is incorporating these primitives into Angular Material. Using MDC Web will align Angular Material more closely with the Material Design specification, expand accessibility, overall improve component quality, and improve our team's velocity.
|
||||
MDC Web is a library created by Google's Material Design team that provides reusable primitives for building Material Design components. The Angular team is incorporating these primitives into Angular Material. Using MDC Web will align Angular Material more closely with the Material Design specification, expand accessibility, improve component quality, and improve our team's velocity.
|
||||
|
||||
### Offer Google engineers better integration with Angular and Google's internal server stack
|
||||
|
||||
This is an internal project to add support for Angular front-ends to Google's internal integrated server stack.
|
||||
|
||||
### Angular versioning & branching
|
||||
### Streamline releases with consolidated Angular versioning & branching
|
||||
|
||||
We want to consolidate release management tooling between Angular's multiple GitHub repositories ([angular/angular](https://github.com/angular/angular), [angular/angular-cli](https://github.com/angular/angular-cli), and [angular/components](https://github.com/angular/components)). This effort will allow us to reuse infrastructure, unify and simplify processes, and improve our release process's reliability.
|
||||
|
||||
## Future
|
||||
### Optimized build speed and bundle sizes with Angular CLI webpack 5
|
||||
|
||||
### Refresh introductory documentation
|
||||
As part of the v11 release, we introduced an opt-in preview of webpack 5 in the Angular CLI. To ensure stability, we’ll continue iterating on the implementation to enable build speed and bundle size improvements.
|
||||
|
||||
We will redefine the user learning journeys and refresh the introductory documentation. We will clearly state the benefits of Angular, how to explore its capabilities, and provide guidance so developers can become proficient with the framework in as little time as possible.
|
||||
|
||||
### Strict typing for `@angular/forms`
|
||||
|
||||
We will work on implementing stricter type checking for reactive forms. This way, we will allow developers to catch more issues during development time, enable better text editor and IDE support, and improve the type checking for reactive forms.
|
||||
|
||||
### webpack 5 in the Angular CLI
|
||||
|
||||
Webpack 5 brings a lot of build speed and bundle size improvements. To make them available for Angular developers, we will invest in migrating Angular CLI from using deprecated and removed webpack APIs.
|
||||
|
||||
### Commit message standardization
|
||||
### Higher developer consistency with commit message standardization
|
||||
|
||||
We want to unify commit message requirements and conformance across Angular repositories ([angular/angular](https://github.com/angular/angular), [angular/components](https://github.com/angular/components), [angular/angular-cli](https://github.com/angular/angular-cli)) to bring consistency to our development process and reuse infrastructure tooling.
|
||||
|
||||
### Optional Zone.js
|
||||
### Accelerated debugging and performance profiling with Angular DevTools
|
||||
|
||||
We are working on development tooling for Angular that will provide utilities for debugging and performance profiling. This project aims to help developers understand the component structure and the change detection in an Angular application.
|
||||
|
||||
### Improved developer onboarding with refreshed introductory documentation
|
||||
|
||||
We will redefine the user learning journeys and refresh the introductory documentation. We will clearly state the benefits of Angular, how to explore its capabilities and provide guidance so developers can become proficient with the framework in as little time as possible.
|
||||
|
||||
## Future
|
||||
|
||||
### Better developer ergonomics with strict typing for `@angular/forms`
|
||||
|
||||
We will work on implementing stricter type checking for reactive forms. This way, we will allow developers to catch more issues during development time, enable better text editor and IDE support, and improve the type checking for reactive forms.
|
||||
|
||||
### Leverage full framework capabilities with Zone.js opt-out
|
||||
|
||||
We are going to design and implement a plan to make Zone.js optional from Angular applications. This way, we will simplify the framework, improve debugging, and reduce application bundle size. Additionally, this will allow us to take advantage of native async/await syntax, which currently Zone.js does not support.
|
||||
|
||||
### Remove legacy [View Engine](guide/ivy)
|
||||
### Reduce framework overhead by removing legacy [View Engine](https://angular.io/guide/ivy)
|
||||
|
||||
After the transition of all our internal tooling to Ivy has completed, we want to remove the legacy View Engine for smaller Angular conceptual overhead, smaller package size, lower maintenance cost, and lower complexity of the codebase.
|
||||
|
||||
### Angular DevTools
|
||||
### Improved test times and debugging with automatic test environment tear down
|
||||
|
||||
We’ll be working on development tooling for Angular that will provide utilities for debugging and performance profiling. This project aims to help developers understand the component structure and the change detection in an Angular application.
|
||||
To improve test time and create better isolation across tests, we want to change `TestBed` to automatically clean up and tear down the test environment after each test run.
|
||||
|
||||
### Optional NgModules
|
||||
### Improved build performance with ngc as a tsc plugin distribution
|
||||
|
||||
Distributing the Angular compiler as a plugin of the TypeScript compiler will substantially improve developers' build performance and reduce maintenance costs.
|
||||
|
||||
### Support adding directives to host elements
|
||||
|
||||
A long-standing feature request is to add the ability to add directives to host elements. The feature will allow developers to augment their own components with additional behaviors without using inheritance. The project will require substantial effort in terms of the definition of APIs, semantics, and implementation.
|
||||
|
||||
### Simplified Angular mental model with optional NgModules
|
||||
|
||||
To simplify the Angular mental model and learning journey, we’ll be working on making NgModules optional. This work will allow developers to develop standalone components and implement an alternative API for declaring the component’s compilation scope.
|
||||
|
||||
### Ergonomic component level code-splitting APIs
|
||||
|
||||
A common problem of web applications is their slow initial load time. A way to improve it is to apply more granular code-splitting on a component level. To encourage this practice, we’ll be working on more ergonomic code-splitting APIs.
|
||||
|
||||
### Migration to ESLint
|
||||
|
||||
With the deprecation of TSLint we will be moving to ESLint. As part of the process, we will work on ensuring backward compatibility with our current recommended TSLint configuration, implement a migration strategy for existing Angular applications and introduce new tooling to the Angular CLI toolchain.
|
||||
|
||||
@@ -1656,7 +1656,7 @@ _before_ the `AppRoutingModule`:
|
||||
|
||||
</code-tabs>
|
||||
|
||||
Remove the initial crisis center route from the `app-routing.module.ts` because now the `HeroesModule` and the `CrisisCenter` modules provide teh feature routes.
|
||||
Remove the initial crisis center route from the `app-routing.module.ts` because now the `HeroesModule` and the `CrisisCenter` modules provide the feature routes.
|
||||
|
||||
The `app-routing.module.ts` file retains the top-level application routes such as the default and wildcard routes.
|
||||
|
||||
|
||||
@@ -279,13 +279,13 @@ That means only your application can read this cookie token and set the custom h
|
||||
Angular's `HttpClient` has built-in support for the client-side half of this technique. Read about it more in the [HttpClient guide](/guide/http#security-xsrf-protection).
|
||||
|
||||
For information about CSRF at the Open Web Application Security Project (OWASP), see
|
||||
<a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29">Cross-Site Request Forgery (CSRF)</a> and
|
||||
<a href="https://www.owasp.org/index.php/CSRF_Prevention_Cheat_Sheet">Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet</a>.
|
||||
[Cross-Site Request Forgery (CSRF)](https://owasp.org/www-community/attacks/csrf) and
|
||||
[Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html).
|
||||
The Stanford University paper
|
||||
<a href="https://seclab.stanford.edu/websec/csrf/csrf.pdf">Robust Defenses for Cross-Site Request Forgery</a> is a rich source of detail.
|
||||
[Robust Defenses for Cross-Site Request Forgery](https://seclab.stanford.edu/websec/csrf/csrf.pdf) is a rich source of detail.
|
||||
|
||||
See also Dave Smith's easy-to-understand
|
||||
<a href="https://www.youtube.com/watch?v=9inczw6qtpY" title="Cross Site Request Funkery Securing Your Angular Apps From Evil Doers">talk on XSRF at AngularConnect 2016</a>.
|
||||
[talk on XSRF at AngularConnect 2016](https://www.youtube.com/watch?v=9inczw6qtpY "Cross Site Request Funkery Securing Your Angular Apps From Evil Doers").
|
||||
|
||||
|
||||
<h3 id='xssi'>
|
||||
|
||||
@@ -8,7 +8,7 @@ Additionally, applications that use these stricter settings are easier to static
|
||||
Specifically, the `strict` flag does the following:
|
||||
|
||||
* Enables [`strict` mode in TypeScript](https://www.staging-typescript.org/tsconfig#strict), as well as other strictness flags recommended by the TypeScript team. Specifically, `forceConsistentCasingInFileNames`, `noImplicitReturns`, `noFallthroughCasesInSwitch`.
|
||||
* Turns on strict Angular compiler flags [`strictTemplates`](guide/angular-compiler-options#stricttemplates), [`strictInjectionParameters`](guide/angular-compiler-options#strictinjectionparameters) and [`strictTemplates`](guide/angular-compiler-options#stricttemplates).
|
||||
* Turns on strict Angular compiler flags [`strictTemplates`](guide/angular-compiler-options#stricttemplates), [`strictInjectionParameters`](guide/angular-compiler-options#strictinjectionparameters) and [`strictInputAccessModifiers`](guide/template-typecheck#troubleshooting-template-errors).
|
||||
* [Bundle size budgets](guide/build#configuring-size-budgets) have been reduced by ~75%.
|
||||
|
||||
You can apply these settings at the workspace and project level.
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
# Style Precedence
|
||||
|
||||
When there are multiple bindings to the same class name or style attribute, Angular uses a set of precedence rules to determine which classes or styles to apply to the element.
|
||||
These rules specify an order for which style- and class-related bindings have priority.
|
||||
This styling precedence is as follows, from the most specific with the highest priority to least specific with the lowest priorty:
|
||||
|
||||
1. Template bindings are the most specific because they apply to the element directly and exclusively, so they have the highest precedence.
|
||||
<table width="100%">
|
||||
<col width="40%"></col>
|
||||
<col width="60%"></col>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Binding type</th>
|
||||
<th>Example</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Property binding</td>
|
||||
<td><code><div [class.foo]="hasFoo"></code><br><code><div [style.color]="color"></code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Map binding</td>
|
||||
<td><code><div [class]="classExpression"></code><br><code><div [style]="styleExpression"></code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Static value</td>
|
||||
<td><code><div class="foo"></code><br><code><div style="color: blue"></code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
1. Directive host bindings are less specific because you can use directives in multiple locations, so they have a lower precedence than template bindings.
|
||||
<table width="100%">
|
||||
<col width="40%"></col>
|
||||
<col width="60%"></col>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Binding type</th>
|
||||
<th>Example</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Property binding</td>
|
||||
<td><code>host: {'[class.foo]': 'hasFoo'}</code><br><code>host: {'[style.color]': 'color'}</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Map binding</td>
|
||||
<td><code>host: {'[class]': 'classExpr'}</code><br><code>host: {'[style]': 'styleExpr'}</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Static value</td>
|
||||
<td><code>host: {'class': 'foo'}</code><br><code>host: {'style': 'color: blue'}</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
1. Component host bindings have the lowest precedence.
|
||||
<table width="100%">
|
||||
<col width="40%"></col>
|
||||
<col width="60%"></col>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Binding type</th>
|
||||
<th>Example</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Property binding</td>
|
||||
<td><code>host: {'[class.foo]': 'hasFoo'}</code><br><code>host: {'[style.color]': 'color'}</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Map binding</td>
|
||||
<td><code>host: {'[class]': 'classExpression'}</code><br><code>host: {'[style]': 'styleExpression'}</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Static value</td>
|
||||
<td><code>host: {'class': 'foo'}</code><br><code>host: {'style': 'color: blue'}</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Precedence and specificity
|
||||
|
||||
In the following example, binding to a specific class, as in `[class.special]`, takes precedence over a generic `[class]` binding.
|
||||
Similarly, binding to a specific style, as in `[style.color]`, takes precedence over a generic `[style]` binding.
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="basic-specificity" header="src/app/app.component.html"></code-example>
|
||||
|
||||
## Precedence and bindings from different sources
|
||||
|
||||
Specificity rules also apply to bindings even when they originate from different sources.
|
||||
An element can have bindings that originate from its own template, from host bindings on matched directives, and from host bindings on matched components.
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="source-specificity" header="src/app/app.component.html"></code-example>
|
||||
|
||||
## Precedence of bindings and static attributes
|
||||
|
||||
Bindings take precedence over static attributes because they are dynamic.
|
||||
In the following case, `class` and `[class]` have similar specificity, but the `[class]` binding takes precedence.
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="dynamic-priority" header="src/app/app.component.html"></code-example>
|
||||
|
||||
{@a styling-delegation}
|
||||
|
||||
## Delegating to styles with lower precedence
|
||||
|
||||
Higher precedence styles can defer to lower precedence styles using `undefined` values.
|
||||
For example, consider the following template:
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="style-delegation" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Imagine that the `dirWithHostBinding` directive and the `comp-with-host-binding` component both have a `[style.width]` host binding.
|
||||
|
||||
<code-example path="attribute-binding/src/app/comp-with-host-binding.component.ts" region="hostbinding" header="src/app/comp-with-host-binding.component.ts and dirWithHostBinding.directive.ts"></code-example>
|
||||
|
||||
If `dirWithHostBinding` sets its binding to `undefined`, the `width` property falls back to the value of the `comp-with-host-binding` host binding.
|
||||
|
||||
<code-example header="dirWithHostBinding directive">
|
||||
@HostBinding('style.width')
|
||||
width = ''; // undefined
|
||||
</code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
If `dirWithHostBinding` sets its binding to `null`, Angular removes the `width` property entirely.
|
||||
|
||||
<code-example header="dirWithHostBinding">
|
||||
@HostBinding('style.width')
|
||||
width = null;
|
||||
</code-example>
|
||||
|
||||
</div>
|
||||
@@ -1,7 +1,15 @@
|
||||
# Template reference variables (`#var`)
|
||||
# Template variables
|
||||
|
||||
A **template reference variable** is often a reference to a DOM element within a template.
|
||||
It can also refer to a directive (which contains a component), an element, [TemplateRef](api/core/TemplateRef), or a <a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components" title="MDN: Web Components">web component</a>.
|
||||
Template variables help you use data from one part of a template in another part of the template.
|
||||
With template variables, you can perform tasks such as respond to user input or finely tune your application's forms.
|
||||
|
||||
A template variable can refer to the following:
|
||||
|
||||
* a DOM element within a template
|
||||
* a directive
|
||||
* an element
|
||||
* [TemplateRef](api/core/TemplateRef)
|
||||
* a <a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components" title="MDN: Web Components">web component</a>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
@@ -9,61 +17,138 @@ See the <live-example></live-example> for a working example containing the code
|
||||
|
||||
</div>
|
||||
|
||||
Use the hash symbol (#) to declare a reference variable.
|
||||
The following reference variable, `#phone`, declares a `phone` variable on an `<input>` element.
|
||||
## Syntax
|
||||
|
||||
In the template, you use the hash symbol, `#`, to declare a template variable.
|
||||
The following template variable, `#phone`, declares a `phone` variable on an `<input>` element.
|
||||
|
||||
<code-example path="template-reference-variables/src/app/app.component.html" region="ref-var" header="src/app/app.component.html"></code-example>
|
||||
|
||||
You can refer to a template reference variable anywhere in the component's template.
|
||||
You can refer to a template variable anywhere in the component's template.
|
||||
Here, a `<button>` further down the template refers to the `phone` variable.
|
||||
|
||||
<code-example path="template-reference-variables/src/app/app.component.html" region="ref-phone" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Angular assigns each template reference variable a value based on where you declare the variable:
|
||||
## How Angular assigns values to template variables
|
||||
|
||||
Angular assigns a template variable a value based on where you declare the variable:
|
||||
|
||||
* If you declare the variable on a component, the variable refers to the component instance.
|
||||
* If you declare the variable on a standard HTML tag, the variable refers to the element.
|
||||
* If you declare the variable on an `<ng-template>` element, the variable refers to a `TemplateRef` instance, which represents the template.
|
||||
For more information on `<ng-template>`, see the [ng-template](guide/structural-directives#the-ng-template) section of [Structural directives](guide/structural-directives).
|
||||
* If the variable specifies a name on the right-hand side, such as `#var="ngModel"`, the variable refers to the directive or component on the element with a matching `exportAs` name.
|
||||
<!-- What does the second half of this mean?^^ Can we explain this more fully? Could I see a working example? -kw -->
|
||||
|
||||
<h3 class="no-toc">How a reference variable gets its value</h3>
|
||||
### Using `NgForm` with template variables
|
||||
|
||||
In most cases, Angular sets the reference variable's value to the element on which it is declared.
|
||||
In most cases, Angular sets the template variable's value to the element on which it occurs.
|
||||
In the previous example, `phone` refers to the phone number `<input>`.
|
||||
The button's click handler passes the `<input>` value to the component's `callPhone()` method.
|
||||
|
||||
The `NgForm` directive can change that behavior and set the value to something else. In the following example, the template reference variable, `itemForm`, appears three times separated
|
||||
by HTML.
|
||||
The `NgForm` directive demonstrates getting a reference to a different value by reference a directive's `exportAs` name.
|
||||
In the following example, the template variable, `itemForm`, appears three times separated by HTML.
|
||||
|
||||
<code-example path="template-reference-variables/src/app/app.component.html" region="ngForm" header="src/app/hero-form.component.html"></code-example>
|
||||
|
||||
The reference value of `itemForm`, without the `ngForm` attribute value, would be
|
||||
the [HTMLFormElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement).
|
||||
There is, however, a difference between a `Component` and a `Directive` in that a `Component`
|
||||
will be referenced without specifying the attribute value, and a `Directive` will not
|
||||
change the implicit reference (that is, the element).
|
||||
Without the `ngForm` attribute value, the reference value of `itemForm` would be
|
||||
the [HTMLFormElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement), `<form>`.
|
||||
There is, however, a difference between a `Component` and a `Directive` in that Angular references a `Component` without specifying the attribute value, and a `Directive` does not change the implicit reference, or the element.
|
||||
<!-- What is the train of thought from talking about a form element to the difference between a component and a directive? Why is the component directive conversation relevant here? -kw -->
|
||||
|
||||
With `NgForm`, `itemForm` is a reference to the [NgForm](api/forms/NgForm "API: NgForm") directive with the ability to track the value and validity of every control in the form.
|
||||
|
||||
Unlike the native `<form>` element, the `NgForm` directive has a `form` property.
|
||||
The `NgForm` `form` property allows you to disable the submit button if the `itemForm.form.valid` is invalid.
|
||||
|
||||
|
||||
## Template variable scope
|
||||
|
||||
However, with `NgForm`, `itemForm` is a reference to the [NgForm](api/forms/NgForm "API: NgForm")
|
||||
directive with the ability to track the value and validity of every control in the form.
|
||||
You can refer to a template variable anywhere within its surrounding template.
|
||||
[Structural directives](guide/built-in-directives), such as `*ngIf` and `*ngFor`, or `<ng-template>` act as a template boundary.
|
||||
You cannot access template variables outside of these boundaries.
|
||||
|
||||
The native `<form>` element doesn't have a `form` property, but the `NgForm` directive does, which allows disabling the submit button
|
||||
if the `itemForm.form.valid` is invalid and passing the entire form control tree
|
||||
to the parent component's `onSubmit()` method.
|
||||
<div class="alert is-helpful">
|
||||
|
||||
<h3 class="no-toc">Template reference variable considerations</h3>
|
||||
Define a variable only once in the template so the runtime value remains predictable.
|
||||
|
||||
A template _reference_ variable (`#phone`) is not the same as a template _input_ variable (`let phone`) such as in an [`*ngFor`](guide/built-in-directives#template-input-variable).
|
||||
See [_Structural directives_](guide/structural-directives#template-input-variable) for more information.
|
||||
</div>
|
||||
|
||||
The scope of a reference variable is the entire template. So, don't define the same variable name more than once in the same template as the runtime value will be unpredictable.
|
||||
### Accessing in a nested template
|
||||
|
||||
### Alternative syntax
|
||||
An inner template can access template variables that the outer template defines.
|
||||
|
||||
You can use the `ref-` prefix alternative to `#`.
|
||||
This example declares the `fax` variable as `ref-fax` instead of `#fax`.
|
||||
In the following example, changing the text in the `<input>` changes the value in the `<span>` because Angular immediately updates changes through the template variable, `ref1`.
|
||||
|
||||
<code-example path="template-reference-variables/src/app/app.component.html" region="template-ref-vars-scope1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<code-example path="template-reference-variables/src/app/app.component.html" region="ref-fax" header="src/app/app.component.html"></code-example>
|
||||
In this case, there is an implied `<ng-template>` around the `<span>` and the definition of the variable is outside of it.
|
||||
Accessing a template variable from the parent template works because the child template inherits the context from the parent template.
|
||||
|
||||
Rewriting the above code in a more verbose form explicitly shows the `<ng-template>`.
|
||||
|
||||
```html
|
||||
|
||||
<input #ref1 type="text" [(ngModel)]="firstExample" />
|
||||
|
||||
<!-- New template -->
|
||||
<ng-template [ngIf]="true">
|
||||
<!-- Since the context is inherited, the value is available to the new template -->
|
||||
<span>Value: {{ ref1.value }}</span>
|
||||
</ng-template>
|
||||
|
||||
```
|
||||
|
||||
However, accessing a template variable from outside the parent template doesn't work.
|
||||
|
||||
```html
|
||||
<input *ngIf="true" #ref2 type="text" [(ngModel)]="secondExample" />
|
||||
<span>Value: {{ ref2?.value }}</span> <!-- doesn't work -->
|
||||
```
|
||||
|
||||
The verbose form shows that `ref2` is outside the parent template.
|
||||
|
||||
```
|
||||
<ng-template [ngIf]="true">
|
||||
<!-- The reference is defined within a template -->
|
||||
<input #ref2 type="text" [(ngModel)]="secondExample" />
|
||||
</ng-template>
|
||||
<!-- ref2 accessed from outside that template doesn't work -->
|
||||
<span>Value: {{ ref2?.value }}</span>
|
||||
```
|
||||
|
||||
Consider the following example that uses `*ngFor`.
|
||||
|
||||
```
|
||||
<ng-container *ngFor="let i of [1,2]">
|
||||
<input #ref type="text" [value]="i" />
|
||||
</ng-container>
|
||||
{{ ref.value }}
|
||||
```
|
||||
|
||||
Here, `ref.value` doesn't work.
|
||||
The structural directive, `*ngFor` instantiates the template twice because `*ngFor` iterates over the two items in the array.
|
||||
It is impossible to define what the `ref.value` reference signifies.
|
||||
|
||||
With structural directives, such as `*ngFor` or `*ngIf`, there is no way for Angular to know if a template is ever instantiated.
|
||||
|
||||
As a result, Angular isn't able to access the value and returns an error.
|
||||
|
||||
### Accessing a template variable within `<ng-template>`
|
||||
|
||||
When you declare the variable on an `<ng-template>`, the variable refers to a `TemplateRef` instance, which represents the template.
|
||||
|
||||
<code-example path="template-reference-variables/src/app/app.component.html" region="template-ref" header="src/app/app.component.html"></code-example>
|
||||
|
||||
In this example, clicking the button calls the `log()` function, which outputs the value of `#ref3` to the console.
|
||||
Because the `#ref` variable is on an `<ng-template>`, the value is `TemplateRef`.
|
||||
|
||||
The following is the expanded browser console output of the `TemplateRef()` function with the name of `TemplateRef`.
|
||||
|
||||
<code-example language="sh">
|
||||
|
||||
▼ ƒ TemplateRef()
|
||||
name: "TemplateRef"
|
||||
__proto__: Function
|
||||
|
||||
</code-example>
|
||||
|
||||
@@ -14,7 +14,7 @@ In the following example, the template statement `deleteHero()` appears in quote
|
||||
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="context-component-statement" header="src/app/app.component.html"></code-example>
|
||||
|
||||
When the user clicks the **Delete hero** button, Angular calls the `deleteHero()` function in the component class.
|
||||
When the user clicks the **Delete hero** button, Angular calls the `deleteHero()` method in the component class.
|
||||
|
||||
You can use template statements with elements, components, or directives in response to events.
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ We'll be using [Headless Chrome](https://developers.google.com/web/updates/2017/
|
||||
|
||||
* In the Karma configuration file, `karma.conf.js`, add a custom launcher called ChromeHeadlessCI below browsers:
|
||||
```
|
||||
browsers: ['Chrome'],
|
||||
browsers: ['ChromeHeadlessCI'],
|
||||
customLaunchers: {
|
||||
ChromeHeadlessCI: {
|
||||
base: 'ChromeHeadless',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Two-way binding `[(...)]`
|
||||
# Two-way binding
|
||||
|
||||
Two-way binding gives your app a way to share data between a component class and
|
||||
its template.
|
||||
Two-way binding gives components in your application a way to share data.
|
||||
Use two-way binding binding to listen for events and update values simultaneously between parent and child components.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
@@ -9,68 +9,73 @@ See the <live-example></live-example> for a working example containing the code
|
||||
|
||||
</div>
|
||||
|
||||
## Basics of two-way binding
|
||||
## Prerequisites
|
||||
|
||||
Two-way binding does two things:
|
||||
To get the most out of two-way binding, you should have a basic understanding of the following concepts:
|
||||
|
||||
1. Sets a specific element property.
|
||||
1. Listens for an element change event.
|
||||
* [Property binding](guide/property-binding)
|
||||
* [Event binding](guide/event-binding)
|
||||
* [Inputs and Outputs](guide/inputs-outputs)
|
||||
|
||||
Angular offers a special _two-way data binding_ syntax for this purpose, `[()]`.
|
||||
The `[()]` syntax combines the brackets
|
||||
of property binding, `[]`, with the parentheses of event binding, `()`.
|
||||
<hr>
|
||||
|
||||
<div class="callout is-important">
|
||||
Two-way binding combines property binding with event binding:
|
||||
|
||||
<header>
|
||||
[( )] = banana in a box
|
||||
</header>
|
||||
* [Property binding](guide/property-binding) sets a specific element property.
|
||||
* [Event binding](guide/event-binding) listens for an element change event.
|
||||
|
||||
Visualize a *banana in a box* to remember that the parentheses go _inside_ the brackets.
|
||||
## Adding two-way data binding
|
||||
|
||||
</div>
|
||||
Angular's two-way binding syntax is a combination of square brackets and parentheses, `[()]`.
|
||||
The `[()]` syntax combines the brackets of property binding, `[]`, with the parentheses of event binding, `()`, as follows.
|
||||
|
||||
The `[()]` syntax is easy to demonstrate when the element has a settable
|
||||
property called `x` and a corresponding event named `xChange`.
|
||||
Here's a `SizerComponent` that fits this pattern.
|
||||
It has a `size` value property and a companion `sizeChange` event:
|
||||
<code-example path="two-way-binding/src/app/app.component.html" header="src/app/app.component.html" region="two-way-syntax"></code-example>
|
||||
|
||||
<code-example path="two-way-binding/src/app/sizer/sizer.component.ts" header="src/app/sizer.component.ts"></code-example>
|
||||
## How two-way binding works
|
||||
|
||||
For two-way data binding to work, the `@Output()` property must use the pattern, `inputChange`, where `input` is the name of the `@Input()` property.
|
||||
For example, if the `@Input()` property is `size`, the `@Output()` property must be `sizeChange`.
|
||||
|
||||
The following `sizerComponent` has a `size` value property and a `sizeChange` event.
|
||||
The `size` property is an `@Input()`, so data can flow into the `sizerComponent`.
|
||||
The `sizeChange` event is an `@Output()`, which allows data to flow out of the `sizerComponent` to the parent component.
|
||||
|
||||
Next, there are two methods, `dec()` to decrease the font size and `inc()` to increase the font size.
|
||||
These two methods use `resize()` to change the value of the `size` property within min/max value constraints, and to emit an event that conveys the new `size` value.
|
||||
|
||||
<code-example path="two-way-binding/src/app/sizer/sizer.component.ts" region="sizer-component" header="src/app/sizer.component.ts"></code-example>
|
||||
|
||||
The `sizerComponent` template has two buttons that each bind the click event to the `inc()` and `dec()` methods.
|
||||
When the user clicks one of the buttons, the `sizerComponent` calls the corresponding method.
|
||||
Both methods, `inc()` and `dec()`, call the `resize()` method with a `+1` or `-1`, which in turn raises the `sizeChange` event with the new size value.
|
||||
|
||||
<code-example path="two-way-binding/src/app/sizer/sizer.component.html" header="src/app/sizer.component.html"></code-example>
|
||||
|
||||
The initial `size` is an input value from a property binding.
|
||||
Clicking the buttons increases or decreases the `size`, within
|
||||
min/max value constraints,
|
||||
and then raises, or emits, the `sizeChange` event with the adjusted size.
|
||||
|
||||
Here's an example in which the `AppComponent.fontSizePx` is two-way bound to the `SizerComponent`:
|
||||
In the `AppComponent` template, `fontSizePx` is two-way bound to the `SizerComponent`.
|
||||
|
||||
<code-example path="two-way-binding/src/app/app.component.html" header="src/app/app.component.html (two-way-1)" region="two-way-1"></code-example>
|
||||
<code-example path="two-way-binding/src/app/app.component.html" header="src/app/app.component.html" region="two-way-1"></code-example>
|
||||
|
||||
The `AppComponent.fontSizePx` establishes the initial `SizerComponent.size` value.
|
||||
In the `AppComponent`, `fontSizePx` establishes the initial `SizerComponent.size` value by setting the value to `16`.
|
||||
|
||||
<code-example path="two-way-binding/src/app/app.component.ts" header="src/app/app.component.ts" region="font-size"></code-example>
|
||||
|
||||
Clicking the buttons updates the `AppComponent.fontSizePx` via the two-way binding.
|
||||
The revised `AppComponent.fontSizePx` value flows through to the _style_ binding,
|
||||
making the displayed text bigger or smaller.
|
||||
Clicking the buttons updates the `AppComponent.fontSizePx`.
|
||||
The revised `AppComponent.fontSizePx` value updates the style binding, which makes the displayed text bigger or smaller.
|
||||
|
||||
The two-way binding syntax is really just syntactic sugar for a _property_ binding and an _event_ binding.
|
||||
Angular desugars the `SizerComponent` binding into this:
|
||||
The two-way binding syntax is shorthand for a combination of property binding and event binding.
|
||||
The `SizerComponent` binding as separate property binding and event binding is as follows.
|
||||
|
||||
<code-example path="two-way-binding/src/app/app.component.html" header="src/app/app.component.html (two-way-2)" region="two-way-2"></code-example>
|
||||
<code-example path="two-way-binding/src/app/app.component.html" header="src/app/app.component.html (expanded)" region="two-way-2"></code-example>
|
||||
|
||||
The `$event` variable contains the payload of the `SizerComponent.sizeChange` event.
|
||||
The `$event` variable contains the data of the `SizerComponent.sizeChange` event.
|
||||
Angular assigns the `$event` value to the `AppComponent.fontSizePx` when the user clicks the buttons.
|
||||
|
||||
## Two-way binding in forms
|
||||
<div class="callout is-helpful">
|
||||
|
||||
The two-way binding syntax is a great convenience compared to
|
||||
separate property and event bindings. It would be convenient to
|
||||
use two-way binding with HTML form elements like `<input>` and
|
||||
`<select>`. However, no native HTML element follows the `x`
|
||||
value and `xChange` event pattern.
|
||||
<header>Two-way binding in forms</header>
|
||||
|
||||
For more on how to use two-way binding in forms, see
|
||||
Angular [NgModel](guide/built-in-directives#ngModel).
|
||||
Because no native HTML element follows the `x` value and `xChange` event pattern, two-way binding with form elements requires `NgModel`.
|
||||
For more information on how to use two-way binding in forms, see Angular [NgModel](guide/built-in-directives#ngModel).
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
# Updating to Angular version 10
|
||||
|
||||
This guide contains information related to updating to version 10 of Angular.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For information on upgrading to Angular version 9, see [Updating to Angular version 9](https://v9.angular.io/guide/updating-to-version-9).
|
||||
|
||||
</div>
|
||||
|
||||
## Updating CLI Apps
|
||||
|
||||
For step-by-step instructions on how to update to the latest Angular release (and leverage our automated migration tools to do so), use the interactive update guide at [update.angular.io](https://update.angular.io).
|
||||
|
||||
If you're curious about the specific migrations being run by the CLI, see the [automated migrations section](#migrations) for details on what code is changing and why.
|
||||
|
||||
## Changes and Deprecations in Version 10
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For information about Angular's deprecation and removal practices, see [Angular Release Practices](guide/releases#deprecation-practices "Angular Release Practices: Deprecation practices").
|
||||
|
||||
</div>
|
||||
|
||||
{@a breaking-changes}
|
||||
### New Breaking Changes
|
||||
|
||||
* Typescript 3.6, 3.7, and 3.8 are no longer supported. Please update to Typescript 3.9.
|
||||
* Input fields of type `number` fire the `valueChanges` event only once per value change (as opposed to twice in some cases). See [PR 36087](https://github.com/angular/angular/pull/36087).
|
||||
* The `minLength` and `maxLength` validators only validate values that have a numeric `length` property. See [PR 36157](https://github.com/angular/angular/pull/36157).
|
||||
* Templates with unknown property bindings or unknown element names now log errors instead of warnings. See [PR 36399](https://github.com/angular/angular/pull/36399).
|
||||
* `UrlMatcher` can now return `null` values. See [PR 36402](https://github.com/angular/angular/pull/36402).
|
||||
* Transplanted views now refresh at insertion point only. See [PR 35968](https://github.com/angular/angular/pull/35968).
|
||||
* Formatting times with the `b` or `B` format codes now supports time periods that cross midnight. See [PR 36611](https://github.com/angular/angular/pull/36611).
|
||||
* Navigation is canceled for routes with at least one empty resolver. See [PR 24621](https://github.com/angular/angular/pull/24621).
|
||||
|
||||
{@a deprecations}
|
||||
### New Deprecations
|
||||
|
||||
| Area | API or Feature | May be removed in |
|
||||
| ----------------------------- | -------------------------------------------------- | ----------------- |
|
||||
| `@angular/core` | [`WrappedValue`](guide/deprecations#wrapped-value) | <!--v10--> v12 |
|
||||
| browser support | IE 9, 10, and IE Mobile | <!--v10--> v11 |
|
||||
|
||||
|
||||
{@a removals}
|
||||
### New Removals of Deprecated APIs
|
||||
|
||||
The following APIs have been removed starting with version 10.0.0*:
|
||||
|
||||
| Package | API | Replacement | Notes |
|
||||
| ---------------- | -------------- | ----------- | ----- |
|
||||
| `@angular/core` | Undecorated base classes that use Angular features | Add Angular decorator | See [migration guide](guide/migration-undecorated-classes) for more info |
|
||||
| `@angular/core` | `ModuleWithProviders` without a generic | `ModuleWithProviders` with a generic | See [migration guide](guide/migration-module-with-providers) for more info |
|
||||
| `@angular/core` | Style Sanitization | no action needed | See [style sanitization API removal](/guide/deprecations#style-sanitization) for more info
|
||||
| `@angular/bazel` | [`Bazel builder and schematics`](guide/deprecations#bazelbuilder) | `bazelbuild/rules_nodejs` | [More info](https://github.com/angular/angular/tree/10.0.x/packages/bazel/src/schematics) |
|
||||
|
||||
|
||||
*To see APIs removed in version 9, check out this guide on the [version 9 docs site](https://v9.angular.io/guide/deprecations#removed).
|
||||
|
||||
{@a ivy}
|
||||
|
||||
## Ivy features and compatibility
|
||||
|
||||
Since version 9, Angular Ivy is the default rendering engine. If you haven't heard of Ivy, you can read more about it in the [Angular Ivy guide](guide/ivy).
|
||||
|
||||
* Among other features, Ivy introduces more comprehensive type-checking within templates. For details, see [Template Type-checking](guide/template-typecheck).
|
||||
|
||||
* For general guidance on debugging and a list of minor changes associated with Ivy, see the [Ivy compatibility guide](guide/ivy-compatibility).
|
||||
|
||||
* For help with opting out of Ivy, see the instructions [here](guide/ivy#opting-out-of-angular-ivy).
|
||||
|
||||
{@a migrations}
|
||||
## Automated Migrations for Version 10
|
||||
|
||||
Read about the migrations the CLI handles for you automatically:
|
||||
|
||||
* [Migrating missing `@Directive()`/`@Component()` decorators](guide/migration-undecorated-classes)
|
||||
* [Migrating `ModuleWithProviders`](guide/migration-module-with-providers)
|
||||
* [`tslib` direct dependency migration](guide/migration-update-libraries-tslib)
|
||||
* [Update `module` and `target` compiler options migration](guide/migration-update-module-and-target-compiler-options)
|
||||
@@ -0,0 +1,73 @@
|
||||
# Updating Angular
|
||||
|
||||
This guide contains information related to updating to the latest version of Angular.
|
||||
|
||||
## Updating CLI Apps
|
||||
|
||||
For step-by-step instructions on how to update to the latest Angular release (and leverage our automated migration tools to do so), use the interactive update guide at [update.angular.io](https://update.angular.io).
|
||||
|
||||
## Changes and Deprecations in Version 11
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For information about Angular's deprecation and removal practices, see [Angular Release Practices](guide/releases#deprecation-practices "Angular Release Practices: Deprecation practices").
|
||||
|
||||
</div>
|
||||
|
||||
{@a breaking-changes}
|
||||
### New Breaking Changes
|
||||
|
||||
* Remove deprecated support for IE 9, 10, and IE mobile. See [PR 38931](https://github.com/angular/angular/pull/38931).
|
||||
* TypeScript 3.9 is no longer supported. Please update to TypeScript 4.0. See [PR 39313](https://github.com/angular/angular/pull/39313).
|
||||
* `NavigationExtras#preserveQueryParams` has been removed from `@angular/router`. See [PR 38762](https://github.com/angular/angular/pull/38762)
|
||||
* `CollectionChangeRecord` has been removed from `@angular/core`. See [PR 38668](https://github.com/angular/angular/pull/38668).
|
||||
* We changed the default value for `relativeLinkResolution` from `'legacy'` to `'corrected'` so that new applications are automatically opted-in to the corrected behavior from [PR 22394](https://github.com/angular/angular/pull/22394). Applications which use the current default are updated by a migration to specify `'legacy'` to ensure the current behavior is maintained when the default is updated. See [PR 25609](https://github.com/angular/angular/pull/25609).
|
||||
* Fixed a bug in the router where the arguments for `future` and `curr` snapshots were reversed in the call to `shouldReuseRoute` when processing child routes. Usually this ordering mistake doesn't matter because most implementations of [`shouldReuseRoute`](api/router/RouteReuseStrategy#shouldReuseRoute) just do
|
||||
an equality comparison between `future` and `curr`. However, some implementations actually do rely on values specifically on
|
||||
one of the two and will need to be updated. See [PR 26949](https://github.com/angular/angular/pull/26949).
|
||||
* `ViewEncapsulation.Native` has been removed. Angular previously supported a view encapsulation mode `ViewEncapsulaion.Native` that was based on the v0 Shadow DOM Draft APIs. These APIs have been superceded by the final Shadow DOM APIs, which are enabled via `ViewEncapsulation.ShadowDom`. For background information about this change, see [Web Components update: more time to upgrade to v1 APIs](https://developers.google.com/web/updates/2019/07/web-components-time-to-upgrade).
|
||||
* `@angular/platform-webworker` has been removed and will no longer be supported. See [PR 38846](https://github.com/angular/angular/pull/38846).
|
||||
* `@angular/platform-webworker` is no longer supported. No further versions will be published. See [PR 38846](https://github.com/angular/angular/pull/38846).
|
||||
* Updated the options for `initialNavigation`. For more information, see [initialNavigation](api/router/InitialNavigation) in the API documentation. See [PR 33128](https://github.com/angular/angular/pull/33128).
|
||||
* `DatePipe` no longer rounds up fractional milliseconds. See [PR 38009](https://github.com/angular/angular/pull/38009).
|
||||
* Locale data arrays are now read-only. See [PR 30397](https://github.com/angular/angular/pull/30397).
|
||||
* The injected `ControlValueAccessor` for `NG_VALUE_ACCESSOR` is now readonly. See [PR 29273](https://github.com/angular/angular/pull/29723).
|
||||
* The type of `AbstractControl#parent` now indicates that it may be null. See [PR 32671](https://github.com/angular/angular/pull/32671).
|
||||
* Calling `overrideProvider` before initializing the TestBed will now throw an error. See [PR 38717](https://github.com/angular/angular/pull/38717).
|
||||
* Types for many Angular built-in pipes have been either narrowed or expanded to be more accurate. For more information, see the corresponding [Pipes](https://angular.io/api?type=pipe) API documentation. See [PR 37447](https://github.com/angular/angular/pull/37447).
|
||||
* Directives in the `@angular/forms` package used to have `any[]` as a type of validators and asyncValidators
|
||||
arguments in constructors. Now these arguments are properly typed, so if your code relies on
|
||||
directive constructor types it may require some updates to improve type safety. See [PR 38994](https://github.com/angular/angular/pull/38944).
|
||||
* `routerLink` now accepts `undefined` inputs. See [PR 39151](https://github.com/angular/angular/pull/39151).
|
||||
* The `async` function from `@angular/core/testing` has been renamed to `waitForAsync` in order to avoid confusion with the native JavaScript `async` syntax. The existing function is deprecated and will be removed in a future version. See [PR 37583](https://github.com/angular/angular/pull/37583).
|
||||
|
||||
{@a deprecations}
|
||||
### New Deprecations
|
||||
|
||||
| Area | API or Feature | May be removed in |
|
||||
| ----------------------------- | -------------------------------------------------- | ----------------- |
|
||||
| `@angular/core/testing` | Rename `async` to `waitForAsync` | <!--v11--> v13 |
|
||||
|
||||
|
||||
{@a removals}
|
||||
### New Removals of Deprecated APIs
|
||||
|
||||
The following APIs have been removed starting with version 11.0.0*:
|
||||
|
||||
| Package | API | Replacement | Notes |
|
||||
| ---------------- | -------------- | ----------- | ----- |
|
||||
| `@angular/router`| `NavigationExtras#preserveQueryParams` | no action needed | NavigationExtras#preserveQueryParams has been removed from `@angular/router`.|
|
||||
| `@angular/core` | `CollectionChangeRecord` | no action needed | CollectionChangeRecord has been removed from `@angular/core`.|
|
||||
| `@angular/core` | `ViewEncapsulation.Native` | no action needed | Angular previously supported a view encapsulation mode `ViewEncapsulaion.Native` that was based on the v0 Shadow DOM Draft APIs. These APIs have been superceeded by the final Shadow DOM APIs, which are enabled via `ViewEncapsulation.ShadowDom`. For background information about this change, see [Web Components update: more time to upgrade to v1 APIs](https://developers.google.com/web/updates/2019/07/web-components-time-to-upgrade).|
|
||||
|
||||
{@a ivy}
|
||||
|
||||
## Ivy features and compatibility
|
||||
|
||||
Since version 9, Angular Ivy is the default rendering engine. If you haven't heard of Ivy, you can read more about it in the [Angular Ivy guide](guide/ivy).
|
||||
|
||||
* Among other features, Ivy introduces more comprehensive type-checking within templates. For details, see [Template Type-checking](guide/template-typecheck).
|
||||
|
||||
* For general guidance on debugging and a list of minor changes associated with Ivy, see the [Ivy compatibility guide](guide/ivy-compatibility).
|
||||
|
||||
* For help with opting out of Ivy, see the instructions [here](guide/ivy#opting-out-of-angular-ivy).
|
||||
@@ -1,5 +1,17 @@
|
||||
# User input
|
||||
|
||||
<div class="callout is-critical">
|
||||
<header>Marked for archiving</header>
|
||||
|
||||
To ensure that you have the best experience possible, this topic is marked for archiving until we determine
|
||||
that it clearly conveys the most accurate information possible.
|
||||
|
||||
In the meantime, this topic might be helpful: [Event binding](guide/event-binding).
|
||||
|
||||
If you think this content should not be archived, please file a [GitHub issue](https://github.com/angular/angular/issues/new?template=3-docs-bug.md).
|
||||
|
||||
</div>
|
||||
|
||||
User actions such as clicking a link, pushing a button, and entering
|
||||
text raise DOM events.
|
||||
This page explains how to bind those events to component event handlers using the Angular
|
||||
@@ -234,8 +246,8 @@ To fix this issue, listen to both the _Enter_ key and the _blur_ event.
|
||||
|
||||
|
||||
## Put it all together
|
||||
The previous page showed how to [display data](guide/displaying-data).
|
||||
This page demonstrated event binding techniques.
|
||||
|
||||
This page demonstrated several event binding techniques.
|
||||
|
||||
Now, put it all together in a micro-app
|
||||
that can display a list of heroes and add new heroes to the list.
|
||||
|
||||
@@ -149,7 +149,7 @@ See [Build target](#build-target) below for more information.
|
||||
|
||||
* The `architect/lint` section configures defaults for options of the `ng lint` command, which performs code analysis on project source files. The default linting tool for Angular is [TSLint](https://palantir.github.io/tslint/).
|
||||
|
||||
* The `architect/extract-i18n` section configures defaults for options of the `ng-xi18n` tool used by the `ng xi18n` command, which extracts marked message strings from source code and outputs translation files.
|
||||
* The `architect/extract-i18n` section configures defaults for options of the `ng extract-i18n` command, which extracts marked message strings from source code and outputs translation files.
|
||||
|
||||
* The `architect/server` section configures defaults for creating a Universal app with server-side rendering, using the `ng run <project>:server` command.
|
||||
|
||||
@@ -241,8 +241,16 @@ For example, the default asset paths can be represented in more detail using the
|
||||
<code-example language="json">
|
||||
|
||||
"assets": [
|
||||
{ "glob": "**/*", "input": "src/assets/", "output": "/assets/" },
|
||||
{ "glob": "favicon.ico", "input": "src/", "output": "/" }
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "src/assets/",
|
||||
"output": "/assets/"
|
||||
},
|
||||
{
|
||||
"glob": "favicon.ico",
|
||||
"input": "src/",
|
||||
"output": "/"
|
||||
}
|
||||
]
|
||||
|
||||
</code-example>
|
||||
@@ -253,7 +261,11 @@ For example, the following configuration copies assets from a node package:
|
||||
<code-example language="json">
|
||||
|
||||
"assets": [
|
||||
{ "glob": "**/*", "input": "./node_modules/some-package/images", "output": "/some-package/" },
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "./node_modules/some-package/images",
|
||||
"output": "/some-package/"
|
||||
}
|
||||
]
|
||||
|
||||
</code-example>
|
||||
@@ -265,7 +277,12 @@ The following example uses the `ignore` field to exclude certain files in the as
|
||||
<code-example language="json">
|
||||
|
||||
"assets": [
|
||||
{ "glob": "**/*", "input": "src/assets/", "ignore": ["**/*.svg"], "output": "/assets/" },
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "src/assets/",
|
||||
"ignore": ["**/*.svg"],
|
||||
"output": "/assets/"
|
||||
}
|
||||
]
|
||||
|
||||
</code-example>
|
||||
@@ -284,10 +301,18 @@ For example, the following object values create and name a bundle that contains
|
||||
<code-example language="json">
|
||||
|
||||
"styles": [
|
||||
{ "input": "src/external-module/styles.scss", "inject": false, "bundleName": "external-module" }
|
||||
{
|
||||
"input": "src/external-module/styles.scss",
|
||||
"inject": false,
|
||||
"bundleName": "external-module"
|
||||
}
|
||||
],
|
||||
"scripts": [
|
||||
{ "input": "src/external-module/main.js", "inject": false, "bundleName": "external-module" }
|
||||
{
|
||||
"input": "src/external-module/main.js",
|
||||
"inject": false,
|
||||
"bundleName": "external-module"
|
||||
}
|
||||
]
|
||||
|
||||
</code-example>
|
||||
@@ -341,25 +366,38 @@ See also [Using runtime-global libraries inside your app](guide/using-libraries#
|
||||
|
||||
### Optimization and source map configuration
|
||||
|
||||
The `optimization` and `sourceMap` command options are simple Boolean flags.
|
||||
You can supply an object as a configuration value for either of these to provide more detailed instruction.
|
||||
The `optimization` and `sourceMap` browser builder options can be either a Boolean or an Object for more fine-grained configuration.
|
||||
In this section we will explain how to fine tune these options.
|
||||
|
||||
* The flag `--optimization="true"` applies to both scripts and styles. You can supply a value such as the following to apply optimization to one or the other:
|
||||
* The `optimization` option applies to scripts, styles and fonts. You can supply a value such as the following to apply optimization to one or the other:
|
||||
|
||||
<code-example language="json">
|
||||
|
||||
"optimization": { "scripts": true, "styles": false }
|
||||
"optimization": {
|
||||
"scripts": true,
|
||||
"styles": false,
|
||||
"fonts": true
|
||||
}
|
||||
|
||||
</code-example>
|
||||
|
||||
* The flag `--sourceMap="true"` outputs source maps for both scripts and styles.
|
||||
You can configure the option to apply to one or the other.
|
||||
You can also choose to output hidden source maps, or resolve vendor package source maps.
|
||||
For example:
|
||||
<div class="alert is-important">
|
||||
|
||||
Fonts optimization requires internet access.
|
||||
When enabled, render blocking requests will be reduced by inlining external Google fonts and icons CSS definitions in the application's HTML index file.
|
||||
|
||||
</div>
|
||||
|
||||
* The `sourceMap` option applies for both scripts and styles. You can also choose to output hidden source maps, or resolve vendor package source maps:
|
||||
|
||||
<code-example language="json">
|
||||
|
||||
"sourceMap": { "scripts": true, "styles": false, "hidden": true, "vendor": true }
|
||||
"sourceMap": {
|
||||
"scripts": true,
|
||||
"styles": false,
|
||||
"hidden": true,
|
||||
"vendor": true
|
||||
}
|
||||
|
||||
</code-example>
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ To understand the benefits of `NgZone`, it is important to have a clear grasp of
|
||||
|
||||
### Displaying and updating data in Angular
|
||||
|
||||
In Angular, you can [display data](guide/displaying-data) by binding controls in an HTML template to the properties of an Angular component.
|
||||
In Angular, you can display data by binding controls in an HTML template to the properties of an Angular component.
|
||||
|
||||
<code-example path="displaying-data/src/app/app.component.1.ts" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
@@ -102,9 +102,9 @@ In Angular, this step is unnecessary. Whenever you update the data, your HTML is
|
||||
|
||||
To understand how change detection works, first consider when the application needs to update the HTML. Typically, updates occur for one of the following reasons:
|
||||
|
||||
1. Component initialization. For example, when bootstrapping an Angular application, Angular loads the bootstrap component and triggers the [ApplicationRef.tick()](api/core/ApplicationRef#tick) to call change detection and View Rendering. Just as in the [displaying data](guide/displaying-data) sample, the `AppComponent` is the bootstrap component. This component has the properties `title` and `myHero`, which the application renders in the HTML.
|
||||
1. Component initialization. For example, when bootstrapping an Angular application, Angular loads the bootstrap component and triggers the [ApplicationRef.tick()](api/core/ApplicationRef#tick) to call change detection and View Rendering.
|
||||
|
||||
2. Event listener. The DOM event listener can update the data in an Angular component and also trigger change detection, as in the following example.
|
||||
1. Event listener. The DOM event listener can update the data in an Angular component and also trigger change detection, as in the following example.
|
||||
|
||||
<code-example path="user-input/src/app/click-me.component.ts" region="click-me-component" header="src/app/click-me.component.ts"></code-example>
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user