Compare commits
117 Commits
10.1.0-nex
...
christianm
Author | SHA1 | Date | |
---|---|---|---|
443e29621f | |||
693b1a3c07 | |||
92c7145139 | |||
d133525502 | |||
cd1817bf6d | |||
0d1491b1a6 | |||
f67774d84b | |||
37668d159e | |||
38554288f5 | |||
04dcc3bceb | |||
0910a2fc0d | |||
3325cb2f86 | |||
a1e8443bfb | |||
599d34b41e | |||
7fd1733882 | |||
2e42123870 | |||
4cbb90daf7 | |||
cf2663b034 | |||
95681b16bd | |||
2d3650bf3b | |||
f121808bab | |||
e620827fa8 | |||
7f82a2c1c8 | |||
a9910f5991 | |||
ad7046b934 | |||
d72b1e44c6 | |||
eae13e42f3 | |||
3373453736 | |||
4a6dcd006b | |||
7c3c8d6d10 | |||
655da32837 | |||
5b31a0a294 | |||
5d3d8b8330 | |||
c8c74153b1 | |||
9dc5e8e7e2 | |||
1a7a7360b0 | |||
8edf5ba29d | |||
72f1eec3ad | |||
136acdfab6 | |||
095cfd961d | |||
38a7021d5e | |||
b3b03c35b5 | |||
fd45f7485d | |||
58f6079873 | |||
e382632473 | |||
cf9a47ba53 | |||
56dd3e77ac | |||
6c9401c338 | |||
019a696a6a | |||
8b25a64200 | |||
bd71f10234 | |||
e0b35bfc18 | |||
c1539b16ae | |||
737506e79c | |||
469aba0140 | |||
d8c47b971c | |||
24b420527a | |||
bf641e1b4b | |||
406f801b70 | |||
c8e77d8536 | |||
6ea2d1e20e | |||
09eee5b312 | |||
904ebfebf3 | |||
545f1dbac9 | |||
b00121c9a6 | |||
45d79efc3f | |||
1d9e56eba0 | |||
e7c722574f | |||
b358495a6c | |||
f4fac406b9 | |||
5fd2c8f2d6 | |||
421e807f80 | |||
df8b387570 | |||
f01b0337d2 | |||
4ec3026a9a | |||
9021d3f5e1 | |||
81542b3b72 | |||
9185c6e971 | |||
69472a1ed0 | |||
10aba15154 | |||
36dd817913 | |||
0eaa084ced | |||
62e19c8813 | |||
95669df4c3 | |||
6b311552f0 | |||
66947cf9fa | |||
a259a84d3f | |||
d1aa4678be | |||
04c220bbdf | |||
72d6032fa4 | |||
53d4859f48 | |||
f66f4a1b3f | |||
88d68d2d21 | |||
4783a071f3 | |||
9322b9a060 | |||
9bd4b74b06 | |||
e6afcf1f94 | |||
4b4b74548d | |||
1550663b9e | |||
c40cbecdd1 | |||
209a365511 | |||
fb735d625b | |||
d19ef6534f | |||
667aba7508 | |||
d380e93b82 | |||
2156beed0c | |||
b98314e306 | |||
e50c7dcc4c | |||
6b731a067a | |||
0a3dbc1e8a | |||
b24a24ec58 | |||
13ef5d6c7d | |||
54373cc895 | |||
bbe3543c69 | |||
bdbbff6a1a | |||
f81d3f6199 | |||
d0c0f25a48 |
@ -377,10 +377,6 @@ jobs:
|
||||
|
||||
test_aio:
|
||||
executor: default-executor
|
||||
parameters:
|
||||
debugArtifactsDir:
|
||||
type: string
|
||||
default: aio/dist/size-debug-artifacts
|
||||
steps:
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
@ -399,15 +395,6 @@ jobs:
|
||||
- run: yarn --cwd aio test-a11y-score-localhost
|
||||
# Check the bundle sizes.
|
||||
- run: yarn --cwd aio payload-size
|
||||
# When `payload-size` check fails, copy the files that were checked into `debugArtifactsDir`.
|
||||
- run:
|
||||
when: on_fail
|
||||
name: Prepare JS bundles to be stored as artifacts
|
||||
command: node aio/scripts/prepare-size-debug-artifacts aio << parameters.debugArtifactsDir >>
|
||||
# Store files in `debugArtifactsDir` (if any) as artifacts for debugging purposes.
|
||||
- store_artifacts:
|
||||
path: << parameters.debugArtifactsDir >>
|
||||
destination: aio
|
||||
# Run unit tests for Firebase redirects
|
||||
- run: yarn --cwd aio redirects-test
|
||||
|
||||
@ -423,9 +410,6 @@ jobs:
|
||||
|
||||
test_aio_local:
|
||||
parameters:
|
||||
debugArtifactsDir:
|
||||
type: string
|
||||
default: aio/dist/size-debug-artifacts
|
||||
viewengine:
|
||||
type: boolean
|
||||
default: false
|
||||
@ -444,15 +428,6 @@ jobs:
|
||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||
# Check the bundle sizes.
|
||||
- run: yarn --cwd aio payload-size aio-local<<# parameters.viewengine >>-viewengine<</ parameters.viewengine >>
|
||||
# When `payload-size` check fails, copy the files that were checked into `debugArtifactsDir`.
|
||||
- run:
|
||||
when: on_fail
|
||||
name: Prepare JS bundles to be stored as artifacts
|
||||
command: node aio/scripts/prepare-size-debug-artifacts aio-local<<# parameters.viewengine >>-viewengine<</ parameters.viewengine >> << parameters.debugArtifactsDir >>
|
||||
# Store files in `debugArtifactsDir` (if any) as artifacts for debugging purposes.
|
||||
- store_artifacts:
|
||||
path: << parameters.debugArtifactsDir >>
|
||||
destination: aio
|
||||
|
||||
test_aio_tools:
|
||||
executor: default-executor
|
||||
|
69
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
69
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
@ -1,69 +0,0 @@
|
||||
---
|
||||
name: "\U0001F41EBug report"
|
||||
about: Report a bug in the Angular Framework
|
||||
---
|
||||
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
|
||||
|
||||
Oh hi there! 😄
|
||||
|
||||
To expedite issue processing please search open and closed issues before submitting a new one.
|
||||
Existing issues often contain information about workarounds, resolution, or progress updates.
|
||||
|
||||
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
|
||||
|
||||
|
||||
# 🐞 bug report
|
||||
|
||||
### Affected Package
|
||||
<!-- Can you pin-point one or more @angular/* packages as the source of the bug? -->
|
||||
<!-- ✍️edit: --> The issue is caused by package @angular/....
|
||||
|
||||
|
||||
### Is this a regression?
|
||||
|
||||
<!-- Did this behavior use to work in the previous version? -->
|
||||
<!-- ✍️--> Yes, the previous version in which this bug was not present was: ....
|
||||
|
||||
|
||||
### Description
|
||||
|
||||
<!-- ✍️--> A clear and concise description of the problem...
|
||||
|
||||
|
||||
## 🔬 Minimal Reproduction
|
||||
<!--
|
||||
Please create and share minimal reproduction of the issue starting with this template: https://stackblitz.com/fork/angular-ivy
|
||||
-->
|
||||
<!-- ✍️--> https://stackblitz.com/...
|
||||
|
||||
<!--
|
||||
If StackBlitz is not suitable for reproduction of your issue, please create a minimal GitHub repository with the reproduction of the issue.
|
||||
A good way to make a minimal reproduction is to create a new app via `ng new repro-app` and add the minimum possible code to show the problem.
|
||||
Share the link to the repo below along with step-by-step instructions to reproduce the problem, as well as expected and actual behavior.
|
||||
|
||||
Issues that don't have enough info and can't be reproduced will be closed.
|
||||
|
||||
You can read more about issue submission guidelines here: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-submitting-an-issue
|
||||
-->
|
||||
|
||||
## 🔥 Exception or Error
|
||||
<pre><code>
|
||||
<!-- If the issue is accompanied by an exception or an error, please share it below: -->
|
||||
<!-- ✍️-->
|
||||
|
||||
</code></pre>
|
||||
|
||||
|
||||
## 🌍 Your Environment
|
||||
|
||||
**Angular Version:**
|
||||
<pre><code>
|
||||
<!-- run `ng version` and paste output below -->
|
||||
<!-- ✍️-->
|
||||
|
||||
</code></pre>
|
||||
|
||||
**Anything else relevant?**
|
||||
<!-- ✍️Is this a browser specific issue? If so, please specify the browser and version. -->
|
||||
|
||||
<!-- ✍️Do any of these matter: operating system, IDE, package manager, HTTP server, ...? If so, please mention it below. -->
|
32
.github/ISSUE_TEMPLATE/2-feature-request.md
vendored
32
.github/ISSUE_TEMPLATE/2-feature-request.md
vendored
@ -1,32 +0,0 @@
|
||||
---
|
||||
name: "\U0001F680Feature request"
|
||||
about: Suggest a feature for Angular Framework
|
||||
|
||||
---
|
||||
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
|
||||
|
||||
Oh hi there! 😄
|
||||
|
||||
To expedite issue processing please search open and closed issues before submitting a new one.
|
||||
Existing issues often contain information about workarounds, resolution, or progress updates.
|
||||
|
||||
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
|
||||
|
||||
|
||||
# 🚀 feature request
|
||||
|
||||
### Relevant Package
|
||||
<!-- Can you pin-point one or more @angular/* packages the are relevant for this feature request? -->
|
||||
<!-- ✍️edit: --> This feature request is for @angular/....
|
||||
|
||||
|
||||
### Description
|
||||
<!-- ✍️--> A clear and concise description of the problem or missing capability...
|
||||
|
||||
|
||||
### Describe the solution you'd like
|
||||
<!-- ✍️--> If you have a solution in mind, please describe it.
|
||||
|
||||
|
||||
### Describe alternatives you've considered
|
||||
<!-- ✍️--> Have you considered any alternative solutions or workarounds?
|
55
.github/ISSUE_TEMPLATE/3-docs-bug.md
vendored
55
.github/ISSUE_TEMPLATE/3-docs-bug.md
vendored
@ -1,55 +0,0 @@
|
||||
---
|
||||
name: "📚 Docs or angular.io issue report"
|
||||
about: Report an issue in Angular's documentation or angular.io application
|
||||
|
||||
---
|
||||
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
|
||||
|
||||
Oh hi there! 😄
|
||||
|
||||
To expedite issue processing please search open and closed issues before submitting a new one.
|
||||
Existing issues often contain information about workarounds, resolution, or progress updates.
|
||||
|
||||
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
|
||||
|
||||
# 📚 Docs or angular.io bug report
|
||||
|
||||
### Description
|
||||
|
||||
<!-- ✍️edit:--> A clear and concise description of the problem...
|
||||
|
||||
|
||||
## 🔬 Minimal Reproduction
|
||||
|
||||
### What's the affected URL?**
|
||||
<!-- ✍️edit:--> https://angular.io/...
|
||||
|
||||
### Reproduction Steps**
|
||||
<!-- If applicable please list the steps to take to reproduce the issue -->
|
||||
<!-- ✍️edit:-->
|
||||
|
||||
### Expected vs Actual Behavior**
|
||||
<!-- If applicable please describe the difference between the expected and actual behavior after following the repro steps. -->
|
||||
<!-- ✍️edit:-->
|
||||
|
||||
|
||||
## 📷Screenshot
|
||||
<!-- Often a screenshot can help to capture the issue better than a long description. -->
|
||||
<!-- ✍️upload a screenshot:-->
|
||||
|
||||
|
||||
## 🔥 Exception or Error
|
||||
<pre><code>
|
||||
<!-- If the issue is accompanied by an exception or an error, please share it below: -->
|
||||
<!-- ✍️-->
|
||||
|
||||
</code></pre>
|
||||
|
||||
|
||||
## 🌍 Your Environment
|
||||
|
||||
### Browser info
|
||||
<!-- ✍️Is this a browser specific issue? If so, please specify the device, browser, and version. -->
|
||||
|
||||
### Anything else relevant?
|
||||
<!-- ✍️Please provide additional info if necessary. -->
|
@ -1,11 +0,0 @@
|
||||
---
|
||||
name: ⚠️ Security issue disclosure
|
||||
about: Report a security issue in Angular Framework, Material, or CLI
|
||||
|
||||
---
|
||||
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
||||
|
||||
Please read https://angular.io/guide/security#report-issues on how to disclose security related issues.
|
||||
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
16
.github/ISSUE_TEMPLATE/5-support-request.md
vendored
16
.github/ISSUE_TEMPLATE/5-support-request.md
vendored
@ -1,16 +0,0 @@
|
||||
---
|
||||
name: "❓Support request"
|
||||
about: Questions and requests for support
|
||||
|
||||
---
|
||||
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
||||
|
||||
Please do not file questions or support requests on the GitHub issues tracker.
|
||||
|
||||
You can get your questions answered using other communication channels. Please see:
|
||||
https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
|
||||
|
||||
Thank you!
|
||||
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
13
.github/ISSUE_TEMPLATE/6-angular-cli.md
vendored
13
.github/ISSUE_TEMPLATE/6-angular-cli.md
vendored
@ -1,13 +0,0 @@
|
||||
---
|
||||
name: "\U0001F6E0️Angular CLI"
|
||||
about: Issues and feature requests for Angular CLI
|
||||
|
||||
---
|
||||
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
||||
|
||||
Please file any Angular CLI issues at: https://github.com/angular/angular-cli/issues/new
|
||||
|
||||
For the time being, we keep Angular CLI issues in a separate repository.
|
||||
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
13
.github/ISSUE_TEMPLATE/7-angular-components.md
vendored
13
.github/ISSUE_TEMPLATE/7-angular-components.md
vendored
@ -1,13 +0,0 @@
|
||||
---
|
||||
name: "\U0001F48EAngular Components"
|
||||
about: Issues and feature requests for Angular Components
|
||||
|
||||
---
|
||||
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
||||
|
||||
Please file any Angular Components issues at: https://github.com/angular/components/issues/new
|
||||
|
||||
For the time being, we keep Angular Components issues in a separate repository.
|
||||
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
22
.github/ISSUE_TEMPLATE/8-translate-docs.md
vendored
Normal file
22
.github/ISSUE_TEMPLATE/8-translate-docs.md
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
---
|
||||
name: "📚Traducir doc al español"
|
||||
about: Solicitud para traducir ciertos docs al español
|
||||
|
||||
---
|
||||
|
||||
📚Traducir: <!-- ✍️ editar: --> creating-libraries.md
|
||||
|
||||
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
|
||||
|
||||
Traducción de la documentación oficial de Angular a español
|
||||
|
||||
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
|
||||
|
||||
|
||||
## Nombre del archivo:
|
||||
<!-- ✍️ editar: --> creating-libraries.md
|
||||
|
||||
|
||||
## Ruta donde se encuentra el archivo dentro del proyecto de Angular
|
||||
|
||||
<!-- ✍️ editar: --> https://github.com/angular-hispano/angular/blob/master/aio/content/guide/creating-libraries.md
|
62
.github/PULL_REQUEST_TEMPLATE.md
vendored
62
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,43 +1,35 @@
|
||||
## PR Checklist
|
||||
Please check if your PR fulfills the following requirements:
|
||||
## Lista de Verificación del PR
|
||||
Comprueba si tu PR cumple los siguientes requisitos:
|
||||
|
||||
- [ ] The commit message follows our guidelines: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
|
||||
- [ ] Tests for the changes have been added (for bug fixes / features)
|
||||
- [ ] Docs have been added / updated (for bug fixes / features)
|
||||
- [ ] El mensaje de commit conforme con [nuestras reglas](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit)
|
||||
- [ ] Prueba los cambios que agregaste (arreglo de bugs / funcionalidades)
|
||||
- [ ] Revisa tus traducciones o cambios de contenido
|
||||
- [ ] Consulté el [diccionario de términos](https://github.com/angular-hispano/angular/issues/9) en español
|
||||
- [ ] Se han creado dos archivos con la extensión correspondiente(.en.md para el archivo en inglés y .md para el Archivo en español)
|
||||
- [ ] PR enlazada con el issue correspondiente
|
||||
|
||||
|
||||
## PR Type
|
||||
What kind of change does this PR introduce?
|
||||
## Tipo de PR
|
||||
¿Qué tipo de cambio introduce este PR?
|
||||
|
||||
<!-- Please check the one that applies to this PR using "x". -->
|
||||
<!-- Marca con una "x" las opciones que aplican. -->
|
||||
|
||||
- [ ] Bugfix
|
||||
- [ ] Feature
|
||||
- [ ] Code style update (formatting, local variables)
|
||||
- [ ] Refactoring (no functional changes, no api changes)
|
||||
- [ ] Build related changes
|
||||
- [ ] CI related changes
|
||||
- [ ] Documentation content changes
|
||||
- [ ] angular.io application / infrastructure changes
|
||||
- [ ] Other... Please describe:
|
||||
- [ ] Funcionalidad
|
||||
- [ ] Actualizar el estilo del código (formato, variables locales)
|
||||
- [ ] Refactorización (no cambios en la funcionalidad, no cambios en el api)
|
||||
- [ ] Cambios relacionados al build
|
||||
- [ ] Cambios relacionados al CI (Integración continua)
|
||||
- [ ] Cambios en el contenido de la documentación
|
||||
- [ ] Cambios en la aplicación / infrastructura de angular.io
|
||||
- [ ] Otro... Por favor describela:
|
||||
|
||||
## ¿Cuál es el comportamiento actual?
|
||||
<!-- Describe el comportamiento actual que está modificando o vincule a un problema relevante.
|
||||
-->
|
||||
|
||||
|
||||
## What is the current behavior?
|
||||
<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->
|
||||
|
||||
Issue Number: N/A
|
||||
|
||||
|
||||
## What is the new behavior?
|
||||
|
||||
|
||||
## Does this PR introduce a breaking change?
|
||||
|
||||
- [ ] Yes
|
||||
- [ ] No
|
||||
|
||||
|
||||
<!-- If this PR contains a breaking change, please describe the impact and migration path for existing applications below. -->
|
||||
|
||||
|
||||
## Other information
|
||||
## ¿Cuál es el nuevo comportamiento?
|
||||
<!--
|
||||
Ejemplo: Archivo en inglés traducido al español
|
||||
-->
|
||||
|
6
.github/angular-robot.yml
vendored
6
.github/angular-robot.yml
vendored
@ -154,6 +154,12 @@ triage:
|
||||
-
|
||||
- "type: RFC / Discussion / question"
|
||||
- "comp: *"
|
||||
-
|
||||
- "type: confusing"
|
||||
- "comp: *"
|
||||
-
|
||||
- "type: use-case"
|
||||
- "comp: *"
|
||||
|
||||
# options for the triage PR plugin
|
||||
triagePR:
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -42,3 +42,6 @@ yarn-error.log
|
||||
|
||||
.notes.md
|
||||
baseline.json
|
||||
|
||||
# Ignore .history for the xyz.local-history VSCode extension
|
||||
.history
|
||||
|
145
.gitmessage
Normal file
145
.gitmessage
Normal file
@ -0,0 +1,145 @@
|
||||
<type>(<scope>): <summary>
|
||||
|
||||
<Describe the motivation behind this change - explain WHY you are making this change. Wrap all lines
|
||||
at 100 characters.>
|
||||
|
||||
Fixes #<issue number>
|
||||
|
||||
# ────────────────────────────────────────── 100 chars ────────────────────────────────────────────┤
|
||||
|
||||
|
||||
# Example Commit Messages
|
||||
# =======================
|
||||
|
||||
|
||||
# ─── Example: Simple refactor ────────────────────────────────────────────────────────────────────┤
|
||||
# refactor(core): rename refreshDynamicEmbeddedViews to refreshEmbeddedViews
|
||||
#
|
||||
# Improve code readability. The original name no longer matches how the function is used.
|
||||
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
|
||||
|
||||
# ─── Example: Simple docs change ─────────────────────────────────────────────────────────────────┤
|
||||
# docs: clarify the service limitation in providers.md guide
|
||||
#
|
||||
# Fixes #36332
|
||||
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
|
||||
|
||||
# ─── Example: A bug fix ──────────────────────────────────────────────────────────────────────────┤
|
||||
# fix(ngcc): ensure lockfile is removed when `analyzeFn` fails
|
||||
#
|
||||
# Previously an error thrown in the `analyzeFn` would cause the ngcc process to exit immediately
|
||||
# without removing the lockfile, and potentially before the unlocker process had been successfully
|
||||
# spawned resulting in the lockfile being orphaned and left behind.
|
||||
#
|
||||
# Now we catch these errors and remove the lockfile as needed.
|
||||
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
|
||||
|
||||
# ─── Example: Breaking change ────────────────────────────────────────────────────────────────────┤
|
||||
# feat(bazel): simplify ng_package by dropping esm5 and fesm5
|
||||
#
|
||||
# esm5 and fesm5 distributions are no longer needed and have been deprecated in the past.
|
||||
#
|
||||
# https://v9.angular.io/guide/deprecations#esm5-and-fesm5-code-formats-in-angular-npm-packages
|
||||
#
|
||||
# This commit modifies ng_package to no longer distribute these two formats in npm packages built by
|
||||
# ng_package (e.g. @angular/core).
|
||||
#
|
||||
# This commit intentionally doesn't fully clean up the ng_package rule to remove all traces of esm5
|
||||
# and fems5 build artifacts as that is a bigger cleanup and currently we are narrowing down the
|
||||
# scope of this change to the MVP needed for v10, which in this case is 'do not put esm5 and fesm5'
|
||||
# into the npm packages.
|
||||
#
|
||||
# More cleanup to follow: https://angular-team.atlassian.net/browse/FW-2143
|
||||
#
|
||||
# BREAKING CHANGE: esm5 and fesm5 format is no longer distributed in Angular's npm packages e.g.
|
||||
# @angular/core
|
||||
#
|
||||
# Angular CLI will automatically downlevel the code to es5 if differential loading is enabled in the
|
||||
# Angular project, so no action is required from Angular CLI users.
|
||||
#
|
||||
# If you are not using Angular CLI to build your application or library, and you need to be able to
|
||||
# build es5 artifacts, then you will need to downlevel the distributed Angular code to es5 on your
|
||||
# own.
|
||||
#
|
||||
#
|
||||
# Fixes #1234
|
||||
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
|
||||
|
||||
|
||||
# Angular Commit Message Format
|
||||
# =============================
|
||||
#
|
||||
# The full specification of the Angular Commit Message Format can be found at
|
||||
# https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
|
||||
#
|
||||
# The following is an excerpt of the specification with the most commonly needed info.
|
||||
#
|
||||
# Each commit message consists of a *header*, a *body*, and a *footer*.
|
||||
#
|
||||
# <header>
|
||||
# <BLANK LINE>
|
||||
# <body>
|
||||
# <BLANK LINE>
|
||||
# <footer>
|
||||
#
|
||||
# The header is mandatory.
|
||||
#
|
||||
# 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 footer is optional.
|
||||
#
|
||||
# Any line of the commit message cannot be longer than 100 characters.
|
||||
#
|
||||
#
|
||||
# Commit Message Header
|
||||
# ---------------------
|
||||
#
|
||||
# <type>(<scope>): <short summary>
|
||||
# │ │ │
|
||||
# │ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
|
||||
# │ │
|
||||
# │ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
|
||||
# │ elements|forms|http|language-service|localize|platform-browser|
|
||||
# │ platform-browser-dynamic|platform-server|platform-webworker|
|
||||
# │ platform-webworker-dynamic|router|service-worker|upgrade|zone.js|
|
||||
# │ packaging|changelog|dev-infra|docs-infra|migrations|ngcc|ve
|
||||
# │ https://github.com/angular/angular/blob/master/CONTRIBUTING.md#scope
|
||||
# │
|
||||
# └─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
|
||||
# https://github.com/angular/angular/blob/master/CONTRIBUTING.md#type
|
||||
#
|
||||
#
|
||||
# Commit Message Body
|
||||
# ---------------------
|
||||
#
|
||||
# Just as in the summary, use the imperative, present tense: "fix" not "fixed" nor "fixes".
|
||||
#
|
||||
# Explain the motivation for the change in the commit message body. This commit message should
|
||||
# explain WHY you are making the change. 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
|
||||
# ---------------------
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# ```
|
||||
# BREAKING CHANGE: <breaking change summary>
|
||||
# <BLANK LINE>
|
||||
# <breaking change description + migration instructions>
|
||||
# <BLANK LINE>
|
||||
# <BLANK LINE>
|
||||
# Fixes #<issue number>
|
||||
# ```
|
||||
#
|
||||
# Breaking Change section should start with the phrase "BREAKING CHANGE: " followed by a summary of
|
||||
# the breaking change, a blank line, and a detailed description of the breaking change that also
|
||||
# includes migration instructions.
|
||||
#
|
52
.ng-dev/commit-message.ts
Normal file
52
.ng-dev/commit-message.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import {CommitMessageConfig} from '../dev-infra/commit-message/config';
|
||||
|
||||
/**
|
||||
* The configuration for `ng-dev commit-message` commands.
|
||||
*/
|
||||
export const commitMessage: CommitMessageConfig = {
|
||||
maxLineLength: 120,
|
||||
minBodyLength: 20,
|
||||
minBodyLengthTypeExcludes: ['docs'],
|
||||
types: [
|
||||
'build',
|
||||
'ci',
|
||||
'docs',
|
||||
'feat',
|
||||
'fix',
|
||||
'perf',
|
||||
'refactor',
|
||||
'release',
|
||||
'style',
|
||||
'test',
|
||||
],
|
||||
scopes: [
|
||||
'animations',
|
||||
'bazel',
|
||||
'benchpress',
|
||||
'changelog',
|
||||
'common',
|
||||
'compiler',
|
||||
'compiler-cli',
|
||||
'core',
|
||||
'dev-infra',
|
||||
'docs-infra',
|
||||
'elements',
|
||||
'forms',
|
||||
'http',
|
||||
'language-service',
|
||||
'localize',
|
||||
'migrations',
|
||||
'ngcc',
|
||||
'packaging',
|
||||
'platform-browser',
|
||||
'platform-browser-dynamic',
|
||||
'platform-server',
|
||||
'platform-webworker',
|
||||
'platform-webworker-dynamic',
|
||||
'router',
|
||||
'service-worker',
|
||||
'upgrade',
|
||||
've',
|
||||
'zone.js',
|
||||
]
|
||||
};
|
@ -1,116 +1,8 @@
|
||||
import {MergeConfig} from '../dev-infra/pr/merge/config';
|
||||
import {commitMessage} from './commit-message';
|
||||
import {format} from './format';
|
||||
import {github} from './github';
|
||||
import {merge} from './merge';
|
||||
|
||||
// The configuration for `ng-dev commit-message` commands.
|
||||
const commitMessage = {
|
||||
'maxLength': 120,
|
||||
'minBodyLength': 100,
|
||||
'minBodyLengthTypeExcludes': ['docs'],
|
||||
'types': [
|
||||
'build',
|
||||
'ci',
|
||||
'docs',
|
||||
'feat',
|
||||
'fix',
|
||||
'perf',
|
||||
'refactor',
|
||||
'release',
|
||||
'style',
|
||||
'test',
|
||||
],
|
||||
'scopes': [
|
||||
'animations',
|
||||
'bazel',
|
||||
'benchpress',
|
||||
'changelog',
|
||||
'common',
|
||||
'compiler',
|
||||
'compiler-cli',
|
||||
'core',
|
||||
'dev-infra',
|
||||
'docs-infra',
|
||||
'elements',
|
||||
'forms',
|
||||
'http',
|
||||
'language-service',
|
||||
'localize',
|
||||
'migrations',
|
||||
'ngcc',
|
||||
'packaging',
|
||||
'platform-browser',
|
||||
'platform-browser-dynamic',
|
||||
'platform-server',
|
||||
'platform-webworker',
|
||||
'platform-webworker-dynamic',
|
||||
'router',
|
||||
'service-worker',
|
||||
'upgrade',
|
||||
've',
|
||||
'zone.js',
|
||||
]
|
||||
};
|
||||
|
||||
// The configuration for `ng-dev format` commands.
|
||||
const format = {
|
||||
'clang-format': {
|
||||
'matchers': [
|
||||
'**/*.{js,ts}',
|
||||
// TODO: burn down format failures and remove aio and integration exceptions.
|
||||
'!aio/**',
|
||||
'!integration/**',
|
||||
// Both third_party and .yarn are directories containing copied code which should
|
||||
// not be modified.
|
||||
'!third_party/**',
|
||||
'!.yarn/**',
|
||||
// Do not format d.ts files as they are generated
|
||||
'!**/*.d.ts',
|
||||
]
|
||||
},
|
||||
'buildifier': true
|
||||
};
|
||||
|
||||
/** Github metadata information for `ng-dev` commands. */
|
||||
const github = {
|
||||
owner: 'angular',
|
||||
name: 'angular',
|
||||
};
|
||||
|
||||
// Configuration for the `ng-dev pr merge` command. The command can be used
|
||||
// for merging upstream pull requests into branches based on a PR target label.
|
||||
const merge = () => {
|
||||
// TODO: resume dynamically determining patch branch
|
||||
const patch = '10.0.x';
|
||||
const config: MergeConfig = {
|
||||
githubApiMerge: false,
|
||||
claSignedLabel: 'cla: yes',
|
||||
mergeReadyLabel: /^PR action: merge(-assistance)?/,
|
||||
caretakerNoteLabel: 'PR action: merge-assistance',
|
||||
commitMessageFixupLabel: 'commit message fixup',
|
||||
labels: [
|
||||
{
|
||||
pattern: 'PR target: master-only',
|
||||
branches: ['master'],
|
||||
},
|
||||
{
|
||||
pattern: 'PR target: patch-only',
|
||||
branches: [patch],
|
||||
},
|
||||
{
|
||||
pattern: 'PR target: master & patch',
|
||||
branches: ['master', patch],
|
||||
},
|
||||
],
|
||||
requiredBaseCommits: {
|
||||
// PRs that target either `master` or the patch branch, need to be rebased
|
||||
// on top of the latest commit message validation fix.
|
||||
// These SHAs are the commits that update the required license text in the header.
|
||||
'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a',
|
||||
[patch]: '27b95ba64a5d99757f4042073fd1860e20e3ed24'
|
||||
},
|
||||
};
|
||||
return config;
|
||||
};
|
||||
|
||||
// Export function to build ng-dev configuration object.
|
||||
module.exports = {
|
||||
commitMessage,
|
||||
format,
|
||||
|
22
.ng-dev/format.ts
Normal file
22
.ng-dev/format.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import {FormatConfig} from '../dev-infra/format/config';
|
||||
|
||||
/**
|
||||
* Configuration for the `ng-dev format` command.
|
||||
*/
|
||||
export const format: FormatConfig = {
|
||||
'clang-format': {
|
||||
'matchers': [
|
||||
'**/*.{js,ts}',
|
||||
// TODO: burn down format failures and remove aio and integration exceptions.
|
||||
'!aio/**',
|
||||
'!integration/**',
|
||||
// Both third_party and .yarn are directories containing copied code which should
|
||||
// not be modified.
|
||||
'!third_party/**',
|
||||
'!.yarn/**',
|
||||
// Do not format d.ts files as they are generated
|
||||
'!**/*.d.ts',
|
||||
]
|
||||
},
|
||||
'buildifier': true
|
||||
};
|
15
.ng-dev/gitconfig
Normal file
15
.ng-dev/gitconfig
Normal file
@ -0,0 +1,15 @@
|
||||
# The file is inert unless it's explicitly included into the local git config via:
|
||||
#
|
||||
# ```
|
||||
# git config --add include.path '../.ng-dev/gitconfig'
|
||||
# ```
|
||||
#
|
||||
# Calling that command will append the following into `.git/config` of the current git workspace
|
||||
# (i.e. $GIT_DIR, typically `angular/.git/config`):
|
||||
#
|
||||
# ```
|
||||
# [include]
|
||||
# path = ../.ng-dev/gitconfig
|
||||
# ```
|
||||
[commit]
|
||||
template = .gitmessage
|
11
.ng-dev/github.ts
Normal file
11
.ng-dev/github.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import {GithubConfig} from '../dev-infra/utils/config';
|
||||
|
||||
/**
|
||||
* Github configuration for the `ng-dev` command. This repository is used as
|
||||
* remote for the merge script and other utilities like `ng-dev pr rebase`.
|
||||
*/
|
||||
|
||||
export const github: GithubConfig = {
|
||||
owner: 'angular',
|
||||
name: 'angular'
|
||||
};
|
38
.ng-dev/merge.ts
Normal file
38
.ng-dev/merge.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import {MergeConfig} from '../dev-infra/pr/merge/config';
|
||||
|
||||
/**
|
||||
* Configuration for the merge tool in `ng-dev`. This sets up the labels which
|
||||
* are respected by the merge script (e.g. the target labels).
|
||||
*/
|
||||
export const merge = (): MergeConfig => {
|
||||
// TODO: resume dynamically determining patch branch
|
||||
const patch = '10.0.x';
|
||||
return {
|
||||
githubApiMerge: false,
|
||||
claSignedLabel: 'cla: yes',
|
||||
mergeReadyLabel: /^PR action: merge(-assistance)?/,
|
||||
caretakerNoteLabel: 'PR action: merge-assistance',
|
||||
commitMessageFixupLabel: 'commit message fixup',
|
||||
labels: [
|
||||
{
|
||||
pattern: 'PR target: master-only',
|
||||
branches: ['master'],
|
||||
},
|
||||
{
|
||||
pattern: 'PR target: patch-only',
|
||||
branches: [patch],
|
||||
},
|
||||
{
|
||||
pattern: 'PR target: master & patch',
|
||||
branches: ['master', patch],
|
||||
},
|
||||
],
|
||||
requiredBaseCommits: {
|
||||
// PRs that target either `master` or the patch branch, need to be rebased
|
||||
// on top of the latest commit message validation fix.
|
||||
// These SHAs are the commits that update the required license text in the header.
|
||||
'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a',
|
||||
[patch]: '27b95ba64a5d99757f4042073fd1860e20e3ed24'
|
||||
},
|
||||
};
|
||||
};
|
@ -175,7 +175,6 @@ groups:
|
||||
- kara # Kara Erickson
|
||||
- kyliau # Keen Yee Liau
|
||||
- manughub # Manu Murthy
|
||||
- matsko # Matias Niemela
|
||||
- mgechev # Minko Gechev
|
||||
- mhevery # Miško Hevery
|
||||
- mmalerba # Miles Malerba
|
||||
@ -206,7 +205,9 @@ groups:
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
- matsko
|
||||
- crisbeto
|
||||
- IgorMinar
|
||||
- jelbourn
|
||||
|
||||
|
||||
# =========================================================
|
||||
@ -346,26 +347,38 @@ groups:
|
||||
'aio/content/guide/ngmodule-vs-jsmodule.md',
|
||||
'aio/content/guide/module-types.md',
|
||||
'aio/content/guide/template-syntax.md',
|
||||
'aio/content/guide/built-in-template-functions.md',
|
||||
'aio/content/examples/built-in-template-functions/**',
|
||||
'aio/content/guide/event-binding.md',
|
||||
'aio/content/examples/event-binding/**',
|
||||
'aio/content/guide/interpolation.md',
|
||||
'aio/content/examples/interpolation/**',
|
||||
'aio/content/examples/template-syntax/**',
|
||||
'aio/content/images/guide/template-syntax/**',
|
||||
'aio/content/guide/binding-syntax.md',
|
||||
'aio/content/examples/binding-syntax/**',
|
||||
'aio/content/guide/property-binding.md',
|
||||
'aio/content/examples/property-binding/**',
|
||||
'aio/content/guide/attribute-binding.md',
|
||||
'aio/content/examples/attribute-binding/**',
|
||||
'aio/content/guide/two-way-binding.md',
|
||||
'aio/content/examples/two-way-binding/**',
|
||||
'aio/content/guide/built-in-directives.md',
|
||||
'aio/content/examples/built-in-directives/**',
|
||||
'aio/content/images/guide/built-in-directives/**',
|
||||
'aio/content/guide/template-reference-variables.md',
|
||||
'aio/content/examples/template-reference-variables/**',
|
||||
'aio/content/guide/inputs-outputs.md',
|
||||
'aio/content/examples/inputs-outputs/**',
|
||||
'aio/content/images/guide/inputs-outputs/**',
|
||||
'aio/content/guide/template-expression-operators.md',
|
||||
'aio/content/examples/template-expression-operators/**',
|
||||
'aio/content/guide/pipes.md',
|
||||
'aio/content/examples/pipes/**',
|
||||
'aio/content/images/guide/pipes/**',
|
||||
'aio/content/guide/providers.md',
|
||||
'aio/content/examples/providers/**',
|
||||
'aio/content/images/guide/providers/**',
|
||||
'aio/content/guide/singleton-services.md',
|
||||
'aio/content/guide/set-document-title.md',
|
||||
'aio/content/examples/set-document-title/**',
|
||||
@ -373,7 +386,9 @@ groups:
|
||||
'aio/content/guide/sharing-ngmodules.md',
|
||||
'aio/content/guide/structural-directives.md',
|
||||
'aio/content/examples/structural-directives/**',
|
||||
'aio/content/guide/svg-in-templates.md',
|
||||
'aio/content/images/guide/structural-directives/**',
|
||||
'aio/content/guide/template-statements.md',
|
||||
'aio/content/guide/user-input.md',
|
||||
'aio/content/examples/user-input/**',
|
||||
'aio/content/images/guide/user-input/**'
|
||||
@ -532,6 +547,7 @@ groups:
|
||||
'packages/examples/router/**',
|
||||
'aio/content/guide/router.md',
|
||||
'aio/content/guide/router-tutorial.md',
|
||||
'aio/content/guide/router-tutorial-toh.md',
|
||||
'aio/content/examples/router-tutorial/**',
|
||||
'aio/content/examples/router/**',
|
||||
'aio/content/images/guide/router/**'
|
||||
@ -612,6 +628,14 @@ groups:
|
||||
contains_any_globs(files.exclude('packages/compiler-cli/**'), [
|
||||
'**/testing/**',
|
||||
'aio/content/guide/testing.md',
|
||||
'aio/content/guide/test-debugging.md',
|
||||
'aio/content/guide/testing-attribute-directives.md',
|
||||
'aio/content/guide/testing-code-coverage.md',
|
||||
'aio/content/guide/testing-components-basics.md',
|
||||
'aio/content/guide/testing-components-scenarios.md',
|
||||
'aio/content/guide/testing-pipes.md',
|
||||
'aio/content/guide/testing-services.md',
|
||||
'aio/content/guide/testing-utility-apis.md',
|
||||
'aio/content/examples/testing/**',
|
||||
'aio/content/images/guide/testing/**'
|
||||
])
|
||||
@ -1131,9 +1155,10 @@ groups:
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
- alxhub
|
||||
- IgorMinar
|
||||
- alxhub
|
||||
- jelbourn
|
||||
- petebacondarwin
|
||||
- pkozlowski-opensource
|
||||
reviews:
|
||||
request: -1 # request reviews from everyone
|
||||
@ -1154,9 +1179,10 @@ groups:
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
- alxhub
|
||||
- IgorMinar
|
||||
- alxhub
|
||||
- jelbourn
|
||||
- petebacondarwin
|
||||
- pkozlowski-opensource
|
||||
reviews:
|
||||
request: -1 # request reviews from everyone
|
||||
@ -1180,6 +1206,7 @@ groups:
|
||||
- IgorMinar
|
||||
- jelbourn
|
||||
- josephperrott
|
||||
- petebacondarwin
|
||||
- pkozlowski-opensource
|
||||
|
||||
|
||||
@ -1201,6 +1228,9 @@ groups:
|
||||
reviewers:
|
||||
users:
|
||||
- IgorMinar
|
||||
- jelbourn
|
||||
- josephperrott
|
||||
- mhevery
|
||||
|
||||
|
||||
# ====================================================
|
||||
|
3
.vscode/recommended-settings.json
vendored
3
.vscode/recommended-settings.json
vendored
@ -26,6 +26,7 @@
|
||||
"**/bazel-out": true,
|
||||
"**/dist": true,
|
||||
"**/aio/src/generated": true,
|
||||
".history": true,
|
||||
},
|
||||
"git.ignoreLimitWarning": true,
|
||||
}
|
||||
}
|
37
CHANGELOG.md
37
CHANGELOG.md
@ -1,3 +1,40 @@
|
||||
<a name="10.0.4"></a>
|
||||
## 10.0.4 (2020-07-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** ng_module rule does not expose flat module information in Ivy ([#36971](https://github.com/angular/angular/issues/36971)) ([b76a2dc](https://github.com/angular/angular/commit/b76a2dc))
|
||||
* **compiler:** check more cases for pipe usage inside host bindings ([#37883](https://github.com/angular/angular/issues/37883)) ([a94383f](https://github.com/angular/angular/commit/a94383f)), closes [#34655](https://github.com/angular/angular/issues/34655) [#37610](https://github.com/angular/angular/issues/37610)
|
||||
* **language-service:** non-existent module format in package output ([#37778](https://github.com/angular/angular/issues/37778)) ([12f1773](https://github.com/angular/angular/commit/12f1773))
|
||||
* **language-service:** remove completion for string ([#37983](https://github.com/angular/angular/issues/37983)) ([387e838](https://github.com/angular/angular/commit/387e838))
|
||||
* **ngcc:** report a warning if ngcc tries to use a solution-style tsconfig ([#38003](https://github.com/angular/angular/issues/38003)) ([e3b8010](https://github.com/angular/angular/commit/e3b8010)), closes [#36386](https://github.com/angular/angular/issues/36386)
|
||||
* **service-worker:** correctly handle relative base href ([#37922](https://github.com/angular/angular/issues/37922)) ([b186db7](https://github.com/angular/angular/commit/b186db7)), closes [#25055](https://github.com/angular/angular/issues/25055) [#25055](https://github.com/angular/angular/issues/25055)
|
||||
* **service-worker:** correctly serve `ngsw/state` with a non-root SW scope ([#37922](https://github.com/angular/angular/issues/37922)) ([dc42c97](https://github.com/angular/angular/commit/dc42c97)), closes [#30505](https://github.com/angular/angular/issues/30505)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **bazel:** provide LinkablePackageInfo from ng_module ([#37778](https://github.com/angular/angular/issues/37778)) ([6cd10a1](https://github.com/angular/angular/commit/6cd10a1)), closes [/github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl#L144-L146](https://github.com//github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl/issues/L144-L146)
|
||||
|
||||
|
||||
<a name="10.1.0-next.1"></a>
|
||||
# 10.1.0-next.1 (2020-07-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** ng_module rule does not expose flat module information in Ivy ([#36971](https://github.com/angular/angular/issues/36971)) ([1550663](https://github.com/angular/angular/commit/1550663))
|
||||
* **compiler:** check more cases for pipe usage inside host bindings ([#37883](https://github.com/angular/angular/issues/37883)) ([9322b9a](https://github.com/angular/angular/commit/9322b9a)), closes [#34655](https://github.com/angular/angular/issues/34655) [#37610](https://github.com/angular/angular/issues/37610)
|
||||
* **compiler-cli:** ensure file_system handles mixed Windows drives ([#37959](https://github.com/angular/angular/issues/37959)) ([6b31155](https://github.com/angular/angular/commit/6b31155)), closes [#36777](https://github.com/angular/angular/issues/36777)
|
||||
* **language-service:** remove completion for string ([#37983](https://github.com/angular/angular/issues/37983)) ([10aba15](https://github.com/angular/angular/commit/10aba15))
|
||||
* **ngcc:** report a warning if ngcc tries to use a solution-style tsconfig ([#38003](https://github.com/angular/angular/issues/38003)) ([b358495](https://github.com/angular/angular/commit/b358495)), closes [#36386](https://github.com/angular/angular/issues/36386)
|
||||
* **router:** ensure duplicate popstate/hashchange events are handled correctly ([#37674](https://github.com/angular/angular/issues/37674)) ([9185c6e](https://github.com/angular/angular/commit/9185c6e)), closes [/github.com/angular/angular/issues/16710#issuecomment-646919529](https://github.com//github.com/angular/angular/issues/16710/issues/issuecomment-646919529) [#16710](https://github.com/angular/angular/issues/16710)
|
||||
* **service-worker:** correctly handle relative base href ([#37922](https://github.com/angular/angular/issues/37922)) ([d19ef65](https://github.com/angular/angular/commit/d19ef65)), closes [#25055](https://github.com/angular/angular/issues/25055) [#25055](https://github.com/angular/angular/issues/25055)
|
||||
* **service-worker:** correctly serve `ngsw/state` with a non-root SW scope ([#37922](https://github.com/angular/angular/issues/37922)) ([2156bee](https://github.com/angular/angular/commit/2156bee)), closes [#30505](https://github.com/angular/angular/issues/30505)
|
||||
|
||||
|
||||
|
||||
<a name="10.1.0-next.0"></a>
|
||||
# 10.1.0-next.0 (2020-07-08)
|
||||
|
||||
|
297
CONTRIBUTING.md
297
CONTRIBUTING.md
@ -1,7 +1,7 @@
|
||||
# Contributing to Angular
|
||||
|
||||
We would love for you to contribute to Angular and help make it even better than it is
|
||||
today! As a contributor, here are the guidelines we would like you to follow:
|
||||
We would love for you to contribute to Angular and help make it even better than it is today!
|
||||
As a contributor, here are the guidelines we would like you to follow:
|
||||
|
||||
- [Code of Conduct](#coc)
|
||||
- [Question or Problem?](#question)
|
||||
@ -12,12 +12,17 @@ today! As a contributor, here are the guidelines we would like you to follow:
|
||||
- [Commit Message Guidelines](#commit)
|
||||
- [Signing the CLA](#cla)
|
||||
|
||||
|
||||
## <a name="coc"></a> Code of Conduct
|
||||
Help us keep Angular open and inclusive. Please read and follow our [Code of Conduct][coc].
|
||||
|
||||
Help us keep Angular open and inclusive.
|
||||
Please read and follow our [Code of Conduct][coc].
|
||||
|
||||
|
||||
## <a name="question"></a> Got a Question or Problem?
|
||||
|
||||
Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests. You've got much better chances of getting your question answered on [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) where the questions should be tagged with tag `angular`.
|
||||
Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests.
|
||||
Instead, we recommend using [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) to ask support-related questions. When creating a new question on Stack Overflow, make sure to add the `angular` tag.
|
||||
|
||||
Stack Overflow is a much better place to ask questions since:
|
||||
|
||||
@ -29,35 +34,41 @@ To save your and our time, we will systematically close all issues that are requ
|
||||
|
||||
If you would like to chat about the question in real-time, you can reach out via [our gitter channel][gitter].
|
||||
|
||||
|
||||
## <a name="issue"></a> Found a Bug?
|
||||
If you find a bug in the source code, you can help us by
|
||||
[submitting an issue](#submit-issue) to our [GitHub Repository][github]. Even better, you can
|
||||
[submit a Pull Request](#submit-pr) with a fix.
|
||||
|
||||
If you find a bug in the source code, you can help us by [submitting an issue](#submit-issue) to our [GitHub Repository][github].
|
||||
Even better, you can [submit a Pull Request](#submit-pr) with a fix.
|
||||
|
||||
|
||||
## <a name="feature"></a> Missing a Feature?
|
||||
You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub
|
||||
Repository. If you would like to *implement* a new feature, please submit an issue with
|
||||
a proposal for your work first, to be sure that we can use it.
|
||||
Please consider what kind of change it is:
|
||||
You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub Repository.
|
||||
If you would like to *implement* a new feature, please consider the size of the change in order to determine the right steps to proceed:
|
||||
|
||||
* For a **Major Feature**, first open an issue and outline your proposal so that it can be discussed.
|
||||
This process allows us to better coordinate our efforts, prevent duplication of work, and help you to craft the change so that it is successfully accepted into the project.
|
||||
|
||||
**Note**: Adding a new topic to the documentation, or significantly re-writing a topic, counts as a major feature.
|
||||
|
||||
* For a **Major Feature**, first open an issue and outline your proposal so that it can be
|
||||
discussed. This will also allow us to better coordinate our efforts, prevent duplication of work,
|
||||
and help you to craft the change so that it is successfully accepted into the project. **Note**:
|
||||
Adding a new topic to the documentation, or significantly re-writing a topic, counts as a major
|
||||
feature.
|
||||
* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
|
||||
|
||||
|
||||
## <a name="submit"></a> Submission Guidelines
|
||||
|
||||
|
||||
### <a name="submit-issue"></a> Submitting an Issue
|
||||
|
||||
Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available.
|
||||
|
||||
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs, we will systematically ask you to provide a minimal reproduction. Having a minimal reproducible scenario gives us a wealth of important information without going back & forth to you with additional questions.
|
||||
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it.
|
||||
In order to reproduce bugs, we require that you provide a minimal reproduction.
|
||||
Having a minimal reproducible scenario gives us a wealth of important information without going back and forth to you with additional questions.
|
||||
|
||||
A minimal reproduction allows us to quickly confirm a bug (or point out a coding problem) as well as confirm that we are fixing the right problem.
|
||||
|
||||
We will be insisting on a minimal reproduction scenario in order to save maintainers' time and ultimately be able to fix more bugs. Interestingly, from our experience, users often find coding problems themselves while preparing a minimal reproduction. We understand that sometimes it might be hard to extract essential bits of code from a larger codebase but we really need to isolate the problem before we can fix it.
|
||||
We require a minimal reproduction to save maintainers' time and ultimately be able to fix more bugs.
|
||||
Often, developers find coding problems themselves while preparing a minimal reproduction.
|
||||
We understand that sometimes it might be hard to extract essential bits of code from a larger codebase but we really need to isolate the problem before we can fix it.
|
||||
|
||||
Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you, we are going to close an issue that doesn't have enough info to be reproduced.
|
||||
|
||||
@ -65,56 +76,66 @@ You can file new issues by selecting from our [new issue templates](https://gith
|
||||
|
||||
|
||||
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
|
||||
|
||||
Before you submit your Pull Request (PR) consider the following guidelines:
|
||||
|
||||
1. Search [GitHub](https://github.com/angular/angular/pulls) for an open or closed PR
|
||||
that relates to your submission. You don't want to duplicate effort.
|
||||
1. Be sure that an issue describes the problem you're fixing, or documents the design for the feature you'd like to add.
|
||||
Discussing the design upfront helps to ensure that we're ready to accept your work.
|
||||
1. Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
|
||||
We cannot accept code without this. Make sure you sign with the primary email address of the Git identity that has been granted access to the Angular repository.
|
||||
1. Fork the angular/angular repo.
|
||||
1. Make your changes in a new git branch:
|
||||
1. Search [GitHub](https://github.com/angular/angular/pulls) for an open or closed PR that relates to your submission.
|
||||
You don't want to duplicate existing efforts.
|
||||
|
||||
2. Be sure that an issue describes the problem you're fixing, or documents the design for the feature you'd like to add.
|
||||
Discussing the design upfront helps to ensure that we're ready to accept your work.
|
||||
|
||||
3. Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
|
||||
We cannot accept code without a signed CLA.
|
||||
Make sure you author all contributed Git commits with email address associated with your CLA signature.
|
||||
|
||||
4. Fork the angular/angular repo.
|
||||
|
||||
5. Make your changes in a new git branch:
|
||||
|
||||
```shell
|
||||
git checkout -b my-fix-branch master
|
||||
```
|
||||
|
||||
1. Create your patch, **including appropriate test cases**.
|
||||
1. Follow our [Coding Rules](#rules).
|
||||
1. Run the full Angular test suite, as described in the [developer documentation][dev-doc],
|
||||
and ensure that all tests pass.
|
||||
1. Commit your changes using a descriptive commit message that follows our
|
||||
[commit message conventions](#commit). Adherence to these conventions is necessary because release notes are automatically generated from these messages.
|
||||
6. Create your patch, **including appropriate test cases**.
|
||||
|
||||
7. Follow our [Coding Rules](#rules).
|
||||
|
||||
8. Run the full Angular test suite, as described in the [developer documentation][dev-doc], and ensure that all tests pass.
|
||||
|
||||
9. Commit your changes using a descriptive commit message that follows our [commit message conventions](#commit).
|
||||
Adherence to these conventions is necessary because release notes are automatically generated from these messages.
|
||||
|
||||
```shell
|
||||
git commit -a
|
||||
```
|
||||
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
|
||||
|
||||
1. Push your branch to GitHub:
|
||||
10. Push your branch to GitHub:
|
||||
|
||||
```shell
|
||||
git push origin my-fix-branch
|
||||
```
|
||||
|
||||
1. In GitHub, send a pull request to `angular:master`.
|
||||
* If we suggest changes then:
|
||||
* Make the required updates.
|
||||
* Re-run the Angular test suites to ensure tests are still passing.
|
||||
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
|
||||
11. In GitHub, send a pull request to `angular:master`.
|
||||
|
||||
```shell
|
||||
git rebase master -i
|
||||
git push -f
|
||||
```
|
||||
If we ask for changes via code reviews then:
|
||||
|
||||
* Make the required updates.
|
||||
* Re-run the Angular test suites to ensure tests are still passing.
|
||||
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
|
||||
|
||||
```shell
|
||||
git rebase master -i
|
||||
git push -f
|
||||
```
|
||||
|
||||
That's it! Thank you for your contribution!
|
||||
|
||||
|
||||
#### After your pull request is merged
|
||||
|
||||
After your pull request is merged, you can safely delete your branch and pull the changes
|
||||
from the main (upstream) repository:
|
||||
After your pull request is merged, you can safely delete your branch and pull the changes from the main (upstream) repository:
|
||||
|
||||
* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
|
||||
|
||||
@ -140,55 +161,66 @@ from the main (upstream) repository:
|
||||
git pull --ff upstream master
|
||||
```
|
||||
|
||||
|
||||
## <a name="rules"></a> Coding Rules
|
||||
To ensure consistency throughout the source code, keep these rules in mind as you are working:
|
||||
|
||||
* All features or bug fixes **must be tested** by one or more specs (unit-tests).
|
||||
* All public API methods **must be documented**. (Details TBC).
|
||||
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at
|
||||
**100 characters**. An automated formatter is available, see
|
||||
[DEVELOPER.md](docs/DEVELOPER.md#clang-format).
|
||||
* All public API methods **must be documented**.
|
||||
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at **100 characters**.
|
||||
|
||||
## <a name="commit"></a> Commit Message Guidelines
|
||||
An automated formatter is available, see [DEVELOPER.md](docs/DEVELOPER.md#clang-format).
|
||||
|
||||
We have very precise rules over how our git commit messages can be formatted. This leads to **more
|
||||
readable messages** that are easy to follow when looking through the **project history**. But also,
|
||||
we use the git commit messages to **generate the Angular change log**.
|
||||
|
||||
### Commit Message Format
|
||||
Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
|
||||
format that includes a **type**, a **scope** and a **subject**:
|
||||
## <a name="commit"></a> Commit Message Format
|
||||
|
||||
*This specification is inspired 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**.
|
||||
|
||||
Each commit message consists of a **header**, a **body**, and a **footer**.
|
||||
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
<header>
|
||||
<BLANK LINE>
|
||||
<body>
|
||||
<BLANK LINE>
|
||||
<footer>
|
||||
```
|
||||
|
||||
The **header** is mandatory and the **scope** of the header is optional.
|
||||
The `header` is mandatory and must conform to the [Commit Message Header](#commit-header) format.
|
||||
|
||||
Any line of the commit message cannot be longer than 100 characters! This allows the message to be easier
|
||||
to read on GitHub as well as in various git tools.
|
||||
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 footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.
|
||||
The `footer` is optional.
|
||||
|
||||
Samples: (even more [samples](https://github.com/angular/angular/commits/master))
|
||||
Any line of the commit message cannot be longer than 100 characters.
|
||||
|
||||
|
||||
#### <a href="commit-header"></a>Commit Message Header
|
||||
|
||||
```
|
||||
docs(changelog): update changelog to beta.5
|
||||
```
|
||||
```
|
||||
fix(release): need to depend on the latest rxjs and zone.js
|
||||
|
||||
The version in our package.json gets copied to the one we publish, and users need the latest of these.
|
||||
<type>(<scope>): <short summary>
|
||||
│ │ │
|
||||
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
|
||||
│ │
|
||||
│ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
|
||||
│ elements|forms|http|language-service|localize|platform-browser|
|
||||
│ platform-browser-dynamic|platform-server|platform-webworker|
|
||||
│ platform-webworker-dynamic|router|service-worker|upgrade|zone.js|
|
||||
│ packaging|changelog|dev-infra|docs-infra|migrations|ngcc|ve
|
||||
│
|
||||
└─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
|
||||
```
|
||||
|
||||
### Revert
|
||||
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body, it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.
|
||||
The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is optional.
|
||||
|
||||
|
||||
##### Type
|
||||
|
||||
### Type
|
||||
Must be one of the following:
|
||||
|
||||
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
|
||||
@ -201,67 +233,95 @@ Must be one of the following:
|
||||
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
|
||||
* **test**: Adding missing tests or correcting existing tests
|
||||
|
||||
### Scope
|
||||
|
||||
##### Scope
|
||||
The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages).
|
||||
|
||||
The following is the list of supported scopes:
|
||||
|
||||
* **animations**
|
||||
* **bazel**
|
||||
* **benchpress**
|
||||
* **common**
|
||||
* **compiler**
|
||||
* **compiler-cli**
|
||||
* **core**
|
||||
* **elements**
|
||||
* **forms**
|
||||
* **http**
|
||||
* **language-service**
|
||||
* **localize**
|
||||
* **platform-browser**
|
||||
* **platform-browser-dynamic**
|
||||
* **platform-server**
|
||||
* **platform-webworker**
|
||||
* **platform-webworker-dynamic**
|
||||
* **router**
|
||||
* **service-worker**
|
||||
* **upgrade**
|
||||
* **zone.js**
|
||||
* `animations`
|
||||
* `bazel`
|
||||
* `benchpress`
|
||||
* `common`
|
||||
* `compiler`
|
||||
* `compiler-cli`
|
||||
* `core`
|
||||
* `elements`
|
||||
* `forms`
|
||||
* `http`
|
||||
* `language-service`
|
||||
* `localize`
|
||||
* `platform-browser`
|
||||
* `platform-browser-dynamic`
|
||||
* `platform-server`
|
||||
* `platform-webworker`
|
||||
* `platform-webworker-dynamic`
|
||||
* `router`
|
||||
* `service-worker`
|
||||
* `upgrade`
|
||||
* `zone.js`
|
||||
|
||||
There are currently a few exceptions to the "use package name" rule:
|
||||
|
||||
* **packaging**: used for changes that change the npm package layout in all of our packages, e.g.
|
||||
public path changes, package.json changes done to all packages, d.ts file/format changes, changes
|
||||
to bundles, etc.
|
||||
* **changelog**: used for updating the release notes in CHANGELOG.md
|
||||
* **docs-infra**: used for docs-app (angular.io) related changes within the /aio directory of the
|
||||
repo
|
||||
* **dev-infra**: used for dev-infra related changes within the directories /scripts, /tools and /dev-infra
|
||||
* **migrations**: used for changes to the `ng update` migrations.
|
||||
* **ngcc**: used for changes to the [Angular Compatibility Compiler](./packages/compiler-cli/ngcc/README.md)
|
||||
* **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`).
|
||||
* `packaging`: used for changes that change the npm package layout in all of our packages, e.g. public path changes, package.json changes done to all packages, d.ts file/format changes, changes to bundles, etc.
|
||||
|
||||
### Subject
|
||||
The subject contains a succinct description of the change:
|
||||
* `changelog`: used for updating the release notes in CHANGELOG.md
|
||||
|
||||
* `dev-infra`: used for dev-infra related changes within the directories /scripts, /tools and /dev-infra
|
||||
|
||||
* `docs-infra`: used for docs-app (angular.io) related changes within the /aio directory of the repo
|
||||
|
||||
* `migrations`: used for changes to the `ng update` migrations.
|
||||
|
||||
* `ngcc`: used for changes to the [Angular Compatibility Compiler](./packages/compiler-cli/ngcc/README.md)
|
||||
|
||||
* `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`).
|
||||
|
||||
|
||||
##### Summary
|
||||
|
||||
Use the summary field to provide a succinct description of the change:
|
||||
|
||||
* use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
* don't capitalize the first letter
|
||||
* no dot (.) at the end
|
||||
|
||||
### Body
|
||||
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
|
||||
The body should include the motivation for the change and contrast this with previous behavior.
|
||||
|
||||
### Footer
|
||||
The footer should contain any information about **Breaking Changes** and is also the place to
|
||||
reference GitHub issues that this commit **Closes**.
|
||||
#### Commit Message Body
|
||||
|
||||
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.
|
||||
Just as in the summary, use the imperative, present tense: "fix" not "fixed" nor "fixes".
|
||||
|
||||
Explain the motivation for the change in the commit message body. This commit message should explain _why_ you are making the change.
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
```
|
||||
BREAKING CHANGE: <breaking change summary>
|
||||
<BLANK LINE>
|
||||
<breaking change description + migration instructions>
|
||||
<BLANK LINE>
|
||||
<BLANK LINE>
|
||||
Fixes #<issue number>
|
||||
```
|
||||
|
||||
Breaking Change section should start with the phrase "BREAKING CHANGE: " followed by a summary of the breaking change, a blank line, and a detailed description of the breaking change that also includes migration instructions.
|
||||
|
||||
|
||||
### Revert commits
|
||||
|
||||
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit.
|
||||
|
||||
The content of the commit message body should contain:
|
||||
|
||||
- information about the SHA of the commit being reverted in the following format: `This reverts commit <SHA>`,
|
||||
- a clear description of the reason for reverting the commit message.
|
||||
|
||||
A detailed explanation can be found in this [document][commit-message-format].
|
||||
|
||||
## <a name="cla"></a> Signing the CLA
|
||||
|
||||
@ -272,18 +332,17 @@ changes to be accepted, the CLA must be signed. It's a quick process, we promise
|
||||
* For corporations, we'll need you to
|
||||
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
|
||||
|
||||
<hr>
|
||||
If you have more than one GitHub accounts, or multiple email addresses associated with a single GitHub account, you must sign the CLA using the primary email address of the GitHub account used to author Git commits and send pull requests.
|
||||
|
||||
If you have more than one Git identity, you must make sure that you sign the CLA using the primary email address associated with the ID that has been granted access to the Angular repository. Git identities can be associated with more than one email address, and only one is primary. Here are some links to help you sort out multiple Git identities and email addresses:
|
||||
The following documents can help you sort out issues with GitHub accounts and multiple email addresses:
|
||||
|
||||
* https://help.github.com/articles/setting-your-commit-email-address-in-git/
|
||||
* https://stackoverflow.com/questions/37245303/what-does-usera-committed-with-userb-13-days-ago-on-github-mean
|
||||
* https://help.github.com/articles/about-commit-email-addresses/
|
||||
* https://help.github.com/articles/blocking-command-line-pushes-that-expose-your-personal-email-address/
|
||||
|
||||
Note that if you have more than one Git identity, it is important to verify that you are logged in with the same ID with which you signed the CLA before you commit changes. If not, your PR will fail the CLA check.
|
||||
|
||||
<hr>
|
||||
|
||||
|
||||
[angular-group]: https://groups.google.com/forum/#!forum/angular
|
||||
[coc]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md
|
||||
|
21
README.md
21
README.md
@ -5,22 +5,21 @@
|
||||
|
||||
# Angular
|
||||
|
||||
Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages.
|
||||
Angular es una plataforma de desarrollo para construir aplicaciones web y móviles que usa TypeScript/JavaScript y otros lenguajes de programación.
|
||||
|
||||
## Quickstart
|
||||
## Guía rápida
|
||||
|
||||
[Get started in 5 minutes][quickstart].
|
||||
[Comienza a usarlo en 5 minutos][quickstart].
|
||||
|
||||
## Changelog
|
||||
## Registro de cambios (Changelog)
|
||||
|
||||
[Learn about the latest improvements][changelog].
|
||||
[Últimas mejoras realizadas][changelog].
|
||||
|
||||
## Want to help?
|
||||
## ¿Quieres ayudar?
|
||||
|
||||
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).
|
||||
¿Quieres encontrar fallos, colaborar con código, o mejorar la documentación? ¡Excelente! Lee nuestras
|
||||
pautas para [colaborar][contributing] y luego revisa algunos de nuestras incidencias (issues) en [ayuda comunitaria](https://github.com/angular-hispano/angular/labels/ayuda%20comunitaria).
|
||||
|
||||
[contributing]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md
|
||||
[quickstart]: https://angular.io/start
|
||||
[contributing]: https://github.com/angular-hispano/angular/blob/master/CONTRIBUTING.md
|
||||
[quickstart]: https://docs.angular.lat/start
|
||||
[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md
|
||||
[ng]: https://angular.io
|
||||
|
@ -58,7 +58,7 @@
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
"src/styles/main.scss"
|
||||
],
|
||||
"scripts": [],
|
||||
"budgets": [
|
||||
@ -158,7 +158,7 @@
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
"src/styles/main.scss"
|
||||
],
|
||||
"scripts": []
|
||||
}
|
||||
@ -193,4 +193,4 @@
|
||||
}
|
||||
},
|
||||
"defaultProject": "site"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
# CLI Overview and Command Reference
|
||||
|
||||
The Angular CLI is a command-line interface tool that you use to initialize, develop, scaffold, and maintain Angular applications. You can use the tool directly in a command shell, or indirectly through an interactive UI such as [Angular Console](https://angularconsole.com).
|
||||
The Angular CLI is a command-line interface tool that you use to initialize, develop, scaffold, and maintain Angular applications directly from a command shell.
|
||||
|
||||
## Installing Angular CLI
|
||||
|
||||
|
@ -32,15 +32,15 @@ export const slideInAnimation =
|
||||
// #enddocregion style-view
|
||||
// #docregion query
|
||||
query(':enter', [
|
||||
style({ left: '-100%'})
|
||||
style({ left: '-100%' })
|
||||
]),
|
||||
query(':leave', animateChild()),
|
||||
group([
|
||||
query(':leave', [
|
||||
animate('300ms ease-out', style({ left: '100%'}))
|
||||
animate('300ms ease-out', style({ left: '100%' }))
|
||||
]),
|
||||
query(':enter', [
|
||||
animate('300ms ease-out', style({ left: '0%'}))
|
||||
animate('300ms ease-out', style({ left: '0%' }))
|
||||
])
|
||||
]),
|
||||
query(':enter', animateChild()),
|
||||
@ -56,15 +56,15 @@ export const slideInAnimation =
|
||||
})
|
||||
]),
|
||||
query(':enter', [
|
||||
style({ left: '-100%'})
|
||||
style({ left: '-100%' })
|
||||
]),
|
||||
query(':leave', animateChild()),
|
||||
group([
|
||||
query(':leave', [
|
||||
animate('200ms ease-out', style({ left: '100%'}))
|
||||
animate('200ms ease-out', style({ left: '100%' }))
|
||||
]),
|
||||
query(':enter', [
|
||||
animate('300ms ease-out', style({ left: '0%'}))
|
||||
animate('300ms ease-out', style({ left: '0%' }))
|
||||
])
|
||||
]),
|
||||
query(':enter', animateChild()),
|
||||
|
@ -17,7 +17,7 @@ Toggle All Animations <input type="checkbox" [checked]="!animationsDisabled" (cl
|
||||
</nav>
|
||||
|
||||
<!-- #docregion route-animations-outlet -->
|
||||
<div [@routeAnimations]="prepareRoute(outlet)" >
|
||||
<div [@routeAnimations]="prepareRoute(outlet)">
|
||||
<router-outlet #outlet="outlet"></router-outlet>
|
||||
</div>
|
||||
<!-- #enddocregion route-animations-outlet -->
|
||||
|
@ -76,15 +76,15 @@ export class ConfigService {
|
||||
console.error('An error occurred:', error.error.message);
|
||||
} else {
|
||||
// The backend returned an unsuccessful response code.
|
||||
// The response body may contain clues as to what went wrong,
|
||||
// The response body may contain clues as to what went wrong.
|
||||
console.error(
|
||||
`Backend returned code ${error.status}, ` +
|
||||
`body was: ${error.error}`);
|
||||
}
|
||||
// return an observable with a user-facing error message
|
||||
// Return an observable with a user-facing error message.
|
||||
return throwError(
|
||||
'Something bad happened; please try again later.');
|
||||
};
|
||||
}
|
||||
// #enddocregion handleError
|
||||
|
||||
makeIntentionalError() {
|
||||
|
@ -3,7 +3,9 @@
|
||||
"files":[
|
||||
"!**/*.d.ts",
|
||||
"!**/*.js",
|
||||
"!**/*.[0-9].*"
|
||||
"!**/*.[0-9].*",
|
||||
"!doc-files/**/*",
|
||||
"**/*.xlf"
|
||||
],
|
||||
"file": "src/app/app.component.ts",
|
||||
"tags": ["Angular", "i18n", "internationalization"]
|
||||
|
@ -1,9 +0,0 @@
|
||||
{
|
||||
"files": [
|
||||
"!dist/",
|
||||
"!**/*.d.ts",
|
||||
"!src/**/*.js",
|
||||
"!doc-files/**/*",
|
||||
"**/*.xlf"
|
||||
]
|
||||
}
|
7
aio/content/examples/providers/src/app/user.service.2.ts
Normal file
7
aio/content/examples/providers/src/app/user.service.2.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'any',
|
||||
})
|
||||
export class UserService {
|
||||
}
|
@ -6,13 +6,11 @@ import { Routes, RouterModule } from '@angular/router'; // CLI imports router
|
||||
const routes: Routes = [
|
||||
{ path: 'first-component', component: FirstComponent },
|
||||
{ path: 'second-component', component: SecondComponent },
|
||||
// #enddocregion routes
|
||||
// #enddocregion routes, routes-with-wildcard
|
||||
{ path: '', redirectTo: '/first-component', pathMatch: 'full' }, // redirect to `first-component`
|
||||
{ path: '**', component: FirstComponent },
|
||||
// #enddocregion redirect
|
||||
// #docregion routes-with-wildcard
|
||||
{ path: '**', component: PageNotFoundComponent }, // Wildcard route for a 404 page
|
||||
// #docregion routes
|
||||
// #docregion redirect
|
||||
];
|
||||
// #enddocregion routes, routes-with-wildcard, redirect
|
||||
|
||||
|
@ -20,7 +20,7 @@ work well for all users, including those who rely on assistive technologies.
|
||||
|
||||
Building accessible web experience often involves setting [ARIA attributes](https://developers.google.com/web/fundamentals/accessibility/semantics-aria)
|
||||
to provide semantic meaning where it might otherwise be missing.
|
||||
Use [attribute binding](guide/template-syntax#attribute-binding) template syntax to control the values of accessibility-related attributes.
|
||||
Use [attribute binding](guide/attribute-binding) template syntax to control the values of accessibility-related attributes.
|
||||
|
||||
When binding to ARIA attributes in Angular, you must use the `attr.` prefix, as the ARIA
|
||||
specification depends specifically on HTML attributes rather than properties of DOM elements.
|
||||
@ -44,7 +44,7 @@ NOTE:
|
||||
|
||||
By convention, HTML attributes use lowercase names (`tabindex`), while properties use camelCase names (`tabIndex`).
|
||||
|
||||
See the [Template Syntax](guide/template-syntax#html-attribute-vs-dom-property) guide for more background on the difference between attributes and properties.
|
||||
See the [Binding syntax](guide/binding-syntax#html-attribute-vs-dom-property) guide for more background on the difference between attributes and properties.
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -74,8 +74,7 @@ The following table lists some of the key AngularJS template features with their
|
||||
The context of the binding is implied and is always the
|
||||
associated component, so it needs no reference variable.
|
||||
|
||||
For more information, see the [Interpolation](guide/template-syntax#interpolation)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
For more information, see the [Interpolation](guide/interpolation) guide.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
@ -141,8 +140,8 @@ The following table lists some of the key AngularJS template features with their
|
||||
|
||||
Angular has true template input variables that are explicitly defined using the `let` keyword.
|
||||
|
||||
For more information, see the [ngFor micro-syntax](guide/template-syntax#microsyntax)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
For more information, see the [ngFor micro-syntax](guide/built-in-directives#microsyntax)
|
||||
section of the [Built-in Directives](guide/built-in-directives) page.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
@ -258,8 +257,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
||||
Angular also has **class binding**, which is a good way to add or remove a single class,
|
||||
as shown in the third example.
|
||||
|
||||
For more information see the [Attribute, class, and style bindings](guide/template-syntax#other-bindings)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
For more information see [Attribute, class, and style bindings](guide/attribute-binding) page.
|
||||
|
||||
</td>
|
||||
|
||||
@ -309,8 +307,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
||||
|
||||
For a list of DOM events, see: https://developer.mozilla.org/en-US/docs/Web/Events.
|
||||
|
||||
For more information, see the [Event binding](guide/template-syntax#event-binding)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
For more information, see the [Event binding](guide/event-binding) page.
|
||||
|
||||
</td>
|
||||
|
||||
@ -407,8 +404,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
||||
Angular uses property binding; there is no built-in *href* directive.
|
||||
Place the element's `href` property in square brackets and set it to a quoted template expression.
|
||||
|
||||
For more information see the [Property binding](guide/template-syntax#property-binding)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
For more information see the [Property binding](guide/property-binding) page.
|
||||
|
||||
In Angular, `href` is no longer used for routing. Routing uses `routerLink`, as shown in the following example.
|
||||
|
||||
@ -487,8 +483,8 @@ The following are some of the key AngularJS built-in directives and their equiva
|
||||
and event binding (from the view to the component), thereby providing two-way binding.
|
||||
|
||||
For more information on two-way binding with `ngModel`, see the [NgModel—Two-way binding to
|
||||
form elements with `[(ngModel)]`](../guide/template-syntax.html#ngModel)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
form elements with `[(ngModel)]`](../guide/built-in-directives#ngModel)
|
||||
section of the [Built-in directives](guide/built-in-directives) page.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
@ -570,8 +566,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
||||
|
||||
In this example, the `<div>` element is hidden if the `favoriteHero` variable is not truthy.
|
||||
|
||||
For more information on property binding, see the [Property binding](guide/template-syntax#property-binding)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
For more information on property binding, see the [Property binding](guide/property-binding) page.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
@ -604,8 +599,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
||||
Angular uses property binding; there is no built-in *src* directive.
|
||||
Place the `src` property in square brackets and set it to a quoted template expression.
|
||||
|
||||
For more information on property binding, see the [Property binding](guide/template-syntax#property-binding)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
For more information on property binding, see the [Property binding](guide/property-binding) page.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
@ -644,11 +638,11 @@ The following are some of the key AngularJS built-in directives and their equiva
|
||||
|
||||
Angular also has **style binding**, which is good way to set a single style. This is shown in the second example.
|
||||
|
||||
For more information on style binding, see the [Style binding](guide/template-syntax#style-binding) section of the
|
||||
[Template Syntax](guide/template-syntax) page.
|
||||
For more information on style binding, see the [Style binding](guide/attribute-binding#style-binding) section of the
|
||||
[Attribute binding](guide/attribute-binding) page.
|
||||
|
||||
For more information on the `ngStyle` directive, see [NgStyle](guide/template-syntax#ngStyle)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
For more information on the `ngStyle` directive, see the [NgStyle](guide/built-in-directives#ngStyle)
|
||||
section of the [Built-in directives](guide/built-in-directives) page.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
@ -704,8 +698,8 @@ The following are some of the key AngularJS built-in directives and their equiva
|
||||
|
||||
The (*) before `ngSwitchCase` and `ngSwitchDefault` is required in this example.
|
||||
|
||||
For more information, see [The NgSwitch directives](guide/template-syntax#ngSwitch)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
For more information, see [The NgSwitch directives](guide/built-in-directives#ngSwitch)
|
||||
section of the [Built-in directives](guide/built-in-directives) page.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
@ -186,7 +186,7 @@ For library projects generated with the CLI, the dev configuration default is `t
|
||||
|
||||
When `true` (recommended), reports an error for a supplied parameter whose injection type cannot be determined. When `false` (currently the default), constructor parameters of classes marked with `@Injectable` whose type cannot be resolved produce a warning.
|
||||
|
||||
When you use the CLI command `ng new`, it is set to `true` by default in the generated project's configuration.
|
||||
When you use the CLI command `ng new --strict`, it is set to `true` in the generated project's configuration.
|
||||
|
||||
### `strictTemplates`
|
||||
|
||||
@ -194,6 +194,7 @@ When `true`, enables [strict template type checking](guide/template-typecheck#st
|
||||
|
||||
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).
|
||||
|
||||
When you use the CLI command `ng new --strict`, it is set to `true` in the generated project's configuration.
|
||||
|
||||
### `trace`
|
||||
|
||||
|
@ -623,7 +623,7 @@ For more information about input type narrowing, see [Input setter coercion](gui
|
||||
|
||||
### Non-null type assertion operator
|
||||
|
||||
Use the [non-null type assertion operator](guide/template-syntax#non-null-assertion-operator) to suppress the `Object is possibly 'undefined'` error when it is inconvenient to use `*ngIf` or when some constraint in the component ensures that the expression is always non-null when the binding expression is interpolated.
|
||||
Use the [non-null type assertion operator](guide/template-expression-operators#non-null-assertion-operator) to suppress the `Object is possibly 'undefined'` error when it is inconvenient to use `*ngIf` or when some constraint in the component ensures that the expression is always non-null when the binding expression is interpolated.
|
||||
|
||||
In the following example, the `person` and `address` properties are always set together, implying that `address` is always non-null if `person` is non-null.
|
||||
There is no convenient way to describe this constraint to TypeScript and the template compiler, but the error is suppressed in the example by using `address!.street`.
|
||||
|
@ -430,7 +430,7 @@ Angular does something similar with the `DOCUMENT` token so you can inject the b
|
||||
|
||||
```ts
|
||||
import { Inject } from '@angular/core';
|
||||
import { DOCUMENT } from '@angular/platform-browser';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
|
||||
@Component({ ... })
|
||||
export class MyComponent {
|
||||
|
@ -1,32 +1,32 @@
|
||||
# App shell
|
||||
|
||||
App shell is a way to render a portion of your application via a route at build time.
|
||||
It can improve the user experience by quickly launching a static rendered page (a skeleton common to all pages) while the browser downloads the full client version and switches to it automatically after the code loads.
|
||||
App shell es una manera de renderizar una porción de tu aplicación a través de una ruta en tiempo de compilación (build time).
|
||||
Puede mejorar la experiencia de usuario lanzando rápidamente una página estática renderizada (un esqueleto común a todas las páginas) mientras el navegador descarga la versión completa del cliente y la muestra automáticamente al finalizar su carga.
|
||||
|
||||
This gives users a meaningful first paint of your application that appears quickly because the browser can simply render the HTML and CSS without the need to initialize any JavaScript.
|
||||
Esto da a los usuarios una primera visualización significativa de su aplicación que aparece rápidamente porque el navegador simplemente puede renderizar HTML y CSS sin la necesidad de inicializar JavaScript.
|
||||
|
||||
Learn more in [The App Shell Model](https://developers.google.com/web/fundamentals/architecture/app-shell).
|
||||
Obténga más información en [El modelo de aplicación Shell](https://developers.google.com/web/fundamentals/architecture/app-shell).
|
||||
|
||||
## Step 1: Prepare the application
|
||||
## Paso 1: Prepara la aplicación
|
||||
|
||||
You can do this with the following CLI command:
|
||||
Puedes hacer esto con el siguiente comando CLI:
|
||||
<code-example language="bash">
|
||||
ng new my-app --routing
|
||||
</code-example>
|
||||
|
||||
For an existing application, you have to manually add the `RouterModule` and defining a `<router-outlet>` within your application.
|
||||
Para una aplicación existente, debes agregar manualmente el `RouterModule` y definir un` <router-outlet> `dentro de tu aplicación.
|
||||
|
||||
## Step 2: Create the app shell
|
||||
## Paso 2: Crea el shell de la aplicación
|
||||
|
||||
Use the CLI to automatically create the app shell.
|
||||
Usa la CLI para crear automáticamente el shell de la aplicación.
|
||||
|
||||
<code-example language="bash">
|
||||
ng generate app-shell
|
||||
</code-example>
|
||||
|
||||
* `client-project` takes the name of your client application.
|
||||
* `client-project` toma el nombre de tu aplicación cliente.
|
||||
|
||||
After running this command you will notice that the `angular.json` configuration file has been updated to add two new targets, with a few other changes.
|
||||
Después de ejecutar este comando, notará que el archivo de configuración `angular.json` se ha actualizado para agregar dos nuevos targets, con algunos otros cambios.
|
||||
|
||||
<code-example language="json">
|
||||
"server": {
|
||||
@ -53,20 +53,18 @@ After running this command you will notice that the `angular.json` configuration
|
||||
}
|
||||
</code-example>
|
||||
|
||||
## Step 3: Verify the app is built with the shell content
|
||||
## Paso 3: Verifica que la aplicación está construida con el contenido del shell
|
||||
|
||||
Use the CLI to build the `app-shell` target.
|
||||
Usa la CLI para construir el `app-shell` target.
|
||||
|
||||
<code-example language="bash">
|
||||
ng run my-app:app-shell
|
||||
</code-example>
|
||||
|
||||
Or to use the production configuration.
|
||||
O usa la configuración de producción.
|
||||
|
||||
<code-example language="bash">
|
||||
ng run my-app:app-shell:production
|
||||
</code-example>
|
||||
|
||||
To verify the build output, open `dist/my-app/index.html`. Look for default text `app-shell works!` to show that the app shell route was rendered as part of the output.
|
||||
|
||||
|
||||
Para verificar el resultado de la compilación, abre `dist/my-app/index.html`. Busca el texto por defecto `app-shell works!` para mostrar que la ruta del shell de la aplicación se ha renderizado como parte de la carpeta de distribución.
|
||||
|
@ -92,7 +92,7 @@ This example from the `HeroListComponent` template uses three of these forms.
|
||||
* The `{{hero.name}}` [*interpolation*](guide/displaying-data#interpolation)
|
||||
displays the component's `hero.name` property value within the `<li>` element.
|
||||
|
||||
* The `[hero]` [*property binding*](guide/template-syntax#property-binding) passes the value of
|
||||
* The `[hero]` [*property binding*](guide/property-binding) passes the value of
|
||||
`selectedHero` from the parent `HeroListComponent` to the `hero` property of the child `HeroDetailComponent`.
|
||||
|
||||
* The `(click)` [*event binding*](guide/user-input#binding-to-user-input-events) calls the component's `selectHero` method when the user clicks a hero's name.
|
||||
@ -126,7 +126,7 @@ Angular pipes let you declare display-value transformations in your template HTM
|
||||
|
||||
Angular defines various pipes, such as the [date](https://angular.io/api/common/DatePipe) pipe and [currency](https://angular.io/api/common/CurrencyPipe) pipe; for a complete list, see the [Pipes API list](https://angular.io/api?type=pipe). You can also define new pipes.
|
||||
|
||||
To specify a value transformation in an HTML template, use the [pipe operator (|)](https://angular.io/guide/template-syntax#pipe).
|
||||
To specify a value transformation in an HTML template, use the [pipe operator (|)](https://angular.io/guide/template-expression-operators#pipe).
|
||||
|
||||
`{{interpolated_value | pipe_name}}`
|
||||
|
||||
@ -179,9 +179,9 @@ The `ngModel` directive, which implements two-way data binding, is an example of
|
||||
<code-example path="architecture/src/app/hero-detail.component.html" header="src/app/hero-detail.component.html (ngModel)" region="ngModel"></code-example>
|
||||
|
||||
Angular has more pre-defined directives that either alter the layout structure
|
||||
(for example, [ngSwitch](guide/template-syntax#ngSwitch))
|
||||
(for example, [ngSwitch](guide/built-in-directives#ngSwitch))
|
||||
or modify aspects of DOM elements and components
|
||||
(for example, [ngStyle](guide/template-syntax#ngStyle) and [ngClass](guide/template-syntax#ngClass)).
|
||||
(for example, [ngStyle](guide/built-in-directives#ngStyle) and [ngClass](guide/built-in-directives#ngClass)).
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
303
aio/content/guide/attribute-binding.md
Normal file
303
aio/content/guide/attribute-binding.md
Normal file
@ -0,0 +1,303 @@
|
||||
# Attribute, class, and style bindings
|
||||
|
||||
The template syntax provides specialized one-way bindings for scenarios less well-suited to property binding.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
## 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.
|
||||
|
||||
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.
|
||||
|
||||
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`.
|
||||
|
||||
One of the primary use cases for attribute binding
|
||||
is to set ARIA attributes, as in this example:
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="attrib-binding-aria" header="src/app/app.component.html"></code-example>
|
||||
|
||||
{@a colspan}
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
#### `colspan` and `colSpan`
|
||||
|
||||
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>
|
||||
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a class-binding}
|
||||
|
||||
## Class binding
|
||||
|
||||
Here's how to set the `class` attribute without a binding in plain HTML:
|
||||
|
||||
```html
|
||||
<!-- standard class attribute setting -->
|
||||
<div class="foo bar">Some text</div>
|
||||
```
|
||||
|
||||
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, 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)).
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
If there are multiple bindings to the same class name, conflicts are resolved using [styling precedence](#styling-precedence).
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
</style>
|
||||
|
||||
<table width="100%">
|
||||
<col width="15%">
|
||||
</col>
|
||||
<col width="20%">
|
||||
</col>
|
||||
<col width="35%">
|
||||
</col>
|
||||
<col width="30%">
|
||||
</col>
|
||||
<tr>
|
||||
<th>
|
||||
Binding Type
|
||||
</th>
|
||||
<th>
|
||||
Syntax
|
||||
</th>
|
||||
<th>
|
||||
Input Type
|
||||
</th>
|
||||
<th>
|
||||
Example Input Values
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Single class binding</td>
|
||||
<td><code>[class.foo]="hasFoo"</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><code>string</code></td>
|
||||
<td><code>"my-class-1 my-class-2 my-class-3"</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>{[key: string]: boolean | undefined | null}</code></td>
|
||||
<td><code>{foo: true, bar: false}</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Array</code><<code>string</code>></td>
|
||||
<td><code>['foo', 'bar']</code></td>
|
||||
</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
|
||||
|
||||
Here's how to set the `style` attribute without a binding in plain HTML:
|
||||
|
||||
```html
|
||||
<!-- standard style attribute setting -->
|
||||
<div style="color: blue">Some text</div>
|
||||
```
|
||||
|
||||
You can also set styles dynamically with a **style binding**.
|
||||
|
||||
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.
|
||||
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`.
|
||||
|
||||
</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;"`.
|
||||
|
||||
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.
|
||||
|
||||
If there are multiple bindings to the same style property, conflicts are resolved using [styling precedence rules](#styling-precedence).
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
</style>
|
||||
|
||||
<table width="100%">
|
||||
<col width="15%">
|
||||
</col>
|
||||
<col width="20%">
|
||||
</col>
|
||||
<col width="35%">
|
||||
</col>
|
||||
<col width="30%">
|
||||
</col>
|
||||
<tr>
|
||||
<th>
|
||||
Binding Type
|
||||
</th>
|
||||
<th>
|
||||
Syntax
|
||||
</th>
|
||||
<th>
|
||||
Input Type
|
||||
</th>
|
||||
<th>
|
||||
Example Input Values
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Single style binding</td>
|
||||
<td><code>[style.width]="width"</code></td>
|
||||
<td><code>string | undefined | null</code></td>
|
||||
<td><code>"100px"</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr>
|
||||
<td>Single style binding with units</td>
|
||||
<td><code>[style.width.px]="width"</code></td>
|
||||
<td><code>number | undefined | null</code></td>
|
||||
<td><code>100</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=3>Multi-style binding</td>
|
||||
<td rowspan=3><code>[style]="styleExpr"</code></td>
|
||||
<td><code>string</code></td>
|
||||
<td><code>"width: 100px; height: 100px"</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>{[key: string]: string | undefined | null}</code></td>
|
||||
<td><code>{width: '100px', height: '100px'}</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Array</code><<code>string</code>></td>
|
||||
<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.
|
@ -18,12 +18,12 @@ There are three kinds of directives in Angular:
|
||||
You saw a component for the first time in the [Getting Started](start "Getting Started with Angular") tutorial.
|
||||
|
||||
*Structural Directives* change the structure of the view.
|
||||
Two examples are [NgFor](guide/template-syntax#ngFor) and [NgIf](guide/template-syntax#ngIf).
|
||||
Two examples are [NgFor](guide/built-in-directives#ngFor) and [NgIf](guide/built-in-directives#ngIf).
|
||||
Learn about them in the [Structural Directives](guide/structural-directives) guide.
|
||||
|
||||
*Attribute directives* are used as attributes of elements.
|
||||
The built-in [NgStyle](guide/template-syntax#ngStyle) directive in the
|
||||
[Template Syntax](guide/template-syntax) guide, for example,
|
||||
The built-in [NgStyle](guide/built-in-directives#ngStyle) directive in the
|
||||
[Built-in directives](guide/built-in-directives) guide, for example,
|
||||
can change several element styles at the same time.
|
||||
|
||||
## Build a simple attribute directive
|
||||
|
318
aio/content/guide/binding-syntax.md
Normal file
318
aio/content/guide/binding-syntax.md
Normal file
@ -0,0 +1,318 @@
|
||||
|
||||
# Binding syntax: an overview
|
||||
|
||||
Data-binding is a mechanism for coordinating what users see, specifically
|
||||
with application data values.
|
||||
While you could push values to and pull values from HTML,
|
||||
the application is easier to write, read, and maintain if you turn these tasks over to a binding framework.
|
||||
You simply declare bindings between binding sources, target HTML elements, and let the framework do the rest.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
Angular provides many kinds of data-binding. Binding types can be grouped into three categories distinguished by the direction of data flow:
|
||||
|
||||
* From the _source-to-view_
|
||||
* From _view-to-source_
|
||||
* Two-way sequence: _view-to-source-to-view_
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
</style>
|
||||
|
||||
<table width="100%">
|
||||
<col width="30%">
|
||||
</col>
|
||||
<col width="50%">
|
||||
</col>
|
||||
<col width="20%">
|
||||
</col>
|
||||
<tr>
|
||||
<th>
|
||||
Type
|
||||
</th>
|
||||
<th>
|
||||
Syntax
|
||||
</th>
|
||||
<th>
|
||||
Category
|
||||
</th>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Interpolation<br>
|
||||
Property<br>
|
||||
Attribute<br>
|
||||
Class<br>
|
||||
Style
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<code-example>
|
||||
{{expression}}
|
||||
[target]="expression"
|
||||
bind-target="expression"
|
||||
</code-example>
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
One-way<br>from data source<br>to view target
|
||||
</td>
|
||||
<tr>
|
||||
<td>
|
||||
Event
|
||||
</td>
|
||||
<td>
|
||||
<code-example>
|
||||
(target)="statement"
|
||||
on-target="statement"
|
||||
</code-example>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
One-way<br>from view target<br>to data source
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Two-way
|
||||
</td>
|
||||
<td>
|
||||
<code-example>
|
||||
[(target)]="expression"
|
||||
bindon-target="expression"
|
||||
</code-example>
|
||||
</td>
|
||||
<td>
|
||||
Two-way
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Binding types other than interpolation have a **target name** to the left of the equal sign, either surrounded by punctuation, `[]` or `()`,
|
||||
or preceded by a prefix: `bind-`, `on-`, `bindon-`.
|
||||
|
||||
The *target* of a binding is the property or event inside the binding punctuation: `[]`, `()` or `[()]`.
|
||||
|
||||
Every public member of a **source** directive is automatically available for binding.
|
||||
You don't have to do anything special to access a directive member in a template expression or statement.
|
||||
|
||||
|
||||
### Data-binding and HTML
|
||||
|
||||
In the normal course of HTML development, you create a visual structure with HTML elements, and
|
||||
you modify those elements by setting element attributes with string constants.
|
||||
|
||||
```html
|
||||
<div class="special">Plain old HTML</div>
|
||||
<img src="images/item.png">
|
||||
<button disabled>Save</button>
|
||||
```
|
||||
|
||||
With data-binding, you can control things like the state of a button:
|
||||
|
||||
<code-example path="binding-syntax/src/app/app.component.html" region="disabled-button" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Notice that the binding is to the `disabled` property of the button's DOM element,
|
||||
**not** the attribute. This applies to data-binding in general. Data-binding works with *properties* of DOM elements, components, and directives, not HTML *attributes*.
|
||||
|
||||
{@a html-attribute-vs-dom-property}
|
||||
|
||||
### HTML attribute vs. DOM property
|
||||
|
||||
The distinction between an HTML attribute and a DOM property is key to understanding
|
||||
how Angular binding works. **Attributes are defined by HTML. Properties are accessed from DOM (Document Object Model) nodes.**
|
||||
|
||||
* A few HTML attributes have 1:1 mapping to properties; for example, `id`.
|
||||
|
||||
* Some HTML attributes don't have corresponding properties; for example, `aria-*`.
|
||||
|
||||
* Some DOM properties don't have corresponding attributes; for example, `textContent`.
|
||||
|
||||
It is important to remember that *HTML attribute* and the *DOM property* are different things, even when they have the same name.
|
||||
In Angular, the only role of HTML attributes is to initialize element and directive state.
|
||||
|
||||
**Template binding works with *properties* and *events*, not *attributes*.**
|
||||
|
||||
When you write a data-binding, you're dealing exclusively with the *DOM properties* and *events* of the target object.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
This general rule can help you build a mental model of attributes and DOM properties:
|
||||
**Attributes initialize DOM properties and then they are done.
|
||||
Property values can change; attribute values can't.**
|
||||
|
||||
There is one exception to this rule.
|
||||
Attributes can be changed by `setAttribute()`, which re-initializes corresponding DOM properties.
|
||||
|
||||
</div>
|
||||
|
||||
For more information, see the [MDN Interfaces documentation](https://developer.mozilla.org/en-US/docs/Web/API#Interfaces) which has API docs for all the standard DOM elements and their properties.
|
||||
Comparing the [`<td>` attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td) attributes to the [`<td>` properties](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement) provides a helpful example for differentiation.
|
||||
In particular, you can navigate from the attributes page to the properties via "DOM interface" link, and navigate the inheritance hierarchy up to `HTMLTableCellElement`.
|
||||
|
||||
|
||||
#### Example 1: an `<input>`
|
||||
|
||||
When the browser renders `<input type="text" value="Sarah">`, it creates a
|
||||
corresponding DOM node with a `value` property initialized to "Sarah".
|
||||
|
||||
```html
|
||||
<input type="text" value="Sarah">
|
||||
```
|
||||
|
||||
When the user enters "Sally" into the `<input>`, the DOM element `value` *property* becomes "Sally".
|
||||
However, if you look at the HTML attribute `value` using `input.getAttribute('value')`, you can see that the *attribute* remains unchanged—it returns "Sarah".
|
||||
|
||||
The HTML attribute `value` specifies the *initial* value; the DOM `value` property is the *current* value.
|
||||
|
||||
To see attributes versus DOM properties in a functioning app, see the <live-example name="binding-syntax"></live-example> especially for binding syntax.
|
||||
|
||||
#### Example 2: a disabled button
|
||||
|
||||
The `disabled` attribute is another example. A button's `disabled`
|
||||
*property* is `false` by default so the button is enabled.
|
||||
|
||||
When you add the `disabled` *attribute*, its presence alone
|
||||
initializes the button's `disabled` *property* to `true`
|
||||
so the button is disabled.
|
||||
|
||||
```html
|
||||
<button disabled>Test Button</button>
|
||||
```
|
||||
|
||||
Adding and removing the `disabled` *attribute* disables and enables the button.
|
||||
However, the value of the *attribute* is irrelevant,
|
||||
which is why you cannot enable a button by writing `<button disabled="false">Still Disabled</button>`.
|
||||
|
||||
To control the state of the button, set the `disabled` *property*,
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Though you could technically set the `[attr.disabled]` attribute binding, the values are different in that the property binding requires to a boolean value, while its corresponding attribute binding relies on whether the value is `null` or not. Consider the following:
|
||||
|
||||
```html
|
||||
<input [disabled]="condition ? true : false">
|
||||
<input [attr.disabled]="condition ? 'disabled' : null">
|
||||
```
|
||||
|
||||
Generally, use property binding over attribute binding as it is more intuitive (being a boolean value), has a shorter syntax, and is more performant.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
To see the `disabled` button example in a functioning app, see the <live-example name="binding-syntax"></live-example> especially for binding syntax. This example shows you how to toggle the disabled property from the component.
|
||||
|
||||
## Binding types and targets
|
||||
|
||||
The **target of a data-binding** is something in the DOM.
|
||||
Depending on the binding type, the target can be a property (element, component, or directive),
|
||||
an event (element, component, or directive), or sometimes an attribute name.
|
||||
The following table summarizes the targets for the different binding types.
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
</style>
|
||||
|
||||
<table width="100%">
|
||||
<col width="10%">
|
||||
</col>
|
||||
<col width="15%">
|
||||
</col>
|
||||
<col width="75%">
|
||||
</col>
|
||||
<tr>
|
||||
<th>
|
||||
Type
|
||||
</th>
|
||||
<th>
|
||||
Target
|
||||
</th>
|
||||
<th>
|
||||
Examples
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Property
|
||||
</td>
|
||||
<td>
|
||||
Element property<br>
|
||||
Component property<br>
|
||||
Directive property
|
||||
</td>
|
||||
<td>
|
||||
<code>src</code>, <code>hero</code>, and <code>ngClass</code> in the following:
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="property-binding-syntax-1"></code-example>
|
||||
<!-- For more information, see [Property Binding](guide/property-binding). -->
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Event
|
||||
</td>
|
||||
<td>
|
||||
Element event<br>
|
||||
Component event<br>
|
||||
Directive event
|
||||
</td>
|
||||
<td>
|
||||
<code>click</code>, <code>deleteRequest</code>, and <code>myClick</code> in the following:
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="event-binding-syntax-1"></code-example>
|
||||
<!-- KW--Why don't these links work in the table? -->
|
||||
<!-- <div>For more information, see [Event Binding](guide/event-binding).</div> -->
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Two-way
|
||||
</td>
|
||||
<td>
|
||||
Event and property
|
||||
</td>
|
||||
<td>
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="2-way-binding-syntax-1"></code-example>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Attribute
|
||||
</td>
|
||||
<td>
|
||||
Attribute
|
||||
(the exception)
|
||||
</td>
|
||||
<td>
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="attribute-binding-syntax-1"></code-example>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Class
|
||||
</td>
|
||||
<td>
|
||||
<code>class</code> property
|
||||
</td>
|
||||
<td>
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="class-binding-syntax-1"></code-example>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Style
|
||||
</td>
|
||||
<td>
|
||||
<code>style</code> property
|
||||
</td>
|
||||
<td>
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="style-binding-syntax-1"></code-example>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
436
aio/content/guide/built-in-directives.md
Normal file
436
aio/content/guide/built-in-directives.md
Normal file
@ -0,0 +1,436 @@
|
||||
# Directivas integradas
|
||||
|
||||
Angular ofrece dos tipos de directivas integradas: [directivas de _atributo_](guide/attribute-directives) y [directivas de _estructura_](guide/structural-directives).
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Ve el <live-example></live-example> para un ejemplo ejecutable conteniendo las porciones de código en esta guía.
|
||||
|
||||
</div>
|
||||
|
||||
Para más detalles, incluyendo cómo construir tus propias directivas personalizadas, ve [Directivas de Atributo](guide/attribute-directives) and [Structural Directives](guide/structural-directives).
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a attribute-directives}
|
||||
|
||||
## Directivas integradas de atributo
|
||||
|
||||
Las directivas de atributo escuchan y modifican el comportamiento de
|
||||
otros elementos HTML, atributos, propiedades, y componentes.
|
||||
|
||||
Por lo general, los aplica a los elementos como si fueran atributos HTML, de ahí el nombre.
|
||||
|
||||
Muchos NgModules como el [`RouterModule`](guide/router "Routing and Navigation")
|
||||
y el [`FormsModule`](guide/forms "Forms") definen sus propias directivas de atributos.
|
||||
Las directivas de atributos más comunes son las siguientes:
|
||||
|
||||
* [`NgClass`](guide/built-in-directives#ngClass)—agrega y elimina un conjunto de clases CSS.
|
||||
* [`NgStyle`](guide/built-in-directives#ngStyle)—agrega y elimina un conjunto de estilos HTML.
|
||||
* [`NgModel`](guide/built-in-directives#ngModel)—agrega enlace de datos bidireccional a un elemento formulario HTML.
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a ngClass}
|
||||
|
||||
## `NgClass`
|
||||
|
||||
Agrega o elimina varias clases CSS simultáneamente con `ngClass`.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="special-div" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
To add or remove a *single* class, use [class binding](guide/attribute-binding#class-binding) rather than `NgClass`.
|
||||
|
||||
</div>
|
||||
|
||||
Consider a `setCurrentClasses()` component method that sets a component property,
|
||||
`currentClasses`, with an object that adds or removes three classes based on the
|
||||
`true`/`false` state of three other component properties. Each key of the object is a CSS class name; its value is `true` if the class should be added,
|
||||
`false` if it should be removed.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.ts" region="setClasses" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
Adding an `ngClass` property binding to `currentClasses` sets the element's classes accordingly:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgClass-1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Remember that in this situation you'd call `setCurrentClasses()`,
|
||||
both initially and when the dependent properties change.
|
||||
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a ngStyle}
|
||||
|
||||
## `NgStyle`
|
||||
|
||||
Use `NgStyle` to set many inline styles simultaneously and dynamically, based on the state of the component.
|
||||
|
||||
### Without `NgStyle`
|
||||
|
||||
For context, consider setting a *single* style value with [style binding](guide/attribute-binding#style-binding), without `NgStyle`.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="without-ng-style" header="src/app/app.component.html"></code-example>
|
||||
|
||||
However, to set *many* inline styles at the same time, use the `NgStyle` directive.
|
||||
|
||||
The following is a `setCurrentStyles()` method that sets a component
|
||||
property, `currentStyles`, with an object that defines three styles,
|
||||
based on the state of three other component properties:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.ts" region="setStyles" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
Adding an `ngStyle` property binding to `currentStyles` sets the element's styles accordingly:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgStyle-2" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Remember to call `setCurrentStyles()`, both initially and when the dependent properties change.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a ngModel}
|
||||
|
||||
## `[(ngModel)]`: Two-way binding
|
||||
|
||||
The `NgModel` directive allows you to display a data property and
|
||||
update that property when the user makes changes. Here's an example:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" header="src/app/app.component.html (NgModel example)" region="NgModel-1"></code-example>
|
||||
|
||||
|
||||
### Import `FormsModule` to use `ngModel`
|
||||
|
||||
Before using the `ngModel` directive in a two-way data binding,
|
||||
you must import the `FormsModule` and add it to the NgModule's `imports` list.
|
||||
Learn more about the `FormsModule` and `ngModel` in [Forms](guide/forms#ngModel).
|
||||
|
||||
Remember to import the `FormsModule` to make `[(ngModel)]` available as follows:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.module.ts" header="src/app/app.module.ts (FormsModule import)" region="import-forms-module"></code-example>
|
||||
|
||||
|
||||
You could achieve the same result with separate bindings to
|
||||
the `<input>` element's `value` property and `input` event:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="without-NgModel" header="src/app/app.component.html"></code-example>
|
||||
|
||||
To streamline the syntax, the `ngModel` directive hides the details behind its own `ngModel` input and `ngModelChange` output properties:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgModelChange" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The `ngModel` data property sets the element's value property and the `ngModelChange` event property
|
||||
listens for changes to the element's value.
|
||||
|
||||
### `NgModel` and value accessors
|
||||
|
||||
The details are specific to each kind of element and therefore the `NgModel` directive only works for an element
|
||||
supported by a [ControlValueAccessor](api/forms/ControlValueAccessor)
|
||||
that adapts an element to this protocol.
|
||||
Angular provides *value accessors* for all of the basic HTML form elements and the
|
||||
[Forms](guide/forms) guide shows how to bind to them.
|
||||
|
||||
You can't apply `[(ngModel)]` to a non-form native element or a
|
||||
third-party custom component until you write a suitable value accessor. For more information, see
|
||||
the API documentation on [DefaultValueAccessor](https://angular.io/api/forms/DefaultValueAccessor).
|
||||
|
||||
You don't need a value accessor for an Angular component that
|
||||
you write because you can name the value and event properties
|
||||
to suit Angular's basic [two-way binding syntax](guide/two-way-binding)
|
||||
and skip `NgModel` altogether.
|
||||
The `sizer` in the
|
||||
[Two-way Binding](guide/two-way-binding) section is an example of this technique.
|
||||
|
||||
Separate `ngModel` bindings are an improvement over binding to the
|
||||
element's native properties, but you can streamline the binding with a
|
||||
single declaration using the `[(ngModel)]` syntax:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgModel-1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
This `[(ngModel)]` syntax can only _set_ a data-bound property.
|
||||
If you need to do something more, you can write the expanded form;
|
||||
for example, the following changes the `<input>` value to uppercase:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="uppercase" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Here are all variations in action, including the uppercase version:
|
||||
|
||||
<div class="lightbox">
|
||||
<img src='generated/images/guide/built-in-directives/ng-model-anim.gif' alt="NgModel variations">
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a structural-directives}
|
||||
|
||||
## Built-in _structural_ directives
|
||||
|
||||
Structural directives are responsible for HTML layout.
|
||||
They shape or reshape the DOM's structure, typically by adding, removing, and manipulating
|
||||
the host elements to which they are attached.
|
||||
|
||||
This section is an introduction to the common built-in structural directives:
|
||||
|
||||
* [`NgIf`](guide/built-in-directives#ngIf)—conditionally creates or destroys subviews from the template.
|
||||
* [`NgFor`](guide/built-in-directives#ngFor)—repeat a node for each item in a list.
|
||||
* [`NgSwitch`](guide/built-in-directives#ngSwitch)—a set of directives that switch among alternative views.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The deep details of structural directives are covered in the
|
||||
[Structural Directives](guide/structural-directives) guide,
|
||||
which explains the following:
|
||||
|
||||
* Why you
|
||||
[prefix the directive name with an asterisk (\*)](guide/structural-directives#the-asterisk--prefix).
|
||||
* 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.
|
||||
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a ngIf}
|
||||
|
||||
## NgIf
|
||||
|
||||
You can add or remove an element from the DOM by applying an `NgIf` directive to
|
||||
a host element.
|
||||
Bind the directive to a condition expression like `isActive` in this example.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgIf-1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Don't forget the asterisk (`*`) in front of `ngIf`. For more information
|
||||
on the asterisk, see the [asterisk (*) prefix](guide/structural-directives#the-asterisk--prefix) section of
|
||||
[Structural Directives](guide/structural-directives).
|
||||
|
||||
</div>
|
||||
|
||||
When the `isActive` expression returns a truthy value, `NgIf` adds the
|
||||
`ItemDetailComponent` to the DOM.
|
||||
When the expression is falsy, `NgIf` removes the `ItemDetailComponent`
|
||||
from the DOM, destroying that component and all of its sub-components.
|
||||
|
||||
|
||||
### Show/hide vs. `NgIf`
|
||||
|
||||
Hiding an element is different from removing it with `NgIf`.
|
||||
For comparison, the following example shows how to control
|
||||
the visibility of an element with a
|
||||
[class](guide/attribute-binding#class-binding) or [style](guide/attribute-binding#style-binding) binding.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgIf-3" header="src/app/app.component.html"></code-example>
|
||||
|
||||
When you hide an element, that element and all of its descendants remain in the DOM.
|
||||
All components for those elements stay in memory and
|
||||
Angular may continue to check for changes.
|
||||
You could be holding onto considerable computing resources and degrading performance
|
||||
unnecessarily.
|
||||
|
||||
`NgIf` works differently. When `NgIf` is `false`, Angular removes the element and its descendants from the DOM.
|
||||
It destroys their components, freeing up resources, which
|
||||
results in a better user experience.
|
||||
|
||||
If you are hiding large component trees, consider `NgIf` as a more
|
||||
efficient alternative to showing/hiding.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For more information on `NgIf` and `ngIfElse`, see the [API documentation about NgIf](api/common/NgIf).
|
||||
|
||||
</div>
|
||||
|
||||
### Guard against null
|
||||
|
||||
Another advantage of `ngIf` is that you can use it to guard against null. Show/hide
|
||||
is best suited for very simple use cases, so when you need a guard, opt instead for `ngIf`. Angular will throw an error if a nested expression tries to access a property of `null`.
|
||||
|
||||
The following shows `NgIf` guarding two `<div>`s.
|
||||
The `currentCustomer` name appears only when there is a `currentCustomer`.
|
||||
The `nullCustomer` will not be displayed as long as it is `null`.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgIf-2" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgIf-2b" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See also the
|
||||
[safe navigation operator](guide/template-expression-operators#safe-navigation-operator "Safe navigation operator (?.)") below.
|
||||
|
||||
</div>
|
||||
<hr/>
|
||||
|
||||
{@a ngFor}
|
||||
## `NgFor`
|
||||
|
||||
`NgFor` is a repeater directive—a way to present a list of items.
|
||||
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`.)
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgFor-1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Don't forget the asterisk (`*`) in front of `ngFor`. For more information
|
||||
on the asterisk, see the [asterisk (*) prefix](guide/structural-directives#the-asterisk--prefix) section of
|
||||
[Structural Directives](guide/structural-directives).
|
||||
|
||||
</div>
|
||||
|
||||
You can also apply an `NgFor` to a component element, as in the following example.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgFor-2" header="src/app/app.component.html"></code-example>
|
||||
|
||||
{@a microsyntax}
|
||||
|
||||
<div class="callout is-critical">
|
||||
<header>*ngFor microsyntax</header>
|
||||
|
||||
The string assigned to `*ngFor` is not a [template expression](guide/interpolation). Rather,
|
||||
it's a *microsyntax*—a little language of its own that Angular interprets.
|
||||
The string `"let item of items"` means:
|
||||
|
||||
> *Take each item in the `items` array, store it in the local `item` looping variable, and
|
||||
make it available to the templated HTML for each iteration.*
|
||||
|
||||
Angular translates this instruction into an `<ng-template>` around the host element,
|
||||
then uses this template repeatedly to create a new set of elements and bindings for each `item`
|
||||
in the list.
|
||||
For more information about microsyntax, see the [Structural Directives](guide/structural-directives#microsyntax) guide.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
{@a template-input-variable}
|
||||
|
||||
{@a template-input-variables}
|
||||
|
||||
### Template input variables
|
||||
|
||||
The `let` keyword before `item` creates a template input variable called `item`.
|
||||
The `ngFor` directive iterates over the `items` array returned by the parent component's `items` property
|
||||
and sets `item` to the current item from the array during each iteration.
|
||||
|
||||
Reference `item` within the `ngFor` host element
|
||||
as well as within its descendants to access the item's properties.
|
||||
The following example references `item` first in an interpolation
|
||||
and then passes in a binding to the `item` property of the `<app-item-detail>` component.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgFor-1-2" header="src/app/app.component.html"></code-example>
|
||||
|
||||
For more information about template input variables, see
|
||||
[Structural Directives](guide/structural-directives#template-input-variable).
|
||||
|
||||
### `*ngFor` with `index`
|
||||
|
||||
The `index` property of the `NgFor` directive context
|
||||
returns the zero-based index of the item in each iteration.
|
||||
You can capture the `index` in a template input variable and use it in the template.
|
||||
|
||||
The next example captures the `index` in a variable named `i` and displays it with the item name.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgFor-3" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
`NgFor` is implemented by the `NgForOf` directive. Read more about the other `NgForOf` context values such as `last`, `even`,
|
||||
and `odd` in the [NgForOf API reference](api/common/NgForOf).
|
||||
|
||||
</div>
|
||||
|
||||
{@a trackBy}
|
||||
### *ngFor with `trackBy`
|
||||
|
||||
If you use `NgFor` with large lists, a small change to one item, such as removing or adding an item, can trigger a cascade of DOM manipulations. For example, re-querying the server could reset a list with all new item objects, even when those items were previously displayed. In this case, Angular sees only a fresh list of new object references and has no choice but to replace the old DOM elements with all new DOM elements.
|
||||
|
||||
You can make this more efficient with `trackBy`.
|
||||
Add a method to the component that returns the value `NgFor` should track.
|
||||
In this case, that value is the hero's `id`. If the `id` has already been rendered,
|
||||
Angular keeps track of it and doesn't re-query the server for the same `id`.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.ts" region="trackByItems" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
In the microsyntax expression, set `trackBy` to the `trackByItems()` method.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="trackBy" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Here is an illustration of the `trackBy` effect.
|
||||
"Reset items" creates new items with the same `item.id`s.
|
||||
"Change ids" creates new items with new `item.id`s.
|
||||
|
||||
* With no `trackBy`, both buttons trigger complete DOM element replacement.
|
||||
* With `trackBy`, only changing the `id` triggers element replacement.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/built-in-directives/ngfor-trackby.gif" alt="Animation of trackBy">
|
||||
</div>
|
||||
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Built-in directives use only public APIs; that is,
|
||||
they do not have special access to any private APIs that other directives can't access.
|
||||
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a ngSwitch}
|
||||
## The `NgSwitch` directives
|
||||
|
||||
NgSwitch is like the JavaScript `switch` statement.
|
||||
It displays one element from among several possible elements, based on a switch condition.
|
||||
Angular puts only the selected element into the DOM.
|
||||
<!-- API Flagged -->
|
||||
`NgSwitch` is actually a set of three, cooperating directives:
|
||||
`NgSwitch`, `NgSwitchCase`, and `NgSwitchDefault` as in the following example.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgSwitch" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/built-in-directives/ngswitch.gif" alt="Animation of NgSwitch">
|
||||
</div>
|
||||
|
||||
`NgSwitch` is the controller directive. Bind it to an expression that returns
|
||||
the *switch value*, such as `feature`. Though the `feature` value in this
|
||||
example is a string, the switch value can be of any type.
|
||||
|
||||
**Bind to `[ngSwitch]`**. You'll get an error if you try to set `*ngSwitch` because
|
||||
`NgSwitch` is an *attribute* directive, not a *structural* directive.
|
||||
Rather than touching the DOM directly, it changes the behavior of its companion directives.
|
||||
|
||||
**Bind to `*ngSwitchCase` and `*ngSwitchDefault`**.
|
||||
The `NgSwitchCase` and `NgSwitchDefault` directives are _structural_ directives
|
||||
because they add or remove elements from the DOM.
|
||||
|
||||
* `NgSwitchCase` adds its element to the DOM when its bound value equals the switch value and removes
|
||||
its bound value when it doesn't equal the switch value.
|
||||
|
||||
* `NgSwitchDefault` adds its element to the DOM when there is no selected `NgSwitchCase`.
|
||||
|
||||
The switch directives are particularly useful for adding and removing *component elements*.
|
||||
This example switches among four `item` components defined in the `item-switch.components.ts` file.
|
||||
Each component has an `item` [input property](guide/inputs-outputs#input "Input property")
|
||||
which is bound to the `currentItem` of the parent component.
|
||||
|
||||
Switch directives work as well with native elements and web components too.
|
||||
For example, you could replace the `<app-best-item>` switch case with the following.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgSwitch-div" header="src/app/app.component.html"></code-example>
|
@ -10,7 +10,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><b>platformBrowserDynamic().bootstrapModule</b>(AppModule);</code></td>
|
||||
<td><p>Bootstraps the app, using the root component from the specified <code>NgModule</code>. </p>
|
||||
<td><p>Carga la app, usando el componente raíz del <code>NgModule</code> especificado.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
@ -24,370 +24,372 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>@<b>NgModule</b>({ declarations: ..., imports: ...,<br> exports: ..., providers: ..., bootstrap: ...})<br>class MyModule {}</code></td>
|
||||
<td><p>Defines a module that contains components, directives, pipes, and providers.</p>
|
||||
<td><p>Define un módulo que contiene componentes, directivas, pipes y proveedores.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>declarations:</b> [MyRedComponent, MyBlueComponent, MyDatePipe]</code></td>
|
||||
<td><p>List of components, directives, and pipes that belong to this module.</p>
|
||||
<td><p>Lista de componentes, directivas y pipes que pertenecen a este módulo.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>imports:</b> [BrowserModule, SomeOtherModule]</code></td>
|
||||
<td><p>List of modules to import into this module. Everything from the imported modules
|
||||
is available to <code>declarations</code> of this module.</p>
|
||||
<td><p>Lista de módulos para importar en este módulo. Todo, desde los módulos importados,
|
||||
está disponible para las declaraciones (<code>declarations</code>) de este módulo.
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>exports:</b> [MyRedComponent, MyDatePipe]</code></td>
|
||||
<td><p>List of components, directives, and pipes visible to modules that import this module.</p>
|
||||
<td><p>Lista de componentes, directivas y pipes visibles a los módulos que importan este módulo.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>providers:</b> [MyService, { provide: ... }]</code></td>
|
||||
<td><p>List of dependency injection providers visible both to the contents of this module and to importers of this module.</p>
|
||||
<td><p>Lista de proveedores de inyección de dependencias visibles tanto para los contenidos de este módulo como para los importadores de este módulo.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>entryComponents:</b> [SomeComponent, OtherComponent]</code></td>
|
||||
<td><p>List of components not referenced in any reachable template, for example dynamically created from code.</p></td>
|
||||
<td><p>Lista de componentes no referenciados en cualquier plantilla accesible, por ejemplo, creada dinámicamente a partir de código.</p></td>
|
||||
</tr><tr>
|
||||
<td><code><b>bootstrap:</b> [MyAppComponent]</code></td>
|
||||
<td><p>List of components to bootstrap when this module is bootstrapped.</p>
|
||||
<td><p>Lista de componentes a empaquetar cuando este módulo se inicia.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
<th>Template syntax</th>
|
||||
<th>Sintaxis de plantilla</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><input <b>[value]</b>="firstName"></code></td>
|
||||
<td><p>Binds property <code>value</code> to the result of expression <code>firstName</code>.</p>
|
||||
<td><p>Vincula la propiedad <code>value</code> al resultado de la expresión <code>firstName</code>.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><div <b>[attr.role]</b>="myAriaRole"></code></td>
|
||||
<td><p>Binds attribute <code>role</code> to the result of expression <code>myAriaRole</code>.</p>
|
||||
<td><p>Vincula el atributo <code>role</code> al resultado de la expresión <code>myAriaRole</code>.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><div <b>[class.extra-sparkle]</b>="isDelightful"></code></td>
|
||||
<td><p>Binds the presence of the CSS class <code>extra-sparkle</code> on the element to the truthiness of the expression <code>isDelightful</code>.</p>
|
||||
<td><p>Vincula la presencia de la clase CSS <code>extra-sparkle</code> sobre el elemento a la veracidad de la expresión <code>isDelightful</code>.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><div <b>[style.width.px]</b>="mySize"></code></td>
|
||||
<td><p>Binds style property <code>width</code> to the result of expression <code>mySize</code> in pixels. Units are optional.</p>
|
||||
<td><p>Vincula la propiedad de estilo <code>width</code> al resultado de la expresión <code>mySize</code> en píxeles. La unidad de medida es opcional.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><button <b>(click)</b>="readRainbow($event)"></code></td>
|
||||
<td><p>Calls method <code>readRainbow</code> when a click event is triggered on this button element (or its children) and passes in the event object.</p>
|
||||
<td><p>Llama al método <code>readRainbow</code> cuando se lanza un evento click en este elemento botón (o sus hijos) y pasa por argumento el objeto evento.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><div title="Hello <b>{{ponyName}}</b>"></code></td>
|
||||
<td><code><div title="Hola <b>{{ponyName}}</b>"></code></td>
|
||||
<td><p>Vincula una propiedad a una cadena interpolada, por ejemplo, "Hola Seabiscuit". Equivalente a:
|
||||
<td><p>Binds a property to an interpolated string, for example, "Hello Seabiscuit". Equivalent to:
|
||||
<code><div [title]="'Hello ' + ponyName"></code></p>
|
||||
<code><div [title]="'Hola ' + ponyName"></code></p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><p>Hello <b>{{ponyName}}</b></p></code></td>
|
||||
<td><p>Binds text content to an interpolated string, for example, "Hello Seabiscuit".</p>
|
||||
<td><code><p>Hola <b>{{ponyName}}</b></p></code></td>
|
||||
<td><p>Vincula el contenido de texto a una cadena interpolada, por ejemplo, "Hola Seabiscuit".</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><my-cmp <b>[(title)]</b>="name"></code></td>
|
||||
<td><p>Sets up two-way data binding. Equivalent to: <code><my-cmp [title]="name" (titleChange)="name=$event"></code></p>
|
||||
<td><p>Establece el two-way data binding. Equivalente a: <code><my-cmp [title]="name" (titleChange)="name=$event"></code></p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><video <b>#movieplayer</b> ...><br> <button <b>(click)</b>="movieplayer.play()"><br></video></code></td>
|
||||
<td><p>Creates a local variable <code>movieplayer</code> that provides access to the <code>video</code> element instance in data-binding and event-binding expressions in the current template.</p>
|
||||
<td><p>Crea una variable local <code>movieplayer</code> que provee acceso a la instancia del elemento <code>video</code> en las expresiones de data-binding y event-binding de la actual plantilla.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><p <b>*myUnless</b>="myExpression">...</p></code></td>
|
||||
<td><p>The <code>*</code> symbol turns the current element into an embedded template. Equivalent to:
|
||||
<td><p>El símbolo <code>*</code> convierte el elemento actual en una plantilla incrustada. Equivalente a:
|
||||
<code><ng-template [myUnless]="myExpression"><p>...</p></ng-template></code></p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><p>Card No.: <b>{{cardNumber | myCardNumberFormatter}}</b></p></code></td>
|
||||
<td><p>Transforms the current value of expression <code>cardNumber</code> via the pipe called <code>myCardNumberFormatter</code>.</p>
|
||||
<td><p>Transforma el valor actual de la expresión <code>cardNumber</code> a través de la pipe <code>myCardNumberFormatter</code>.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><p>Employer: <b>{{employer?.companyName}}</b></p></code></td>
|
||||
<td><p>The safe navigation operator (<code>?</code>) means that the <code>employer</code> field is optional and if <code>undefined</code>, the rest of the expression should be ignored.</p>
|
||||
<td><p>El operador de navegación seguro (<code>?</code>) significa que el campo <code>employer</code> es opcional y que si es <code>undefined</code>, el resto de la expresión debería ser ignorado.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><<b>svg:</b>rect x="0" y="0" width="100" height="100"/></code></td>
|
||||
<td><p>An SVG snippet template needs an <code>svg:</code> prefix on its root element to disambiguate the SVG element from an HTML component.</p>
|
||||
<td><p>Una plantilla de fragmento SVG necesita un prefijo <code>svg:</code> en su elemento raíz para distinguir el elemento SVG de un componente HTML.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><<b>svg</b>><br> <rect x="0" y="0" width="100" height="100"/><br></<b>svg</b>></code></td>
|
||||
<td><p>An <code><svg></code> root element is detected as an SVG element automatically, without the prefix.</p>
|
||||
<td><p>Un elemento raíz <code><svg></code> es detectado como un elemento SVG automáticamente, sin el prefijo.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
<th>Built-in directives</th>
|
||||
<th>Directivas incorporadas</th>
|
||||
<th><p><code>import { CommonModule } from '@angular/common';</code>
|
||||
</p>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><section <b>*ngIf</b>="showSection"></code></td>
|
||||
<td><p>Removes or recreates a portion of the DOM tree based on the <code>showSection</code> expression.</p>
|
||||
<td><p>Elimina o recrea una parte del árbol DOM basado en la expresión <code>showSection</code>.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><li <b>*ngFor</b>="let item of list"></code></td>
|
||||
<td><p>Turns the li element and its contents into a template, and uses that to instantiate a view for each item in list.</p>
|
||||
<td><p>Convierte el elemento li y su contenido en una plantilla, y lo utiliza para crear una vista por cada elemento de la lista.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><div <b>[ngSwitch]</b>="conditionExpression"><br> <ng-template <b>[<b>ngSwitchCase</b>]</b>="case1Exp">...</ng-template><br> <ng-template <b>ngSwitchCase</b>="case2LiteralString">...</ng-template><br> <ng-template <b>ngSwitchDefault</b>>...</ng-template><br></div></code></td>
|
||||
<td><p>Conditionally swaps the contents of the div by selecting one of the embedded templates based on the current value of <code>conditionExpression</code>.</p>
|
||||
<td><p>Intercambia condicionalmente el contenido del div seleccionando una de las plantillas incrustadas en función del valor actual de <code>conditionExpression</code>.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><div <b>[ngClass]</b>="{'active': isActive, 'disabled': isDisabled}"></code></td>
|
||||
<td><p>Binds the presence of CSS classes on the element to the truthiness of the associated map values. The right-hand expression should return {class-name: true/false} map.</p>
|
||||
<td><p>Vincula la presencia de clases CSS en el elemento a la veracidad de los valores de mapa asociados. La expresión de la derecha debería devolver el mapa {class-name: true/false}.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><div <b>[ngStyle]</b>="{'property': 'value'}"></code><br><code><div <b>[ngStyle]</b>="dynamicStyles()"></code></td>
|
||||
<td><p>Allows you to assign styles to an HTML element using CSS. You can use CSS directly, as in the first example, or you can call a method from the component.</p>
|
||||
<p>Te permite asignar estilos a un elemento HTML usando CSS. Puedes usar CSS directamente, como en el primer ejemplo, o puedes llamar a un método desde el componente.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
<th>Forms</th>
|
||||
<th>Formularios</th>
|
||||
<th><p><code>import { FormsModule } from '@angular/forms';</code>
|
||||
</p>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><input <b>[(ngModel)]</b>="userName"></code></td>
|
||||
<td><p>Provides two-way data-binding, parsing, and validation for form controls.</p>
|
||||
<td><p>Provee two-way data-binding, conversión y validación para controles de formulario.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
<th>Class decorators</th>
|
||||
<th>Decoradores de clases</th>
|
||||
<th><p><code>import { Directive, ... } from '@angular/core';</code>
|
||||
</p>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><b>@Component({...})</b><br>class MyComponent() {}</code></td>
|
||||
<td><p>Declares that a class is a component and provides metadata about the component.</p>
|
||||
<td><p>Declara que una clase es un componente y proporciona metadatos sobre el componente.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>@Directive({...})</b><br>class MyDirective() {}</code></td>
|
||||
<td><p>Declares that a class is a directive and provides metadata about the directive.</p>
|
||||
<td><p>Declara que una clase es una directiva y proporciona metadatos sobre la directiva.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>@Pipe({...})</b><br>class MyPipe() {}</code></td>
|
||||
<td><p>Declares that a class is a pipe and provides metadata about the pipe.</p>
|
||||
<td><p>Declara que una clase es una pipe y proporciona metadatos sobre la pipe.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>@Injectable()</b><br>class MyService() {}</code></td>
|
||||
<td><p>Declares that a class can be provided and injected by other classes. Without this decorator, the compiler won't generate enough metadata to allow the class to be created properly when it's injected somewhere.</p>
|
||||
<td><p>Declara que una clase puede ser proporcionada e inyectada por otras clases. Sin este decorador, el compilador no generará suficientes metadatos para permitir que la clase se cree correctamente cuando se inyecta en alguna parte.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
<th>Directive configuration</th>
|
||||
<th>Configuración de Directiva</th>
|
||||
<th><p><code>@Directive({ property1: value1, ... })</code>
|
||||
</p>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><b>selector:</b> '.cool-button:not(a)'</code></td>
|
||||
<td><p>Specifies a CSS selector that identifies this directive within a template. Supported selectors include <code>element</code>,
|
||||
<td><p>Especifica un selector CSS que identifica esta directiva dentro de una plantilla. Los selectores compatibles incluyen <code>element</code>,
|
||||
<code>[attribute]</code>, <code>.class</code>, and <code>:not()</code>.</p>
|
||||
<p>Does not support parent-child relationship selectors.</p>
|
||||
<p>No soporta selectores de relación padre-hijo.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>providers:</b> [MyService, { provide: ... }]</code></td>
|
||||
<td><p>List of dependency injection providers for this directive and its children.</p>
|
||||
<td><p>Lista de proveedores de inyección de dependencia para esta directiva y sus hijos.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
<th>Component configuration</th>
|
||||
<th>Configuración de Componente</th>
|
||||
<th><p>
|
||||
<code>@Component</code> extends <code>@Directive</code>,
|
||||
so the <code>@Directive</code> configuration applies to components as well</p>
|
||||
<code>@Component</code> extiende <code>@Directive</code>,
|
||||
entonces la configuración de <code>@Directive</code> se aplica también a los componentes</p>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><b>moduleId:</b> module.id</code></td>
|
||||
<td><p>If set, the <code>templateUrl</code> and <code>styleUrl</code> are resolved relative to the component.</p>
|
||||
<td><p>Si está presente, el <code>templateUrl</code> y <code>styleUrl</code> se resuelven en relación con el componente.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>viewProviders:</b> [MyService, { provide: ... }]</code></td>
|
||||
<td><p>List of dependency injection providers scoped to this component's view.</p>
|
||||
<td><p>Lista de proveedores de inyección de dependencias en la vista de este componente.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>template:</b> 'Hello {{name}}'<br><b>templateUrl:</b> 'my-component.html'</code></td>
|
||||
<td><p>Inline template or external template URL of the component's view.</p>
|
||||
<td><code><b>template:</b> 'Hola {{name}}'<br><b>templateUrl:</b> 'my-component.html'</code></td>
|
||||
<td><p>Plantilla en línea o URL de plantilla externa de la vista del componente.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>styles:</b> ['.primary {color: red}']<br><b>styleUrls:</b> ['my-component.css']</code></td>
|
||||
<td><p>List of inline CSS styles or external stylesheet URLs for styling the component’s view.</p>
|
||||
<td><p>Lista de estilos CSS en línea o URL de hojas de estilo externas para estilar la vista del componente.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
<th>Class field decorators for directives and components</th>
|
||||
<th>Decoradores para los campos de la clase para directivas y componentes.</th>
|
||||
<th><p><code>import { Input, ... } from '@angular/core';</code>
|
||||
</p>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><b>@Input()</b> myProperty;</code></td>
|
||||
<td><p>Declares an input property that you can update via property binding (example:
|
||||
<td><p>Declara una propiedad de entrada (input) que puede actualizar mediante el enlace de propiedad (property binding) (ejemplo:
|
||||
<code><my-cmp [myProperty]="someExpression"></code>).</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>@Output()</b> myEvent = new EventEmitter();</code></td>
|
||||
<td><p>Declares an output property that fires events that you can subscribe to with an event binding (example: <code><my-cmp (myEvent)="doSomething()"></code>).</p>
|
||||
<td><p>Declara una propiedad de salida (output) que dispara eventos a los que puedes suscribirse con un enlace de evento (event binding) (ejemplo: <code><my-cmp (myEvent)="doSomething()"></code>).</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>@HostBinding('class.valid')</b> isValid;</code></td>
|
||||
<td><p>Binds a host element property (here, the CSS class <code>valid</code>) to a directive/component property (<code>isValid</code>).</p>
|
||||
<td><p>Vincula una propiedad del elemento anfitrión (aquí, la clase CSS <code>valid</code>) a una propiedad de directiva/componente (<code>isValid</code>).</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>@HostListener('click', ['$event'])</b> onClick(e) {...}</code></td>
|
||||
<td><p>Subscribes to a host element event (<code>click</code>) with a directive/component method (<code>onClick</code>), optionally passing an argument (<code>$event</code>).</p>
|
||||
<td><p>Se suscribe a un evento del elemento anfitrión (<code>click</code>) con un método de directiva/componente (<code>onClick</code>), opcionalmente, pasando un argumento (<code>$event</code>).</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>@ContentChild(myPredicate)</b> myChildComponent;</code></td>
|
||||
<td><p>Binds the first result of the component content query (<code>myPredicate</code>) to a property (<code>myChildComponent</code>) of the class.</p>
|
||||
<td><p>Vincula el primer resultado de la consulta de contenido del componente (<code>myPredicate</code>) a una propiedad (<code>myChildComponent</code>) de la clase.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>@ContentChildren(myPredicate)</b> myChildComponents;</code></td>
|
||||
<td><p>Binds the results of the component content query (<code>myPredicate</code>) to a property (<code>myChildComponents</code>) of the class.</p>
|
||||
<td><p>Vincula los resultados de la consulta de contenido del componente (<code>myPredicate</code>) a una propiedad (<code>myChildComponents</code>) de la clase.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>@ViewChild(myPredicate)</b> myChildComponent;</code></td>
|
||||
<td><p>Binds the first result of the component view query (<code>myPredicate</code>) to a property (<code>myChildComponent</code>) of the class. Not available for directives.</p>
|
||||
<td><p>Vincula el primer resultado de la consulta de vista del componente (<code>myPredicate</code>) a una propiedad (<code>myChildComponent</code>) de la clase. No disponible para directivas.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>@ViewChildren(myPredicate)</b> myChildComponents;</code></td>
|
||||
<td><p>Binds the results of the component view query (<code>myPredicate</code>) to a property (<code>myChildComponents</code>) of the class. Not available for directives.</p>
|
||||
<td><p>Vincula los resultados de la consulta de vista del componente (<code>myPredicate</code>) a una propiedad (<code>myChildComponents</code>) de la clase. No disponible para directivas.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
<th>Directive and component change detection and lifecycle hooks</th>
|
||||
<th><p>(implemented as class methods)
|
||||
|
||||
<th>Detección de cambios (change detection) y ciclos de vida (lifecycle hooks) en directivas y componentes</th>
|
||||
<th><p>(implementado como métodos de clase)
|
||||
</p>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><b>constructor(myService: MyService, ...)</b> { ... }</code></td>
|
||||
<td><p>Called before any other lifecycle hook. Use it to inject dependencies, but avoid any serious work here.</p>
|
||||
<td><p>Se llama antes que cualquier ciclo de vida. Úselo para inyectar dependencias, pero evite cualquier trabajo serio aquí.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>ngOnChanges(changeRecord)</b> { ... }</code></td>
|
||||
<td><p>Called after every change to input properties and before processing content or child views.</p>
|
||||
<td><p>Se llama después de cada cambio en las propiedades de entrada (input) y antes de procesar contenido o vistas de hijos.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>ngOnInit()</b> { ... }</code></td>
|
||||
<td><p>Called after the constructor, initializing input properties, and the first call to <code>ngOnChanges</code>.</p>
|
||||
<td><p>Se llama después del constructor, inicializando propiedades de entrada (input), y la primera llamada a <code>ngOnChanges</code>.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>ngDoCheck()</b> { ... }</code></td>
|
||||
<td><p>Called every time that the input properties of a component or a directive are checked. Use it to extend change detection by performing a custom check.</p>
|
||||
<td><p>Se llama cada vez que se verifican las propiedades de entrada (input) de un componente o una directiva. Úselo para extender la detección de cambios (change detection) realizando una verificación personalizada.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>ngAfterContentInit()</b> { ... }</code></td>
|
||||
<td><p>Called after <code>ngOnInit</code> when the component's or directive's content has been initialized.</p>
|
||||
<td><p>Se llama después de <code>ngOnInit</code> cuando el contenido del componente o directiva ha sido inicializado.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>ngAfterContentChecked()</b> { ... }</code></td>
|
||||
<td><p>Called after every check of the component's or directive's content.</p>
|
||||
<td><p>Se llama después de cada verificación del contenido del componente o directiva.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>ngAfterViewInit()</b> { ... }</code></td>
|
||||
<td><p>Called after <code>ngAfterContentInit</code> when the component's views and child views / the view that a directive is in has been initialized.</p>
|
||||
<td><p>Se llama después de <code>ngAfterContentInit</code> cuando las vistas del componente y las vistas hijas / la vista en la que se encuentra una directiva ha sido inicializado.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>ngAfterViewChecked()</b> { ... }</code></td>
|
||||
<td><p>Called after every check of the component's views and child views / the view that a directive is in.</p>
|
||||
<td><p>Se llama después de cada verificación de las vistas del componentes y las vistas hijas / la vista en la que se encuentra una directiva.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>ngOnDestroy()</b> { ... }</code></td>
|
||||
<td><p>Called once, before the instance is destroyed.</p>
|
||||
<td><p>Se llama una vez, antes de que la instancia se destruya.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
<th>Dependency injection configuration</th>
|
||||
<th>Configuración de inyección de dependencia</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>{ <b>provide</b>: MyService, <b>useClass</b>: MyMockService }</code></td>
|
||||
<td><p>Sets or overrides the provider for <code>MyService</code> to the <code>MyMockService</code> class.</p>
|
||||
<td><p>Establece o sobre-escribe el proveedor para <code>MyService</code> en la clase <code>MyMockService</code>.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code>{ <b>provide</b>: MyService, <b>useFactory</b>: myFactory }</code></td>
|
||||
<td><p>Sets or overrides the provider for <code>MyService</code> to the <code>myFactory</code> factory function.</p>
|
||||
<td><p>Establece o sobre-escribe el proveedor para <code>MyService</code> en la factoría de función <code>myFactory</code>.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code>{ <b>provide</b>: MyValue, <b>useValue</b>: 41 }</code></td>
|
||||
<td><p>Sets or overrides the provider for <code>MyValue</code> to the value <code>41</code>.</p>
|
||||
<td><p>Establece o sobre-escribe el proveedor para <code>MyValue</code> al valor <code>41</code>.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
<th>Routing and navigation</th>
|
||||
<th>Enrutamiento y navegación</th>
|
||||
<th><p><code>import { Routes, RouterModule, ... } from '@angular/router';</code>
|
||||
</p>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>const routes: <b>Routes</b> = [<br> { path: '', component: HomeComponent },<br> { path: 'path/:routeParam', component: MyComponent },<br> { path: 'staticPath', component: ... },<br> { path: '**', component: ... },<br> { path: 'oldPath', redirectTo: '/staticPath' },<br> { path: ..., component: ..., data: { message: 'Custom' } }<br>]);<br><br>const routing = RouterModule.forRoot(routes);</code></td>
|
||||
<td><p>Configures routes for the application. Supports static, parameterized, redirect, and wildcard routes. Also supports custom route data and resolve.</p>
|
||||
<td><p>Configura rutas para la aplicación. Soporta rutas estáticas, parametrizadas, de redireccionamiento y comodines. También soporta datos de ruta personalizados y los resuelve.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><br><<b>router-outlet</b>></<b>router-outlet</b>><br><<b>router-outlet</b> name="aux"></<b>router-outlet</b>><br></code></td>
|
||||
<td><p>Marks the location to load the component of the active route.</p>
|
||||
<td><p>Marca la ubicación para cargar el componente de la ruta activa.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><br><a routerLink="/path"><br><a <b>[routerLink]</b>="[ '/path', routeParam ]"><br><a <b>[routerLink]</b>="[ '/path', { matrixParam: 'value' } ]"><br><a <b>[routerLink]</b>="[ '/path' ]" [queryParams]="{ page: 1 }"><br><a <b>[routerLink]</b>="[ '/path' ]" fragment="anchor"><br></code></td>
|
||||
<td><p>Creates a link to a different view based on a route instruction consisting of a route path, required and optional parameters, query parameters, and a fragment. To navigate to a root route, use the <code>/</code> prefix; for a child route, use the <code>./</code>prefix; for a sibling or parent, use the <code>../</code> prefix.</p>
|
||||
<td><p>Crea un enlace a una vista diferente basada en una instrucción de ruta que consta de un camino de de ruta, parámetros obligatorios y opcionales, parámetros de consulta y un fragmento. Para navegar a un camino de ruta, usa el prefijo <code>/</code>; para una ruta hija, usa el prefijo <code>./</code>; para un padre o hermano, usa el prefijo <code>../</code>.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><a [routerLink]="[ '/path' ]" routerLinkActive="active"></code></td>
|
||||
<td><p>The provided classes are added to the element when the <code>routerLink</code> becomes the current active route.</p>
|
||||
<td><p>Las clases proporcionadas se agregan al elemento cuando el <code>routerLink</code> se convierte en la ruta activa actual.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code>class <b>CanActivate</b>Guard implements <b>CanActivate</b> {<br> canActivate(<br> route: ActivatedRouteSnapshot,<br> state: RouterStateSnapshot<br> ): Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolean|UrlTree { ... }<br>}<br><br>{ path: ..., canActivate: [<b>CanActivate</b>Guard] }</code></td>
|
||||
<td><p>An interface for defining a class that the router should call first to determine if it should activate this component. Should return a boolean|UrlTree or an Observable/Promise that resolves to a boolean|UrlTree.</p>
|
||||
<td><p>Una interfaz para definir una clase que el enrutador debe llamar primero para determinar si debe activar este componente. Debe devolver un boolean|UrlTree o un Observable/Promise que se resuelba en un boolean|UrlTree.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code>class <b>CanDeactivate</b>Guard implements <b>CanDeactivate</b><T> {<br> canDeactivate(<br> component: T,<br> route: ActivatedRouteSnapshot,<br> state: RouterStateSnapshot<br> ): Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolean|UrlTree { ... }<br>}<br><br>{ path: ..., canDeactivate: [<b>CanDeactivate</b>Guard] }</code></td>
|
||||
<td><p>An interface for defining a class that the router should call first to determine if it should deactivate this component after a navigation. Should return a boolean|UrlTree or an Observable/Promise that resolves to a boolean|UrlTree.</p>
|
||||
<td><p>Una interfaz para definir una clase que el enrutador debería llamar primero para determinar si debería desactivar este componente después de una navegación. Debe devolver un boolean|UrlTree o un Observable/Promise que se resuelva a boolean|UrlTree.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code>class <b>CanActivateChild</b>Guard implements <b>CanActivateChild</b> {<br> canActivateChild(<br> route: ActivatedRouteSnapshot,<br> state: RouterStateSnapshot<br> ): Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolean|UrlTree { ... }<br>}<br><br>{ path: ..., canActivateChild: [CanActivateGuard],<br> children: ... }</code></td>
|
||||
<td><p>An interface for defining a class that the router should call first to determine if it should activate the child route. Should return a boolean|UrlTree or an Observable/Promise that resolves to a boolean|UrlTree.</p>
|
||||
<td><p>Una interfaz para definir una clase que el enrutador debe llamar primero para determinar si debe activar la ruta hija. Debe devolver un boolean|UrlTree o un Observable/Promise que se resuelva en un boolean|UrlTree.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code>class <b>Resolve</b>Guard implements <b>Resolve</b><T> {<br> resolve(<br> route: ActivatedRouteSnapshot,<br> state: RouterStateSnapshot<br> ): Observable<any>|Promise<any>|any { ... }<br>}<br><br>{ path: ..., resolve: [<b>Resolve</b>Guard] }</code></td>
|
||||
<td><p>An interface for defining a class that the router should call first to resolve route data before rendering the route. Should return a value or an Observable/Promise that resolves to a value.</p>
|
||||
<td><p>Una interfaz para definir una clase que el enrutador debe llamar primero para resolver los datos de la ruta antes de representar la ruta. Debe devolver un valor o un Observable/Promise que se resuelva en un valor.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code>class <b>CanLoad</b>Guard implements <b>CanLoad</b> {<br> canLoad(<br> route: Route<br> ): Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolean|UrlTree { ... }<br>}<br><br>{ path: ..., canLoad: [<b>CanLoad</b>Guard], loadChildren: ... }</code></td>
|
||||
<td><p>An interface for defining a class that the router should call first to check if the lazy loaded module should be loaded. Should return a boolean|UrlTree or an Observable/Promise that resolves to a boolean|UrlTree.</p>
|
||||
<td><p>Una interfaz para definir una clase a la que el enrutador debe llamar primero para verificar si el módulo perezoso cargado (lazy loaded module) debe cargarse. Debe devolver un boolean|UrlTree o un Observable/Promise que se resuelva en un boolean|UrlTree.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
@ -25,7 +25,7 @@ in which two or more components share information.
|
||||
## Pass data from parent to child with input binding
|
||||
|
||||
`HeroChildComponent` has two ***input properties***,
|
||||
typically adorned with [@Input decorations](guide/template-syntax#inputs-outputs).
|
||||
typically adorned with [@Input() decorator](guide/inputs-outputs#input).
|
||||
|
||||
|
||||
<code-example path="component-interaction/src/app/hero-child.component.ts" header="component-interaction/src/app/hero-child.component.ts">
|
||||
@ -180,7 +180,7 @@ The child component exposes an `EventEmitter` property with which it `emits` eve
|
||||
The parent binds to that event property and reacts to those events.
|
||||
|
||||
The child's `EventEmitter` property is an ***output property***,
|
||||
typically adorned with an [@Output decoration](guide/template-syntax#inputs-outputs)
|
||||
typically adorned with an [@Output() decorator](guide/inputs-outputs#output)
|
||||
as seen in this `VoterComponent`:
|
||||
|
||||
|
||||
|
@ -132,7 +132,7 @@ If you've never published a package in npm before, you must create a user accoun
|
||||
|
||||
For now, it is not recommended to publish Ivy libraries to NPM because Ivy generated code is not backward compatible with View Engine, so apps using View Engine will not be able to consume them. Furthermore, the internal Ivy instructions are not yet stable, which can potentially break consumers using a different Angular version from the one used to build the library.
|
||||
|
||||
When a published library is used in an Ivy app, the Angular CLI will automatically convert it to Ivy using a tool known as the Angular compatibility compiler (`ngcc`). Thus, by publishing your libraries using the View Engine compiler ensures that they can be transparently consumed by both View Engine and Ivy apps.
|
||||
When a published library is used in an Ivy app, the Angular CLI will automatically convert it to Ivy using a tool known as the Angular compatibility compiler (`ngcc`). Thus, publishing your libraries using the View Engine compiler ensures that they can be transparently consumed by both View Engine and Ivy apps.
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -262,7 +262,7 @@ For example, when bootstrapping an application, you can register many initialize
|
||||
|
||||
```
|
||||
export const APP_TOKENS = [
|
||||
{ provide: PLATFORM_INITIALIZER, useFactory: platformInitialized, multi: true },
|
||||
{ provide: PLATFORM_INITIALIZER, useFactory: platformInitialized, multi: true },
|
||||
{ provide: APP_INITIALIZER, useFactory: delayBootstrapping, multi: true },
|
||||
{ provide: APP_BOOTSTRAP_LISTENER, useFactory: appBootstrapped, multi: true },
|
||||
];
|
||||
@ -284,6 +284,23 @@ Search for [Constants in API documentation](api?type=const) to find more built-i
|
||||
|
||||
</div>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Note that the reference to the array returned for a `multi` provider is shared between all the
|
||||
places where the token is injected. We recommend avoiding mutations of the array (especially for
|
||||
predefined tokens) as it may lead to unexpected behavior in other parts of the app that inject
|
||||
the same token. You can prevent the value from being mutated by setting its type to `ReadonlyArray`.
|
||||
|
||||
</div>
|
||||
|
||||
You can use `ReadonlyArray` to type your `multi` provider, so TypeScript triggers an error in case
|
||||
of unwanted array mutations:
|
||||
|
||||
```
|
||||
constructor(@Inject(MULTI_PROVIDER) multiProvider: ReadonlyArray<MultiProvider>) {
|
||||
}
|
||||
```
|
||||
|
||||
{@a tree-shakable-provider}
|
||||
{@a tree-shakable-providers}
|
||||
|
||||
|
@ -320,7 +320,7 @@ You can dramatically reduce launch time by only loading the application modules
|
||||
absolutely must be present when the app starts.
|
||||
|
||||
Configure the Angular Router to defer loading of all other modules (and their associated code), either by
|
||||
[waiting until the app has launched](guide/router#preloading "Preloading")
|
||||
[waiting until the app has launched](guide/router-tutorial-toh#preloading "Preloading")
|
||||
or by [_lazy loading_](guide/router#lazy-loading "Lazy loading")
|
||||
them on demand.
|
||||
|
||||
@ -328,7 +328,7 @@ them on demand.
|
||||
|
||||
<header>Don't eagerly import something from a lazy-loaded module</header>
|
||||
|
||||
If you mean to lazy-load a module, be careful not import it
|
||||
If you mean to lazy-load a module, be careful not to import it
|
||||
in a file that's eagerly loaded when the app starts (such as the root `AppModule`).
|
||||
If you do that, the module will be loaded immediately.
|
||||
|
||||
|
@ -153,14 +153,14 @@ It marks that `<li>` element (and its children) as the "repeater template":
|
||||
<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/template-syntax#ngfor) of the [Template Syntax](guide/template-syntax) page.
|
||||
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/template-syntax#microsyntax) section of
|
||||
the [Template Syntax](guide/template-syntax) page.
|
||||
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
|
||||
@ -255,7 +255,7 @@ To see it in action, add the following paragraph at the bottom of the template:
|
||||
<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/template-syntax#ngIf) of the [Template Syntax](guide/template-syntax) page.
|
||||
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>
|
||||
|
||||
@ -266,7 +266,7 @@ When the component's list of heroes has more than three items, Angular adds the
|
||||
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 expressions](guide/template-syntax#template-expressions).
|
||||
For more information, see [template expression operators](guide/interpolation#template-expressions).
|
||||
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
@ -186,7 +186,7 @@ aDialog.content = 123; // <-- ERROR: TypeScript knows this should be a string.
|
||||
aDialog.body = 'News'; // <-- ERROR: TypeScript knows there is no `body` property on `aDialog`.
|
||||
```
|
||||
|
||||
This is a good way to quickly get TypeScript features, such as type checking and autocomplete support, for you custom element. But it can get cumbersome if you need it in several places, because you have to cast the return type on every occurrence.
|
||||
This is a good way to quickly get TypeScript features, such as type checking and autocomplete support, for your custom element. But it can get cumbersome if you need it in several places, because you have to cast the return type on every occurrence.
|
||||
|
||||
An alternative way, that only requires defining each custom element's type once, is augmenting the `HTMLElementTagNameMap`, which TypeScript uses to infer the type of a returned element based on its tag name (for DOM methods such as `document.createElement()`, `document.querySelector()`, etc.):
|
||||
|
||||
|
108
aio/content/guide/event-binding.md
Normal file
108
aio/content/guide/event-binding.md
Normal file
@ -0,0 +1,108 @@
|
||||
# Event binding `(event)`
|
||||
|
||||
Event binding allows you to listen for certain events such as
|
||||
keystrokes, mouse movements, clicks, and touches.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</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:
|
||||
|
||||
<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.
|
||||
|
||||
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.
|
||||
|
||||
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>
|
||||
|
||||
<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`.
|
||||
|
||||
<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.
|
||||
|
||||
## Template statements have side effects
|
||||
|
||||
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.
|
||||
|
||||
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.
|
@ -55,7 +55,7 @@ This initial root-level application is the *default app* for CLI commands (unles
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Besides using the CLI on the command line, you can also use an interactive development environment like [Angular Console](https://angularconsole.com/), or manipulate files directly in the app's source folder and configuration files.
|
||||
Besides using the CLI on the command line, you can also manipulate files directly in the app's source folder and configuration files.
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -117,7 +117,7 @@ As users change values and make selections through the view, the new values must
|
||||
Similarly, when the program logic changes values in the data model, those values must be reflected in the view.
|
||||
|
||||
Reactive and template-driven forms differ in how they handle data flowing from the user or from programmatic changes.
|
||||
The following diagrams illustrate both kinds of data flow for each type of form, using the a favorite-color input field defined above.
|
||||
The following diagrams illustrate both kinds of data flow for each type of form, using the favorite-color input field defined above.
|
||||
|
||||
### Data flow in reactive forms
|
||||
|
||||
|
@ -36,7 +36,7 @@ This tutorial teaches you how to do the following:
|
||||
* Use `ngModel` to create two-way data bindings for reading and writing input-control values.
|
||||
* Provide visual feedback using special CSS classes that track the state of the controls.
|
||||
* Display validation errors to users and enable or disable form controls based on the form status.
|
||||
* Share information across HTML elements using [template reference variables](guide/template-syntax#template-reference-variables-var).
|
||||
* Share information across HTML elements using [template reference variables](guide/template-reference-variables).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@ -93,7 +93,7 @@ In the course of this tutorial, you bind a sample form to data and handle user i
|
||||
* Add custom CSS to provide visual feedback on the status.
|
||||
* Show and hide validation-error messages.
|
||||
4. Respond to a native HTML button-click event by adding to the model data.
|
||||
5. Handle form submission using the [`ngSubmit`(api/forms/NgForm#properties)] output property of the form.
|
||||
5. Handle form submission using the [`ngSubmit`](api/forms/NgForm#properties) output property of the form.
|
||||
* Disable the **Submit** button until the form is valid.
|
||||
* After submit, swap out the finished form for different content on the page.
|
||||
|
||||
@ -184,7 +184,7 @@ The note reminds you to remove the diagnostic lines when you have finished obser
|
||||
|
||||
When you imported the `FormsModule` in your component, Angular automatically created and attached an [NgForm](api/forms/NgForm "API reference for NgForm") directive to the `<form>` tag in the template (because `NgForm` has the selector `form` that matches `<form>` elements).
|
||||
|
||||
To get access to the `NgForm` and the overall form status, declare a [template reference variable](guide/template-syntax#template-reference-variables-var).
|
||||
To get access to the `NgForm` and the overall form status, declare a [template reference variable](guide/template-reference-variables).
|
||||
|
||||
1. Edit the template file `hero-form.component.html`.
|
||||
|
||||
@ -467,7 +467,7 @@ You will bind the form property that indicates its overall validity to the **Sub
|
||||
3. Run the application now. Notice that the button is enabled—although
|
||||
it doesn't do anything useful yet.
|
||||
|
||||
4. Delete the **Name** value. This violates the "required" rule, so it displays the error message&emdash;and notice that it also disables the **Submit** button.
|
||||
4. Delete the **Name** value. This violates the "required" rule, so it displays the error message—and notice that it also disables the **Submit** button.
|
||||
|
||||
|
||||
You didn't have to explicitly wire the button's enabled state to the form's validity.
|
||||
|
@ -210,6 +210,7 @@ An Angular component class is responsible for exposing data and handling most of
|
||||
|
||||
Read more about component classes, templates, and views in [Introduction to Angular concepts](guide/architecture).
|
||||
|
||||
|
||||
## configuration
|
||||
|
||||
See [workspace configuration](#cli-config)
|
||||
@ -252,15 +253,15 @@ Data binding is an alternative to manually pushing application data values into
|
||||
event listeners, pulling changed values from the screen, and
|
||||
updating application data values.
|
||||
|
||||
Read about the following forms of binding in [Template Syntax](guide/template-syntax):
|
||||
Read about the following forms of binding in Angular's [Template Syntax](guide/template-syntax):
|
||||
|
||||
* [Interpolation](guide/template-syntax#interpolation)
|
||||
* [Property binding](guide/template-syntax#property-binding)
|
||||
* [Event binding](guide/template-syntax#event-binding)
|
||||
* [Attribute binding](guide/template-syntax#attribute-binding)
|
||||
* [Class binding](guide/template-syntax#class-binding)
|
||||
* [Style binding](guide/template-syntax#style-binding)
|
||||
* [Two-way data binding with ngModel](guide/template-syntax#ngModel)
|
||||
* [Interpolation](guide/interpolation)
|
||||
* [Property binding](guide/property-binding)
|
||||
* [Event binding](guide/event-binding)
|
||||
* [Attribute binding](guide/attribute-binding)
|
||||
* [Class binding](guide/attribute-binding#class-binding)
|
||||
* [Style binding](guide/attribute-binding#style-binding)
|
||||
* [Two-way data binding with ngModel](guide/built-in-directives#ngModel)
|
||||
|
||||
{@a declarable}
|
||||
|
||||
@ -472,11 +473,11 @@ Learn more about the injector hierarchy in [Hierarchical Dependency Injectors](g
|
||||
## input
|
||||
|
||||
When defining a [directive](#directive), the `@Input()` decorator on a directive property
|
||||
makes that property available as a *target* of a [property binding](guide/template-syntax#property-binding).
|
||||
makes that property available as a *target* of a [property binding](guide/property-binding).
|
||||
Data values flow into an input property from the data source identified
|
||||
in the [template expression](#template-expression) to the right of the equal sign.
|
||||
|
||||
To learn more, see [input and output properties](guide/template-syntax#inputs-outputs).
|
||||
To learn more, see [input and output properties](guide/inputs-outputs).
|
||||
|
||||
{@a interpolation}
|
||||
|
||||
@ -491,7 +492,7 @@ or displayed between element tags, as in this example.
|
||||
```
|
||||
|
||||
|
||||
Read more about [interpolation](guide/template-syntax#interpolation) in [Template Syntax](guide/template-syntax).
|
||||
Read more in the [Interpolation](guide/interpolation) guide.
|
||||
|
||||
{@a ivy}
|
||||
|
||||
@ -578,7 +579,6 @@ Angular calls these hook methods in the following order:
|
||||
|
||||
To learn more, see [Lifecycle Hooks](guide/lifecycle-hooks).
|
||||
|
||||
|
||||
{@a M}
|
||||
|
||||
{@a module}
|
||||
@ -653,11 +653,11 @@ An object passed to the `subscribe()` method for an [observable](#observable). T
|
||||
## output
|
||||
|
||||
When defining a [directive](#directive), the `@Output{}` decorator on a directive property
|
||||
makes that property available as a *target* of [event binding](guide/template-syntax#event-binding).
|
||||
makes that property available as a *target* of [event binding](guide/event-binding).
|
||||
Events stream *out* of this property to the receiver identified
|
||||
in the [template expression](#template-expression) to the right of the equal sign.
|
||||
|
||||
To learn more, see [Input and Output Properties](guide/template-syntax#inputs-outputs).
|
||||
To learn more, see [Input and Output Properties](guide/inputs-outputs).
|
||||
|
||||
|
||||
{@a P}
|
||||
@ -732,13 +732,33 @@ The alternative is a [template-driven form](#template-driven-forms).
|
||||
When using reactive forms:
|
||||
|
||||
* The "source of truth", the form model, is defined in the component class.
|
||||
* Validation is set up through validation functions rather than valdation directives.
|
||||
* Validation is set up through validation functions rather than validation directives.
|
||||
* Each control is explicitly created in the component class by creating a `FormControl` instance manually or with `FormBuilder`.
|
||||
* The template input elements do *not* use `ngModel`.
|
||||
* The associated Angular directives are prefixed with `form`, such as `formControl`, `formGroup`, and `formControlName`.
|
||||
|
||||
The alternative is a template-driven form. For an introduction and comparison of both forms approaches, see [Introduction to Angular Forms](guide/forms-overview).
|
||||
|
||||
{@a resolver}
|
||||
|
||||
## resolver
|
||||
|
||||
A class that implements the [Resolve](api/router/Resolve "API reference") interface (or a function with the same signature as the [resolve() method](api/router/Resolve#resolve "API reference")) that you use to produce or retrieve data that is needed before navigation to a requested route can be completed.
|
||||
|
||||
Resolvers run after all [route guards](#route-guard "Definition") for a route tree have been executed and have succeeded.
|
||||
|
||||
See an example of using a [resolve guard](guide/router-tutorial-toh#resolve-guard "Routing techniques tutorial") to retrieve dynamic data.
|
||||
|
||||
{@a route-guard}
|
||||
|
||||
## route guard
|
||||
|
||||
A method that controls navigation to a requested route in a routing application.
|
||||
Guards determine whether a route can be activated or deactivated, and whether a lazy-loaded module can be loaded.
|
||||
|
||||
Learn more in the [Routing and Navigation](guide/router#preventing-unauthorized-access "Examples") guide.
|
||||
|
||||
|
||||
{@a router}
|
||||
{@a router-module}
|
||||
|
||||
@ -917,7 +937,7 @@ The alternative is a reactive form. For an introduction and comparison of both f
|
||||
|
||||
A TypeScript-like syntax that Angular evaluates within a [data binding](#data-binding).
|
||||
|
||||
Read about how to write template expressions in [Template expressions](guide/template-syntax#template-expressions).
|
||||
Read about how to write template expressions in the [template expressions](guide/interpolation#template-expressions) section of the [Interpolation](guide/interpolation) guide.
|
||||
|
||||
{@a token}
|
||||
|
||||
|
@ -277,7 +277,7 @@ searchHeroes(term: string): Observable {
|
||||
return this.http.jsonp(heroesUrl, 'callback').pipe(
|
||||
catchError(this.handleError('searchHeroes', [])) // then handle the error
|
||||
);
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
This request passes the `heroesURL` as the first parameter and the callback function name as the second parameter.
|
||||
|
342
aio/content/guide/inputs-outputs.md
Normal file
342
aio/content/guide/inputs-outputs.md
Normal file
@ -0,0 +1,342 @@
|
||||
# `@Input()` and `@Output()` properties
|
||||
|
||||
`@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.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
Consider this example of a child/parent relationship:
|
||||
|
||||
```html
|
||||
<parent-component>
|
||||
<child-component></child-component>
|
||||
</parent-component>
|
||||
|
||||
```
|
||||
|
||||
Here, the `<child-component>` selector, or child directive, is embedded
|
||||
within a `<parent-component>`, which serves as the child's context.
|
||||
|
||||
`@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.
|
||||
|
||||
<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.
|
||||
|
||||
|
||||
<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:
|
||||
|
||||
* The child component class and template
|
||||
* The parent component class and template
|
||||
|
||||
|
||||
### In the child
|
||||
|
||||
To use the `@Input()` decorator in a child component class, first import
|
||||
`Input` and then decorate the property with `@Input()`:
|
||||
|
||||
<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.
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
<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`:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/app.component.ts" region="parent-property" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
With `@Input()`, Angular passes the value for `currentItem` to the child so that `item` renders as `Television`.
|
||||
|
||||
The following diagram shows this structure:
|
||||
|
||||
<div class="lightbox">
|
||||
<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 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.
|
||||
|
||||
<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>
|
||||
|
||||
{@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).
|
||||
|
||||
|
||||
<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.
|
||||
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.
|
||||
|
||||
When you use `@Output()`, edit these parts of your app:
|
||||
|
||||
* The child component class and template
|
||||
* The parent component class and template
|
||||
|
||||
|
||||
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.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
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).
|
||||
|
||||
</div>
|
||||
|
||||
## In the child
|
||||
|
||||
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.
|
||||
|
||||
First, be sure to import `Output` and `EventEmitter`
|
||||
in the child component class:
|
||||
|
||||
```js
|
||||
import { Output, EventEmitter } from '@angular/core';
|
||||
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
|
||||
<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 different parts of the above declaration are as follows:
|
||||
|
||||
* `@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 `#newItem` variable.
|
||||
|
||||
<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 `(click)` event is bound to the `addNewItem()` method in the child component class which
|
||||
takes as its argument whatever the value of `#newItem` is.
|
||||
|
||||
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.
|
||||
|
||||
## 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.
|
||||
|
||||
<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.
|
||||
|
||||
### In 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`.
|
||||
|
||||
<code-example path="inputs-outputs/src/app/app.component.html" region="output-parent" header="src/app/app.component.html"></code-example>
|
||||
|
||||
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.
|
||||
|
||||
Now, in order to see the `@Output()` working, 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.
|
||||
|
||||
|
||||
## `@Input()` and `@Output()` together
|
||||
|
||||
You can use `@Input()` and `@Output()` on the same child component as in the following:
|
||||
|
||||
<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 following diagram is of an `@Input()` and an `@Output()` on the same
|
||||
child component and shows the different parts of each:
|
||||
|
||||
<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.
|
||||
|
||||
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>
|
175
aio/content/guide/interpolation.md
Normal file
175
aio/content/guide/interpolation.md
Normal file
@ -0,0 +1,175 @@
|
||||
# Interpolation and template expressions
|
||||
|
||||
Interpolation allows you to incorporate calculated strings into the text
|
||||
between HTML element tags and within attribute assignments. Template
|
||||
expressions are what you use to calculate those strings.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for all of
|
||||
the syntax and code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
## Interpolation `{{...}}`
|
||||
|
||||
Interpolation refers to embedding expressions into marked up text.
|
||||
By default, interpolation uses as its delimiter the double curly braces, `{{` and `}}`.
|
||||
|
||||
In the following snippet, `{{ currentCustomer }}` is an example of interpolation.
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="interpolation-example1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The text between the braces is often the name of a component
|
||||
property. Angular replaces that name with the
|
||||
string value of the corresponding component property.
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="component-property" header="src/app/app.component.html"></code-example>
|
||||
|
||||
In the example above, Angular evaluates the `title` and `itemImageUrl` properties
|
||||
and fills in the blanks, first displaying some title text and then an image.
|
||||
|
||||
More generally, the text between the braces is a **template expression**
|
||||
that Angular first **evaluates** and then **converts to a string**.
|
||||
The following interpolation illustrates the point by adding two numbers:
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="convert-string" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The expression can invoke methods of the host component such as `getVal()` in
|
||||
the following example:
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="invoke-method" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Angular evaluates all expressions in double curly braces,
|
||||
converts the expression results to strings, and links them with neighboring literal strings. Finally,
|
||||
it assigns this composite interpolated result to an **element or directive property**.
|
||||
|
||||
You appear to be inserting the result between element tags and assigning it to attributes.
|
||||
However, interpolation is a special syntax that Angular converts into a *property binding*.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
If you'd like to use something other than `{{` and `}}`, you can
|
||||
configure the interpolation delimiter via the
|
||||
[interpolation](api/core/Component#interpolation)
|
||||
option in the `Component` metadata.
|
||||
|
||||
</div>
|
||||
|
||||
## Template expressions
|
||||
|
||||
A template **expression** produces a value and appears within the double
|
||||
curly braces, `{{ }}`.
|
||||
Angular executes the expression and assigns it to a property of a binding target;
|
||||
the target could be an HTML element, a component, or a directive.
|
||||
|
||||
The interpolation braces in `{{1 + 1}}` surround the template expression `1 + 1`.
|
||||
In the property binding,
|
||||
a template expression appears in quotes to the right of the `=` symbol as in `[property]="expression"`.
|
||||
|
||||
In terms of syntax, template expressions are similar to JavaScript.
|
||||
Many JavaScript expressions are legal template expressions, with a few exceptions.
|
||||
|
||||
You can't use JavaScript expressions that have or promote side effects,
|
||||
including:
|
||||
|
||||
* Assignments (`=`, `+=`, `-=`, `...`)
|
||||
* Operators such as `new`, `typeof`, `instanceof`, etc.
|
||||
* Chaining expressions with <code>;</code> or <code>,</code>
|
||||
* The increment and decrement operators `++` and `--`
|
||||
* Some of the ES2015+ operators
|
||||
|
||||
Other notable differences from JavaScript syntax include:
|
||||
|
||||
* No support for the bitwise operators such as `|` and `&`
|
||||
* New [template expression operators](guide/template-expression-operators), such as `|`, `?.` and `!`
|
||||
|
||||
|
||||
## Expression context
|
||||
|
||||
The *expression context* is typically the _component_ instance.
|
||||
In the following snippets, the `recommended` within double curly braces and the
|
||||
`itemImageUrl2` in quotes refer to properties of the `AppComponent`.
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="component-context" header="src/app/app.component.html"></code-example>
|
||||
|
||||
An expression may also refer to properties of the _template's_ context
|
||||
such as a template input variable,
|
||||
<!-- link to built-in-directives#template-input-variables -->
|
||||
`let customer`, or a template reference variable, `#customerInput`.
|
||||
<!-- link to guide/template-ref-variables -->
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="template-input-variable" header="src/app/app.component.html (template input variable)"></code-example>
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="template-reference-variable" header="src/app/app.component.html (template reference variable)"></code-example>
|
||||
|
||||
The context for terms in an expression is a blend of the _template variables_,
|
||||
the directive's _context_ object (if it has one), and the component's _members_.
|
||||
If you reference a name that belongs to more than one of these namespaces,
|
||||
the template variable name takes precedence, followed by a name in the directive's _context_,
|
||||
and, lastly, the component's member names.
|
||||
|
||||
The previous example presents such a name collision. The component has a `customer`
|
||||
property and the `*ngFor` defines a `customer` template variable.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The `customer` in `{{customer.name}}`
|
||||
refers to the template input variable, not the component's property.
|
||||
|
||||
Template expressions cannot refer to anything in
|
||||
the global namespace, except `undefined`. They can't refer to
|
||||
`window` or `document`. Additionally, they
|
||||
can't call `console.log()` or `Math.max()` and they are restricted to referencing
|
||||
members of the expression context.
|
||||
|
||||
</div>
|
||||
|
||||
## Expression guidelines
|
||||
|
||||
When using template expressions follow these guidelines:
|
||||
|
||||
* [Simplicity](guide/interpolation#simplicity)
|
||||
* [Quick execution](guide/interpolation#quick-execution)
|
||||
* [No visible side effects](guide/interpolation#no-visible-side-effects)
|
||||
|
||||
### Simplicity
|
||||
|
||||
Although it's possible to write complex template expressions, it's a better
|
||||
practice to avoid them.
|
||||
|
||||
A property name or method call should be the norm, but an occasional Boolean negation, `!`, is OK.
|
||||
Otherwise, confine application and business logic to the component,
|
||||
where it is easier to develop and test.
|
||||
|
||||
### Quick execution
|
||||
|
||||
Angular executes template expressions after every change detection cycle.
|
||||
Change detection cycles are triggered by many asynchronous activities such as
|
||||
promise resolutions, HTTP results, timer events, key presses and mouse moves.
|
||||
|
||||
Expressions should finish quickly or the user experience may drag, especially on slower devices.
|
||||
Consider caching values when their computation is expensive.
|
||||
|
||||
### No visible side effects
|
||||
|
||||
A template expression should not change any application state other than the value of the
|
||||
target property.
|
||||
|
||||
This rule is essential to Angular's "unidirectional data flow" policy.
|
||||
You should never worry that reading a component value might change some other displayed value.
|
||||
The view should be stable throughout a single rendering pass.
|
||||
|
||||
An [idempotent](https://en.wikipedia.org/wiki/Idempotence) expression is ideal because
|
||||
it is free of side effects and improves Angular's change detection performance.
|
||||
In Angular terms, an idempotent expression always returns
|
||||
*exactly the same thing* until one of its dependent values changes.
|
||||
|
||||
Dependent values should not change during a single turn of the event loop.
|
||||
If an idempotent expression returns a string or a number, it returns the same string or number when called twice in a row. If the expression returns an object, including an `array`, it returns the same object *reference* when called twice in a row.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
There is one exception to this behavior that applies to `*ngFor`. `*ngFor` has `trackBy` functionality that can deal with referential inequality of objects when iterating over them. See [*ngFor with `trackBy`](guide/built-in-directives #ngfor-with-trackby) for details.
|
||||
|
||||
</div>
|
@ -311,7 +311,7 @@ ngOnInit() {
|
||||
}
|
||||
</code-example>
|
||||
|
||||
For more information with a working example, see the [routing tutorial section on preloading](guide/router#preloading-background-loading-of-feature-areas).
|
||||
For more information with a working example, see the [routing tutorial section on preloading](guide/router-tutorial-toh#preloading-background-loading-of-feature-areas).
|
||||
|
||||
|
||||
<hr>
|
||||
|
@ -2,13 +2,13 @@
|
||||
|
||||
Angular makes use of observables as an interface to handle a variety of common asynchronous operations. For example:
|
||||
|
||||
* You can define [custom events](guide/template-syntax#custom-events-with-eventemitter) that send observable output data from a child to a parent component.
|
||||
* You can define [custom events](guide/event-binding#custom-events-with-eventemitter) that send observable output data from a child to a parent component.
|
||||
* The HTTP module uses observables to handle AJAX requests and responses.
|
||||
* The Router and Forms modules use observables to listen for and respond to user-input events.
|
||||
|
||||
## Transmitting data between components
|
||||
|
||||
Angular provides an `EventEmitter` class that is used when publishing values from a component through the [`@Output()` decorator](guide/template-syntax#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#how-to-use-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.
|
||||
|
||||
|
@ -58,7 +58,7 @@ The tabs in the example show the following:
|
||||
</code-tabs>
|
||||
|
||||
The component's `birthday` value flows through the
|
||||
[pipe operator](guide/template-syntax#pipe) ( | ) to the [`date`](api/common/DatePipe)
|
||||
[pipe operator](guide/template-expression-operators#pipe) ( | ) to the [`date`](api/common/DatePipe)
|
||||
function.
|
||||
|
||||
{@a parameterizing-a-pipe}
|
||||
@ -374,7 +374,7 @@ As shown in the code below, only the pipe in the template changes.
|
||||
|
||||
[Observables](/guide/glossary#observable "Definition of observable") let you pass messages between parts of your application.
|
||||
Observables are recommended for event handling, asynchronous programming, and handling multiple values.
|
||||
Observables can deliver single or multiple values of any type, either synchronously (as a function delivers a value to its caller) or asynchronously on a schedule.
|
||||
Observables can deliver single or multiple values of any type, either synchronously (as a function delivers a value to its caller) or asynchronously on a schedule.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
228
aio/content/guide/property-binding.md
Normal file
228
aio/content/guide/property-binding.md
Normal file
@ -0,0 +1,228 @@
|
||||
|
||||
# Property binding `[property]`
|
||||
|
||||
Use property binding to _set_ properties of target elements or
|
||||
directive `@Input()` decorators.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
## One-way in
|
||||
|
||||
Property binding flows a value in one direction,
|
||||
from a component's property into a target element property.
|
||||
|
||||
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).
|
||||
|
||||
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).
|
||||
|
||||
## Examples
|
||||
|
||||
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:
|
||||
|
||||
<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>
|
||||
|
||||
For more details, see the [MDN HTMLTableCellElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement) documentation.
|
||||
|
||||
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`:
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="disabled-button" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Another is setting a property of a directive:
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="class-binding" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Yet another is setting the model property of a custom component—a great way
|
||||
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.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="property-binding" header="src/app/app.component.html"></code-example>
|
||||
|
||||
There's also the `bind-` prefix alternative:
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="bind-prefix" 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.
|
||||
So in this case, `src` is the name of the `<img>` element 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:
|
||||
|
||||
<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.
|
||||
|
||||
If the name fails to match a property of a known directive or element, Angular reports an “unknown directive” error.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
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`.
|
||||
|
||||
</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:
|
||||
|
||||
<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>
|
||||
|
||||
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
|
||||
|
||||
The previous simple example showed passing in a string. To pass in an object,
|
||||
the syntax and thinking are the same.
|
||||
|
||||
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.
|
||||
|
||||
<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:
|
||||
|
||||
<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.
|
||||
|
||||
<code-example language="bash">
|
||||
"Template <script>alert("evil never sleeps")</script> Syntax" is the interpolated evil title.
|
||||
"Template alert("evil never sleeps")Syntax" is the property bound evil title.
|
||||
</code-example>
|
@ -52,6 +52,14 @@ Any component created within a lazy loaded module’s context, such as by router
|
||||
|
||||
Though you can provide services by lazy loading modules, not all services can be lazy loaded. For instance, some modules only work in the root module, such as the Router. The Router works with the global location object in the browser.
|
||||
|
||||
As of Angular version 9, you can provide a new instance of a service with each lazy loaded module. The following code adds this functionality to `UserService`.
|
||||
|
||||
<code-example path="providers/src/app/user.service.2.ts" header="src/app/user.service.ts"></code-example>
|
||||
|
||||
With `providedIn: 'any'`, all eagerly loaded modules share a singleton instance; however, lazy loaded modules each get their own unique instance, as shown in the following diagram.
|
||||
|
||||
<img src="generated/images/guide/providers/any-provider.svg" alt="any-provider-scope" class="left">
|
||||
|
||||
|
||||
## Limiting provider scope with components
|
||||
|
||||
|
@ -111,7 +111,7 @@ Let's assume that we are routing from the *Home => About*.
|
||||
|
||||
The animation code does the following after styling the views:
|
||||
|
||||
* `query(':enter style({ left: '-100%'})` matches the view that is added and hides the newly added view by positioning it to the far left.
|
||||
* `query(':enter', style({ left: '-100%' }))` matches the view that is added and hides the newly added view by positioning it to the far left.
|
||||
* Calls `animateChild()` on the view that is leaving, to run its child animations.
|
||||
* Uses `group()` function to make the inner animations run in parallel.
|
||||
* Within the `group()` function:
|
||||
|
2893
aio/content/guide/router-tutorial-toh.md
Normal file
2893
aio/content/guide/router-tutorial-toh.md
Normal file
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,7 @@ This tutorial describes how you can build a single-page application, SPA that us
|
||||
|
||||
|
||||
In an SPA, all of your application's functions exist in a single HTML page.
|
||||
As users access your application's features, the browser needs to render only the parts that matter to the user, instead of loading a new page. This pattern can significantly improve your application's user exprience.
|
||||
As users access your application's features, the browser needs to render only the parts that matter to the user, instead of loading a new page. This pattern can significantly improve your application's user experience.
|
||||
|
||||
To define how users navigate through your application, you use routes. You can add routes to define how users navigate from one part of your application to another.
|
||||
You can also configure routes to guard against unexpected or unauthorized behavior.
|
||||
@ -105,7 +105,7 @@ In this section, you'll define two routes:
|
||||
* The route `/crisis-center` opens the `crisis-center` component.
|
||||
* The route `/heroes-list` opens the `heroes-list` component.
|
||||
|
||||
A route definition is a JavaScript object. Each route typically has two propteries. The first property, `path`, is a string
|
||||
A route definition is a JavaScript object. Each route typically has two properties. The first property, `path`, is a string
|
||||
that specifies the URL path for the route. The second property, `component`, is a string that specifies
|
||||
what component your application should display for that path.
|
||||
|
||||
@ -220,7 +220,7 @@ Now when you open your application, it displays the `heroes-list` component by d
|
||||
## Adding a 404 page
|
||||
|
||||
It is possible for a user to try to access a route that you have not defined. To account for
|
||||
this behavior, a best practice is to display a 404 page. In this section, you'll create a 404 page and
|
||||
this behavior, the best practice is to display a 404 page. In this section, you'll create a 404 page and
|
||||
update your route configuration to show that page for any unspecified routes.
|
||||
|
||||
1. From the terminal, create a new component, `PageNotFound`.
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -39,14 +39,14 @@ No brackets. No parentheses. Just `*ngIf` set to a string.
|
||||
|
||||
You'll learn in this guide that the [asterisk (*) is a convenience notation](guide/structural-directives#asterisk)
|
||||
and the string is a [_microsyntax_](guide/structural-directives#microsyntax) rather than the usual
|
||||
[template expression](guide/template-syntax#template-expressions).
|
||||
[template expression](guide/interpolation#template-expressions).
|
||||
Angular desugars this notation into a marked-up `<ng-template>` that surrounds the
|
||||
host element and its descendents.
|
||||
host element and its descendants.
|
||||
Each structural directive does something different with that template.
|
||||
|
||||
Three of the common, built-in structural directives—[NgIf](guide/template-syntax#ngIf),
|
||||
[NgFor](guide/template-syntax#ngFor), and [NgSwitch...](guide/template-syntax#ngSwitch)—are
|
||||
described in the [_Template Syntax_](guide/template-syntax) guide and seen in samples throughout the Angular documentation.
|
||||
Three of the common, built-in structural directives—[NgIf](guide/built-in-directives#ngIf),
|
||||
[NgFor](guide/built-in-directives#ngFor), and [NgSwitch...](guide/built-in-directives#ngSwitch)—are
|
||||
described in the [Built-in directives](guide/built-in-directives) guide and seen in samples throughout the Angular documentation.
|
||||
Here's an example of them in a template:
|
||||
|
||||
|
||||
@ -96,7 +96,7 @@ Technically it's a directive with a template.
|
||||
|
||||
An [*attribute* directive](guide/attribute-directives) changes the appearance or behavior
|
||||
of an element, component, or another directive.
|
||||
For example, the built-in [`NgStyle`](guide/template-syntax#ngStyle) directive
|
||||
For example, the built-in [`NgStyle`](guide/built-in-directives#ngStyle) directive
|
||||
changes several element styles at the same time.
|
||||
|
||||
You can apply many _attribute_ directives to one host element.
|
||||
@ -440,7 +440,7 @@ There are several such variables in this example: `hero`, `i`, and `odd`.
|
||||
All are preceded by the keyword `let`.
|
||||
|
||||
A _template input variable_ is **_not_** the same as a
|
||||
[template _reference_ variable](guide/template-syntax#ref-vars),
|
||||
[template _reference_ variable](guide/template-reference-variables),
|
||||
neither _semantically_ nor _syntactically_.
|
||||
|
||||
You declare a template _input_ variable using the `let` keyword (`let hero`).
|
||||
@ -786,7 +786,7 @@ That means the directive needs an `appUnless` property, decorated with `@Input`
|
||||
|
||||
|
||||
|
||||
Read about `@Input` in the [_Template Syntax_](guide/template-syntax#inputs-outputs) guide.
|
||||
Read about `@Input` in the [`@Input()` and `@Output()` properties](guide/inputs-outputs) guide.
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -3286,7 +3286,7 @@ helps instantly identify which members of the component serve which purpose.
|
||||
|
||||
|
||||
|
||||
**Why?** Angular allows for an [alternative syntax](guide/template-syntax#binding-syntax) `on-*`. If the event itself was prefixed with `on` this would result in an `on-onEvent` binding expression.
|
||||
**Why?** Angular allows for an [alternative syntax](guide/binding-syntax) `on-*`. If the event itself was prefixed with `on` this would result in an `on-onEvent` binding expression.
|
||||
|
||||
|
||||
</div>
|
||||
|
27
aio/content/guide/svg-in-templates.md
Normal file
27
aio/content/guide/svg-in-templates.md
Normal file
@ -0,0 +1,27 @@
|
||||
# SVG in templates
|
||||
|
||||
It is possible to use SVG as valid templates in Angular. All of the template syntax below is
|
||||
applicable to both SVG and HTML. Learn more in the SVG [1.1](https://www.w3.org/TR/SVG11/) and
|
||||
[2.0](https://www.w3.org/TR/SVG2/) specifications.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example name="template-syntax"></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
Why would you use SVG as template, instead of simply adding it as image to your application?
|
||||
|
||||
When you use an SVG as the template, you are able to use directives and bindings just like with HTML
|
||||
templates. This means that you will be able to dynamically generate interactive graphics.
|
||||
|
||||
Refer to the sample code snippet below for a syntax example:
|
||||
|
||||
<code-example path="template-syntax/src/app/svg.component.ts" header="src/app/svg.component.ts"></code-example>
|
||||
|
||||
Add the following code to your `svg.component.svg` file:
|
||||
|
||||
<code-example path="template-syntax/src/app/svg.component.svg" header="src/app/svg.component.svg"></code-example>
|
||||
|
||||
Here you can see the use of a `click()` event binding and the property binding syntax
|
||||
(`[attr.fill]="fillColor"`).
|
144
aio/content/guide/template-expression-operators.md
Normal file
144
aio/content/guide/template-expression-operators.md
Normal file
@ -0,0 +1,144 @@
|
||||
<!-- {@a expression-operators} -->
|
||||
|
||||
# Template expression operators
|
||||
|
||||
The Angular template expression language employs a subset of JavaScript syntax supplemented with a few special operators
|
||||
for specific scenarios. The next sections cover three of these operators:
|
||||
|
||||
* [pipe](guide/template-expression-operators#pipe)
|
||||
* [safe navigation operator](guide/template-expression-operators#safe-navigation-operator)
|
||||
* [non-null assertion operator](guide/template-expression-operators#non-null-assertion-operator)
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
{@a pipe}
|
||||
|
||||
## The pipe operator (`|`)
|
||||
|
||||
The result of an expression might require some transformation before you're ready to use it in a binding.
|
||||
For example, you might display a number as a currency, change text to uppercase, or filter a list and sort it.
|
||||
|
||||
Pipes are simple functions that accept an input value and return a transformed value.
|
||||
They're easy to apply within template expressions, using the pipe operator (`|`):
|
||||
|
||||
<code-example path="template-expression-operators/src/app/app.component.html" region="uppercase-pipe" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The pipe operator passes the result of an expression on the left to a pipe function on the right.
|
||||
|
||||
You can chain expressions through multiple pipes:
|
||||
|
||||
<code-example path="template-expression-operators/src/app/app.component.html" region="pipe-chain" header="src/app/app.component.html"></code-example>
|
||||
|
||||
And you can also [apply parameters](guide/pipes#parameterizing-a-pipe) to a pipe:
|
||||
|
||||
<code-example path="template-expression-operators/src/app/app.component.html" region="date-pipe" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The `json` pipe is particularly helpful for debugging bindings:
|
||||
|
||||
<code-example path="template-expression-operators/src/app/app.component.html" region="json-pipe" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The generated output would look something like this:
|
||||
|
||||
<code-example language="json">
|
||||
{ "name": "Telephone",
|
||||
"manufactureDate": "1980-02-25T05:00:00.000Z",
|
||||
"price": 98 }
|
||||
</code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The pipe operator has a higher precedence than the ternary operator (`?:`),
|
||||
which means `a ? b : c | x` is parsed as `a ? b : (c | x)`.
|
||||
Nevertheless, for a number of reasons,
|
||||
the pipe operator cannot be used without parentheses in the first and second operands of `?:`.
|
||||
A good practice is to use parentheses in the third operand too.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a safe-navigation-operator}
|
||||
|
||||
## The safe navigation operator ( `?` ) and null property paths
|
||||
|
||||
The Angular safe navigation operator, `?`, guards against `null` and `undefined`
|
||||
values in property paths. Here, it protects against a view render failure if `item` is `null`.
|
||||
|
||||
<code-example path="template-expression-operators/src/app/app.component.html" region="safe" header="src/app/app.component.html"></code-example>
|
||||
|
||||
If `item` is `null`, the view still renders but the displayed value is blank; you see only "The item name is:" with nothing after it.
|
||||
|
||||
Consider the next example, with a `nullItem`.
|
||||
|
||||
<code-example language="html">
|
||||
The null item name is {{nullItem.name}}
|
||||
</code-example>
|
||||
|
||||
Since there is no safe navigation operator and `nullItem` is `null`, JavaScript and Angular would throw a `null` reference error and break the rendering process of Angular:
|
||||
|
||||
<code-example language="bash">
|
||||
TypeError: Cannot read property 'name' of null.
|
||||
</code-example>
|
||||
|
||||
Sometimes however, `null` values in the property
|
||||
path may be OK under certain circumstances,
|
||||
especially when the value starts out null but the data arrives eventually.
|
||||
|
||||
With the safe navigation operator, `?`, Angular stops evaluating the expression when it hits the first `null` value and renders the view without errors.
|
||||
|
||||
It works perfectly with long property paths such as `a?.b?.c?.d`.
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a non-null-assertion-operator}
|
||||
|
||||
## The non-null assertion operator ( `!` )
|
||||
|
||||
As of Typescript 2.0, you can enforce [strict null checking](http://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html "Strict null checking in TypeScript") with the `--strictNullChecks` flag. TypeScript then ensures that no variable is unintentionally `null` or `undefined`.
|
||||
|
||||
In this mode, typed variables disallow `null` and `undefined` by default. The type checker throws an error if you leave a variable unassigned or try to assign `null` or `undefined` to a variable whose type disallows `null` and `undefined`.
|
||||
|
||||
The type checker also throws an error if it can't determine whether a variable will be `null` or `undefined` at runtime. You tell the type checker not to throw an error by applying the postfix
|
||||
[non-null assertion operator, !](http://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator "Non-null assertion operator").
|
||||
|
||||
The Angular non-null assertion operator, `!`, serves the same purpose in
|
||||
an Angular template. For example, you can assert that `item` properties are also defined.
|
||||
|
||||
<code-example path="template-expression-operators/src/app/app.component.html" region="non-null" header="src/app/app.component.html"></code-example>
|
||||
|
||||
When the Angular compiler turns your template into TypeScript code,
|
||||
it prevents TypeScript from reporting that `item.color` might be `null` or `undefined`.
|
||||
|
||||
Unlike the [_safe navigation operator_](guide/template-expression-operators#safe-navigation-operator "Safe navigation operator (?)"),
|
||||
the non-null assertion operator does not guard against `null` or `undefined`.
|
||||
Rather, it tells the TypeScript type checker to suspend strict `null` checks for a specific property expression.
|
||||
|
||||
The non-null assertion operator, `!`, is optional with the exception that you must use it when you turn on strict null checks.
|
||||
|
||||
{@a any-type-cast-function}
|
||||
|
||||
## The `$any()` type cast function
|
||||
|
||||
Sometimes a binding expression triggers a type error during [AOT compilation](guide/aot-compiler) and it is not possible or difficult to fully specify the type.
|
||||
To silence the error, you can use the `$any()` cast function to cast
|
||||
the expression to the [`any` type](http://www.typescriptlang.org/docs/handbook/basic-types.html#any) as in the following example:
|
||||
|
||||
<code-example path="built-in-template-functions/src/app/app.component.html" region="any-type-cast-function-1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
When the Angular compiler turns this template into TypeScript code,
|
||||
it prevents TypeScript from reporting that `bestByDate` is not a member of the `item`
|
||||
object when it runs type checking on the template.
|
||||
|
||||
The `$any()` cast function also works with `this` to allow access to undeclared members of
|
||||
the component.
|
||||
|
||||
<code-example path="built-in-template-functions/src/app/app.component.html" region="any-type-cast-function-2" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The `$any()` cast function works anywhere in a binding expression where a method call is valid.
|
||||
|
62
aio/content/guide/template-reference-variables.md
Normal file
62
aio/content/guide/template-reference-variables.md
Normal file
@ -0,0 +1,62 @@
|
||||
# Template reference variables (`#var`)
|
||||
|
||||
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>.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
Use the hash symbol (#) to declare a reference variable.
|
||||
The following reference 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.
|
||||
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>
|
||||
|
||||
<h3 class="no-toc">How a reference variable gets its value</h3>
|
||||
|
||||
In most cases, Angular sets the reference variable's value to the element on which it is declared.
|
||||
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.
|
||||
|
||||
<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).
|
||||
|
||||
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
<h3 class="no-toc">Template reference variable considerations</h3>
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
### Alternative syntax
|
||||
|
||||
You can use the `ref-` prefix alternative to `#`.
|
||||
This example declares the `fax` variable as `ref-fax` instead of `#fax`.
|
||||
|
||||
|
||||
<code-example path="template-reference-variables/src/app/app.component.html" region="ref-fax" header="src/app/app.component.html"></code-example>
|
||||
|
65
aio/content/guide/template-statements.md
Normal file
65
aio/content/guide/template-statements.md
Normal file
@ -0,0 +1,65 @@
|
||||
# Template statements
|
||||
|
||||
A template **statement** responds to an **event** raised by a binding target
|
||||
such as an element, component, or directive.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example name="template-syntax">Template syntax</live-example> for
|
||||
the syntax and code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
The following template statement appears in quotes to the right of the `=` symbol as in `(event)="statement"`.
|
||||
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="context-component-statement" header="src/app/app.component.html"></code-example>
|
||||
|
||||
A template statement *has a side effect*.
|
||||
That's the whole point of an event.
|
||||
It's how you update application state from user action.
|
||||
|
||||
Responding to events is the other side of Angular's "unidirectional data flow".
|
||||
You're free to change anything, anywhere, during this turn of the event loop.
|
||||
|
||||
Like template expressions, template *statements* use a language that looks like JavaScript.
|
||||
The template statement parser differs from the template expression parser and
|
||||
specifically supports both basic assignment (`=`) and chaining expressions with <code>;</code>.
|
||||
|
||||
However, certain JavaScript and template expression syntax is not allowed:
|
||||
|
||||
* <code>new</code>
|
||||
* increment and decrement operators, `++` and `--`
|
||||
* operator assignment, such as `+=` and `-=`
|
||||
* the bitwise operators, such as `|` and `&`
|
||||
* the [pipe operator](guide/template-expression-operators#pipe)
|
||||
|
||||
## Statement context
|
||||
|
||||
As with expressions, statements can refer only to what's in the statement context
|
||||
such as an event handling method of the component instance.
|
||||
|
||||
The *statement context* is typically the component instance.
|
||||
The *deleteHero* in `(click)="deleteHero()"` is a method of the data-bound component.
|
||||
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="context-component-statement" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The statement context may also refer to properties of the template's own context.
|
||||
In the following examples, the template `$event` object,
|
||||
a [template input variable](guide/built-in-directives#template-input-variable) (`let hero`),
|
||||
and a [template reference variable](guide/template-reference-variables) (`#heroForm`)
|
||||
are passed to an event handling method of the component.
|
||||
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="context-var-statement" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Template context names take precedence over component context names.
|
||||
In `deleteHero(hero)` above, the `hero` is the template input variable,
|
||||
not the component's `hero` property.
|
||||
|
||||
## Statement guidelines
|
||||
|
||||
Template statements cannot refer to anything in the global namespace. They
|
||||
can't refer to `window` or `document`.
|
||||
They can't call `console.log` or `Math.max`.
|
||||
|
||||
As with expressions, avoid writing complex template statements.
|
||||
A method call or simple property assignment should be the norm.
|
File diff suppressed because it is too large
Load Diff
@ -106,8 +106,8 @@ There can also be false positives when the typings of an Angular library are eit
|
||||
|
||||
In case of a false positive like these, there are a few options:
|
||||
|
||||
* Use the [`$any()` type-cast function](guide/template-syntax#any-type-cast-function) in certain contexts to opt out of type-checking for a part of the expression.
|
||||
* You can disable strict checks entirely by setting `strictTemplates: false` in the application's TypeScript configuration file.
|
||||
* Use the [`$any()` type-cast function](guide/template-expression-operators#any-type-cast-function) in certain contexts to opt out of type-checking for a part of the expression.
|
||||
* You can disable strict checks entirely by setting `strictTemplates: false` in the application's TypeScript configuration file, `tsconfig.json`.
|
||||
* You can disable certain type-checking operations individually, while maintaining strictness in other aspects, by setting a _strictness flag_ to `false`.
|
||||
* If you want to use `strictTemplates` and `strictNullChecks` together, you can opt out of strict null type checking specifically for input bindings via `strictNullInputTypes`.
|
||||
|
||||
@ -286,7 +286,7 @@ Care should be taken that if an `ngAcceptInputType_` override is present for a g
|
||||
|
||||
## Disabling type checking using `$any()`
|
||||
|
||||
Disable checking of a binding expression by surrounding the expression in a call to the [`$any()` cast pseudo-function](guide/template-syntax).
|
||||
Disable checking of a binding expression by surrounding the expression in a call to the [`$any()` cast pseudo-function](guide/template-expression-operators).
|
||||
The compiler treats it as a cast to the `any` type just like in TypeScript when a `<any>` or `as any` cast is used.
|
||||
|
||||
In the following example, casting `person` to the `any` type suppresses the error `Property address does not exist`.
|
||||
|
28
aio/content/guide/test-debugging.md
Normal file
28
aio/content/guide/test-debugging.md
Normal file
@ -0,0 +1,28 @@
|
||||
# Debugging tests
|
||||
|
||||
If your tests aren't working as you expect them to, you can inspect and debug them in the browser.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For the sample app that the testing guides describe, see the <live-example name="testing" embedded-style noDownload>sample app</live-example>.
|
||||
|
||||
For the tests features in the testing guides, see <live-example name="testing" stackblitz="specs" noDownload>tests</live-example>.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
Debug specs in the browser in the same way that you debug an application.
|
||||
|
||||
1. Reveal the Karma browser window. See [Set up testing](guide/testing#set-up-testing) if you need help with this step.
|
||||
1. Click the **DEBUG** button; it opens a new browser tab and re-runs the tests.
|
||||
1. Open the browser's “Developer Tools” (`Ctrl-Shift-I` on Windows; `Command-Option-I` in macOS).
|
||||
1. Pick the "sources" section.
|
||||
1. Open the `1st.spec.ts` test file (Control/Command-P, then start typing the name of the file).
|
||||
1. Set a breakpoint in the test.
|
||||
1. Refresh the browser, and it stops at the breakpoint.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src='generated/images/guide/testing/karma-1st-spec-debug.png' alt="Karma debugging">
|
||||
</div>
|
||||
|
||||
<hr>
|
78
aio/content/guide/testing-attribute-directives.md
Normal file
78
aio/content/guide/testing-attribute-directives.md
Normal file
@ -0,0 +1,78 @@
|
||||
|
||||
{@a attribute-directive}
|
||||
|
||||
# Testing Attribute Directives
|
||||
|
||||
An _attribute directive_ modifies the behavior of an element, component or another directive.
|
||||
Its name reflects the way the directive is applied: as an attribute on a host element.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For the sample app that the testing guides describe, see the <live-example name="testing" embedded-style noDownload>sample app</live-example>.
|
||||
|
||||
For the tests features in the testing guides, see <live-example name="testing" stackblitz="specs" noDownload>tests</live-example>.
|
||||
|
||||
</div>
|
||||
|
||||
## Testing the `HighlightDirective`
|
||||
|
||||
The sample application's `HighlightDirective` sets the background color of an element
|
||||
based on either a data bound color or a default color (lightgray).
|
||||
It also sets a custom property of the element (`customProperty`) to `true`
|
||||
for no reason other than to show that it can.
|
||||
|
||||
<code-example path="testing/src/app/shared/highlight.directive.ts" header="app/shared/highlight.directive.ts"></code-example>
|
||||
|
||||
It's used throughout the application, perhaps most simply in the `AboutComponent`:
|
||||
|
||||
<code-example path="testing/src/app/about/about.component.ts" header="app/about/about.component.ts"></code-example>
|
||||
|
||||
Testing the specific use of the `HighlightDirective` within the `AboutComponent` requires only the techniques explored in the ["Nested component tests"](guide/testing-components-scenarios#nested-component-tests) section of [Component testing scenarios](guide/testing-components-scenarios).
|
||||
|
||||
<code-example path="testing/src/app/about/about.component.spec.ts" region="tests" header="app/about/about.component.spec.ts"></code-example>
|
||||
|
||||
However, testing a single use case is unlikely to explore the full range of a directive's capabilities.
|
||||
Finding and testing all components that use the directive is tedious, brittle, and almost as unlikely to afford full coverage.
|
||||
|
||||
_Class-only tests_ might be helpful,
|
||||
but attribute directives like this one tend to manipulate the DOM.
|
||||
Isolated unit tests don't touch the DOM and, therefore,
|
||||
do not inspire confidence in the directive's efficacy.
|
||||
|
||||
A better solution is to create an artificial test component that demonstrates all ways to apply the directive.
|
||||
|
||||
<code-example path="testing/src/app/shared/highlight.directive.spec.ts" region="test-component" header="app/shared/highlight.directive.spec.ts (TestComponent)"></code-example>
|
||||
|
||||
<div class="lightbox">
|
||||
<img src='generated/images/guide/testing/highlight-directive-spec.png' alt="HighlightDirective spec in action">
|
||||
</div>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The `<input>` case binds the `HighlightDirective` to the name of a color value in the input box.
|
||||
The initial value is the word "cyan" which should be the background color of the input box.
|
||||
|
||||
</div>
|
||||
|
||||
Here are some tests of this component:
|
||||
|
||||
<code-example path="testing/src/app/shared/highlight.directive.spec.ts" region="selected-tests" header="app/shared/highlight.directive.spec.ts (selected tests)"></code-example>
|
||||
|
||||
A few techniques are noteworthy:
|
||||
|
||||
- The `By.directive` predicate is a great way to get the elements that have this directive _when their element types are unknown_.
|
||||
|
||||
- The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:not">`:not` pseudo-class</a>
|
||||
in `By.css('h2:not([highlight])')` helps find `<h2>` elements that _do not_ have the directive.
|
||||
`By.css('*:not([highlight])')` finds _any_ element that does not have the directive.
|
||||
|
||||
- `DebugElement.styles` affords access to element styles even in the absence of a real browser, thanks to the `DebugElement` abstraction.
|
||||
But feel free to exploit the `nativeElement` when that seems easier or more clear than the abstraction.
|
||||
|
||||
- Angular adds a directive to the injector of the element to which it is applied.
|
||||
The test for the default color uses the injector of the second `<h2>` to get its `HighlightDirective` instance
|
||||
and its `defaultColor`.
|
||||
|
||||
- `DebugElement.properties` affords access to the artificial custom property that is set by the directive.
|
||||
|
||||
<hr>
|
57
aio/content/guide/testing-code-coverage.md
Normal file
57
aio/content/guide/testing-code-coverage.md
Normal file
@ -0,0 +1,57 @@
|
||||
{@a code-coverage}
|
||||
|
||||
# Find out how much code you're testing
|
||||
|
||||
The CLI can run unit tests and create code coverage reports.
|
||||
Code coverage reports show you any parts of your code base that may not be properly tested by your unit tests.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For the sample app that the testing guides describe, see the <live-example name="testing" embedded-style noDownload>sample app</live-example>.
|
||||
|
||||
For the tests features in the testing guides, see <live-example name="testing" stackblitz="specs" noDownload>tests</live-example>.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
To generate a coverage report run the following command in the root of your project.
|
||||
|
||||
<code-example language="sh" class="code-shell">
|
||||
ng test --no-watch --code-coverage
|
||||
</code-example>
|
||||
|
||||
When the tests are complete, the command creates a new `/coverage` folder in the project. Open the `index.html` file to see a report with your source code and code coverage values.
|
||||
|
||||
If you want to create code-coverage reports every time you test, you can set the following option in the CLI configuration file, `angular.json`:
|
||||
|
||||
```
|
||||
"test": {
|
||||
"options": {
|
||||
"codeCoverage": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Code coverage enforcement
|
||||
|
||||
The code coverage percentages let you estimate how much of your code is tested.
|
||||
If your team decides on a set minimum amount to be unit tested, you can enforce this minimum with the Angular CLI.
|
||||
|
||||
For example, suppose you want the code base to have a minimum of 80% code coverage.
|
||||
To enable this, open the [Karma](https://karma-runner.github.io) test platform configuration file, `karma.conf.js`, and add the following in the `coverageIstanbulReporter:` key.
|
||||
|
||||
```
|
||||
coverageIstanbulReporter: {
|
||||
reports: [ 'html', 'lcovonly' ],
|
||||
fixWebpackSourcePaths: true,
|
||||
thresholds: {
|
||||
statements: 80,
|
||||
lines: 80,
|
||||
branches: 80,
|
||||
functions: 80
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `thresholds` property causes the tool to enforce a minimum of 80% code coverage when the unit tests are run in the project.
|
||||
|
380
aio/content/guide/testing-components-basics.md
Normal file
380
aio/content/guide/testing-components-basics.md
Normal file
@ -0,0 +1,380 @@
|
||||
# Basics of testing components
|
||||
|
||||
A component, unlike all other parts of an Angular application,
|
||||
combines an HTML template and a TypeScript class.
|
||||
The component truly is the template and the class _working together_. To adequately test a component, you should test that they work together
|
||||
as intended.
|
||||
|
||||
Such tests require creating the component's host element in the browser DOM,
|
||||
as Angular does, and investigating the component class's interaction with
|
||||
the DOM as described by its template.
|
||||
|
||||
The Angular `TestBed` facilitates this kind of testing as you'll see in the sections below.
|
||||
But in many cases, _testing the component class alone_, without DOM involvement,
|
||||
can validate much of the component's behavior in an easier, more obvious way.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For the sample app that the testing guides describe, see the <live-example name="testing" embedded-style noDownload>sample app</live-example>.
|
||||
|
||||
For the tests features in the testing guides, see <live-example name="testing" stackblitz="specs" noDownload>tests</live-example>.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
{@a component-class-testing}
|
||||
|
||||
## Component class testing
|
||||
|
||||
Test a component class on its own as you would test a service class.
|
||||
|
||||
Component class testing should be kept very clean and simple.
|
||||
It should test only a single unit.
|
||||
At first glance, you should be able to understand
|
||||
what the test is testing.
|
||||
|
||||
Consider this `LightswitchComponent` which toggles a light on and off
|
||||
(represented by an on-screen message) when the user clicks the button.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/demo/demo.ts"
|
||||
region="LightswitchComp"
|
||||
header="app/demo/demo.ts (LightswitchComp)"></code-example>
|
||||
|
||||
You might decide only to test that the `clicked()` method
|
||||
toggles the light's _on/off_ state and sets the message appropriately.
|
||||
|
||||
This component class has no dependencies. To test these types of classes, follow the same steps as you would for a service that has no dependencies:
|
||||
|
||||
1. Create a component using the new keyword.
|
||||
2. Poke at its API.
|
||||
3. Assert expectations on its public state.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/demo/demo.spec.ts"
|
||||
region="Lightswitch"
|
||||
header="app/demo/demo.spec.ts (Lightswitch tests)"></code-example>
|
||||
|
||||
Here is the `DashboardHeroComponent` from the _Tour of Heroes_ tutorial.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/dashboard/dashboard-hero.component.ts"
|
||||
region="class"
|
||||
header="app/dashboard/dashboard-hero.component.ts (component)"></code-example>
|
||||
|
||||
It appears within the template of a parent component,
|
||||
which binds a _hero_ to the `@Input` property and
|
||||
listens for an event raised through the _selected_ `@Output` property.
|
||||
|
||||
You can test that the class code works without creating the `DashboardHeroComponent`
|
||||
or its parent component.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/dashboard/dashboard-hero.component.spec.ts"
|
||||
region="class-only"
|
||||
header="app/dashboard/dashboard-hero.component.spec.ts (class tests)"></code-example>
|
||||
|
||||
When a component has dependencies, you may wish to use the `TestBed` to both
|
||||
create the component and its dependencies.
|
||||
|
||||
The following `WelcomeComponent` depends on the `UserService` to know the name of the user to greet.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/welcome/welcome.component.ts"
|
||||
region="class"
|
||||
header="app/welcome/welcome.component.ts"></code-example>
|
||||
|
||||
You might start by creating a mock of the `UserService` that meets the minimum needs of this component.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/welcome/welcome.component.spec.ts"
|
||||
region="mock-user-service"
|
||||
header="app/welcome/welcome.component.spec.ts (MockUserService)"></code-example>
|
||||
|
||||
Then provide and inject _both the_ **component** _and the service_ in the `TestBed` configuration.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/welcome/welcome.component.spec.ts"
|
||||
region="class-only-before-each"
|
||||
header="app/welcome/welcome.component.spec.ts (class-only setup)"></code-example>
|
||||
|
||||
Then exercise the component class, remembering to call the [lifecycle hook methods](guide/lifecycle-hooks) as Angular does when running the app.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/welcome/welcome.component.spec.ts"
|
||||
region="class-only-tests"
|
||||
header="app/welcome/welcome.component.spec.ts (class-only tests)"></code-example>
|
||||
|
||||
## Component DOM testing
|
||||
|
||||
Testing the component _class_ is as easy as [testing a service](guide/testing-services).
|
||||
|
||||
But a component is more than just its class.
|
||||
A component interacts with the DOM and with other components.
|
||||
The _class-only_ tests can tell you about class behavior.
|
||||
They cannot tell you if the component is going to render properly,
|
||||
respond to user input and gestures, or integrate with its parent and child components.
|
||||
|
||||
None of the _class-only_ tests above can answer key questions about how the
|
||||
components actually behave on screen.
|
||||
|
||||
- Is `Lightswitch.clicked()` bound to anything such that the user can invoke it?
|
||||
- Is the `Lightswitch.message` displayed?
|
||||
- Can the user actually select the hero displayed by `DashboardHeroComponent`?
|
||||
- Is the hero name displayed as expected (i.e, in uppercase)?
|
||||
- Is the welcome message displayed by the template of `WelcomeComponent`?
|
||||
|
||||
These may not be troubling questions for the simple components illustrated above.
|
||||
But many components have complex interactions with the DOM elements
|
||||
described in their templates, causing HTML to appear and disappear as
|
||||
the component state changes.
|
||||
|
||||
To answer these kinds of questions, you have to create the DOM elements associated
|
||||
with the components, you must examine the DOM to confirm that component state
|
||||
displays properly at the appropriate times, and you must simulate user interaction
|
||||
with the screen to determine whether those interactions cause the component to
|
||||
behave as expected.
|
||||
|
||||
To write these kinds of test, you'll use additional features of the `TestBed`
|
||||
as well as other testing helpers.
|
||||
|
||||
### CLI-generated tests
|
||||
|
||||
The CLI creates an initial test file for you by default when you ask it to
|
||||
generate a new component.
|
||||
|
||||
For example, the following CLI command generates a `BannerComponent` in the `app/banner` folder (with inline template and styles):
|
||||
|
||||
<code-example language="sh" class="code-shell">
|
||||
ng generate component banner --inline-template --inline-style --module app
|
||||
</code-example>
|
||||
|
||||
It also generates an initial test file for the component, `banner-external.component.spec.ts`, that looks like this:
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/banner/banner-initial.component.spec.ts"
|
||||
region="v1"
|
||||
header="app/banner/banner-external.component.spec.ts (initial)"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Because `compileComponents` is asynchronous, it uses
|
||||
the [`async`](api/core/testing/async) utility
|
||||
function imported from `@angular/core/testing`.
|
||||
|
||||
Please refer to the [async](guide/testing-components-scenarios#async) section for more details.
|
||||
|
||||
</div>
|
||||
|
||||
### Reduce the setup
|
||||
|
||||
Only the last three lines of this file actually test the component
|
||||
and all they do is assert that Angular can create the component.
|
||||
|
||||
The rest of the file is boilerplate setup code anticipating more advanced tests that _might_ become necessary if the component evolves into something substantial.
|
||||
|
||||
You'll learn about these advanced test features below.
|
||||
For now, you can radically reduce this test file to a more manageable size:
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/banner/banner-initial.component.spec.ts"
|
||||
region="v2"
|
||||
header="app/banner/banner-initial.component.spec.ts (minimal)"></code-example>
|
||||
|
||||
In this example, the metadata object passed to `TestBed.configureTestingModule`
|
||||
simply declares `BannerComponent`, the component to test.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/banner/banner-initial.component.spec.ts"
|
||||
region="configureTestingModule">
|
||||
</code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
There's no need to declare or import anything else.
|
||||
The default test module is pre-configured with
|
||||
something like the `BrowserModule` from `@angular/platform-browser`.
|
||||
|
||||
Later you'll call `TestBed.configureTestingModule()` with
|
||||
imports, providers, and more declarations to suit your testing needs.
|
||||
Optional `override` methods can further fine-tune aspects of the configuration.
|
||||
|
||||
</div>
|
||||
|
||||
{@a create-component}
|
||||
|
||||
### _createComponent()_
|
||||
|
||||
After configuring `TestBed`, you call its `createComponent()` method.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/banner/banner-initial.component.spec.ts"
|
||||
region="createComponent">
|
||||
</code-example>
|
||||
|
||||
`TestBed.createComponent()` creates an instance of the `BannerComponent`,
|
||||
adds a corresponding element to the test-runner DOM,
|
||||
and returns a [`ComponentFixture`](#component-fixture).
|
||||
|
||||
<div class="alert is-important">
|
||||
|
||||
Do not re-configure `TestBed` after calling `createComponent`.
|
||||
|
||||
The `createComponent` method freezes the current `TestBed` definition,
|
||||
closing it to further configuration.
|
||||
|
||||
You cannot call any more `TestBed` configuration methods, not `configureTestingModule()`,
|
||||
nor `get()`, nor any of the `override...` methods.
|
||||
If you try, `TestBed` throws an error.
|
||||
|
||||
</div>
|
||||
|
||||
{@a component-fixture}
|
||||
|
||||
### _ComponentFixture_
|
||||
|
||||
The [ComponentFixture](api/core/testing/ComponentFixture) is a test harness for interacting with the created component and its corresponding element.
|
||||
|
||||
Access the component instance through the fixture and confirm it exists with a Jasmine expectation:
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/banner/banner-initial.component.spec.ts"
|
||||
region="componentInstance">
|
||||
</code-example>
|
||||
|
||||
### _beforeEach()_
|
||||
|
||||
You will add more tests as this component evolves.
|
||||
Rather than duplicate the `TestBed` configuration for each test,
|
||||
you refactor to pull the setup into a Jasmine `beforeEach()` and some supporting variables:
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/banner/banner-initial.component.spec.ts"
|
||||
region="v3"
|
||||
></code-example>
|
||||
|
||||
Now add a test that gets the component's element from `fixture.nativeElement` and
|
||||
looks for the expected text.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/banner/banner-initial.component.spec.ts"
|
||||
region="v4-test-2">
|
||||
</code-example>
|
||||
|
||||
{@a native-element}
|
||||
|
||||
### _nativeElement_
|
||||
|
||||
The value of `ComponentFixture.nativeElement` has the `any` type.
|
||||
Later you'll encounter the `DebugElement.nativeElement` and it too has the `any` type.
|
||||
|
||||
Angular can't know at compile time what kind of HTML element the `nativeElement` is or
|
||||
if it even is an HTML element.
|
||||
The app might be running on a _non-browser platform_, such as the server or a
|
||||
[Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API),
|
||||
where the element may have a diminished API or not exist at all.
|
||||
|
||||
The tests in this guide are designed to run in a browser so a
|
||||
`nativeElement` value will always be an `HTMLElement` or
|
||||
one of its derived classes.
|
||||
|
||||
Knowing that it is an `HTMLElement` of some sort, you can use
|
||||
the standard HTML `querySelector` to dive deeper into the element tree.
|
||||
|
||||
Here's another test that calls `HTMLElement.querySelector` to get the paragraph element and look for the banner text:
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/banner/banner-initial.component.spec.ts"
|
||||
region="v4-test-3">
|
||||
</code-example>
|
||||
|
||||
{@a debug-element}
|
||||
|
||||
### _DebugElement_
|
||||
|
||||
The Angular _fixture_ provides the component's element directly through the `fixture.nativeElement`.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/banner/banner-initial.component.spec.ts"
|
||||
region="nativeElement">
|
||||
</code-example>
|
||||
|
||||
This is actually a convenience method, implemented as `fixture.debugElement.nativeElement`.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/banner/banner-initial.component.spec.ts"
|
||||
region="debugElement-nativeElement">
|
||||
</code-example>
|
||||
|
||||
There's a good reason for this circuitous path to the element.
|
||||
|
||||
The properties of the `nativeElement` depend upon the runtime environment.
|
||||
You could be running these tests on a _non-browser_ platform that doesn't have a DOM or
|
||||
whose DOM-emulation doesn't support the full `HTMLElement` API.
|
||||
|
||||
Angular relies on the `DebugElement` abstraction to work safely across _all supported platforms_.
|
||||
Instead of creating an HTML element tree, Angular creates a `DebugElement` tree that wraps the _native elements_ for the runtime platform.
|
||||
The `nativeElement` property unwraps the `DebugElement` and returns the platform-specific element object.
|
||||
|
||||
Because the sample tests for this guide are designed to run only in a browser,
|
||||
a `nativeElement` in these tests is always an `HTMLElement`
|
||||
whose familiar methods and properties you can explore within a test.
|
||||
|
||||
Here's the previous test, re-implemented with `fixture.debugElement.nativeElement`:
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/banner/banner-initial.component.spec.ts"
|
||||
region="v4-test-4">
|
||||
</code-example>
|
||||
|
||||
The `DebugElement` has other methods and properties that
|
||||
are useful in tests, as you'll see elsewhere in this guide.
|
||||
|
||||
You import the `DebugElement` symbol from the Angular core library.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/banner/banner-initial.component.spec.ts"
|
||||
region="import-debug-element">
|
||||
</code-example>
|
||||
|
||||
{@a by-css}
|
||||
### _By.css()_
|
||||
|
||||
Although the tests in this guide all run in the browser,
|
||||
some apps might run on a different platform at least some of the time.
|
||||
|
||||
For example, the component might render first on the server as part of a strategy to make the application launch faster on poorly connected devices. The server-side renderer might not support the full HTML element API.
|
||||
If it doesn't support `querySelector`, the previous test could fail.
|
||||
|
||||
The `DebugElement` offers query methods that work for all supported platforms.
|
||||
These query methods take a _predicate_ function that returns `true` when a node in the `DebugElement` tree matches the selection criteria.
|
||||
|
||||
You create a _predicate_ with the help of a `By` class imported from a
|
||||
library for the runtime platform. Here's the `By` import for the browser platform:
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/banner/banner-initial.component.spec.ts"
|
||||
region="import-by">
|
||||
</code-example>
|
||||
|
||||
The following example re-implements the previous test with
|
||||
`DebugElement.query()` and the browser's `By.css` method.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/banner/banner-initial.component.spec.ts"
|
||||
region="v4-test-5">
|
||||
</code-example>
|
||||
|
||||
Some noteworthy observations:
|
||||
|
||||
- The `By.css()` static method selects `DebugElement` nodes
|
||||
with a [standard CSS selector](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_started/Selectors 'CSS selectors').
|
||||
- The query returns a `DebugElement` for the paragraph.
|
||||
- You must unwrap that result to get the paragraph element.
|
||||
|
||||
When you're filtering by CSS selector and only testing properties of a browser's _native element_, the `By.css` approach may be overkill.
|
||||
|
||||
It's often easier and more clear to filter with a standard `HTMLElement` method
|
||||
such as `querySelector()` or `querySelectorAll()`,
|
||||
as you'll see in the next set of tests.
|
||||
|
1826
aio/content/guide/testing-components-scenarios.md
Normal file
1826
aio/content/guide/testing-components-scenarios.md
Normal file
File diff suppressed because it is too large
Load Diff
41
aio/content/guide/testing-pipes.md
Normal file
41
aio/content/guide/testing-pipes.md
Normal file
@ -0,0 +1,41 @@
|
||||
# Testing Pipes
|
||||
|
||||
You can test [pipes](guide/pipes) without the Angular testing utilities.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For the sample app that the testing guides describe, see the <live-example name="testing" embedded-style noDownload>sample app</live-example>.
|
||||
|
||||
For the tests features in the testing guides, see <live-example name="testing" stackblitz="specs" noDownload>tests</live-example>.
|
||||
|
||||
</div>
|
||||
|
||||
## Testing the `TitleCasePipe`
|
||||
|
||||
A pipe class has one method, `transform`, that manipulates the input
|
||||
value into a transformed output value.
|
||||
The `transform` implementation rarely interacts with the DOM.
|
||||
Most pipes have no dependence on Angular other than the `@Pipe`
|
||||
metadata and an interface.
|
||||
|
||||
Consider a `TitleCasePipe` that capitalizes the first letter of each word.
|
||||
Here's an implementation with a regular expression.
|
||||
|
||||
<code-example path="testing/src/app/shared/title-case.pipe.ts" header="app/shared/title-case.pipe.ts"></code-example>
|
||||
|
||||
Anything that uses a regular expression is worth testing thoroughly.
|
||||
Use simple Jasmine to explore the expected cases and the edge cases.
|
||||
|
||||
<code-example path="testing/src/app/shared/title-case.pipe.spec.ts" region="excerpt" header="app/shared/title-case.pipe.spec.ts"></code-example>
|
||||
|
||||
{@a write-tests}
|
||||
|
||||
## Writing DOM tests to support a pipe test
|
||||
|
||||
These are tests of the pipe _in isolation_.
|
||||
They can't tell if the `TitleCasePipe` is working properly as applied in the application components.
|
||||
|
||||
Consider adding component tests such as this one:
|
||||
|
||||
<code-example path="testing/src/app/hero/hero-detail.component.spec.ts" region="title-case-pipe" header="app/hero/hero-detail.component.spec.ts (pipe test)"></code-example>
|
||||
|
199
aio/content/guide/testing-services.md
Normal file
199
aio/content/guide/testing-services.md
Normal file
@ -0,0 +1,199 @@
|
||||
# Testing services
|
||||
|
||||
|
||||
To check that your services are working as you intend, you can write tests specifically for them.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For the sample app that the testing guides describe, see the <live-example name="testing" embedded-style noDownload>sample app</live-example>.
|
||||
|
||||
For the tests features in the testing guides, see <live-example name="testing" stackblitz="specs" noDownload>tests</live-example>.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
Services are often the easiest files to unit test.
|
||||
Here are some synchronous and asynchronous unit tests of the `ValueService`
|
||||
written without assistance from Angular testing utilities.
|
||||
|
||||
<code-example path="testing/src/app/demo/demo.spec.ts" region="ValueService" header="app/demo/demo.spec.ts"></code-example>
|
||||
|
||||
{@a services-with-dependencies}
|
||||
|
||||
## Services with dependencies
|
||||
|
||||
Services often depend on other services that Angular injects into the constructor.
|
||||
In many cases, it's easy to create and _inject_ these dependencies by hand while
|
||||
calling the service's constructor.
|
||||
|
||||
The `MasterService` is a simple example:
|
||||
|
||||
<code-example path="testing/src/app/demo/demo.ts" region="MasterService" header="app/demo/demo.ts"></code-example>
|
||||
|
||||
`MasterService` delegates its only method, `getValue`, to the injected `ValueService`.
|
||||
|
||||
Here are several ways to test it.
|
||||
|
||||
<code-example path="testing/src/app/demo/demo.spec.ts" region="MasterService" header="app/demo/demo.spec.ts"></code-example>
|
||||
|
||||
The first test creates a `ValueService` with `new` and passes it to the `MasterService` constructor.
|
||||
|
||||
However, injecting the real service rarely works well as most dependent services are difficult to create and control.
|
||||
|
||||
Instead you can mock the dependency, use a dummy value, or create a
|
||||
[spy](https://jasmine.github.io/2.0/introduction.html#section-Spies)
|
||||
on the pertinent service method.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Prefer spies as they are usually the easiest way to mock services.
|
||||
|
||||
</div>
|
||||
|
||||
These standard testing techniques are great for unit testing services in isolation.
|
||||
|
||||
However, you almost always inject services into application classes using Angular
|
||||
dependency injection and you should have tests that reflect that usage pattern.
|
||||
Angular testing utilities make it easy to investigate how injected services behave.
|
||||
|
||||
## Testing services with the _TestBed_
|
||||
|
||||
Your app relies on Angular [dependency injection (DI)](guide/dependency-injection)
|
||||
to create services.
|
||||
When a service has a dependent service, DI finds or creates that dependent service.
|
||||
And if that dependent service has its own dependencies, DI finds-or-creates them as well.
|
||||
|
||||
As service _consumer_, you don't worry about any of this.
|
||||
You don't worry about the order of constructor arguments or how they're created.
|
||||
|
||||
As a service _tester_, you must at least think about the first level of service dependencies
|
||||
but you _can_ let Angular DI do the service creation and deal with constructor argument order
|
||||
when you use the `TestBed` testing utility to provide and create services.
|
||||
|
||||
{@a testbed}
|
||||
|
||||
## Angular _TestBed_
|
||||
|
||||
The `TestBed` is the most important of the Angular testing utilities.
|
||||
The `TestBed` creates a dynamically-constructed Angular _test_ module that emulates
|
||||
an Angular [@NgModule](guide/ngmodules).
|
||||
|
||||
The `TestBed.configureTestingModule()` method takes a metadata object that can have most of the properties of an [@NgModule](guide/ngmodules).
|
||||
|
||||
To test a service, you set the `providers` metadata property with an
|
||||
array of the services that you'll test or mock.
|
||||
|
||||
<code-example path="testing/src/app/demo/demo.testbed.spec.ts" region="value-service-before-each" header="app/demo/demo.testbed.spec.ts (provide ValueService in beforeEach)"></code-example>
|
||||
|
||||
Then inject it inside a test by calling `TestBed.inject()` with the service class as the argument.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
**Note:** `TestBed.get()` was deprecated as of Angular version 9.
|
||||
To help minimize breaking changes, Angular introduces a new function called `TestBed.inject()`, which you should use instead.
|
||||
For information on the removal of `TestBed.get()`,
|
||||
see its entry in the [Deprecations index](guide/deprecations#index).
|
||||
|
||||
</div>
|
||||
|
||||
<code-example path="testing/src/app/demo/demo.testbed.spec.ts" region="value-service-inject-it"></code-example>
|
||||
|
||||
Or inside the `beforeEach()` if you prefer to inject the service as part of your setup.
|
||||
|
||||
<code-example path="testing/src/app/demo/demo.testbed.spec.ts" region="value-service-inject-before-each"> </code-example>
|
||||
|
||||
When testing a service with a dependency, provide the mock in the `providers` array.
|
||||
|
||||
In the following example, the mock is a spy object.
|
||||
|
||||
<code-example path="testing/src/app/demo/demo.testbed.spec.ts" region="master-service-before-each"></code-example>
|
||||
|
||||
The test consumes that spy in the same way it did earlier.
|
||||
|
||||
<code-example path="testing/src/app/demo/demo.testbed.spec.ts" region="master-service-it">
|
||||
</code-example>
|
||||
|
||||
{@a no-before-each}
|
||||
|
||||
## Testing without _beforeEach()_
|
||||
|
||||
Most test suites in this guide call `beforeEach()` to set the preconditions for each `it()` test
|
||||
and rely on the `TestBed` to create classes and inject services.
|
||||
|
||||
There's another school of testing that never calls `beforeEach()` and prefers to create classes explicitly rather than use the `TestBed`.
|
||||
|
||||
Here's how you might rewrite one of the `MasterService` tests in that style.
|
||||
|
||||
Begin by putting re-usable, preparatory code in a _setup_ function instead of `beforeEach()`.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/demo/demo.spec.ts"
|
||||
region="no-before-each-setup"
|
||||
header="app/demo/demo.spec.ts (setup)"></code-example>
|
||||
|
||||
The `setup()` function returns an object literal
|
||||
with the variables, such as `masterService`, that a test might reference.
|
||||
You don't define _semi-global_ variables (e.g., `let masterService: MasterService`)
|
||||
in the body of the `describe()`.
|
||||
|
||||
Then each test invokes `setup()` in its first line, before continuing
|
||||
with steps that manipulate the test subject and assert expectations.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/demo/demo.spec.ts"
|
||||
region="no-before-each-test"></code-example>
|
||||
|
||||
Notice how the test uses
|
||||
[_destructuring assignment_](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)
|
||||
to extract the setup variables that it needs.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/demo/demo.spec.ts"
|
||||
region="no-before-each-setup-call">
|
||||
</code-example>
|
||||
|
||||
Many developers feel this approach is cleaner and more explicit than the
|
||||
traditional `beforeEach()` style.
|
||||
|
||||
Although this testing guide follows the traditional style and
|
||||
the default [CLI schematics](https://github.com/angular/angular-cli)
|
||||
generate test files with `beforeEach()` and `TestBed`,
|
||||
feel free to adopt _this alternative approach_ in your own projects.
|
||||
|
||||
## Testing HTTP services
|
||||
|
||||
Data services that make HTTP calls to remote servers typically inject and delegate
|
||||
to the Angular [`HttpClient`](guide/http) service for XHR calls.
|
||||
|
||||
You can test a data service with an injected `HttpClient` spy as you would
|
||||
test any service with a dependency.
|
||||
<code-example
|
||||
path="testing/src/app/model/hero.service.spec.ts"
|
||||
region="test-with-spies"
|
||||
header="app/model/hero.service.spec.ts (tests with spies)">
|
||||
</code-example>
|
||||
|
||||
<div class="alert is-important">
|
||||
|
||||
The `HeroService` methods return `Observables`. You must
|
||||
_subscribe_ to an observable to (a) cause it to execute and (b)
|
||||
assert that the method succeeds or fails.
|
||||
|
||||
The `subscribe()` method takes a success (`next`) and fail (`error`) callback.
|
||||
Make sure you provide _both_ callbacks so that you capture errors.
|
||||
Neglecting to do so produces an asynchronous uncaught observable error that
|
||||
the test runner will likely attribute to a completely different test.
|
||||
|
||||
</div>
|
||||
|
||||
## _HttpClientTestingModule_
|
||||
|
||||
Extended interactions between a data service and the `HttpClient` can be complex
|
||||
and difficult to mock with spies.
|
||||
|
||||
The `HttpClientTestingModule` can make these testing scenarios more manageable.
|
||||
|
||||
While the _code sample_ accompanying this guide demonstrates `HttpClientTestingModule`,
|
||||
this page defers to the [Http guide](guide/http#testing-http-requests),
|
||||
which covers testing with the `HttpClientTestingModule` in detail.
|
||||
|
794
aio/content/guide/testing-utility-apis.md
Normal file
794
aio/content/guide/testing-utility-apis.md
Normal file
@ -0,0 +1,794 @@
|
||||
# Testing Utility APIs
|
||||
|
||||
This page describes the most useful Angular testing features.
|
||||
|
||||
The Angular testing utilities include the `TestBed`, the `ComponentFixture`, and a handful of functions that control the test environment.
|
||||
The [_TestBed_](#testbed-api-summary) and [_ComponentFixture_](#component-fixture-api-summary) classes are covered separately.
|
||||
|
||||
Here's a summary of the stand-alone functions, in order of likely utility:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>
|
||||
Function
|
||||
</th>
|
||||
<th>
|
||||
Description
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>async</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Runs the body of a test (`it`) or setup (`beforeEach`) function within a special _async test zone_.
|
||||
See [discussion above](guide/testing-components-scenarios#async).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>fakeAsync</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Runs the body of a test (`it`) within a special _fakeAsync test zone_, enabling
|
||||
a linear control flow coding style. See [discussion above](guide/testing-components-scenarios#fake-async).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>tick</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Simulates the passage of time and the completion of pending asynchronous activities
|
||||
by flushing both _timer_ and _micro-task_ queues within the _fakeAsync test zone_.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The curious, dedicated reader might enjoy this lengthy blog post,
|
||||
["_Tasks, microtasks, queues and schedules_"](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/).
|
||||
|
||||
</div>
|
||||
|
||||
Accepts an optional argument that moves the virtual clock forward
|
||||
by the specified number of milliseconds,
|
||||
clearing asynchronous activities scheduled within that timeframe.
|
||||
See [discussion above](guide/testing-components-scenarios#tick).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>inject</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Injects one or more services from the current `TestBed` injector into a test function.
|
||||
It cannot inject a service provided by the component itself.
|
||||
See discussion of the [debugElement.injector](guide/testing-components-scenarios#get-injected-services).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>discardPeriodicTasks</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
When a `fakeAsync()` test ends with pending timer event _tasks_ (queued `setTimeOut` and `setInterval` callbacks),
|
||||
the test fails with a clear error message.
|
||||
|
||||
In general, a test should end with no queued tasks.
|
||||
When pending timer tasks are expected, call `discardPeriodicTasks` to flush the _task_ queue
|
||||
and avoid the error.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>flushMicrotasks</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
When a `fakeAsync()` test ends with pending _micro-tasks_ such as unresolved promises,
|
||||
the test fails with a clear error message.
|
||||
|
||||
In general, a test should wait for micro-tasks to finish.
|
||||
When pending microtasks are expected, call `flushMicrotasks` to flush the _micro-task_ queue
|
||||
and avoid the error.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>ComponentFixtureAutoDetect</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
A provider token for a service that turns on [automatic change detection](guide/testing-components-scenarios#automatic-change-detection).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>getTestBed</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Gets the current instance of the `TestBed`.
|
||||
Usually unnecessary because the static class methods of the `TestBed` class are typically sufficient.
|
||||
The `TestBed` instance exposes a few rarely used members that are not available as
|
||||
static methods.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
{@a testbed-class-summary}
|
||||
|
||||
## _TestBed_ class summary
|
||||
|
||||
The `TestBed` class is one of the principal Angular testing utilities.
|
||||
Its API is quite large and can be overwhelming until you've explored it,
|
||||
a little at a time. Read the early part of this guide first
|
||||
to get the basics before trying to absorb the full API.
|
||||
|
||||
The module definition passed to `configureTestingModule`
|
||||
is a subset of the `@NgModule` metadata properties.
|
||||
|
||||
<code-example language="javascript">
|
||||
type TestModuleMetadata = {
|
||||
providers?: any[];
|
||||
declarations?: any[];
|
||||
imports?: any[];
|
||||
schemas?: Array<SchemaMetadata | any[]>;
|
||||
};
|
||||
</code-example>
|
||||
|
||||
{@a metadata-override-object}
|
||||
|
||||
Each override method takes a `MetadataOverride<T>` where `T` is the kind of metadata
|
||||
appropriate to the method, that is, the parameter of an `@NgModule`,
|
||||
`@Component`, `@Directive`, or `@Pipe`.
|
||||
|
||||
<code-example language="javascript">
|
||||
type MetadataOverride<T> = {
|
||||
add?: Partial<T>;
|
||||
remove?: Partial<T>;
|
||||
set?: Partial<T>;
|
||||
};
|
||||
</code-example>
|
||||
|
||||
{@a testbed-methods}
|
||||
{@a testbed-api-summary}
|
||||
|
||||
The `TestBed` API consists of static class methods that either update or reference a _global_ instance of the `TestBed`.
|
||||
|
||||
Internally, all static methods cover methods of the current runtime `TestBed` instance,
|
||||
which is also returned by the `getTestBed()` function.
|
||||
|
||||
Call `TestBed` methods _within_ a `beforeEach()` to ensure a fresh start before each individual test.
|
||||
|
||||
Here are the most important static methods, in order of likely utility.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>
|
||||
Methods
|
||||
</th>
|
||||
<th>
|
||||
Description
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>configureTestingModule</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
The testing shims (`karma-test-shim`, `browser-test-shim`)
|
||||
establish the [initial test environment](guide/testing) and a default testing module.
|
||||
The default testing module is configured with basic declaratives and some Angular service substitutes that every tester needs.
|
||||
|
||||
Call `configureTestingModule` to refine the testing module configuration for a particular set of tests
|
||||
by adding and removing imports, declarations (of components, directives, and pipes), and providers.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>compileComponents</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Compile the testing module asynchronously after you've finished configuring it.
|
||||
You **must** call this method if _any_ of the testing module components have a `templateUrl`
|
||||
or `styleUrls` because fetching component template and style files is necessarily asynchronous.
|
||||
See [above](guide/testing-components-scenarios#compile-components).
|
||||
|
||||
After calling `compileComponents`, the `TestBed` configuration is frozen for the duration of the current spec.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>createComponent<T></code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Create an instance of a component of type `T` based on the current `TestBed` configuration.
|
||||
After calling `compileComponent`, the `TestBed` configuration is frozen for the duration of the current spec.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>overrideModule</code>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Replace metadata for the given `NgModule`. Recall that modules can import other modules.
|
||||
The `overrideModule` method can reach deeply into the current testing module to
|
||||
modify one of these inner modules.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>overrideComponent</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Replace metadata for the given component class, which could be nested deeply
|
||||
within an inner module.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>overrideDirective</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Replace metadata for the given directive class, which could be nested deeply
|
||||
within an inner module.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>overridePipe</code>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Replace metadata for the given pipe class, which could be nested deeply
|
||||
within an inner module.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
{@a testbed-inject}
|
||||
<code>inject</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Retrieve a service from the current `TestBed` injector.
|
||||
|
||||
The `inject` function is often adequate for this purpose.
|
||||
But `inject` throws an error if it can't provide the service.
|
||||
|
||||
What if the service is optional?
|
||||
|
||||
The `TestBed.inject()` method takes an optional second parameter,
|
||||
the object to return if Angular can't find the provider
|
||||
(`null` in this example):
|
||||
|
||||
<code-example path="testing/src/app/demo/demo.testbed.spec.ts" region="testbed-get-w-null" header="app/demo/demo.testbed.spec.ts"></code-example>
|
||||
|
||||
After calling `TestBed.inject`, the `TestBed` configuration is frozen for the duration of the current spec.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
{@a testbed-initTestEnvironment}
|
||||
<code>initTestEnvironment</code>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Initialize the testing environment for the entire test run.
|
||||
|
||||
The testing shims (`karma-test-shim`, `browser-test-shim`) call it for you
|
||||
so there is rarely a reason for you to call it yourself.
|
||||
|
||||
You may call this method _exactly once_. If you must change
|
||||
this default in the middle of your test run, call `resetTestEnvironment` first.
|
||||
|
||||
Specify the Angular compiler factory, a `PlatformRef`, and a default Angular testing module.
|
||||
Alternatives for non-browser platforms are available in the general form
|
||||
`@angular/platform-<platform_name>/testing/<platform_name>`.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>resetTestEnvironment</code>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Reset the initial test environment, including the default testing module.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
A few of the `TestBed` instance methods are not covered by static `TestBed` _class_ methods.
|
||||
These are rarely needed.
|
||||
|
||||
{@a component-fixture-api-summary}
|
||||
|
||||
## The _ComponentFixture_
|
||||
|
||||
The `TestBed.createComponent<T>`
|
||||
creates an instance of the component `T`
|
||||
and returns a strongly typed `ComponentFixture` for that component.
|
||||
|
||||
The `ComponentFixture` properties and methods provide access to the component,
|
||||
its DOM representation, and aspects of its Angular environment.
|
||||
|
||||
{@a component-fixture-properties}
|
||||
|
||||
### _ComponentFixture_ properties
|
||||
|
||||
Here are the most important properties for testers, in order of likely utility.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>
|
||||
Properties
|
||||
</th>
|
||||
<th>
|
||||
Description
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>componentInstance</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
The instance of the component class created by `TestBed.createComponent`.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>debugElement</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
The `DebugElement` associated with the root element of the component.
|
||||
|
||||
The `debugElement` provides insight into the component and its DOM element during test and debugging.
|
||||
It's a critical property for testers. The most interesting members are covered [below](#debug-element-details).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>nativeElement</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
The native DOM element at the root of the component.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>changeDetectorRef</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
The `ChangeDetectorRef` for the component.
|
||||
|
||||
The `ChangeDetectorRef` is most valuable when testing a
|
||||
component that has the `ChangeDetectionStrategy.OnPush` method
|
||||
or the component's change detection is under your programmatic control.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{@a component-fixture-methods}
|
||||
|
||||
### _ComponentFixture_ methods
|
||||
|
||||
The _fixture_ methods cause Angular to perform certain tasks on the component tree.
|
||||
Call these method to trigger Angular behavior in response to simulated user action.
|
||||
|
||||
Here are the most useful methods for testers.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>
|
||||
Methods
|
||||
</th>
|
||||
<th>
|
||||
Description
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>detectChanges</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Trigger a change detection cycle for the component.
|
||||
|
||||
Call it to initialize the component (it calls `ngOnInit`) and after your
|
||||
test code, change the component's data bound property values.
|
||||
Angular can't see that you've changed `personComponent.name` and won't update the `name`
|
||||
binding until you call `detectChanges`.
|
||||
|
||||
Runs `checkNoChanges` afterwards to confirm that there are no circular updates unless
|
||||
called as `detectChanges(false)`;
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>autoDetectChanges</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Set this to `true` when you want the fixture to detect changes automatically.
|
||||
|
||||
When autodetect is `true`, the test fixture calls `detectChanges` immediately
|
||||
after creating the component. Then it listens for pertinent zone events
|
||||
and calls `detectChanges` accordingly.
|
||||
When your test code modifies component property values directly,
|
||||
you probably still have to call `fixture.detectChanges` to trigger data binding updates.
|
||||
|
||||
The default is `false`. Testers who prefer fine control over test behavior
|
||||
tend to keep it `false`.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>checkNoChanges</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Do a change detection run to make sure there are no pending changes.
|
||||
Throws an exceptions if there are.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>isStable</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
If the fixture is currently _stable_, returns `true`.
|
||||
If there are async tasks that have not completed, returns `false`.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>whenStable</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Returns a promise that resolves when the fixture is stable.
|
||||
|
||||
To resume testing after completion of asynchronous activity or
|
||||
asynchronous change detection, hook that promise.
|
||||
See [above](guide/testing-components-scenarios#when-stable).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>destroy</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Trigger component destruction.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{@a debug-element-details}
|
||||
|
||||
#### _DebugElement_
|
||||
|
||||
The `DebugElement` provides crucial insights into the component's DOM representation.
|
||||
|
||||
From the test root component's `DebugElement` returned by `fixture.debugElement`,
|
||||
you can walk (and query) the fixture's entire element and component subtrees.
|
||||
|
||||
Here are the most useful `DebugElement` members for testers, in approximate order of utility:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>
|
||||
Member
|
||||
</th>
|
||||
<th>
|
||||
Description
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>nativeElement</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
The corresponding DOM element in the browser (null for WebWorkers).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>query</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Calling `query(predicate: Predicate<DebugElement>)` returns the first `DebugElement`
|
||||
that matches the [predicate](#query-predicate) at any depth in the subtree.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>queryAll</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Calling `queryAll(predicate: Predicate<DebugElement>)` returns all `DebugElements`
|
||||
that matches the [predicate](#query-predicate) at any depth in subtree.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>injector</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
The host dependency injector.
|
||||
For example, the root element's component instance injector.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>componentInstance</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
The element's own component instance, if it has one.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>context</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
An object that provides parent context for this element.
|
||||
Often an ancestor component instance that governs this element.
|
||||
|
||||
When an element is repeated within `*ngFor`, the context is an `NgForRow` whose `$implicit`
|
||||
property is the value of the row instance value.
|
||||
For example, the `hero` in `*ngFor="let hero of heroes"`.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>children</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
The immediate `DebugElement` children. Walk the tree by descending through `children`.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
`DebugElement` also has `childNodes`, a list of `DebugNode` objects.
|
||||
`DebugElement` derives from `DebugNode` objects and there are often
|
||||
more nodes than elements. Testers can usually ignore plain nodes.
|
||||
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>parent</code>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
The `DebugElement` parent. Null if this is the root element.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>name</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
The element tag name, if it is an element.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>triggerEventHandler</code>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Triggers the event by its name if there is a corresponding listener
|
||||
in the element's `listeners` collection.
|
||||
The second parameter is the _event object_ expected by the handler.
|
||||
See [above](guide/testing-components-scenarios#trigger-event-handler).
|
||||
|
||||
If the event lacks a listener or there's some other problem,
|
||||
consider calling `nativeElement.dispatchEvent(eventObject)`.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>listeners</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
The callbacks attached to the component's `@Output` properties and/or the element's event properties.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>providerTokens</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
This component's injector lookup tokens.
|
||||
Includes the component itself plus the tokens that the component lists in its `providers` metadata.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>source</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Where to find this element in the source component template.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top">
|
||||
<code>references</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Dictionary of objects associated with template local variables (e.g. `#foo`),
|
||||
keyed by the local variable name.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{@a query-predicate}
|
||||
|
||||
The `DebugElement.query(predicate)` and `DebugElement.queryAll(predicate)` methods take a
|
||||
predicate that filters the source element's subtree for matching `DebugElement`.
|
||||
|
||||
The predicate is any method that takes a `DebugElement` and returns a _truthy_ value.
|
||||
The following example finds all `DebugElements` with a reference to a template local variable named "content":
|
||||
|
||||
<code-example path="testing/src/app/demo/demo.testbed.spec.ts" region="custom-predicate" header="app/demo/demo.testbed.spec.ts"></code-example>
|
||||
|
||||
The Angular `By` class has three static methods for common predicates:
|
||||
|
||||
- `By.all` - return all elements.
|
||||
- `By.css(selector)` - return elements with matching CSS selectors.
|
||||
- `By.directive(directive)` - return elements that Angular matched to an instance of the directive class.
|
||||
|
||||
<code-example path="testing/src/app/hero/hero-list.component.spec.ts" region="by" header="app/hero/hero-list.component.spec.ts"></code-example>
|
||||
|
||||
<hr>
|
||||
|
File diff suppressed because it is too large
Load Diff
76
aio/content/guide/two-way-binding.md
Normal file
76
aio/content/guide/two-way-binding.md
Normal file
@ -0,0 +1,76 @@
|
||||
# Two-way binding `[(...)]`
|
||||
|
||||
Two-way binding gives your app a way to share data between a component class and
|
||||
its template.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
## Basics of two-way binding
|
||||
|
||||
Two-way binding does two things:
|
||||
|
||||
1. Sets a specific element property.
|
||||
1. Listens for an element change event.
|
||||
|
||||
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, `()`.
|
||||
|
||||
<div class="callout is-important">
|
||||
|
||||
<header>
|
||||
[( )] = banana in a box
|
||||
</header>
|
||||
|
||||
Visualize a *banana in a box* to remember that the parentheses go _inside_ the brackets.
|
||||
|
||||
</div>
|
||||
|
||||
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/sizer/sizer.component.ts" header="src/app/sizer.component.ts"></code-example>
|
||||
|
||||
<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`:
|
||||
|
||||
<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>
|
||||
|
||||
The `AppComponent.fontSizePx` establishes the initial `SizerComponent.size` value.
|
||||
|
||||
<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.
|
||||
|
||||
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:
|
||||
|
||||
<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>
|
||||
|
||||
The `$event` variable contains the payload 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
|
||||
|
||||
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.
|
||||
|
||||
For more on how to use two-way binding in forms, see
|
||||
Angular [NgModel](guide/built-in-directives#ngModel).
|
@ -308,7 +308,7 @@ So when IE is refreshed (manually or automatically by `ng serve`), sometimes the
|
||||
|
||||
## Appendix: Test using `fakeAsync()/async()`
|
||||
|
||||
If you use the `fakeAsync()/async()` helper function to run unit tests (for details, read the [Testing guide](guide/testing#async-test-with-fakeasync)), you need to import `zone.js/dist/zone-testing` in your test setup file.
|
||||
If you use the `fakeAsync()/async()` helper function to run unit tests (for details, read the [Testing guide](guide/testing-components-scenarios#fake-async)), you need to import `zone.js/dist/zone-testing` in your test setup file.
|
||||
|
||||
<div class="alert is-important">
|
||||
If you create project with `Angular/CLI`, it is already imported in `src/test.ts`.
|
||||
|
@ -1567,7 +1567,7 @@ with Angular's two-way `[(ngModel)]` binding syntax:
|
||||
<code-example path="upgrade-phonecat-2-hybrid/app/phone-list/phone-list.template.html" region="controls" header="app/phone-list/phone-list.template.html (search controls)"></code-example>
|
||||
|
||||
Replace the list's `ng-repeat` with an `*ngFor` as
|
||||
[described in the Template Syntax page](guide/template-syntax#directives).
|
||||
[described in the Template Syntax page](guide/built-in-directives).
|
||||
Replace the image tag's `ng-src` with a binding to the native `src` property.
|
||||
|
||||
<code-example path="upgrade-phonecat-2-hybrid/app/phone-list/phone-list.template.html" region="list" header="app/phone-list/phone-list.template.html (phones)"></code-example>
|
||||
@ -1637,7 +1637,7 @@ There are several notable changes here:
|
||||
bindings for the standard `src` property.
|
||||
|
||||
* You're using the property binding syntax around `ng-class`. Though Angular
|
||||
does have [a very similar `ngClass`](guide/template-syntax#directives)
|
||||
does have [a very similar `ngClass`](guide/built-in-directives)
|
||||
as AngularJS does, its value is not magically evaluated as an expression.
|
||||
In Angular, you always specify in the template when an attribute's value is
|
||||
a property expression, as opposed to a literal string.
|
||||
|
@ -10,13 +10,13 @@ Run the <live-example></live-example>.
|
||||
|
||||
## Binding to user input events
|
||||
|
||||
You can use [Angular event bindings](guide/template-syntax#event-binding)
|
||||
You can use [Angular event bindings](guide/event-binding)
|
||||
to respond to any [DOM event](https://developer.mozilla.org/en-US/docs/Web/Events).
|
||||
Many DOM events are triggered by user input. Binding to these events provides a way to
|
||||
get input from the user.
|
||||
|
||||
To bind to a DOM event, surround the DOM event name in parentheses and assign a quoted
|
||||
[template statement](guide/template-syntax#template-statements) to it.
|
||||
[template statement](guide/template-statements) to it.
|
||||
|
||||
The following example shows an event binding that implements a click handler:
|
||||
|
||||
@ -70,7 +70,7 @@ In this case, `target` refers to the [`<input>` element](https://developer.mozil
|
||||
|
||||
After each call, the `onKey()` method appends the contents of the input box value to the list
|
||||
in the component's `values` property, followed by a separator character (|).
|
||||
The [interpolation](guide/template-syntax#interpolation)
|
||||
The [interpolation](guide/interpolation)
|
||||
displays the accumulating input box changes from the `values` property.
|
||||
|
||||
Suppose the user enters the letters "abc", and then backspaces to remove them one by one.
|
||||
@ -139,7 +139,7 @@ The next section shows how to use template reference variables to address this p
|
||||
|
||||
## Get user input from a template reference variable
|
||||
There's another way to get the user data: use Angular
|
||||
[**template reference variables**](guide/template-syntax#ref-vars).
|
||||
[**template reference variables**](guide/template-reference-variables).
|
||||
These variables provide direct access to an element from within the template.
|
||||
To declare a template reference variable, precede an identifier with a hash (or pound) character (#).
|
||||
|
||||
|
@ -8,7 +8,7 @@ See the [Angular Resources](resources) page for links to the most popular ones.
|
||||
Libraries are published as [npm packages](guide/npm-packages), usually together with schematics that integrate them with the Angular CLI.
|
||||
To integrate reusable library code into an application, you need to install the package and import the provided functionality where you will use it. For most published Angular libraries, you can use the Angular CLI `ng add <lib_name>` command.
|
||||
|
||||
The `ng add` command uses the npm package manager or [yarn](https://yarnpkg.com/) to install the library package, and invokes schematics that are included in the package to other scaffolding within the project code, such as adding import statements, fonts, themes, and so on.
|
||||
The `ng add` command uses a package manager such as [npm](https://www.npmjs.com/) or [yarn](https://yarnpkg.com/) to install the library package, and invokes schematics that are included in the package to other scaffolding within the project code, such as adding import statements, fonts, themes, and so on.
|
||||
|
||||
A published library typically provides a README or other documentation on how to add that lib to your app.
|
||||
For an example, see [Angular Material](https://material.angular.io/) docs.
|
||||
|
BIN
aio/content/images/bios/ajitsinghkaler.jpg
Normal file
BIN
aio/content/images/bios/ajitsinghkaler.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
Binary file not shown.
Before Width: | Height: | Size: 17 KiB |
BIN
aio/content/images/bios/twerske.jpg
Normal file
BIN
aio/content/images/bios/twerske.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
3
aio/content/images/guide/providers/any-provider.svg
Normal file
3
aio/content/images/guide/providers/any-provider.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 9.6 KiB |
@ -576,6 +576,13 @@
|
||||
"picture": "cexbrayat.jpg",
|
||||
"bio": "Author of `Become a ninja with Angular (2+)` https://books.ninja-squad.com/angular - Angular trainer and @Ninja-Squad co-founder"
|
||||
},
|
||||
"ajitsinghkaler": {
|
||||
"name": "Ajit Singh",
|
||||
"groups": ["Collaborators"],
|
||||
"picture": "ajitsinghkaler.jpg",
|
||||
"twitter": "ajitsinghkaler",
|
||||
"bio": "Software Engineer in Bangalore, India who loves to learn something new and is interested in front end technologies"
|
||||
},
|
||||
"CaerusKaru": {
|
||||
"name": "Adam Plumer",
|
||||
"groups": ["Collaborators"],
|
||||
@ -662,12 +669,6 @@
|
||||
"picture": "bonnie.jpg",
|
||||
"bio": "Bonnie has been specializing in Angular since 2013. She is the founder of ngHouston Angular Meetup and a regular panelist on Angular Air. She is also the very proud parent component of @thelittlestdev!"
|
||||
},
|
||||
"globegitter": {
|
||||
"name": "Markus Padourek",
|
||||
"groups": ["Collaborators"],
|
||||
"mentor": "gregmagolan",
|
||||
"picture": "globegitter.jpg"
|
||||
},
|
||||
"ahsanayaz": {
|
||||
"name": "Muhammad Ahsan Ayaz",
|
||||
"picture": "ahsanayaz.jpg",
|
||||
@ -830,5 +831,14 @@
|
||||
"twitter": "ahasall",
|
||||
"website": "https://www.amadousall.com",
|
||||
"bio": "Amadou is a Frontend Software Engineer from Senegal based in France. He currently works at Air France where he helps developers build better Angular applications. Passionate about web technologies, Amadou is an international speaker, a technical writer, and a Google Developer Expert in Angular."
|
||||
},
|
||||
"twerske": {
|
||||
"name": "Emma Twersky",
|
||||
"picture": "twerske.jpg",
|
||||
"twitter": "twerske",
|
||||
"website": "http://twerske.github.io",
|
||||
"bio": "Emma is a Developer Advocate at Google. She is passionate about good user experiences and design.",
|
||||
"groups": ["Angular"],
|
||||
"lead": "mgechev"
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ Most Angular code can be written with just the latest JavaScript, using [types](
|
||||
|
||||
## Feedback
|
||||
|
||||
<h4>You can sit with us!</h4>
|
||||
<h3>You can sit with us!</h3>
|
||||
|
||||
We want to hear from you. [Report problems or submit suggestions for future docs.](https://github.com/angular/angular/issues/new/choose "Angular GitHub repository new issue form")
|
||||
|
||||
|
@ -14,8 +14,8 @@
|
||||
|
||||
<!-- CONTAINER -->
|
||||
<div class="homepage-container">
|
||||
<div class="hero-headline no-toc">One framework.<br>Mobile & desktop.</div>
|
||||
<a class="button hero-cta" href="docs">Get Started</a>
|
||||
<div class="hero-headline no-toc">Un framework.<br>Móvil y escritorio.</div>
|
||||
<a class="button hero-cta" href="docs">Empezar</a>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
@ -41,8 +41,8 @@
|
||||
|
||||
<div class="text-container">
|
||||
<div class="text-block promo-1-desc l-pad-top-2">
|
||||
<div class="text-headline">Develop Across All Platforms</div>
|
||||
<p class="text-body">Learn one way to build applications with Angular and reuse your code and abilities to build apps for any deployment target. For web, mobile web, native mobile and native desktop.
|
||||
<div class="text-headline">Desarrolla en todas las plataformas</div>
|
||||
<p class="text-body">Aprende una forma de crear aplicaciones con Angular y reutiliza tu código y habilidades para crear aplicaciones para cualquier objetivo de implementación. Para web, web móvil, móvil nativo y escritorio nativo.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -53,9 +53,9 @@
|
||||
<div layout="row" layout-xs="column" class="home-row">
|
||||
<div class="text-container">
|
||||
<div class="text-block">
|
||||
<div class="text-headline">Speed & Performance</div>
|
||||
<p class="text-body">Achieve the maximum speed possible on the Web Platform today, and take it further, via Web Workers and server-side rendering.</p>
|
||||
<p class="text-body">Angular puts you in control over scalability. Meet huge data requirements by building data models on RxJS, Immutable.js or another push-model.</p>
|
||||
<div class="text-headline">Velocidad y Rendimiento</div>
|
||||
<p class="text-body">Logra la máxima velocidad posible en la Plataforma Web hoy y avance, a través de Web Workers y renderizado del lado del servidor.</p>
|
||||
<p class="text-body">Angular te permite controlar la escalabilidad. Satisface requerimientos enormes de datos construyendo modelos en RxJS, Immutable.js o algún otro.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -75,8 +75,8 @@
|
||||
|
||||
<div class="text-container">
|
||||
<div class="text-block promo-3-desc">
|
||||
<div class="text-headline">Incredible Tooling</div>
|
||||
<p class="text-body">Build features quickly with simple, declarative templates. Extend the template language with your own components and use a wide array of existing components. Get immediate Angular-specific help and feedback with nearly every IDE and editor. All this comes together so you can focus on building amazing apps rather than trying to make the code work.
|
||||
<div class="text-headline">Herramientas Increíbles</div>
|
||||
<p class="text-body">Crea funciones rápidamente con plantillas simples y declarativas. Extiende el lenguaje de plantilla con tus propios componentes y usa una amplia gama de componentes existentes. Obtén ayuda inmediata y comentarios específicos de Angular con casi todos los IDE y editores. Todo esto se une para que puedas concentrarte en crear aplicaciones increíbles en lugar de intentar que el código funcione.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -88,8 +88,9 @@
|
||||
<div layout="row" layout-xs="column" class="home-row">
|
||||
<div class="text-container">
|
||||
<div class="text-block l-pad-top-2">
|
||||
<div class="text-headline">Loved by Millions</div>
|
||||
<p class="text-body">From prototype through global deployment, Angular delivers the productivity and scalable infrastructure that supports Google's largest applications.</p>
|
||||
<div class="text-headline">Amada por millones</div>
|
||||
<p class="text-body">Desde el prototipo hasta la implementación global, Angular ofrece la productividad y la infraestructura escalable que soportan a las aplicaciones más grandes de Google.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -106,8 +107,9 @@
|
||||
<div class="card">
|
||||
<img src="generated/images/marketing/home/code-icon.svg" height="70px" alt="Get Started with Angular">
|
||||
<div class="card-text-container">
|
||||
<div class="text-headline">Try it now</div>
|
||||
<p>Explore Angular's capabilities with a ready-made sample app. No setup required.</p>
|
||||
<div class="text-headline">Pruebalo ahora</div>
|
||||
<p>Explora las capacidades de Angular con una aplicación de muestra preparada. No se requiere configuración.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
@ -97,6 +97,11 @@
|
||||
"Data Libraries": {
|
||||
"order": 3,
|
||||
"resources": {
|
||||
"formly": {
|
||||
"desc": "Formly is a dynamic (JSON powered) form library, built on top of Angular Reactive Forms.",
|
||||
"title": "Formly",
|
||||
"url": "https://formly.dev"
|
||||
},
|
||||
"rx-web": {
|
||||
"desc": "RxWeb Reactive Form Validators provides all types of complex, conditional, cross field, and dynamic validation on validator-based reactive forms, model-based reactive forms, and template driven forms.",
|
||||
"title": "RxWeb Reactive Form Validators",
|
||||
@ -236,6 +241,12 @@
|
||||
"logo": "",
|
||||
"title": "Protractor",
|
||||
"url": "https://protractor.angular.io/"
|
||||
},
|
||||
"scully": {
|
||||
"desc": "Scully (Jamstack Toolchain for Angular) makes building, testing, and deploying Jamstack apps extremely simple.",
|
||||
"title": "Scully",
|
||||
"logo": "https://raw.githubusercontent.com/scullyio/scully/main/assets/logos/PNG/Green/scullyio-logo-green.png",
|
||||
"url": "https://scully.io"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2,7 +2,7 @@
|
||||
"TopBar": [
|
||||
{
|
||||
"url": "features",
|
||||
"title": "Features"
|
||||
"title": "Caracteristicas"
|
||||
},
|
||||
{
|
||||
"url": "docs",
|
||||
@ -10,11 +10,11 @@
|
||||
},
|
||||
{
|
||||
"url": "resources",
|
||||
"title": "Resources"
|
||||
"title": "Recursos"
|
||||
},
|
||||
{
|
||||
"url": "events",
|
||||
"title": "Events"
|
||||
"title": "Eventos"
|
||||
},
|
||||
{
|
||||
"url": "https://blog.angular.io/",
|
||||
@ -23,19 +23,19 @@
|
||||
],
|
||||
"TopBarNarrow": [
|
||||
{
|
||||
"title": "About Angular",
|
||||
"title": "Acerca de Angular",
|
||||
"children": [
|
||||
{
|
||||
"url": "features",
|
||||
"title": "Features"
|
||||
"title": "Caracteristicas"
|
||||
},
|
||||
{
|
||||
"url": "resources",
|
||||
"title": "Resources"
|
||||
"title": "Recursos"
|
||||
},
|
||||
{
|
||||
"url": "events",
|
||||
"title": "Events"
|
||||
"title": "Eventos"
|
||||
},
|
||||
{
|
||||
"url": "https://blog.angular.io/",
|
||||
@ -189,9 +189,75 @@
|
||||
"tooltip": "Property binding helps show app data in the UI."
|
||||
},
|
||||
{
|
||||
"url": "guide/template-syntax",
|
||||
"title": "Template Syntax",
|
||||
"tooltip": "Learn how to write templates that display data and consume user events with the help of data binding."
|
||||
"tooltip": "Syntax to use in templates for binding, expressions, and directives.",
|
||||
"children": [
|
||||
{
|
||||
"url": "guide/template-syntax",
|
||||
"title": "Introduction",
|
||||
"tooltip": "Introduction to writing templates that display data and consume user events with the help of data binding."
|
||||
},
|
||||
{
|
||||
"url": "guide/interpolation",
|
||||
"title": "Interpolation",
|
||||
"tooltip": "An introduction to interpolation and expressions in HTML."
|
||||
},
|
||||
{
|
||||
"url": "guide/template-statements",
|
||||
"title": "Template statements",
|
||||
"tooltip": "Introductory guide to statements in templates that respond to events that components, directives, or elements raise."
|
||||
},
|
||||
{
|
||||
"url": "guide/binding-syntax",
|
||||
"title": "Binding syntax",
|
||||
"tooltip": "Introductory guide to coordinating app values."
|
||||
},
|
||||
{
|
||||
"url": "guide/property-binding",
|
||||
"title": "Property binding",
|
||||
"tooltip": "Introductory guide to setting element or input properties."
|
||||
},
|
||||
{
|
||||
"url": "guide/attribute-binding",
|
||||
"title": "Attribute, class, and style bindings",
|
||||
"tooltip": "Introductory guide to setting the value of HTML attributes."
|
||||
},
|
||||
{
|
||||
"url": "guide/event-binding",
|
||||
"title": "Event binding",
|
||||
"tooltip": "Introductory guide to listening for user interaction."
|
||||
},
|
||||
{
|
||||
"url": "guide/two-way-binding",
|
||||
"title": "Two-way binding",
|
||||
"tooltip": "Introductory guide to sharing data between a class and a template."
|
||||
},
|
||||
{
|
||||
"url": "guide/built-in-directives",
|
||||
"title": "Built-in directives",
|
||||
"tooltip": "Introductory guide to some of the most popular built-in directives."
|
||||
},
|
||||
{
|
||||
"url": "guide/template-reference-variables",
|
||||
"title": "Template reference variables",
|
||||
"tooltip": "Introductory guide to referring to DOM elements within a template."
|
||||
},
|
||||
{
|
||||
"url": "guide/inputs-outputs",
|
||||
"title": "Inputs and Outputs",
|
||||
"tooltip": "Introductory guide to sharing data between parent and child directives or components."
|
||||
},
|
||||
{
|
||||
"url": "guide/template-expression-operators",
|
||||
"title": "Template expression operators",
|
||||
"tooltip": "Introductory guide to transforming data, ensuring safe navigation, and guarding against null variables in templates."
|
||||
},
|
||||
{
|
||||
"url": "guide/svg-in-templates",
|
||||
"title": "SVG in templates",
|
||||
"tooltip": "Guide to using SVGs as templates to create interactive graphics."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "guide/user-input",
|
||||
@ -526,28 +592,74 @@
|
||||
"url": "guide/angular-compiler-options",
|
||||
"title": "Angular Compiler Options",
|
||||
"tooltip": "Configuring AOT compilation."
|
||||
},
|
||||
{
|
||||
},
|
||||
{
|
||||
"url": "guide/aot-metadata-errors",
|
||||
"title": "AOT Metadata Errors",
|
||||
"tooltip": "Troubleshooting AOT compilation."
|
||||
},
|
||||
{
|
||||
"url": "guide/template-typecheck",
|
||||
"title": "Template Type-checking",
|
||||
"tooltip": "Template type-checking in Angular."
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
"url": "guide/template-typecheck",
|
||||
"title": "Template Type-checking",
|
||||
"tooltip": "Template type-checking in Angular."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "guide/build",
|
||||
"title": "Building & Serving",
|
||||
"tooltip": "Building and serving Angular apps."
|
||||
},
|
||||
{
|
||||
"url": "guide/testing",
|
||||
"title": "Testing",
|
||||
"tooltip": "Techniques and practices for testing an Angular app."
|
||||
"tooltip": "Testing your Angular apps.",
|
||||
"children": [
|
||||
{
|
||||
"url": "guide/testing",
|
||||
"title": "Intro to Testing",
|
||||
"tooltip": "Introduction to testing an Angular app."
|
||||
},
|
||||
{
|
||||
"url": "guide/testing-code-coverage",
|
||||
"title": "Code Coverage",
|
||||
"tooltip": "Determine how much of your code is tested."
|
||||
},
|
||||
{
|
||||
"url": "guide/testing-services",
|
||||
"title": "Testing Services",
|
||||
"tooltip": "How to test services."
|
||||
},
|
||||
{
|
||||
"url": "guide/testing-components-basics",
|
||||
"title": "Basics of Testing Components",
|
||||
"tooltip": "The fundamentals of how to test components."
|
||||
},
|
||||
{
|
||||
"url": "guide/testing-components-scenarios",
|
||||
"title": "Component Testing Scenarios",
|
||||
"tooltip": "Use cases for testing components."
|
||||
},
|
||||
{
|
||||
"url": "guide/testing-attribute-directives",
|
||||
"title": "Testing Attribute Directives",
|
||||
"tooltip": "How to test attribute directives."
|
||||
},
|
||||
{
|
||||
"url": "guide/testing-pipes",
|
||||
"title": "Testing Pipes",
|
||||
"tooltip": "Writing tests for pipes."
|
||||
},
|
||||
{
|
||||
"url": "guide/test-debugging",
|
||||
"title": "Debugging Tests",
|
||||
"tooltip": "How to debug tests."
|
||||
},
|
||||
{
|
||||
"url": "guide/testing-utility-apis",
|
||||
"title": "Testing Utility APIs",
|
||||
"tooltip": "Features of the Angular testing utilities."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "guide/deployment",
|
||||
@ -672,9 +784,20 @@
|
||||
"tooltip": "End-to-end tutorials for learning Angular concepts and patterns.",
|
||||
"children": [
|
||||
{
|
||||
"url": "guide/router-tutorial",
|
||||
"title": "Using Angular Routes in a Single-page Application",
|
||||
"tooltip": "A tutorial that covers many patterns associated with Angular routing."
|
||||
"title": "Routing",
|
||||
"tooltip": "End-to-end tutorials for learning about Angular's router.",
|
||||
"children": [
|
||||
{
|
||||
"url": "guide/router-tutorial",
|
||||
"title": "Using Angular Routes in a Single-page Application",
|
||||
"tooltip": "A tutorial that covers many patterns associated with Angular routing."
|
||||
},
|
||||
{
|
||||
"url": "guide/router-tutorial-toh",
|
||||
"title": "Router tutorial: tour of heroes",
|
||||
"tooltip": "Explore how to use Angular's router. Based on the Tour of Heroes example."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "guide/forms",
|
||||
@ -832,80 +955,100 @@
|
||||
],
|
||||
"Footer": [
|
||||
{
|
||||
"title": "Resources",
|
||||
"title": "Recursos",
|
||||
"children": [
|
||||
{
|
||||
"url": "about",
|
||||
"title": "About",
|
||||
"tooltip": "Angular contributors."
|
||||
"title": "Contribuyentes",
|
||||
"tooltip": "Contribuyentes de Angular."
|
||||
},
|
||||
{
|
||||
"url": "resources",
|
||||
"title": "Resource Listing",
|
||||
"tooltip": "Angular tools, training, and blogs from around the web."
|
||||
"title": "Listado de recursos",
|
||||
"tooltip": "Herramientas de Angular, capacitación y blogs de toda la web."
|
||||
},
|
||||
{
|
||||
"url": "presskit",
|
||||
"title": "Press Kit",
|
||||
"tooltip": "Press contacts, logos, and branding."
|
||||
"title": "Kit de prensa",
|
||||
"tooltip": "Contactos de prensa, logotipos y marcas."
|
||||
},
|
||||
{
|
||||
"url": "https://blog.angular.io/",
|
||||
"title": "Blog",
|
||||
"tooltip": "Angular Blog"
|
||||
"tooltip": "Blog de Angular"
|
||||
},
|
||||
{
|
||||
"url": "analytics",
|
||||
"title": "Usage Analytics",
|
||||
"tooltip": "Angular Usage Analytics"
|
||||
"title": "Analítica de uso",
|
||||
"tooltip": "Analítica de uso Angular"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Help",
|
||||
"title": "Consigue ayuda",
|
||||
"children": [
|
||||
{
|
||||
"url": "https://chat.angular.lat/",
|
||||
"title": "Angular Hispano Chat",
|
||||
"tooltip": "Chatea en castellano sobre Angular con otros miembros de la comunidad."
|
||||
},
|
||||
{
|
||||
"url": "https://angular.lat/coc",
|
||||
"title": "Código de Conducta",
|
||||
"tooltip": "Tratarnos con respeto y proporcionar un lugar seguro para contribuir."
|
||||
},
|
||||
{
|
||||
"url": "https://stackoverflow.com/questions/tagged/angular",
|
||||
"title": "Stack Overflow",
|
||||
"tooltip": "Stack Overflow: where the community answers your technical Angular questions."
|
||||
"tooltip": "Stack Overflow: donde la comunidad responde sus preguntas técnicas de Angular."
|
||||
},
|
||||
{
|
||||
"url": "https://gitter.im/angular/angular",
|
||||
"title": "Gitter",
|
||||
"tooltip": "Chat about Angular with other birds of a feather."
|
||||
"tooltip": "Chatea en inglés sobre Angular con otros miembros de la comunidad."
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/angular/angular/issues",
|
||||
"title": "Report Issues",
|
||||
"tooltip": "Post issues and suggestions on github."
|
||||
"title": "Informar Issues",
|
||||
"tooltip": "Publica problemas y sugerencias en GitHub."
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md",
|
||||
"title": "Code of Conduct",
|
||||
"tooltip": "Treating each other with respect."
|
||||
"url": "https://github.com/angular-hispano/angular/issues",
|
||||
"title": "Issues de traducción",
|
||||
"tooltip": "Publica issues y sugerencias de traducción en GitHub."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Community",
|
||||
"title": "Comunidad",
|
||||
"children": [
|
||||
{
|
||||
"url": "events",
|
||||
"title": "Events",
|
||||
"tooltip": "Angular events around the world."
|
||||
"url": "https://angular.lat/conferencias",
|
||||
"title": "Eventos Hispanos",
|
||||
"tooltip": "Eventos en castellano de Angular alrededor del mundo."
|
||||
},
|
||||
{
|
||||
"url": "https://angular.lat/meetups",
|
||||
"title": "Meetups Hispanos",
|
||||
"tooltip": "Asista a una reunión y aprenda de otros desarrolladores."
|
||||
},
|
||||
{
|
||||
"url": "http://www.meetup.com/topics/angularjs/",
|
||||
"title": "Meetups",
|
||||
"tooltip": "Attend a meetup and learn from fellow developers."
|
||||
"title": "Mas Meetups",
|
||||
"tooltip": "Asista a una reunión y aprenda de otros desarrolladores."
|
||||
},
|
||||
{
|
||||
"url": "https://twitter.com/angular",
|
||||
"url": "events",
|
||||
"title": "Mas Eventos",
|
||||
"tooltip": "Eventos de Angular alrededor del mundo."
|
||||
},
|
||||
{
|
||||
"url": "https://twitter.com/AngularHispana",
|
||||
"title": "Twitter",
|
||||
"tooltip": "Twitter"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/angular/angular",
|
||||
"url": "https://github.com/angular-hispano",
|
||||
"title": "GitHub",
|
||||
"tooltip": "GitHub"
|
||||
},
|
||||
@ -917,7 +1060,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Languages",
|
||||
"title": "Idiomas",
|
||||
"children": [
|
||||
{
|
||||
"title": "简体中文版",
|
||||
|
@ -22,7 +22,7 @@ StackBlitz projects are public by default, allowing you to share your Angular ap
|
||||
|
||||
To build your application locally or for production, download the source code from your StackBlitz project by clicking the `Download Project` icon in the left menu across from `Project` to download your files.
|
||||
|
||||
Once you have the source code downloaded and unzipped, use the [Angular Console](https://angularconsole.com "Angular Console web site") to serve the application, or install `Node.js` and serve your app with the Angular CLI.
|
||||
Once you have the source code downloaded and unzipped, install `Node.js` and serve your app with the Angular CLI.
|
||||
|
||||
From the terminal, install the Angular CLI globally with:
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user