Compare commits
308 Commits
master
...
11.0.0-nex
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4baabf9cd3 | ||
![]() |
7244e1b4e3 | ||
![]() |
b1682526dd | ||
![]() |
75610505c6 | ||
![]() |
ba3f4c26bb | ||
![]() |
c8f056beb6 | ||
![]() |
a2068523fd | ||
![]() |
145ab3d7e0 | ||
![]() |
3082f7378b | ||
![]() |
297b123151 | ||
![]() |
a93605f2a4 | ||
![]() |
15dfd3439a | ||
![]() |
123bff7cb6 | ||
![]() |
6158dc16b4 | ||
![]() |
b0a43872a8 | ||
![]() |
856e74ac98 | ||
![]() |
6ae3b68acf | ||
![]() |
49f27e31ed | ||
![]() |
1a62f74496 | ||
![]() |
2b1b7180db | ||
![]() |
fdd4fa0009 | ||
![]() |
984ed39195 | ||
![]() |
0c0c54d615 | ||
![]() |
dfbfabc052 | ||
![]() |
f3f6a42342 | ||
![]() |
e498ea9b5a | ||
![]() |
a91f0f6b82 | ||
![]() |
d5ddb9f340 | ||
![]() |
b68fab547a | ||
![]() |
16a560119a | ||
![]() |
88d7bb8386 | ||
![]() |
2d6105a784 | ||
![]() |
95b8a8706a | ||
![]() |
d92a0dd72f | ||
![]() |
55485713a3 | ||
![]() |
d3169c533e | ||
![]() |
e4424863c2 | ||
![]() |
d795a00137 | ||
![]() |
7fb388f929 | ||
![]() |
02c6bff9cf | ||
![]() |
ef28e15884 | ||
![]() |
a33d630a21 | ||
![]() |
c4b8964424 | ||
![]() |
dd8d8c8289 | ||
![]() |
129107191c | ||
![]() |
722699fb0c | ||
![]() |
5614258cc7 | ||
![]() |
e62a918542 | ||
![]() |
49ee90b1b5 | ||
![]() |
7849fdde09 | ||
![]() |
97adc27207 | ||
![]() |
41bc2701c4 | ||
![]() |
a765530277 | ||
![]() |
5b33798796 | ||
![]() |
44074499dc | ||
![]() |
ba54671993 | ||
![]() |
a85109fd72 | ||
![]() |
85a2626620 | ||
![]() |
d192c87f6a | ||
![]() |
3817e5f1df | ||
![]() |
171a0d0696 | ||
![]() |
a1c1c450dc | ||
![]() |
fd44d84a33 | ||
![]() |
f0688b4d18 | ||
![]() |
b9ca6d20cc | ||
![]() |
e00535a2a4 | ||
![]() |
593bd594e3 | ||
![]() |
284c70ee9d | ||
![]() |
78e1ecb161 | ||
![]() |
3934f0a833 | ||
![]() |
297c060ae7 | ||
![]() |
077f51685a | ||
![]() |
e162da0753 | ||
![]() |
354138eba9 | ||
![]() |
6768fe9927 | ||
![]() |
57c442f930 | ||
![]() |
f667e374a9 | ||
![]() |
15207e3c9c | ||
![]() |
66129f8ea6 | ||
![]() |
da14b72550 | ||
![]() |
27cc56b359 | ||
![]() |
6acea54f62 | ||
![]() |
2d52c80332 | ||
![]() |
03447ba52f | ||
![]() |
8f349b2375 | ||
![]() |
19598b47ca | ||
![]() |
f56ece4fdc | ||
![]() |
cf2e8b99a8 | ||
![]() |
c4556db9f5 | ||
![]() |
a46e0e48a3 | ||
![]() |
9e77bd3087 | ||
![]() |
26f28200bf | ||
![]() |
ce1efc1af2 | ||
![]() |
d1415162cb | ||
![]() |
db21c4fb44 | ||
![]() |
281865bbcf | ||
![]() |
3406ec15a4 | ||
![]() |
85951a0465 | ||
![]() |
0ae00bb1f7 | ||
![]() |
1373a98e25 | ||
![]() |
1ed6913b8b | ||
![]() |
3c4b8b97c1 | ||
![]() |
f9421184ef | ||
![]() |
c6ebb77cec | ||
![]() |
a69507a0ad | ||
![]() |
886f58d4fe | ||
![]() |
18f84a0328 | ||
![]() |
b0ca3cd0c4 | ||
![]() |
3d77b64fc3 | ||
![]() |
f645d26e3f | ||
![]() |
6d9bfb8368 | ||
![]() |
7997fc5f97 | ||
![]() |
3cb2a79399 | ||
![]() |
d896c33b0e | ||
![]() |
19a484302d | ||
![]() |
ded075a79c | ||
![]() |
ba95b79a21 | ||
![]() |
4faac78e32 | ||
![]() |
4360eed9b7 | ||
![]() |
c880e393e9 | ||
![]() |
b0c79f2373 | ||
![]() |
a32a317ea1 | ||
![]() |
bfb7eec698 | ||
![]() |
7e0b3fd953 | ||
![]() |
7a6a061a9e | ||
![]() |
109555b33a | ||
![]() |
bf31ef29f6 | ||
![]() |
40096bee00 | ||
![]() |
45a73dddfd | ||
![]() |
687477279b | ||
![]() |
4007422cc6 | ||
![]() |
1150649139 | ||
![]() |
7869de6136 | ||
![]() |
2c4a98a285 | ||
![]() |
92ff6d93eb | ||
![]() |
83ace4ed30 | ||
![]() |
926ffcd8ac | ||
![]() |
97475d7408 | ||
![]() |
a29f9a9fb3 | ||
![]() |
9f28f82598 | ||
![]() |
261f689e9b | ||
![]() |
1d9873c44c | ||
![]() |
d9da7e5a18 | ||
![]() |
79d8795633 | ||
![]() |
3e57ca1d98 | ||
![]() |
c2d017de83 | ||
![]() |
7baa7ebfc4 | ||
![]() |
4e5286180b | ||
![]() |
73001b42fe | ||
![]() |
c90eb5450d | ||
![]() |
3e97435f1c | ||
![]() |
1c7e5cef3e | ||
![]() |
2cb3d58b42 | ||
![]() |
44bb85ade4 | ||
![]() |
50f4d8a1ce | ||
![]() |
fdea1804d6 | ||
![]() |
1d8c5d88cd | ||
![]() |
a68f1a78a7 | ||
![]() |
86e11f1110 | ||
![]() |
5da1934115 | ||
![]() |
86e7cd8117 | ||
![]() |
e6ee7c2aeb | ||
![]() |
54687f7765 | ||
![]() |
59c234cfb4 | ||
![]() |
a6f3cd93a9 | ||
![]() |
d9fea857db | ||
![]() |
03dbcc7a56 | ||
![]() |
c142b071eb | ||
![]() |
71acf9dd49 | ||
![]() |
f5a148b1b7 | ||
![]() |
4f28192d62 | ||
![]() |
0fc2bef0cd | ||
![]() |
f5d1e9a2d1 | ||
![]() |
036a2faf02 | ||
![]() |
5be4edfa17 | ||
![]() |
38d6596742 | ||
![]() |
0a7a5e3aff | ||
![]() |
d5fabc303d | ||
![]() |
ebc0e46501 | ||
![]() |
3487b549fd | ||
![]() |
52c7a4bfc6 | ||
![]() |
827ba05914 | ||
![]() |
b2857b4e3a | ||
![]() |
5d5caf21b8 | ||
![]() |
c1bc070b40 | ||
![]() |
930eeaf177 | ||
![]() |
2dd29fbae7 | ||
![]() |
9613660fee | ||
![]() |
c0523fc3b4 | ||
![]() |
de1cffb23b | ||
![]() |
31f4557621 | ||
![]() |
7723bfd9ba | ||
![]() |
e8ea839df8 | ||
![]() |
90cec40cce | ||
![]() |
4036281007 | ||
![]() |
164cd274a4 | ||
![]() |
fedcfec346 | ||
![]() |
618cb32407 | ||
![]() |
4aee0087ea | ||
![]() |
0681a20d28 | ||
![]() |
fb06903237 | ||
![]() |
ecc6fd0d28 | ||
![]() |
80cab26023 | ||
![]() |
841dfa68f9 | ||
![]() |
f0af387f6c | ||
![]() |
14e90bef58 | ||
![]() |
db3a21b382 | ||
![]() |
b8351f3b10 | ||
![]() |
81053d3160 | ||
![]() |
bdba1a062d | ||
![]() |
23f855b300 | ||
![]() |
94a3e0e81d | ||
![]() |
9cbde86534 | ||
![]() |
18e474f522 | ||
![]() |
cb3db0d31b | ||
![]() |
d36828a7a1 | ||
![]() |
f18e2d5898 | ||
![]() |
375f0a6f67 | ||
![]() |
281b647f15 | ||
![]() |
0fc44e0436 | ||
![]() |
201a546af8 | ||
![]() |
6e643d9874 | ||
![]() |
4985267211 | ||
![]() |
b48cc6ead5 | ||
![]() |
874792dc43 | ||
![]() |
e7da4040d6 | ||
![]() |
2a643e1ab6 | ||
![]() |
364284b0dc | ||
![]() |
956b25a100 | ||
![]() |
8017ca4db3 | ||
![]() |
22f1ac3e37 | ||
![]() |
4ee5e730ab | ||
![]() |
6442875c99 | ||
![]() |
8f24bc9443 | ||
![]() |
ac461e1efd | ||
![]() |
f245c6bb15 | ||
![]() |
68a9a01a64 | ||
![]() |
8cd4099db9 | ||
![]() |
0b54c0c6b4 | ||
![]() |
1ec609946f | ||
![]() |
7ad32649c0 | ||
![]() |
9ad69c1503 | ||
![]() |
9af2de821c | ||
![]() |
0270020ac2 | ||
![]() |
6b662d10c1 | ||
![]() |
55fd725e74 | ||
![]() |
f77fd5e02a | ||
![]() |
63ba74fe4e | ||
![]() |
aaa1d8e2fe | ||
![]() |
dbfb50e9f4 | ||
![]() |
bee44b3359 | ||
![]() |
723a9ff095 | ||
![]() |
e472f5f688 | ||
![]() |
8373b720f3 | ||
![]() |
301513311e | ||
![]() |
64cf087ae5 | ||
![]() |
fec9dcbeb0 | ||
![]() |
e0e5c9f195 | ||
![]() |
cfe424e875 | ||
![]() |
3b9c802dee | ||
![]() |
ca07da4563 | ||
![]() |
81c3e809aa | ||
![]() |
be96510ce9 | ||
![]() |
cb05c0102f | ||
![]() |
5f90b64328 | ||
![]() |
71079ce47e | ||
![]() |
ca798804b2 | ||
![]() |
b071495f92 | ||
![]() |
d5f819ebc1 | ||
![]() |
1388c1761f | ||
![]() |
fb8f4b4d72 | ||
![]() |
f42e6ce917 | ||
![]() |
175c79d1d8 | ||
![]() |
945751e2e8 | ||
![]() |
b769771d60 | ||
![]() |
a80f654af9 | ||
![]() |
aa847cb014 | ||
![]() |
8763d8201c | ||
![]() |
9f7a37b4e9 | ||
![]() |
773f7908c0 | ||
![]() |
f4ced74e3a | ||
![]() |
8366effeec | ||
![]() |
5f2e475abf | ||
![]() |
aa3520eb7d | ||
![]() |
823dd5b341 | ||
![]() |
d6d7caa2a8 | ||
![]() |
dcf7baf3d1 | ||
![]() |
4d17418569 | ||
![]() |
a2e069fdda | ||
![]() |
28534d83ee | ||
![]() |
a6292faa97 | ||
![]() |
e2e5f83869 | ||
![]() |
71138f6004 | ||
![]() |
fa0104017a | ||
![]() |
80b67e02b7 | ||
![]() |
18098d38b8 | ||
![]() |
9514fd9080 | ||
![]() |
2e9fdbde9e | ||
![]() |
df76a2048b | ||
![]() |
3d156162af | ||
![]() |
5dc8d287aa | ||
![]() |
6da9e5851a | ||
![]() |
250e299dc3 | ||
![]() |
8f708b561c | ||
![]() |
e34c33cd46 | ||
![]() |
6d8c73a4d6 | ||
![]() |
6ff28ac944 | ||
![]() |
0de93fd402 |
@ -30,6 +30,11 @@ var_4: &cache_key_fallback v7-angular-node-12-{{ checksum ".bazelversion" }}
|
||||
var_3_win: &cache_key_win v7-angular-win-node-12-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
||||
var_4_win: &cache_key_win_fallback v7-angular-win-node-12-{{ checksum ".bazelversion" }}
|
||||
|
||||
# Cache key for the `components-repo-unit-tests` job. **Note** when updating the SHA in the
|
||||
# cache keys also update the SHA for the "COMPONENTS_REPO_COMMIT" environment variable.
|
||||
var_5: &components_repo_unit_tests_cache_key v9-angular-components-09e68db8ed5b1253f2fe38ff954ef0df019fc25a
|
||||
var_6: &components_repo_unit_tests_cache_key_fallback v9-angular-components-
|
||||
|
||||
# Workspace initially persisted by the `setup` job, and then enhanced by `build-npm-packages` and
|
||||
# `build-ivy-npm-packages`.
|
||||
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
|
||||
@ -151,6 +156,27 @@ commands:
|
||||
git config --global url."ssh://git@github.com".insteadOf "https://github.com" || true
|
||||
git config --global gc.auto 0 || true
|
||||
|
||||
init_saucelabs_environment:
|
||||
description: Sets up a domain that resolves to the local host.
|
||||
steps:
|
||||
- run:
|
||||
name: Preparing environment for running tests on Sauce Labs.
|
||||
command: |
|
||||
# For SauceLabs jobs, we set up a domain which resolves to the machine which launched
|
||||
# the tunnel. We do this because devices are sometimes not able to properly resolve
|
||||
# `localhost` or `127.0.0.1` through the SauceLabs tunnel. Using a domain that does not
|
||||
# resolve to anything on SauceLabs VMs ensures that such requests are always resolved
|
||||
# through the tunnel, and resolve to the actual tunnel host machine (i.e. the CircleCI VM).
|
||||
# More context can be found in: https://github.com/angular/angular/pull/35171.
|
||||
setPublicVar SAUCE_LOCALHOST_ALIAS_DOMAIN "angular-ci.local"
|
||||
setSecretVar SAUCE_ACCESS_KEY $(echo $SAUCE_ACCESS_KEY | rev)
|
||||
- run:
|
||||
# Sets up a local domain in the machine's host file that resolves to the local
|
||||
# host. This domain is helpful in Sauce Labs tests where devices are not able to
|
||||
# properly resolve `localhost` or `127.0.0.1` through the sauce-connect tunnel.
|
||||
name: Setting up alias domain for local host.
|
||||
command: echo "127.0.0.1 $SAUCE_LOCALHOST_ALIAS_DOMAIN" | sudo tee -a /etc/hosts
|
||||
|
||||
# Normally this would be an individual job instead of a command.
|
||||
# But startup and setup time for each individual windows job are high enough to discourage
|
||||
# many small jobs, so instead we use a command for setup unless the gain becomes significant.
|
||||
@ -246,8 +272,109 @@ jobs:
|
||||
- run: yarn -s tslint
|
||||
- run: yarn -s ng-dev format changed $CI_GIT_BASE_REVISION --check
|
||||
- run: yarn -s ts-circular-deps:check
|
||||
- run: yarn -s ng-dev pullapprove verify
|
||||
- run: yarn -s ng-dev commit-message validate-range --range $CI_COMMIT_RANGE
|
||||
|
||||
test:
|
||||
executor:
|
||||
name: default-executor
|
||||
# Now that large integration tests are running locally in parallel (they can't run on RBE yet
|
||||
# as they require network access for yarn install), this test is running out of memory
|
||||
# consistently with the xlarge machine.
|
||||
# TODO: switch back to xlarge once integration tests are running on remote-exec
|
||||
resource_class: 2xlarge+
|
||||
steps:
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- install_chrome_libs
|
||||
- install_java
|
||||
- run:
|
||||
command: yarn bazel test //... --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only
|
||||
no_output_timeout: 20m
|
||||
|
||||
# Temporary job to test what will happen when we flip the Ivy flag to true
|
||||
test_ivy_aot:
|
||||
executor:
|
||||
name: default-executor
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- install_chrome_libs
|
||||
# We need to explicitly specify the --symlink_prefix option because otherwise we would
|
||||
# not be able to easily find the output bin directory when uploading artifacts for size
|
||||
# measurements.
|
||||
- run:
|
||||
command: yarn test-ivy-aot //... --symlink_prefix=dist/
|
||||
no_output_timeout: 20m
|
||||
|
||||
# Publish bundle artifacts which will be used to calculate the size change. **Note**: Make
|
||||
# sure that the size plugin from the Angular robot fetches the artifacts from this CircleCI
|
||||
# job (see .github/angular-robot.yml). Additionally any artifacts need to be stored with the
|
||||
# following path format: "{projectName}/{context}/{fileName}". This format is necessary
|
||||
# because otherwise the bot is not able to pick up the artifacts from CircleCI. See:
|
||||
# https://github.com/angular/github-robot/blob/master/functions/src/plugins/size.ts#L392-L394
|
||||
- store_artifacts:
|
||||
path: dist/bin/packages/core/test/bundling/hello_world/bundle.min.js
|
||||
destination: core/hello_world/bundle
|
||||
- store_artifacts:
|
||||
path: dist/bin/packages/core/test/bundling/todo/bundle.min.js
|
||||
destination: core/todo/bundle
|
||||
- store_artifacts:
|
||||
path: dist/bin/packages/core/test/bundling/hello_world/bundle.min.js.br
|
||||
destination: core/hello_world/bundle.br
|
||||
- store_artifacts:
|
||||
path: dist/bin/packages/core/test/bundling/todo/bundle.min.js.br
|
||||
destination: core/todo/bundle.br
|
||||
|
||||
# NOTE: This is currently limited to master builds only. See the `monitoring` configuration.
|
||||
saucelabs_view_engine:
|
||||
executor:
|
||||
name: default-executor
|
||||
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
||||
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
||||
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- init_saucelabs_environment
|
||||
- run:
|
||||
name: Run Bazel tests on Saucelabs with ViewEngine
|
||||
# See /tools/saucelabs/README.md for more info
|
||||
command: |
|
||||
yarn bazel run //tools/saucelabs:sauce_service_setup
|
||||
TESTS=$(./node_modules/.bin/bazelisk query --output label '(kind(karma_web_test, ...) intersect attr("tags", "saucelabs", ...)) except attr("tags", "ivy-only", ...) except attr("tags", "fixme-saucelabs-ve", ...)')
|
||||
yarn bazel test --config=saucelabs ${TESTS}
|
||||
yarn bazel run //tools/saucelabs:sauce_service_stop
|
||||
no_output_timeout: 40m
|
||||
- notify_webhook_on_fail:
|
||||
webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
||||
|
||||
# NOTE: This is currently limited to master builds only. See the `monitoring` configuration.
|
||||
saucelabs_ivy:
|
||||
executor:
|
||||
name: default-executor
|
||||
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
||||
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
||||
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- init_saucelabs_environment
|
||||
- run:
|
||||
name: Run Bazel tests on Saucelabs with Ivy
|
||||
# See /tools/saucelabs/README.md for more info
|
||||
command: |
|
||||
yarn bazel run //tools/saucelabs:sauce_service_setup
|
||||
TESTS=$(./node_modules/.bin/bazelisk query --output label '(kind(karma_web_test, ...) intersect attr("tags", "saucelabs", ...)) except attr("tags", "no-ivy-aot", ...) except attr("tags", "fixme-saucelabs-ivy", ...)')
|
||||
yarn bazel test --config=saucelabs --config=ivy ${TESTS}
|
||||
yarn bazel run //tools/saucelabs:sauce_service_stop
|
||||
no_output_timeout: 40m
|
||||
- notify_webhook_on_fail:
|
||||
webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
||||
|
||||
test_aio:
|
||||
executor: default-executor
|
||||
steps:
|
||||
@ -266,6 +393,10 @@ jobs:
|
||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||
# Run accessibility tests
|
||||
- run: yarn --cwd aio test-a11y-score-localhost
|
||||
# Check the bundle sizes.
|
||||
- run: yarn --cwd aio payload-size
|
||||
# Run unit tests for Firebase redirects
|
||||
- run: yarn --cwd aio redirects-test
|
||||
|
||||
deploy_aio:
|
||||
executor: default-executor
|
||||
@ -295,6 +426,8 @@ jobs:
|
||||
- run: yarn --cwd aio e2e --configuration=ci
|
||||
# Run PWA-score tests
|
||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||
# Check the bundle sizes.
|
||||
- run: yarn --cwd aio payload-size aio-local<<# parameters.viewengine >>-viewengine<</ parameters.viewengine >>
|
||||
|
||||
test_aio_tools:
|
||||
executor: default-executor
|
||||
@ -308,6 +441,26 @@ jobs:
|
||||
- run: yarn --cwd aio tools-test
|
||||
- run: ./aio/aio-builds-setup/scripts/test.sh
|
||||
|
||||
test_docs_examples:
|
||||
parameters:
|
||||
viewengine:
|
||||
type: boolean
|
||||
default: false
|
||||
executor:
|
||||
name: default-executor
|
||||
resource_class: xlarge
|
||||
parallelism: 5
|
||||
steps:
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- install_chrome_libs
|
||||
# Install aio
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
# Run examples tests. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
||||
# Since the parallelism is set to "5", there will be five parallel CircleCI containers.
|
||||
# with either "0", "1", etc as node index. This can be passed to the "--shard" argument.
|
||||
- run: yarn --cwd aio example-e2e --setup --local <<# parameters.viewengine >>--viewengine<</ parameters.viewengine >> --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL} --retry 2
|
||||
|
||||
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
||||
aio_preview:
|
||||
executor: default-executor
|
||||
@ -336,6 +489,7 @@ jobs:
|
||||
name: Wait for preview and run tests
|
||||
command: node aio/scripts/test-preview.js $CI_PULL_REQUEST $CI_COMMIT $CI_AIO_MIN_PWA_SCORE
|
||||
|
||||
|
||||
# The `build-npm-packages` tasks exist for backwards-compatibility with old scripts and
|
||||
# tests that rely on the pre-Bazel `dist/packages-dist` output structure (build.sh).
|
||||
# Having multiple jobs that independently build in this manner duplicates some work; we build
|
||||
@ -347,7 +501,7 @@ jobs:
|
||||
build-npm-packages:
|
||||
executor:
|
||||
name: default-executor
|
||||
resource_class: medium
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
@ -369,6 +523,262 @@ jobs:
|
||||
- "~/bazel_repository_cache"
|
||||
- "~/.cache/bazelisk"
|
||||
|
||||
# Build the ivy npm packages.
|
||||
build-ivy-npm-packages:
|
||||
executor:
|
||||
name: default-executor
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- run: node scripts/build/build-ivy-npm-packages.js
|
||||
|
||||
# Save the npm packages from //packages/... for other workflow jobs to read
|
||||
- persist_to_workspace:
|
||||
root: *workspace_location
|
||||
paths:
|
||||
- ng/dist/packages-dist-ivy-aot
|
||||
- ng/dist/zone.js-dist-ivy-aot
|
||||
|
||||
# This job creates compressed tarballs (`.tgz` files) for all Angular packages and stores them as
|
||||
# build artifacts. This makes it easy to try out changes from a PR build for testing purposes.
|
||||
# More info CircleCI build artifacts: https://circleci.com/docs/2.0/artifacts
|
||||
#
|
||||
# NOTE: Currently, this job only runs for PR builds. See `publish_snapshot` for non-PR builds.
|
||||
publish_packages_as_artifacts:
|
||||
executor: default-executor
|
||||
environment:
|
||||
NG_PACKAGES_DIR: &ng_packages_dir 'dist/packages-dist'
|
||||
NG_PACKAGES_ARCHIVES_DIR: &ng_packages_archives_dir 'dist/packages-dist-archives'
|
||||
ZONEJS_PACKAGES_DIR: &zonejs_packages_dir 'dist/zone.js-dist'
|
||||
ZONEJS_PACKAGES_ARCHIVES_DIR: &zonejs_packages_archives_dir 'dist/zone.js-dist-archives'
|
||||
steps:
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
# Publish `@angular/*` packages.
|
||||
- run:
|
||||
name: Create artifacts for @angular/* packages
|
||||
command: ./scripts/ci/create-package-archives.sh $CI_BRANCH $CI_COMMIT $NG_PACKAGES_DIR $NG_PACKAGES_ARCHIVES_DIR
|
||||
- store_artifacts:
|
||||
path: *ng_packages_archives_dir
|
||||
destination: angular
|
||||
# Publish `zone.js` package.
|
||||
- run:
|
||||
name: Create artifacts for zone.js package
|
||||
command: ./scripts/ci/create-package-archives.sh $CI_BRANCH $CI_COMMIT $ZONEJS_PACKAGES_DIR $ZONEJS_PACKAGES_ARCHIVES_DIR
|
||||
- store_artifacts:
|
||||
path: *zonejs_packages_archives_dir
|
||||
destination: zone.js
|
||||
|
||||
# This job updates the content of repos like github.com/angular/core-builds
|
||||
# for every green build on angular/angular.
|
||||
publish_snapshot:
|
||||
executor: default-executor
|
||||
steps:
|
||||
# See below - ideally this job should not trigger for non-upstream builds.
|
||||
# But since it does, we have to check this condition.
|
||||
- run:
|
||||
name: Skip this job for Pull Requests and Fork builds
|
||||
# Note: Using `CIRCLE_*` env variables (instead of those defined in `env.sh` so that this
|
||||
# step can be run before `init_environment`.
|
||||
command: >
|
||||
if [[ -n "${CIRCLE_PR_NUMBER}" ]] ||
|
||||
[[ "$CIRCLE_PROJECT_USERNAME" != "angular" ]] ||
|
||||
[[ "$CIRCLE_PROJECT_REPONAME" != "angular" ]]; then
|
||||
circleci step halt
|
||||
fi
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
# CircleCI has a config setting to force SSH for all github connections
|
||||
# This is not compatible with our mechanism of using a Personal Access Token
|
||||
# Clear the global setting
|
||||
- run: git config --global --unset "url.ssh://git@github.com.insteadof"
|
||||
- run:
|
||||
name: Decrypt github credentials
|
||||
# We need ensure that the same default digest is used for encoding and decoding with
|
||||
# OpenSSL. OpenSSL versions might have different default digests which can cause
|
||||
# decryption failures based on the installed OpenSSL version. https://stackoverflow.com/a/39641378/4317734
|
||||
command: 'openssl aes-256-cbc -d -in .circleci/github_token -md md5 -k "${KEY}" -out ~/.git_credentials'
|
||||
- run: ./scripts/ci/publish-build-artifacts.sh
|
||||
|
||||
aio_monitoring_stable:
|
||||
executor: default-executor
|
||||
steps:
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- install_chrome_libs
|
||||
- run: setPublicVar_CI_STABLE_BRANCH
|
||||
- run:
|
||||
name: Check out `aio/` and yarn from the stable branch
|
||||
command: |
|
||||
git fetch origin $CI_STABLE_BRANCH
|
||||
git checkout --force origin/$CI_STABLE_BRANCH -- aio/ .yarn/ .yarnrc
|
||||
# Ignore yarn's engines check, because we checked out `aio/package.json` from the stable
|
||||
# branch and there could be a node version skew, which is acceptable in this monitoring job.
|
||||
- run: yarn config set ignore-engines true
|
||||
- run:
|
||||
name: Run tests against https://angular.io/
|
||||
command: ./aio/scripts/test-production.sh https://angular.io/ $CI_AIO_MIN_PWA_SCORE
|
||||
- notify_webhook_on_fail:
|
||||
webhook_url_env_var: SLACK_CARETAKER_WEBHOOK_URL
|
||||
- notify_webhook_on_fail:
|
||||
webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
||||
|
||||
aio_monitoring_next:
|
||||
executor: default-executor
|
||||
steps:
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- install_chrome_libs
|
||||
- run:
|
||||
name: Run tests against https://next.angular.io/
|
||||
command: ./aio/scripts/test-production.sh https://next.angular.io/ $CI_AIO_MIN_PWA_SCORE
|
||||
- notify_webhook_on_fail:
|
||||
webhook_url_env_var: SLACK_CARETAKER_WEBHOOK_URL
|
||||
- notify_webhook_on_fail:
|
||||
webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
||||
|
||||
legacy-unit-tests-saucelabs:
|
||||
executor:
|
||||
name: default-executor
|
||||
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
||||
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
||||
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- init_saucelabs_environment
|
||||
- run:
|
||||
name: Starting Saucelabs tunnel service
|
||||
command: ./tools/saucelabs/sauce-service.sh run
|
||||
background: true
|
||||
# add module umd tsc compile option so the test can work
|
||||
# properly in the legacy browsers
|
||||
- run: yarn tsc -p packages --module UMD
|
||||
- run: yarn tsc -p modules --module UMD
|
||||
- run: yarn bazel build //packages/zone.js:npm_package
|
||||
# Build test fixtures for a test that rely on Bazel-generated fixtures. Note that disabling
|
||||
# specific tests which are reliant on such generated fixtures is not an option as SystemJS
|
||||
# in the Saucelabs legacy job always fetches referenced files, even if the imports would be
|
||||
# guarded by an check to skip in the Saucelabs legacy job. We should be good running such
|
||||
# test in all supported browsers on Saucelabs anyway until this job can be removed.
|
||||
- run:
|
||||
name: Preparing Bazel-generated fixtures required in legacy tests
|
||||
command: |
|
||||
yarn bazel build //packages/core/test:downleveled_es5_fixture
|
||||
# Needed for the ES5 downlevel reflector test in `packages/core/test/reflection`.
|
||||
cp dist/bin/packages/core/test/reflection/es5_downleveled_inheritance_fixture.js \
|
||||
dist/all/@angular/core/test/reflection/es5_downleveled_inheritance_fixture.js
|
||||
- run:
|
||||
# Waiting on ready ensures that we don't run tests too early without Saucelabs not being ready.
|
||||
name: Waiting for Saucelabs tunnel to connect
|
||||
command: ./tools/saucelabs/sauce-service.sh ready-wait
|
||||
- run:
|
||||
name: Running tests on Saucelabs.
|
||||
command: |
|
||||
browsers=$(node -e 'console.log(require("./browser-providers.conf").sauceAliases.CI_REQUIRED.join(","))')
|
||||
yarn karma start ./karma-js.conf.js --single-run --browsers=${browsers}
|
||||
- run:
|
||||
name: Stop Saucelabs tunnel service
|
||||
command: ./tools/saucelabs/sauce-service.sh stop
|
||||
|
||||
# Job that runs all unit tests of the `angular/components` repository.
|
||||
components-repo-unit-tests:
|
||||
executor:
|
||||
name: default-executor
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
# Restore the cache before cloning the repository because the clone script re-uses
|
||||
# the restored repository if present. This reduces the amount of times the components
|
||||
# repository needs to be cloned (this is slow and increases based on commits in the repo).
|
||||
- restore_cache:
|
||||
keys:
|
||||
- *components_repo_unit_tests_cache_key
|
||||
# Whenever the `angular/components` SHA is updated, the cache key will no longer
|
||||
# match. The fallback cache will still match, and CircleCI will restore the most
|
||||
# recently cached repository folder. Without the fallback cache, we'd need to download
|
||||
# the repository from scratch and it would slow down the job. This is because we can't
|
||||
# clone the repository with reduced `--depth`, but rather need to clone the whole
|
||||
# repository to be able to support arbitrary SHAs.
|
||||
- *components_repo_unit_tests_cache_key_fallback
|
||||
- run:
|
||||
name: "Fetching angular/components repository"
|
||||
command: ./scripts/ci/clone_angular_components_repo.sh
|
||||
- run:
|
||||
# Run yarn install to fetch the Bazel binaries as used in the components repo.
|
||||
name: Installing dependencies.
|
||||
# TODO: remove this once the repo has been updated to use NodeJS v12 and Yarn 1.19.1.
|
||||
# We temporarily ignore the "engines" because the Angular components repository has
|
||||
# minimum dependency on NodeJS v12 and Yarn 1.19.1, but the framework repository uses
|
||||
# older versions.
|
||||
command: yarn --ignore-engines --cwd ${COMPONENTS_REPO_TMP_DIR} install --frozen-lockfile --non-interactive
|
||||
- save_cache:
|
||||
key: *components_repo_unit_tests_cache_key
|
||||
paths:
|
||||
# Temporary directory must be kept in sync with the `$COMPONENTS_REPO_TMP_DIR` env
|
||||
# variable. It needs to be hardcoded here, because env variables interpolation is
|
||||
# not supported.
|
||||
- "/tmp/angular-components-repo"
|
||||
- run:
|
||||
# Updates the `angular/components` `package.json` file to refer to the release output
|
||||
# inside the `packages-dist` directory. Note that it's not necessary to perform a yarn
|
||||
# install as Bazel runs Yarn automatically when needed.
|
||||
name: Setting up release packages.
|
||||
command: node scripts/ci/update-deps-to-dist-packages.js ${COMPONENTS_REPO_TMP_DIR}/package.json dist/packages-dist/
|
||||
- run:
|
||||
name: "Running `angular/components` unit tests"
|
||||
command: ./scripts/ci/run_angular_components_unit_tests.sh
|
||||
|
||||
test_zonejs:
|
||||
executor:
|
||||
name: default-executor
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
# Install
|
||||
- run: yarn --cwd packages/zone.js install --frozen-lockfile --non-interactive
|
||||
# Run zone.js tools tests
|
||||
- run: yarn --cwd packages/zone.js promisetest
|
||||
- run: yarn --cwd packages/zone.js promisefinallytest
|
||||
- run: yarn bazel build //packages/zone.js:npm_package &&
|
||||
cp dist/bin/packages/zone.js/npm_package/bundles/zone-mix.umd.js ./packages/zone.js/test/extra/ &&
|
||||
cp dist/bin/packages/zone.js/npm_package/bundles/zone-patch-electron.umd.js ./packages/zone.js/test/extra/ &&
|
||||
yarn --cwd packages/zone.js electrontest
|
||||
- run: yarn --cwd packages/zone.js jesttest
|
||||
- run: yarn --cwd packages/zone.js/test/typings install --frozen-lockfile --non-interactive
|
||||
- run: yarn --cwd packages/zone.js/test/typings test
|
||||
|
||||
# Windows jobs
|
||||
# Docs: https://circleci.com/docs/2.0/hello-world-windows/
|
||||
test_win:
|
||||
executor: windows-executor
|
||||
steps:
|
||||
- setup_win
|
||||
- run:
|
||||
# Ran into a command parsing problem where `-browser:chromium-local` was converted to
|
||||
# `-browser: chromium-local` (a space was added) in https://circleci.com/gh/angular/angular/357511.
|
||||
# Probably a powershell command parsing thing. There's no problem using a yarn script though.
|
||||
command: yarn circleci-win-ve
|
||||
no_output_timeout: 45m
|
||||
# Save bazel repository cache to use on subsequent runs.
|
||||
# We don't save node_modules because it's faster to use the linux workspace and reinstall.
|
||||
- save_cache:
|
||||
key: *cache_key_win
|
||||
paths:
|
||||
- "C:/Users/circleci/bazel_repository_cache"
|
||||
|
||||
test_ivy_aot_win:
|
||||
executor: windows-executor
|
||||
steps:
|
||||
- setup_win
|
||||
- run:
|
||||
command: yarn circleci-win-ivy
|
||||
no_output_timeout: 45m
|
||||
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
@ -381,9 +791,21 @@ workflows:
|
||||
- lint:
|
||||
requires:
|
||||
- setup
|
||||
- test:
|
||||
requires:
|
||||
- setup
|
||||
- test_ivy_aot:
|
||||
requires:
|
||||
- setup
|
||||
- build-npm-packages:
|
||||
requires:
|
||||
- setup
|
||||
- build-ivy-npm-packages:
|
||||
requires:
|
||||
- setup
|
||||
- legacy-unit-tests-saucelabs:
|
||||
requires:
|
||||
- setup
|
||||
- test_aio:
|
||||
requires:
|
||||
- setup
|
||||
@ -393,9 +815,22 @@ workflows:
|
||||
- test_aio_local:
|
||||
requires:
|
||||
- build-npm-packages
|
||||
- test_aio_local:
|
||||
name: test_aio_local_viewengine
|
||||
viewengine: true
|
||||
requires:
|
||||
- build-npm-packages
|
||||
- test_aio_tools:
|
||||
requires:
|
||||
- build-npm-packages
|
||||
- test_docs_examples:
|
||||
requires:
|
||||
- build-npm-packages
|
||||
- test_docs_examples:
|
||||
name: test_docs_examples_viewengine
|
||||
viewengine: true
|
||||
requires:
|
||||
- build-npm-packages
|
||||
- aio_preview:
|
||||
# Only run on PR builds. (There can be no previews for non-PR builds.)
|
||||
<<: *only_on_pull_requests
|
||||
@ -404,3 +839,78 @@ workflows:
|
||||
- test_aio_preview:
|
||||
requires:
|
||||
- aio_preview
|
||||
- publish_packages_as_artifacts:
|
||||
requires:
|
||||
- build-npm-packages
|
||||
- publish_snapshot:
|
||||
# Note: no filters on this job because we want it to run for all upstream branches
|
||||
# We'd really like to filter out pull requests here, but not yet available:
|
||||
# https://discuss.circleci.com/t/workflows-pull-request-filter/14396/4
|
||||
# Instead, the job just exits immediately at the first step.
|
||||
requires:
|
||||
# Only publish if tests and integration tests pass
|
||||
- test
|
||||
- test_ivy_aot
|
||||
# Only publish if `aio`/`docs` tests using the locally built Angular packages pass
|
||||
- test_aio_local
|
||||
- test_aio_local_viewengine
|
||||
- test_docs_examples
|
||||
- test_docs_examples_viewengine
|
||||
# Get the artifacts to publish from the build-packages-dist job
|
||||
# since the publishing script expects the legacy outputs layout.
|
||||
- build-npm-packages
|
||||
- build-ivy-npm-packages
|
||||
- legacy-unit-tests-saucelabs
|
||||
- components-repo-unit-tests:
|
||||
requires:
|
||||
- build-npm-packages
|
||||
- test_zonejs:
|
||||
requires:
|
||||
- setup
|
||||
# Windows Jobs
|
||||
# These are very slow so we run them on non-PRs only for now.
|
||||
# TODO: remove the filter when CircleCI makes Windows FS faster.
|
||||
# The Windows jobs are only run after their non-windows counterparts finish successfully.
|
||||
# This isn't strictly necessary as there is no artifact dependency, but helps economize
|
||||
# CI resources by not attempting to build when we know should fail.
|
||||
- test_win:
|
||||
<<: *skip_on_pull_requests
|
||||
requires:
|
||||
- test
|
||||
- test_ivy_aot_win:
|
||||
<<: *skip_on_pull_requests
|
||||
requires:
|
||||
- test_ivy_aot
|
||||
|
||||
monitoring:
|
||||
jobs:
|
||||
- setup
|
||||
- aio_monitoring_stable:
|
||||
requires:
|
||||
- setup
|
||||
- aio_monitoring_next:
|
||||
requires:
|
||||
- setup
|
||||
- saucelabs_ivy:
|
||||
# Testing saucelabs via Bazel currently taking longer than the legacy saucelabs job as it
|
||||
# each karma_web_test target is provisioning and tearing down browsers which is adding
|
||||
# a lot of overhead. Running once daily on master only to avoid wasting resources and
|
||||
# slowing down CI for PRs.
|
||||
# TODO: Run this job on all branches (including PRs) once karma_web_test targets can
|
||||
# share provisioned browsers and we can remove the legacy saucelabs job.
|
||||
requires:
|
||||
- setup
|
||||
- saucelabs_view_engine:
|
||||
# Testing saucelabs via Bazel currently taking longer than the legacy saucelabs job as it
|
||||
# each karma_web_test target is provisioning and tearing down browsers which is adding
|
||||
# a lot of overhead. Running once daily on master only to avoid wasting resources and
|
||||
# slowing down CI for PRs.
|
||||
# TODO: Run this job on all branches (including PRs) once karma_web_test targets can
|
||||
# share provisioned browsers and we can remove the legacy saucelabs job.
|
||||
requires:
|
||||
- setup
|
||||
triggers:
|
||||
- schedule:
|
||||
<<: *only_on_master
|
||||
# Runs monitoring jobs at 10:00AM every day.
|
||||
cron: "0 10 * * *"
|
||||
|
@ -17,7 +17,7 @@ echo "source $envHelpersPath;" >> $BASH_ENV;
|
||||
####################################################################################################
|
||||
setPublicVar CI "$CI"
|
||||
setPublicVar PROJECT_ROOT "$projectDir";
|
||||
setPublicVar CI_AIO_MIN_PWA_SCORE "62";
|
||||
setPublicVar CI_AIO_MIN_PWA_SCORE "95";
|
||||
# This is the branch being built; e.g. `pull/12345` for PR builds.
|
||||
setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
|
||||
setPublicVar CI_BUILD_URL "$CIRCLE_BUILD_URL";
|
||||
|
69
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
Normal file
69
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
---
|
||||
name: "\U0001F41E Bug 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
Normal file
32
.github/ISSUE_TEMPLATE/2-feature-request.md
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
name: "\U0001F680 Feature 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
Normal file
55
.github/ISSUE_TEMPLATE/3-docs-bug.md
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
---
|
||||
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. -->
|
11
.github/ISSUE_TEMPLATE/4-security-issue-disclosure.md
vendored
Normal file
11
.github/ISSUE_TEMPLATE/4-security-issue-disclosure.md
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
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
Normal file
16
.github/ISSUE_TEMPLATE/5-support-request.md
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
---
|
||||
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
Normal file
13
.github/ISSUE_TEMPLATE/6-angular-cli.md
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
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
Normal file
13
.github/ISSUE_TEMPLATE/7-angular-components.md
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
name: "\U0001F48E Angular 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
22
.github/ISSUE_TEMPLATE/8-translate-docs.md
vendored
@ -1,22 +0,0 @@
|
||||
---
|
||||
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,35 +1,43 @@
|
||||
## Lista de Verificación del PR
|
||||
Comprueba si tu PR cumple los siguientes requisitos:
|
||||
## PR Checklist
|
||||
Please check if your PR fulfills the following requirements:
|
||||
|
||||
- [ ] El mensaje de commit esta conforme con [nuestras reglas](https://github.com/angular-hispano/angular/blob/master/CONTRIBUTING.md#-formato-para-el-mensaje-de-los-commits)
|
||||
- [ ] Probe los cambios que agregué (arreglo de bugs / funcionalidades)
|
||||
- [ ] Revisé previamente las traducciones o cambios de contenido
|
||||
- [ ] Consulté el [diccionario de términos](https://github.com/angular-hispano/angular/blob/master/aio/diccionario-de-términos.md) en español
|
||||
- [ ] He creado dos archivos con la extensión correspondiente(.en.md para el archivo en inglés y .md para el Archivo en español)
|
||||
- [ ] He enlazado el commit con el issue correspondiente <!-- ejemplo Fixes #X -->
|
||||
- [ ] 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)
|
||||
|
||||
|
||||
## Tipo de PR
|
||||
¿Qué tipo de cambio introduce este PR?
|
||||
## PR Type
|
||||
What kind of change does this PR introduce?
|
||||
|
||||
<!-- Marca con una "x" las opciones que aplican. -->
|
||||
<!-- Please check the one that applies to this PR using "x". -->
|
||||
|
||||
- [ ] Bugfix
|
||||
- [ ] Funcionalidad
|
||||
- [ ] Actualización de 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 / infraestructura de angular.io
|
||||
- [ ] Otro... Por favor describe la:
|
||||
|
||||
## ¿Cuál es el comportamiento actual?
|
||||
<!-- Describe el comportamiento actual que está modificando o vincule a un problema relevante.
|
||||
-->
|
||||
- [ ] 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:
|
||||
|
||||
|
||||
## ¿Cuál es el nuevo comportamiento?
|
||||
<!--
|
||||
Ejemplo: Archivo en inglés traducido al español
|
||||
-->
|
||||
## 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
|
||||
|
29
.github/angular-robot.yml
vendored
29
.github/angular-robot.yml
vendored
@ -68,20 +68,20 @@ merge:
|
||||
- "packages/**/integrationtest/**"
|
||||
- "packages/**/test/**"
|
||||
- "packages/zone.js/*"
|
||||
- "packages/zone.js/dist/**"
|
||||
- "packages/zone.js/doc/**"
|
||||
- "packages/zone.js/example/**"
|
||||
- "packages/zone.js/scripts/**"
|
||||
|
||||
# comment that will be added to a PR when there is a conflict, leave empty or set to false to disable
|
||||
mergeConflictComment: "Hi @{{PRAuthor}}! This PR has merge conflicts due to recent upstream merges.
|
||||
\nPlease help to unblock it by resolving these conflicts. Thanks!"
|
||||
mergeConflictComment: "Hi @{{PRAuthor}}! This PR has merge conflicts due to recent upstream merges.\nPlease help to unblock it by resolving these conflicts. Thanks!"
|
||||
|
||||
# label to monitor
|
||||
mergeLabel: "PR action: merge"
|
||||
mergeLabel: "action: merge"
|
||||
|
||||
# adding any of these labels will also add the merge label
|
||||
mergeLinkedLabels:
|
||||
- "PR action: merge-assistance"
|
||||
- "action: merge-assistance"
|
||||
|
||||
# list of checks that will determine if the merge label can be added
|
||||
checks:
|
||||
@ -94,17 +94,17 @@ merge:
|
||||
|
||||
# whether the PR shouldn't have a conflict with the base branch
|
||||
noConflict: true
|
||||
# list of labels that a PR needs to have, checked with a regexp (e.g. "PR target:" will work for the label "PR target: master")
|
||||
# list of labels that a PR needs to have, checked with a regexp (e.g. "target:" will work for the label "target: master")
|
||||
requiredLabels:
|
||||
- "PR target: *"
|
||||
- "target: *"
|
||||
- "cla: yes"
|
||||
|
||||
# list of labels that a PR shouldn't have, checked after the required labels with a regexp
|
||||
forbiddenLabels:
|
||||
- "PR target: TBD"
|
||||
- "PR action: cleanup"
|
||||
- "PR action: review"
|
||||
- "PR state: blocked"
|
||||
- "target: TBD"
|
||||
- "action: cleanup"
|
||||
- "action: review"
|
||||
- "state: blocked"
|
||||
- "cla: no"
|
||||
|
||||
# list of PR statuses that need to be successful
|
||||
@ -121,12 +121,7 @@ merge:
|
||||
# the comment that will be added when the merge label is added despite failing checks, leave empty or set to false to disable
|
||||
# {{MERGE_LABEL}} will be replaced by the value of the mergeLabel option
|
||||
# {{PLACEHOLDER}} will be replaced by the list of failing checks
|
||||
mergeRemovedComment: "I see that you just added the `{{MERGE_LABEL}}` label, but the following checks are still failing:
|
||||
\n{{PLACEHOLDER}}
|
||||
\n
|
||||
\n**If you want your PR to be merged, it has to pass all the CI checks.**
|
||||
\n
|
||||
\nIf you can't get the PR to a green state due to flakes or broken master, please try rebasing to master and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help."
|
||||
mergeRemovedComment: "I see that you just added the `{{MERGE_LABEL}}` label, but the following checks are still failing:\n{{PLACEHOLDER}}\n\n**If you want your PR to be merged, it has to pass all the CI checks.**\n\nIf you can't get the PR to a green state due to flakes or broken master, please try rebasing to master and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help."
|
||||
|
||||
# options for the triage plugin
|
||||
triage:
|
||||
@ -186,4 +181,4 @@ rerunCircleCI:
|
||||
# set to true to disable
|
||||
disabled: false
|
||||
# the label which when added triggers a rerun of the default CircleCI workflow
|
||||
triggerRerunLabel: "PR action: rerun CI at HEAD"
|
||||
triggerRerunLabel: "action: rerun CI at HEAD"
|
||||
|
2
.github/workflows/lock-closed.yml
vendored
2
.github/workflows/lock-closed.yml
vendored
@ -10,6 +10,6 @@ jobs:
|
||||
if: github.repository == 'angular/angular'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: angular/dev-infra/github-actions/lock-closed@66462f6
|
||||
- uses: angular/dev-infra/github-actions/lock-closed@414834b2b24dd2df37c6ed00808387ee6fd91b66
|
||||
with:
|
||||
lock-bot-key: ${{ secrets.LOCK_BOT_PRIVATE_KEY }}
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -40,6 +40,9 @@ yarn-error.log
|
||||
# User specific bazel settings
|
||||
.bazelrc.user
|
||||
|
||||
# User specific ng-dev settings
|
||||
.ng-dev.user*
|
||||
|
||||
.notes.md
|
||||
baseline.json
|
||||
|
||||
|
19
.ng-dev/caretaker.ts
Normal file
19
.ng-dev/caretaker.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import {CaretakerConfig} from '../dev-infra/caretaker/config';
|
||||
|
||||
/** The configuration for `ng-dev caretaker` commands. */
|
||||
export const caretaker: CaretakerConfig = {
|
||||
githubQueries: [
|
||||
{
|
||||
name: 'Merge Queue',
|
||||
query: `is:pr is:open status:success label:"action: merge"`,
|
||||
},
|
||||
{
|
||||
name: 'Merge Assistance Queue',
|
||||
query: `is:pr is:open status:success label:"action: merge-assistance"`,
|
||||
},
|
||||
{
|
||||
name: 'Primary Triage Queue',
|
||||
query: `is:open is:issue no:milestone`,
|
||||
}
|
||||
]
|
||||
};
|
@ -6,20 +6,7 @@ import {CommitMessageConfig} from '../dev-infra/commit-message/config';
|
||||
export const commitMessage: CommitMessageConfig = {
|
||||
maxLineLength: 120,
|
||||
minBodyLength: 20,
|
||||
minBodyLengthTypeExcludes: ['docs', 'upstream'],
|
||||
types: [
|
||||
'build',
|
||||
'ci',
|
||||
'docs',
|
||||
'feat',
|
||||
'fix',
|
||||
'perf',
|
||||
'refactor',
|
||||
'release',
|
||||
'style',
|
||||
'test',
|
||||
'upstream',
|
||||
],
|
||||
minBodyLengthTypeExcludes: ['docs'],
|
||||
scopes: [
|
||||
'animations',
|
||||
'bazel',
|
||||
|
@ -1,3 +1,4 @@
|
||||
import {caretaker} from './caretaker';
|
||||
import {commitMessage} from './commit-message';
|
||||
import {format} from './format';
|
||||
import {github} from './github';
|
||||
@ -8,4 +9,5 @@ module.exports = {
|
||||
format,
|
||||
github,
|
||||
merge,
|
||||
caretaker,
|
||||
};
|
||||
|
@ -1,38 +1,25 @@
|
||||
import {MergeConfig} from '../dev-infra/pr/merge/config';
|
||||
import {DevInfraMergeConfig} from '../dev-infra/pr/merge/config';
|
||||
import {getDefaultTargetLabelConfiguration} from '../dev-infra/pr/merge/defaults';
|
||||
import {github} from './github';
|
||||
|
||||
/**
|
||||
* 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';
|
||||
export const merge: DevInfraMergeConfig['merge'] = async api => {
|
||||
return {
|
||||
githubApiMerge: false,
|
||||
claSignedLabel: 'cla: yes',
|
||||
mergeReadyLabel: /^PR action: merge(-assistance)?/,
|
||||
caretakerNoteLabel: 'PR action: merge-assistance',
|
||||
mergeReadyLabel: /^action: merge(-assistance)?/,
|
||||
caretakerNoteLabel: '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],
|
||||
},
|
||||
],
|
||||
labels: await getDefaultTargetLabelConfiguration(api, github, '@angular/core'),
|
||||
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'
|
||||
'10.0.x': '27b95ba64a5d99757f4042073fd1860e20e3ed24',
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -509,8 +509,8 @@ groups:
|
||||
- >
|
||||
contains_any_globs(files, [
|
||||
'packages/core/src/i18n/**',
|
||||
'packages/core/src/render3/i18n.ts',
|
||||
'packages/core/src/render3/i18n.md',
|
||||
'packages/core/src/render3/i18n/**',
|
||||
'packages/core/src/render3/instructions/i18n.ts',
|
||||
'packages/core/src/render3/interfaces/i18n.ts',
|
||||
'packages/common/locales/**',
|
||||
'packages/common/src/i18n/**',
|
||||
|
@ -44654,7 +44654,7 @@ const FOLDERS_IGNORE = [
|
||||
const DEFAULT_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([...FOLDERS_IGNORE,
|
||||
|
||||
// ignore cruft
|
||||
'yarn.lock', '.lock-wscript', '.wafpickle-{0..9}', '*.swp', '._*', 'npm-debug.log', 'yarn-error.log', '.npmrc', '.yarnrc', '.npmignore', '.gitignore', '.DS_Store']);
|
||||
'yarn.lock', '.lock-wscript', '.wafpickle-{0..9}', '*.swp', '._*', 'npm-debug.log', 'yarn-error.log', '.npmrc', '.yarnrc', '.yarnrc.yml', '.npmignore', '.gitignore', '.DS_Store']);
|
||||
|
||||
const NEVER_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([
|
||||
// never ignore these files
|
||||
@ -44663,6 +44663,7 @@ const NEVER_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([
|
||||
function packWithIgnoreAndHeaders(cwd, ignoreFunction, { mapHeader } = {}) {
|
||||
return tar.pack(cwd, {
|
||||
ignore: ignoreFunction,
|
||||
sort: true,
|
||||
map: header => {
|
||||
const suffix = header.name === '.' ? '' : `/${header.name}`;
|
||||
header.name = `package${suffix}`;
|
||||
@ -46678,7 +46679,7 @@ function mkdirfix (name, opts, cb) {
|
||||
/* 194 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
module.exports = {"name":"yarn","installationMethod":"unknown","version":"1.22.4","license":"BSD-2-Clause","preferGlobal":true,"description":"📦🐈 Fast, reliable, and secure dependency management.","dependencies":{"@zkochan/cmd-shim":"^3.1.0","babel-runtime":"^6.26.0","bytes":"^3.0.0","camelcase":"^4.0.0","chalk":"^2.1.0","cli-table3":"^0.4.0","commander":"^2.9.0","death":"^1.0.0","debug":"^3.0.0","deep-equal":"^1.0.1","detect-indent":"^5.0.0","dnscache":"^1.0.1","glob":"^7.1.1","gunzip-maybe":"^1.4.0","hash-for-dep":"^1.2.3","imports-loader":"^0.8.0","ini":"^1.3.4","inquirer":"^6.2.0","invariant":"^2.2.0","is-builtin-module":"^2.0.0","is-ci":"^1.0.10","is-webpack-bundle":"^1.0.0","js-yaml":"^3.13.1","leven":"^2.0.0","loud-rejection":"^1.2.0","micromatch":"^2.3.11","mkdirp":"^0.5.1","node-emoji":"^1.6.1","normalize-url":"^2.0.0","npm-logical-tree":"^1.2.1","object-path":"^0.11.2","proper-lockfile":"^2.0.0","puka":"^1.0.0","read":"^1.0.7","request":"^2.87.0","request-capture-har":"^1.2.2","rimraf":"^2.5.0","semver":"^5.1.0","ssri":"^5.3.0","strip-ansi":"^4.0.0","strip-bom":"^3.0.0","tar-fs":"^1.16.0","tar-stream":"^1.6.1","uuid":"^3.0.1","v8-compile-cache":"^2.0.0","validate-npm-package-license":"^3.0.4","yn":"^2.0.0"},"devDependencies":{"babel-core":"^6.26.0","babel-eslint":"^7.2.3","babel-loader":"^6.2.5","babel-plugin-array-includes":"^2.0.3","babel-plugin-inline-import":"^3.0.0","babel-plugin-transform-builtin-extend":"^1.1.2","babel-plugin-transform-inline-imports-commonjs":"^1.0.0","babel-plugin-transform-runtime":"^6.4.3","babel-preset-env":"^1.6.0","babel-preset-flow":"^6.23.0","babel-preset-stage-0":"^6.0.0","babylon":"^6.5.0","commitizen":"^2.9.6","cz-conventional-changelog":"^2.0.0","eslint":"^4.3.0","eslint-config-fb-strict":"^22.0.0","eslint-plugin-babel":"^5.0.0","eslint-plugin-flowtype":"^2.35.0","eslint-plugin-jasmine":"^2.6.2","eslint-plugin-jest":"^21.0.0","eslint-plugin-jsx-a11y":"^6.0.2","eslint-plugin-prefer-object-spread":"^1.2.1","eslint-plugin-prettier":"^2.1.2","eslint-plugin-react":"^7.1.0","eslint-plugin-relay":"^0.0.28","eslint-plugin-yarn-internal":"file:scripts/eslint-rules","execa":"^0.11.0","fancy-log":"^1.3.2","flow-bin":"^0.66.0","git-release-notes":"^3.0.0","gulp":"^4.0.0","gulp-babel":"^7.0.0","gulp-if":"^2.0.1","gulp-newer":"^1.0.0","gulp-plumber":"^1.0.1","gulp-sourcemaps":"^2.2.0","jest":"^22.4.4","jsinspect":"^0.12.6","minimatch":"^3.0.4","mock-stdin":"^0.3.0","prettier":"^1.5.2","string-replace-loader":"^2.1.1","temp":"^0.8.3","webpack":"^2.1.0-beta.25","yargs":"^6.3.0"},"resolutions":{"sshpk":"^1.14.2"},"engines":{"node":">=4.0.0"},"repository":"yarnpkg/yarn","bin":{"yarn":"./bin/yarn.js","yarnpkg":"./bin/yarn.js"},"scripts":{"build":"gulp build","build-bundle":"node ./scripts/build-webpack.js","build-chocolatey":"powershell ./scripts/build-chocolatey.ps1","build-deb":"./scripts/build-deb.sh","build-dist":"bash ./scripts/build-dist.sh","build-win-installer":"scripts\\build-windows-installer.bat","changelog":"git-release-notes $(git describe --tags --abbrev=0 $(git describe --tags --abbrev=0)^)..$(git describe --tags --abbrev=0) scripts/changelog.md","dupe-check":"yarn jsinspect ./src","lint":"eslint . && flow check","pkg-tests":"yarn --cwd packages/pkg-tests jest yarn.test.js","prettier":"eslint src __tests__ --fix","release-branch":"./scripts/release-branch.sh","test":"yarn lint && yarn test-only","test-only":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --verbose","test-only-debug":"node --inspect-brk --max_old_space_size=4096 node_modules/jest/bin/jest.js --runInBand --verbose","test-coverage":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --coverage --verbose","watch":"gulp watch","commit":"git-cz"},"jest":{"collectCoverageFrom":["src/**/*.js"],"testEnvironment":"node","modulePathIgnorePatterns":["__tests__/fixtures/","packages/pkg-tests/pkg-tests-fixtures","dist/"],"testPathIgnorePatterns":["__tests__/(fixtures|__mocks__)/","updates/","_(temp|mock|install|init|helpers).js$","packages/pkg-tests"]},"config":{"commitizen":{"path":"./node_modules/cz-conventional-changelog"}}}
|
||||
module.exports = {"name":"yarn","installationMethod":"unknown","version":"1.22.5","license":"BSD-2-Clause","preferGlobal":true,"description":"📦🐈 Fast, reliable, and secure dependency management.","dependencies":{"@zkochan/cmd-shim":"^3.1.0","babel-runtime":"^6.26.0","bytes":"^3.0.0","camelcase":"^4.0.0","chalk":"^2.1.0","cli-table3":"^0.4.0","commander":"^2.9.0","death":"^1.0.0","debug":"^3.0.0","deep-equal":"^1.0.1","detect-indent":"^5.0.0","dnscache":"^1.0.1","glob":"^7.1.1","gunzip-maybe":"^1.4.0","hash-for-dep":"^1.2.3","imports-loader":"^0.8.0","ini":"^1.3.4","inquirer":"^6.2.0","invariant":"^2.2.0","is-builtin-module":"^2.0.0","is-ci":"^1.0.10","is-webpack-bundle":"^1.0.0","js-yaml":"^3.13.1","leven":"^2.0.0","loud-rejection":"^1.2.0","micromatch":"^2.3.11","mkdirp":"^0.5.1","node-emoji":"^1.6.1","normalize-url":"^2.0.0","npm-logical-tree":"^1.2.1","object-path":"^0.11.2","proper-lockfile":"^2.0.0","puka":"^1.0.0","read":"^1.0.7","request":"^2.87.0","request-capture-har":"^1.2.2","rimraf":"^2.5.0","semver":"^5.1.0","ssri":"^5.3.0","strip-ansi":"^4.0.0","strip-bom":"^3.0.0","tar-fs":"^1.16.0","tar-stream":"^1.6.1","uuid":"^3.0.1","v8-compile-cache":"^2.0.0","validate-npm-package-license":"^3.0.4","yn":"^2.0.0"},"devDependencies":{"babel-core":"^6.26.0","babel-eslint":"^7.2.3","babel-loader":"^6.2.5","babel-plugin-array-includes":"^2.0.3","babel-plugin-inline-import":"^3.0.0","babel-plugin-transform-builtin-extend":"^1.1.2","babel-plugin-transform-inline-imports-commonjs":"^1.0.0","babel-plugin-transform-runtime":"^6.4.3","babel-preset-env":"^1.6.0","babel-preset-flow":"^6.23.0","babel-preset-stage-0":"^6.0.0","babylon":"^6.5.0","commitizen":"^2.9.6","cz-conventional-changelog":"^2.0.0","eslint":"^4.3.0","eslint-config-fb-strict":"^22.0.0","eslint-plugin-babel":"^5.0.0","eslint-plugin-flowtype":"^2.35.0","eslint-plugin-jasmine":"^2.6.2","eslint-plugin-jest":"^21.0.0","eslint-plugin-jsx-a11y":"^6.0.2","eslint-plugin-prefer-object-spread":"^1.2.1","eslint-plugin-prettier":"^2.1.2","eslint-plugin-react":"^7.1.0","eslint-plugin-relay":"^0.0.28","eslint-plugin-yarn-internal":"file:scripts/eslint-rules","execa":"^0.11.0","fancy-log":"^1.3.2","flow-bin":"^0.66.0","git-release-notes":"^3.0.0","gulp":"^4.0.0","gulp-babel":"^7.0.0","gulp-if":"^2.0.1","gulp-newer":"^1.0.0","gulp-plumber":"^1.0.1","gulp-sourcemaps":"^2.2.0","jest":"^22.4.4","jsinspect":"^0.12.6","minimatch":"^3.0.4","mock-stdin":"^0.3.0","prettier":"^1.5.2","string-replace-loader":"^2.1.1","temp":"^0.8.3","webpack":"^2.1.0-beta.25","yargs":"^6.3.0"},"resolutions":{"sshpk":"^1.14.2"},"engines":{"node":">=4.0.0"},"repository":"yarnpkg/yarn","bin":{"yarn":"./bin/yarn.js","yarnpkg":"./bin/yarn.js"},"scripts":{"build":"gulp build","build-bundle":"node ./scripts/build-webpack.js","build-chocolatey":"powershell ./scripts/build-chocolatey.ps1","build-deb":"./scripts/build-deb.sh","build-dist":"bash ./scripts/build-dist.sh","build-win-installer":"scripts\\build-windows-installer.bat","changelog":"git-release-notes $(git describe --tags --abbrev=0 $(git describe --tags --abbrev=0)^)..$(git describe --tags --abbrev=0) scripts/changelog.md","dupe-check":"yarn jsinspect ./src","lint":"eslint . && flow check","pkg-tests":"yarn --cwd packages/pkg-tests jest yarn.test.js","prettier":"eslint src __tests__ --fix","release-branch":"./scripts/release-branch.sh","test":"yarn lint && yarn test-only","test-only":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --verbose","test-only-debug":"node --inspect-brk --max_old_space_size=4096 node_modules/jest/bin/jest.js --runInBand --verbose","test-coverage":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --coverage --verbose","watch":"gulp watch","commit":"git-cz"},"jest":{"collectCoverageFrom":["src/**/*.js"],"testEnvironment":"node","modulePathIgnorePatterns":["__tests__/fixtures/","packages/pkg-tests/pkg-tests-fixtures","dist/"],"testPathIgnorePatterns":["__tests__/(fixtures|__mocks__)/","updates/","_(temp|mock|install|init|helpers).js$","packages/pkg-tests"]},"config":{"commitizen":{"path":"./node_modules/cz-conventional-changelog"}}}
|
||||
|
||||
/***/ }),
|
||||
/* 195 */
|
||||
@ -98338,7 +98339,7 @@ var _buildSubCommands = (0, (_buildSubCommands2 || _load_buildSubCommands()).def
|
||||
|
||||
const bundle = yield fetchBundle(config, bundleUrl);
|
||||
|
||||
const yarnPath = path.resolve(config.lockfileFolder, `.yarn/releases/yarn-${bundleVersion}.js`);
|
||||
const yarnPath = path.resolve(config.lockfileFolder, `.yarn/releases/yarn-${bundleVersion}.cjs`);
|
||||
reporter.log(`Saving it into ${chalk.magenta(yarnPath)}...`);
|
||||
yield (_fs || _load_fs()).mkdirp(path.dirname(yarnPath));
|
||||
yield (_fs || _load_fs()).writeFile(yarnPath, bundle);
|
||||
@ -100190,7 +100191,7 @@ let main = exports.main = (() => {
|
||||
|
||||
const config = new (_config || _load_config()).default(reporter);
|
||||
const outputWrapperEnabled = (0, (_conversion || _load_conversion()).boolifyWithDefault)(process.env.YARN_WRAP_OUTPUT, true);
|
||||
const shouldWrapOutput = outputWrapperEnabled && !(_commander || _load_commander()).default.json && command.hasWrapper((_commander || _load_commander()).default, (_commander || _load_commander()).default.args);
|
||||
const shouldWrapOutput = outputWrapperEnabled && !(_commander || _load_commander()).default.json && command.hasWrapper((_commander || _load_commander()).default, (_commander || _load_commander()).default.args) && !(commandName === 'init' && (_commander || _load_commander()).default[`2`]);
|
||||
|
||||
if (shouldWrapOutput) {
|
||||
reporter.header(commandName, { name: 'yarn', version: (_yarnVersion || _load_yarnVersion()).version });
|
||||
@ -100604,7 +100605,7 @@ let start = (() => {
|
||||
});
|
||||
|
||||
try {
|
||||
if (yarnPath.endsWith(`.js`)) {
|
||||
if (/\.[cm]?js$/.test(yarnPath)) {
|
||||
exitCode = yield (0, (_child || _load_child()).spawnp)(process.execPath, [yarnPath, ...argv], opts);
|
||||
} else {
|
||||
exitCode = yield (0, (_child || _load_child()).spawnp)(yarnPath, argv, opts);
|
2
.yarnrc
2
.yarnrc
@ -2,4 +2,4 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
yarn-path ".yarn/releases/yarn-1.22.4.js"
|
||||
yarn-path ".yarn/releases/yarn-1.22.5.js"
|
||||
|
@ -34,7 +34,7 @@ filegroup(
|
||||
filegroup(
|
||||
name = "angularjs_scripts",
|
||||
srcs = [
|
||||
# We also declare the unminfied AngularJS files since these can be used for
|
||||
# We also declare the unminified AngularJS files since these can be used for
|
||||
# local debugging (e.g. see: packages/upgrade/test/common/test_helpers.ts)
|
||||
"@npm//:node_modules/angular/angular.js",
|
||||
"@npm//:node_modules/angular/angular.min.js",
|
||||
|
419
CHANGELOG.md
419
CHANGELOG.md
@ -1,19 +1,331 @@
|
||||
<a name="10.1.0-next.4"></a>
|
||||
# 10.1.0-next.4 (2020-08-04)
|
||||
<a name="11.0.0-next.3"></a>
|
||||
# 11.0.0-next.3 (2020-09-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **common:** narrow `NgIf` context variables in template type checker ([#36627](https://github.com/angular/angular/issues/36627)) ([9c8bc4a](https://github.com/angular/angular/commit/9c8bc4a))
|
||||
* **compiler:** mark `NgModuleFactory` construction as not side effectful ([#38147](https://github.com/angular/angular/issues/38147)) ([7f8c222](https://github.com/angular/angular/commit/7f8c222))
|
||||
* **common:** add `params` and `reportProgress` options to `HttpClient.put()` overload ([#37873](https://github.com/angular/angular/issues/37873)) ([dd8d8c8](https://github.com/angular/angular/commit/dd8d8c8)), closes [#23600](https://github.com/angular/angular/issues/23600)
|
||||
* **compiler-cli:** generate `let` statements in ES2015+ mode ([#38775](https://github.com/angular/angular/issues/38775)) ([123bff7](https://github.com/angular/angular/commit/123bff7))
|
||||
* **core:** ensure TestBed is not instantiated before override provider ([#38717](https://github.com/angular/angular/issues/38717)) ([c8f056b](https://github.com/angular/angular/commit/c8f056b))
|
||||
* **forms:** type NG_VALUE_ACCESSOR injection token as array ([#29723](https://github.com/angular/angular/issues/29723)) ([2b1b718](https://github.com/angular/angular/commit/2b1b718)), closes [#29351](https://github.com/angular/angular/issues/29351)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **core:** rename async to waitForAsync to avoid confusing ([#37583](https://github.com/angular/angular/issues/37583)) ([8f07429](https://github.com/angular/angular/commit/8f07429))
|
||||
* **core:** update reference and doc to change `async` to `waitAsync`. ([#37583](https://github.com/angular/angular/issues/37583)) ([8fbf40b](https://github.com/angular/angular/commit/8fbf40b))
|
||||
* **common:** Add ISO week-numbering year formats support to formatDate ([#38828](https://github.com/angular/angular/issues/38828)) ([984ed39](https://github.com/angular/angular/commit/984ed39))
|
||||
* **compiler:** Parse and recover on incomplete opening HTML tags ([#38681](https://github.com/angular/angular/issues/38681)) ([6ae3b68](https://github.com/angular/angular/commit/6ae3b68)), closes [#38596](https://github.com/angular/angular/issues/38596)
|
||||
* **router:** add migration to update calls to navigateByUrl and createUrlTree with invalid parameters ([#38825](https://github.com/angular/angular/issues/38825)) ([7849fdd](https://github.com/angular/angular/commit/7849fdd)), closes [#38227](https://github.com/angular/angular/issues/38227)
|
||||
* **service-worker:** add the option to prefer network for navigation requests ([#38565](https://github.com/angular/angular/issues/38565)) ([a206852](https://github.com/angular/angular/commit/a206852)), closes [#38194](https://github.com/angular/angular/issues/38194)
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **core:** If you call `TestBed.overrideProvider` after TestBed initialization, provider overrides are not applied. This
|
||||
behavior is consistent with other override methods (such as `TestBed.overrideDirective`, etc) but they
|
||||
throw an error to indicate that, when the check was missing in the `TestBed.overrideProvider` function.
|
||||
Now calling `TestBed.overrideProvider` after TestBed initialization also triggers an
|
||||
error, thus there is a chance that some tests (where `TestBed.overrideProvider` is
|
||||
called after TestBed initialization) will start to fail and require updates to move `TestBed.overrideProvider` calls
|
||||
before TestBed initialization is completed.
|
||||
|
||||
|
||||
|
||||
<a name="10.1.3"></a>
|
||||
## 10.1.3 (2020-09-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **http:** Fix error message when we call jsonp without importing HttpClientJsonpModule ([#38756](https://github.com/angular/angular/issues/38756)) ([3902ec0](https://github.com/angular/angular/commit/3902ec0))
|
||||
* **ngcc:** fix compilation of `ChangeDetectorRef` in pipe constructors ([#38892](https://github.com/angular/angular/issues/38892)) ([093c3a1](https://github.com/angular/angular/commit/093c3a1)), closes [#38666](https://github.com/angular/angular/issues/38666) [#38883](https://github.com/angular/angular/issues/38883)
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* feat(router): better warning message when a router outlet has not been instantiated ([#38920](https://github.com/angular/angular/issues/38920)) ([04d0aa6](https://github.com/angular/angular/commit/04d0aa6))
|
||||
|
||||
|
||||
|
||||
<a name="11.0.0-next.2"></a>
|
||||
# 11.0.0-next.2 (2020-09-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **common:** do not round up fractions of a millisecond in `DatePipe` ([#38009](https://github.com/angular/angular/issues/38009)) ([26f2820](https://github.com/angular/angular/commit/26f2820)), closes [/www.ecma-international.org/ecma-262/5.1/#sec-15](https://github.com//www.ecma-international.org/ecma-262/5.1//issues/sec-15) [#37989](https://github.com/angular/angular/issues/37989)
|
||||
* **common:** mark locale data arrays as readonly ([#30397](https://github.com/angular/angular/issues/30397)) ([6acea54](https://github.com/angular/angular/commit/6acea54)), closes [#27003](https://github.com/angular/angular/issues/27003)
|
||||
* **compiler:** source span for microsyntax text att should be key span ([#38766](https://github.com/angular/angular/issues/38766)) ([8f349b2](https://github.com/angular/angular/commit/8f349b2))
|
||||
* **router:** Fix arguments order for call to shouldReuseRoute ([#26949](https://github.com/angular/angular/issues/26949)) ([3817e5f](https://github.com/angular/angular/commit/3817e5f)), closes [#16192](https://github.com/angular/angular/issues/16192) [#16192](https://github.com/angular/angular/issues/16192)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **compiler-cli:** `TemplateTypeChecker` operation to get `Symbol` from a template node ([#38618](https://github.com/angular/angular/issues/38618)) ([c4556db](https://github.com/angular/angular/commit/c4556db))
|
||||
* **compiler-cli:** Add ability to get `Symbol` of `Template`s and `Element`s in component template ([#38618](https://github.com/angular/angular/issues/38618)) ([cf2e8b9](https://github.com/angular/angular/commit/cf2e8b9))
|
||||
* **compiler-cli:** Add ability to get `Symbol` of AST expression in component template ([#38618](https://github.com/angular/angular/issues/38618)) ([f56ece4](https://github.com/angular/angular/commit/f56ece4))
|
||||
* **compiler-cli:** add ability to get symbol of reference or variable ([#38618](https://github.com/angular/angular/issues/38618)) ([19598b4](https://github.com/angular/angular/commit/19598b4))
|
||||
* **compiler-cli:** define interfaces to be used for TemplateTypeChecker ([#38618](https://github.com/angular/angular/issues/38618)) ([9e77bd3](https://github.com/angular/angular/commit/9e77bd3))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **compiler-cli:** only emit directive/pipe references that are used ([#38539](https://github.com/angular/angular/issues/38539)) ([077f516](https://github.com/angular/angular/commit/077f516))
|
||||
* **compiler-cli:** optimize computation of type-check scope information ([#38539](https://github.com/angular/angular/issues/38539)) ([297c060](https://github.com/angular/angular/commit/297c060))
|
||||
* **router:** use `ngDevMode` to tree-shake error messages in router ([#38674](https://github.com/angular/angular/issues/38674)) ([db21c4f](https://github.com/angular/angular/commit/db21c4f))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **router:** This change corrects the argument order when calling
|
||||
RouteReuseStrategy#shouldReuseRoute. Previously, when evaluating child
|
||||
routes, they would be called with the future and current arguments would
|
||||
be swapped. If your RouteReuseStrategy relies specifically on only the future
|
||||
or current snapshot state, you may need to update the shouldReuseRoute
|
||||
implementation's use of "future" and "current" ActivateRouteSnapshots.
|
||||
* **common:** The locale data API has been marked as returning readonly arrays, rather
|
||||
than mutable arrays, since these arrays are shared across calls to the
|
||||
API. If you were mutating them (e.g. calling `sort()`, `push()`, `splice()`, etc)
|
||||
then your code will not longer compile. If you need to mutate the array, you
|
||||
should now take a copy (e.g. by calling `slice()`) and mutate the copy.
|
||||
* **common:** When passing a date-time formatted string to the `DatePipe` in a format that contains
|
||||
fractions of a millisecond, the milliseconds will now always be rounded down rather than
|
||||
to the nearest millisecond.
|
||||
|
||||
Most applications will not be affected by this change. If this is not the desired behaviour
|
||||
then consider pre-processing the string to round the millisecond part before passing
|
||||
it to the `DatePipe`.
|
||||
|
||||
|
||||
|
||||
<a name="10.1.2"></a>
|
||||
## 10.1.2 (2020-09-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler:** detect pipes in ICUs in template binder ([#38810](https://github.com/angular/angular/issues/38810)) ([ec2dbe7](https://github.com/angular/angular/commit/ec2dbe7)), closes [#38539](https://github.com/angular/angular/issues/38539) [#38539](https://github.com/angular/angular/issues/38539) [#38539](https://github.com/angular/angular/issues/38539)
|
||||
* **core:** clear the `RefreshTransplantedView` when detached ([#38768](https://github.com/angular/angular/issues/38768)) ([edb7f90](https://github.com/angular/angular/commit/edb7f90)), closes [#38619](https://github.com/angular/angular/issues/38619)
|
||||
* **localize:** ensure that `formatOptions` is optional ([#38787](https://github.com/angular/angular/issues/38787)) ([a47383d](https://github.com/angular/angular/commit/a47383d))
|
||||
* **router:** Ensure routes are processed in priority order and only if needed ([#38780](https://github.com/angular/angular/issues/38780)) ([9c51ba3](https://github.com/angular/angular/commit/9c51ba3)), closes [#38691](https://github.com/angular/angular/issues/38691)
|
||||
* **upgrade:** add try/catch when downgrading injectables ([#38671](https://github.com/angular/angular/issues/38671)) ([5de2ac3](https://github.com/angular/angular/commit/5de2ac3)), closes [#37579](https://github.com/angular/angular/issues/37579)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **compiler-cli:** only emit directive/pipe references that are used ([#38843](https://github.com/angular/angular/issues/38843)) ([5658405](https://github.com/angular/angular/commit/5658405))
|
||||
* **compiler-cli:** optimize computation of type-check scope information ([#38843](https://github.com/angular/angular/issues/38843)) ([ebede67](https://github.com/angular/angular/commit/ebede67))
|
||||
* **ngcc:** introduce cache for sharing data across entry-points ([#38840](https://github.com/angular/angular/issues/38840)) ([58411e7](https://github.com/angular/angular/commit/58411e7))
|
||||
* **ngcc:** reduce maximum worker count ([#38840](https://github.com/angular/angular/issues/38840)) ([ea36466](https://github.com/angular/angular/commit/ea36466))
|
||||
|
||||
|
||||
|
||||
<a name="11.0.0-next.1"></a>
|
||||
# 11.0.0-next.1 (2020-09-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler-cli:** compute source-mappings for localized strings ([#38645](https://github.com/angular/angular/issues/38645)) ([7e0b3fd](https://github.com/angular/angular/commit/7e0b3fd)), closes [#38588](https://github.com/angular/angular/issues/38588)
|
||||
* **core:** remove CollectionChangeRecord symbol ([#38668](https://github.com/angular/angular/issues/38668)) ([fdea180](https://github.com/angular/angular/commit/fdea180))
|
||||
* **router:** support lazy loading for empty path named outlets ([#38379](https://github.com/angular/angular/issues/38379)) ([926ffcd](https://github.com/angular/angular/commit/926ffcd)), closes [#12842](https://github.com/angular/angular/issues/12842)
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **core:** CollectionChangeRecord has been removed, use IterableChangeRecord
|
||||
instead
|
||||
|
||||
|
||||
|
||||
<a name="10.1.1"></a>
|
||||
## 10.1.1 (2020-09-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler:** correct confusion between field and property names ([#38685](https://github.com/angular/angular/issues/38685)) ([a1c34c6](https://github.com/angular/angular/commit/a1c34c6))
|
||||
* **compiler-cli:** compute source-mappings for localized strings ([#38747](https://github.com/angular/angular/issues/38747)) ([b4eb016](https://github.com/angular/angular/commit/b4eb016)), closes [#38588](https://github.com/angular/angular/issues/38588)
|
||||
* **compiler-cli:** ensure that a declaration is available in type-to-value conversion ([#38684](https://github.com/angular/angular/issues/38684)) ([56d5ff2](https://github.com/angular/angular/commit/56d5ff2)), closes [#38670](https://github.com/angular/angular/issues/38670)
|
||||
* **core:** reset `tView` between tests in Ivy TestBed ([#38659](https://github.com/angular/angular/issues/38659)) ([efc7606](https://github.com/angular/angular/commit/efc7606)), closes [#38600](https://github.com/angular/angular/issues/38600)
|
||||
* **localize:** do not expose NodeJS typings in $localize runtime code ([#38700](https://github.com/angular/angular/issues/38700)) ([4de8dc3](https://github.com/angular/angular/commit/4de8dc3)), closes [#38692](https://github.com/angular/angular/issues/38692)
|
||||
* **localize:** enable whitespace preservation marker in XLIFF files ([#38737](https://github.com/angular/angular/issues/38737)) ([190dca0](https://github.com/angular/angular/commit/190dca0)), closes [#38679](https://github.com/angular/angular/issues/38679)
|
||||
* **localize:** install `[@angular](https://github.com/angular)/localize` in `devDependencies` by default ([#38680](https://github.com/angular/angular/issues/38680)) ([dbab744](https://github.com/angular/angular/commit/dbab744)), closes [#38329](https://github.com/angular/angular/issues/38329)
|
||||
* **localize:** render context of translation file parse errors ([#38673](https://github.com/angular/angular/issues/38673)) ([32f33f0](https://github.com/angular/angular/commit/32f33f0)), closes [#38377](https://github.com/angular/angular/issues/38377)
|
||||
* **localize:** render location in XLIFF 2 even if there is no metadata ([#38713](https://github.com/angular/angular/issues/38713)) ([ab4f953](https://github.com/angular/angular/commit/ab4f953)), closes [#38705](https://github.com/angular/angular/issues/38705)
|
||||
* **ngcc:** use aliased exported types correctly ([#38666](https://github.com/angular/angular/issues/38666)) ([6a28675](https://github.com/angular/angular/commit/6a28675)), closes [#38238](https://github.com/angular/angular/issues/38238)
|
||||
* **router:** If users are using the Alt key when clicking the router links, prioritize browser’s default behavior ([#38375](https://github.com/angular/angular/issues/38375)) ([309709d](https://github.com/angular/angular/commit/309709d))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **core:** use `ngDevMode` to tree-shake error messages ([#38612](https://github.com/angular/angular/issues/38612)) ([b084bff](https://github.com/angular/angular/commit/b084bff))
|
||||
|
||||
|
||||
|
||||
<a name="11.0.0-next.0"></a>
|
||||
# 11.0.0-next.0 (2020-09-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **forms:** ensure to emit `statusChanges` on subsequent value update/validations ([#38354](https://github.com/angular/angular/issues/38354)) ([d9fea85](https://github.com/angular/angular/commit/d9fea85)), closes [#20424](https://github.com/angular/angular/issues/20424) [#14542](https://github.com/angular/angular/issues/14542)
|
||||
* **service-worker:** fix condition to check for a cache-busted request ([#36847](https://github.com/angular/angular/issues/36847)) ([5be4edf](https://github.com/angular/angular/commit/5be4edf))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **service-worker:** add `UnrecoverableStateError` ([#36847](https://github.com/angular/angular/issues/36847)) ([036a2fa](https://github.com/angular/angular/commit/036a2fa)), closes [#36539](https://github.com/angular/angular/issues/36539)
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **forms:** Previously if FormControl, FormGroup and FormArray class instances had async validators
|
||||
defined at initialization time, the status change event was not emitted once async validator
|
||||
completed. After this change the status event is emitted into the `statusChanges` observable.
|
||||
If your code relies on the old behavior, you can filter/ignore this additional status change
|
||||
event.
|
||||
|
||||
|
||||
|
||||
<a name="10.1.0"></a>
|
||||
# 10.1.0 (2020-09-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **bazel:** provide LinkablePackageInfo from ng_module ([#37623](https://github.com/angular/angular/issues/37623)) ([6898eab](https://github.com/angular/angular/commit/6898eab))
|
||||
* **common:** add ReadonlyMap in place of Map in keyValuePipe ([#37311](https://github.com/angular/angular/issues/37311)) ([3373453](https://github.com/angular/angular/commit/3373453)), closes [#37308](https://github.com/angular/angular/issues/37308)
|
||||
* **compiler-cli:** add `SourceFile.getOriginalLocation()` to sourcemaps package ([#32912](https://github.com/angular/angular/issues/32912)) ([6abb8d0](https://github.com/angular/angular/commit/6abb8d0))
|
||||
* **compiler-cli:** Add compiler option to report errors when assigning to restricted input fields ([#38249](https://github.com/angular/angular/issues/38249)) ([71138f6](https://github.com/angular/angular/commit/71138f6))
|
||||
* **compiler-cli:** add support for TypeScript 4.0 ([#38076](https://github.com/angular/angular/issues/38076)) ([0fc44e0](https://github.com/angular/angular/commit/0fc44e0))
|
||||
* **compiler-cli:** explain why an expression cannot be used in AOT compilations ([#37587](https://github.com/angular/angular/issues/37587)) ([712f1bd](https://github.com/angular/angular/commit/712f1bd))
|
||||
* **compiler:** support unary operators for more accurate type checking ([#37918](https://github.com/angular/angular/issues/37918)) ([874792d](https://github.com/angular/angular/commit/874792d)), closes [#20845](https://github.com/angular/angular/issues/20845) [#36178](https://github.com/angular/angular/issues/36178)
|
||||
* **core:** rename async to waitForAsync to avoid confusing ([#37583](https://github.com/angular/angular/issues/37583)) ([8f07429](https://github.com/angular/angular/commit/8f07429))
|
||||
* **core:** support injection token as predicate in queries ([#37506](https://github.com/angular/angular/issues/37506)) ([97dc85b](https://github.com/angular/angular/commit/97dc85b)), closes [#21152](https://github.com/angular/angular/issues/21152) [#36144](https://github.com/angular/angular/issues/36144)
|
||||
* **core:** update reference and doc to change `async` to `waitAsync`. ([#37583](https://github.com/angular/angular/issues/37583)) ([8fbf40b](https://github.com/angular/angular/commit/8fbf40b))
|
||||
* **forms:** AbstractControl to store raw validators in addition to combined validators function ([#37881](https://github.com/angular/angular/issues/37881)) ([ad7046b](https://github.com/angular/angular/commit/ad7046b))
|
||||
* **localize:** allow duplicate messages to be handled during extraction ([#38082](https://github.com/angular/angular/issues/38082)) ([cf9a47b](https://github.com/angular/angular/commit/cf9a47b)), closes [#38077](https://github.com/angular/angular/issues/38077)
|
||||
* **localize:** expose `canParse()` diagnostics ([#37909](https://github.com/angular/angular/issues/37909)) ([ec32eba](https://github.com/angular/angular/commit/ec32eba)), closes [#37901](https://github.com/angular/angular/issues/37901)
|
||||
* **localize:** implement message extraction tool ([#32912](https://github.com/angular/angular/issues/32912)) ([190561d](https://github.com/angular/angular/commit/190561d))
|
||||
* **platform-browser:** Allow `sms`-URLs ([#31463](https://github.com/angular/angular/issues/31463)) ([fc5c34d](https://github.com/angular/angular/commit/fc5c34d)), closes [#31462](https://github.com/angular/angular/issues/31462)
|
||||
* **platform-server:** add option for absolute URL HTTP support ([#37539](https://github.com/angular/angular/issues/37539)) ([d37049a](https://github.com/angular/angular/commit/d37049a)), closes [#37071](https://github.com/angular/angular/issues/37071)
|
||||
* **router:** better warning message when a router outlet has not been instantiated ([#30246](https://github.com/angular/angular/issues/30246)) ([1609815](https://github.com/angular/angular/commit/1609815))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** fix integration test for bazel building ([#38629](https://github.com/angular/angular/issues/38629)) ([dd82f2f](https://github.com/angular/angular/commit/dd82f2f))
|
||||
* **common:** date pipe gives wrong week number ([#37632](https://github.com/angular/angular/issues/37632)) ([ef1fb6d](https://github.com/angular/angular/commit/ef1fb6d)), closes [#33961](https://github.com/angular/angular/issues/33961)
|
||||
* **common:** narrow `NgIf` context variables in template type checker ([#36627](https://github.com/angular/angular/issues/36627)) ([9c8bc4a](https://github.com/angular/angular/commit/9c8bc4a))
|
||||
* **compiler-cli:** avoid creating value expressions for symbols from type-only imports ([#37912](https://github.com/angular/angular/issues/37912)) ([18098d3](https://github.com/angular/angular/commit/18098d3)), closes [#37900](https://github.com/angular/angular/issues/37900)
|
||||
* **compiler-cli:** ensure source-maps can handle webpack:// protocol ([#32912](https://github.com/angular/angular/issues/32912)) ([decd95e](https://github.com/angular/angular/commit/decd95e))
|
||||
* **compiler-cli:** only read source-map comment from last line ([#32912](https://github.com/angular/angular/issues/32912)) ([07a07e3](https://github.com/angular/angular/commit/07a07e3))
|
||||
* **compiler-cli:** type-check inputs that include undefined when there's coercion members ([#38273](https://github.com/angular/angular/issues/38273)) ([7525f3a](https://github.com/angular/angular/commit/7525f3a))
|
||||
* **compiler:** incorrectly inferring namespace for HTML nodes inside SVG ([#38477](https://github.com/angular/angular/issues/38477)) ([0dda97e](https://github.com/angular/angular/commit/0dda97e)), closes [#37218](https://github.com/angular/angular/issues/37218)
|
||||
* **compiler:** mark `NgModuleFactory` construction as not side effectful ([#38147](https://github.com/angular/angular/issues/38147)) ([7f8c222](https://github.com/angular/angular/commit/7f8c222))
|
||||
* **core:** Allow modification of lifecycle hooks any time before bootstrap ([#35464](https://github.com/angular/angular/issues/35464)) ([737506e](https://github.com/angular/angular/commit/737506e)), closes [#30497](https://github.com/angular/angular/issues/30497)
|
||||
* **core:** detect DI parameters in JIT mode for downleveled ES2015 classes ([#38463](https://github.com/angular/angular/issues/38463)) ([ca07da4](https://github.com/angular/angular/commit/ca07da4)), closes [#38453](https://github.com/angular/angular/issues/38453)
|
||||
* **core:** determine required DOMParser feature availability ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([c509243](https://github.com/angular/angular/commit/c509243))
|
||||
* **core:** do not trigger CSP alert/report in Firefox and Chrome ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([b950d46](https://github.com/angular/angular/commit/b950d46)), closes [#25214](https://github.com/angular/angular/issues/25214)
|
||||
* **core:** move generated i18n statements to the `consts` field of ComponentDef ([#38404](https://github.com/angular/angular/issues/38404)) ([cb05c01](https://github.com/angular/angular/commit/cb05c01))
|
||||
* **elements:** run strategy methods in correct zone ([#37814](https://github.com/angular/angular/issues/37814)) ([8df888d](https://github.com/angular/angular/commit/8df888d)), closes [#24181](https://github.com/angular/angular/issues/24181)
|
||||
* **forms:** handle form groups/arrays own pending async validation ([#22575](https://github.com/angular/angular/issues/22575)) ([77b62a5](https://github.com/angular/angular/commit/77b62a5)), closes [#10064](https://github.com/angular/angular/issues/10064)
|
||||
* **language-service:** non-existent module format in package output ([#37623](https://github.com/angular/angular/issues/37623)) ([413a0fb](https://github.com/angular/angular/commit/413a0fb))
|
||||
* **localize:** ensure required XLIFF parameters are serialized ([#38575](https://github.com/angular/angular/issues/38575)) ([f0af387](https://github.com/angular/angular/commit/f0af387)), closes [#38570](https://github.com/angular/angular/issues/38570)
|
||||
* **localize:** extract the correct message ids ([#38498](https://github.com/angular/angular/issues/38498)) ([ac461e1](https://github.com/angular/angular/commit/ac461e1))
|
||||
* **localize:** render ICU placeholders in extracted translation files ([#38484](https://github.com/angular/angular/issues/38484)) ([81c3e80](https://github.com/angular/angular/commit/81c3e80))
|
||||
* **localize:** render text of extracted placeholders ([#38536](https://github.com/angular/angular/issues/38536)) ([14e90be](https://github.com/angular/angular/commit/14e90be))
|
||||
* **ngcc:** detect synthesized delegate constructors for downleveled ES2015 classes ([#38463](https://github.com/angular/angular/issues/38463)) ([3b9c802](https://github.com/angular/angular/commit/3b9c802)), closes [#38453](https://github.com/angular/angular/issues/38453) [#38453](https://github.com/angular/angular/issues/38453)
|
||||
* **router:** defer loading of wildcard module until needed ([#38348](https://github.com/angular/angular/issues/38348)) ([8f708b5](https://github.com/angular/angular/commit/8f708b5)), closes [#25494](https://github.com/angular/angular/issues/25494)
|
||||
* **router:** fix navigation ignoring logic to compare to the browser url ([#37716](https://github.com/angular/angular/issues/37716)) ([a5ffca0](https://github.com/angular/angular/commit/a5ffca0)), closes [#16710](https://github.com/angular/angular/issues/16710) [#13586](https://github.com/angular/angular/issues/13586)
|
||||
* **router:** properly compare array queryParams for equality ([#37709](https://github.com/angular/angular/issues/37709)) ([#37860](https://github.com/angular/angular/issues/37860)) ([1801d0c](https://github.com/angular/angular/commit/1801d0c))
|
||||
* **router:** remove parenthesis for primary outlet segment after removing auxiliary outlet segment ([#24656](https://github.com/angular/angular/issues/24656)) ([#37163](https://github.com/angular/angular/issues/37163)) ([71f008f](https://github.com/angular/angular/commit/71f008f))
|
||||
* **router:** restore 'history.state' object for navigations coming from Angular router ([#28108](https://github.com/angular/angular/issues/28108)) ([#28176](https://github.com/angular/angular/issues/28176)) ([df76a20](https://github.com/angular/angular/commit/df76a20))
|
||||
|
||||
### Code Refactoring
|
||||
* **router:** export DefaultRouteReuseStrategy to Router public_api ([#31575](https://github.com/angular/angular/issues/31575)) ([ca79880](https://github.com/angular/angular/commit/ca79880))
|
||||
|
||||
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
* **compiler-cli:** don't emit template guards when child scope is empty ([#38418](https://github.com/angular/angular/issues/38418)) ([1388c17](https://github.com/angular/angular/commit/1388c17))
|
||||
* **compiler-cli:** fix regressions in incremental program reuse ([#37641](https://github.com/angular/angular/issues/37641)) ([5103d90](https://github.com/angular/angular/commit/5103d90))
|
||||
* **compiler-cli:** only generate directive declarations when used ([#38418](https://github.com/angular/angular/issues/38418)) ([fb8f4b4](https://github.com/angular/angular/commit/fb8f4b4))
|
||||
* **compiler-cli:** only generate type-check code for referenced DOM elements ([#38418](https://github.com/angular/angular/issues/38418)) ([f42e6ce](https://github.com/angular/angular/commit/f42e6ce))
|
||||
* **forms:** use internal `ngDevMode` flag to tree-shake error messages in prod builds ([#37821](https://github.com/angular/angular/issues/37821)) ([201a546](https://github.com/angular/angular/commit/201a546)), closes [#37697](https://github.com/angular/angular/issues/37697)
|
||||
* **ngcc:** shortcircuit tokenizing in ESM dependency host ([#37639](https://github.com/angular/angular/issues/37639)) ([bd7f440](https://github.com/angular/angular/commit/bd7f440))
|
||||
* **ngcc:** use `EntryPointManifest` to speed up noop `ProgramBaseEntryPointFinder` ([#37665](https://github.com/angular/angular/issues/37665)) ([9318e23](https://github.com/angular/angular/commit/9318e23))
|
||||
* **router:** apply prioritizedGuardValue operator to optimize CanLoad guards ([#37523](https://github.com/angular/angular/issues/37523)) ([d7dd295](https://github.com/angular/angular/commit/d7dd295))
|
||||
|
||||
|
||||
|
||||
<a name="10.0.14"></a>
|
||||
## 10.0.14 (2020-08-26)
|
||||
|
||||
|
||||
<a name="10.0.12"></a>
|
||||
## 10.0.12 (2020-08-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler-cli:** adding references to const enums in runtime code ([#38542](https://github.com/angular/angular/issues/38542)) ([814b436](https://github.com/angular/angular/commit/814b436)), closes [#38513](https://github.com/angular/angular/issues/38513)
|
||||
* **core:** remove closing body tag from inert DOM builder ([#38454](https://github.com/angular/angular/issues/38454)) ([5528536](https://github.com/angular/angular/commit/5528536))
|
||||
* **localize:** include the last placeholder in parsed translation text ([#38452](https://github.com/angular/angular/issues/38452)) ([57d1a48](https://github.com/angular/angular/commit/57d1a48))
|
||||
* **localize:** parse all parts of a translation with nested HTML ([#38452](https://github.com/angular/angular/issues/38452)) ([07b99f5](https://github.com/angular/angular/commit/07b99f5)), closes [#38422](https://github.com/angular/angular/issues/38422)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **language-service:** introduce hybrid visitor to locate AST node ([#38540](https://github.com/angular/angular/issues/38540)) ([66d8c22](https://github.com/angular/angular/commit/66d8c22))
|
||||
|
||||
|
||||
<a name="10.0.11"></a>
|
||||
## 10.0.11 (2020-08-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **router:** ensure routerLinkActive updates when associated routerLinks change (resubmit of [#38349](https://github.com/angular/angular/issues/38349)) ([#38511](https://github.com/angular/angular/issues/38511)) ([0af9533](https://github.com/angular/angular/commit/0af9533)), closes [#18469](https://github.com/angular/angular/issues/18469)
|
||||
|
||||
|
||||
|
||||
<a name="10.0.10"></a>
|
||||
## 10.0.10 (2020-08-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **common:** Allow scrolling when browser supports scrollTo ([#38468](https://github.com/angular/angular/issues/38468)) ([b32126c](https://github.com/angular/angular/commit/b32126c)), closes [#30630](https://github.com/angular/angular/issues/30630)
|
||||
* **core:** detect DI parameters in JIT mode for downleveled ES2015 classes ([#38500](https://github.com/angular/angular/issues/38500)) ([863acb6](https://github.com/angular/angular/commit/863acb6)), closes [#38453](https://github.com/angular/angular/issues/38453)
|
||||
* **core:** error if CSS custom property in host binding has number in name ([#38432](https://github.com/angular/angular/issues/38432)) ([cb83b8a](https://github.com/angular/angular/commit/cb83b8a)), closes [#37292](https://github.com/angular/angular/issues/37292)
|
||||
* **core:** fix multiple nested views removal from ViewContainerRef ([#38317](https://github.com/angular/angular/issues/38317)) ([d5e09f4](https://github.com/angular/angular/commit/d5e09f4)), closes [#38201](https://github.com/angular/angular/issues/38201)
|
||||
* **ngcc:** detect synthesized delegate constructors for downleveled ES2015 classes ([#38500](https://github.com/angular/angular/issues/38500)) ([f3dd6c2](https://github.com/angular/angular/commit/f3dd6c2)), closes [#38453](https://github.com/angular/angular/issues/38453) [#38453](https://github.com/angular/angular/issues/38453)
|
||||
* **router:** ensure routerLinkActive updates when associated routerLinks change ([#38349](https://github.com/angular/angular/issues/38349)) ([989e8a1](https://github.com/angular/angular/commit/989e8a1)), closes [#18469](https://github.com/angular/angular/issues/18469)
|
||||
|
||||
|
||||
|
||||
<a name="10.0.9"></a>
|
||||
## 10.0.9 (2020-08-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **common:** ensure scrollRestoration is writable ([#30630](https://github.com/angular/angular/issues/30630)) ([#38357](https://github.com/angular/angular/issues/38357)) ([58f4b3a](https://github.com/angular/angular/commit/58f4b3a)), closes [#30629](https://github.com/angular/angular/issues/30629)
|
||||
* **compiler:** evaluate safe navigation expressions in correct binding order ([#37911](https://github.com/angular/angular/issues/37911)) ([f5b9d87](https://github.com/angular/angular/commit/f5b9d87)), closes [#37194](https://github.com/angular/angular/issues/37194)
|
||||
* **compiler-cli:** avoid creating value expressions for symbols from type-only imports ([#38415](https://github.com/angular/angular/issues/38415)) ([ca2b4bc](https://github.com/angular/angular/commit/ca2b4bc)), closes [#37912](https://github.com/angular/angular/issues/37912)
|
||||
* **compiler-cli:** infer quote expressions as any type in type checker ([#37917](https://github.com/angular/angular/issues/37917)) ([5b87c67](https://github.com/angular/angular/commit/5b87c67)), closes [#36568](https://github.com/angular/angular/issues/36568)
|
||||
* **compiler-cli:** mark eager `NgModuleFactory` construction as not side effectful ([#38320](https://github.com/angular/angular/issues/38320)) ([016a41b](https://github.com/angular/angular/commit/016a41b)), closes [#38147](https://github.com/angular/angular/issues/38147)
|
||||
* **compiler-cli:** match wrapHost parameter types within plugin interface ([#38004](https://github.com/angular/angular/issues/38004)) ([df01a82](https://github.com/angular/angular/commit/df01a82))
|
||||
* **compiler-cli:** preserve quotes in class member names ([#38387](https://github.com/angular/angular/issues/38387)) ([c9acb7b](https://github.com/angular/angular/commit/c9acb7b)), closes [#38311](https://github.com/angular/angular/issues/38311)
|
||||
* **core:** prevent NgModule scope being overwritten in JIT compiler ([#37795](https://github.com/angular/angular/issues/37795)) ([3acebdc](https://github.com/angular/angular/commit/3acebdc)), closes [#37105](https://github.com/angular/angular/issues/37105)
|
||||
* **core:** queries not matching string injection tokens ([#38321](https://github.com/angular/angular/issues/38321)) ([32109dc](https://github.com/angular/angular/commit/32109dc)), closes [#38313](https://github.com/angular/angular/issues/38313) [#38315](https://github.com/angular/angular/issues/38315)
|
||||
* **core:** Store the currently selected ICU in `LView` ([#38345](https://github.com/angular/angular/issues/38345)) ([ee5123f](https://github.com/angular/angular/commit/ee5123f))
|
||||
* **platform-server:** remove styles added by ServerStylesHost on destruction ([#38367](https://github.com/angular/angular/issues/38367)) ([7f11149](https://github.com/angular/angular/commit/7f11149))
|
||||
* **router:** prevent calling unsubscribe on undefined subscription in RouterPreloader ([#38344](https://github.com/angular/angular/issues/38344)) ([4151314](https://github.com/angular/angular/commit/4151314))
|
||||
* **service-worker:** fix the chrome debugger syntax highlighter ([#38332](https://github.com/angular/angular/issues/38332)) ([f5d5bac](https://github.com/angular/angular/commit/f5d5bac))
|
||||
|
||||
|
||||
<a name="10.0.8"></a>
|
||||
## 10.0.8 (2020-08-04)
|
||||
@ -36,16 +348,6 @@
|
||||
|
||||
|
||||
|
||||
<a name="10.1.0-next.3"></a>
|
||||
# 10.1.0-next.3 (2020-07-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **elements:** run strategy methods in correct zone ([#37814](https://github.com/angular/angular/issues/37814)) ([8df888d](https://github.com/angular/angular/commit/8df888d)), closes [#24181](https://github.com/angular/angular/issues/24181)
|
||||
|
||||
|
||||
|
||||
<a name="10.0.6"></a>
|
||||
## 10.0.6 (2020-07-28)
|
||||
|
||||
@ -59,23 +361,6 @@
|
||||
|
||||
|
||||
|
||||
<a name="10.1.0-next.2"></a>
|
||||
# 10.1.0-next.2 (2020-07-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** Allow modification of lifecycle hooks any time before bootstrap ([#35464](https://github.com/angular/angular/issues/35464)) ([737506e](https://github.com/angular/angular/commit/737506e)), closes [#30497](https://github.com/angular/angular/issues/30497)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **common:** add ReadonlyMap in place of Map in keyValuePipe ([#37311](https://github.com/angular/angular/issues/37311)) ([3373453](https://github.com/angular/angular/commit/3373453)), closes [#37308](https://github.com/angular/angular/issues/37308)
|
||||
* **forms:** AbstractControl to store raw validators in addition to combined validators function ([#37881](https://github.com/angular/angular/issues/37881)) ([ad7046b](https://github.com/angular/angular/commit/ad7046b))
|
||||
* **localize:** allow duplicate messages to be handled during extraction ([#38082](https://github.com/angular/angular/issues/38082)) ([cf9a47b](https://github.com/angular/angular/commit/cf9a47b)), closes [#38077](https://github.com/angular/angular/issues/38077)
|
||||
|
||||
|
||||
|
||||
<a name="10.0.5"></a>
|
||||
## 10.0.5 (2020-07-22)
|
||||
|
||||
@ -110,62 +395,6 @@
|
||||
* **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)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **common:** date pipe gives wrong week number ([#37632](https://github.com/angular/angular/issues/37632)) ([ef1fb6d](https://github.com/angular/angular/commit/ef1fb6d)), closes [#33961](https://github.com/angular/angular/issues/33961)
|
||||
* **compiler-cli:** ensure source-maps can handle webpack:// protocol ([#32912](https://github.com/angular/angular/issues/32912)) ([decd95e](https://github.com/angular/angular/commit/decd95e))
|
||||
* **compiler-cli:** only read source-map comment from last line ([#32912](https://github.com/angular/angular/issues/32912)) ([07a07e3](https://github.com/angular/angular/commit/07a07e3))
|
||||
* **core:** determine required DOMParser feature availability ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([c509243](https://github.com/angular/angular/commit/c509243))
|
||||
* **core:** do not trigger CSP alert/report in Firefox and Chrome ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([b950d46](https://github.com/angular/angular/commit/b950d46)), closes [#25214](https://github.com/angular/angular/issues/25214)
|
||||
* **forms:** handle form groups/arrays own pending async validation ([#22575](https://github.com/angular/angular/issues/22575)) ([77b62a5](https://github.com/angular/angular/commit/77b62a5)), closes [#10064](https://github.com/angular/angular/issues/10064)
|
||||
* **language-service:** non-existent module format in package output ([#37623](https://github.com/angular/angular/issues/37623)) ([413a0fb](https://github.com/angular/angular/commit/413a0fb))
|
||||
* **router:** fix navigation ignoring logic to compare to the browser url ([#37716](https://github.com/angular/angular/issues/37716)) ([a5ffca0](https://github.com/angular/angular/commit/a5ffca0)), closes [#16710](https://github.com/angular/angular/issues/16710) [#13586](https://github.com/angular/angular/issues/13586)
|
||||
* **router:** properly compare array queryParams for equality ([#37709](https://github.com/angular/angular/issues/37709)) ([#37860](https://github.com/angular/angular/issues/37860)) ([1801d0c](https://github.com/angular/angular/commit/1801d0c))
|
||||
* **router:** remove parenthesis for primary outlet segment after removing auxiliary outlet segment ([#24656](https://github.com/angular/angular/issues/24656)) ([#37163](https://github.com/angular/angular/issues/37163)) ([71f008f](https://github.com/angular/angular/commit/71f008f))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **bazel:** provide LinkablePackageInfo from ng_module ([#37623](https://github.com/angular/angular/issues/37623)) ([6898eab](https://github.com/angular/angular/commit/6898eab))
|
||||
* **compiler-cli:** add `SourceFile.getOriginalLocation()` to sourcemaps package ([#32912](https://github.com/angular/angular/issues/32912)) ([6abb8d0](https://github.com/angular/angular/commit/6abb8d0))
|
||||
* **compiler-cli:** explain why an expression cannot be used in AOT compilations ([#37587](https://github.com/angular/angular/issues/37587)) ([712f1bd](https://github.com/angular/angular/commit/712f1bd))
|
||||
* **core:** support injection token as predicate in queries ([#37506](https://github.com/angular/angular/issues/37506)) ([97dc85b](https://github.com/angular/angular/commit/97dc85b)), closes [#21152](https://github.com/angular/angular/issues/21152) [#36144](https://github.com/angular/angular/issues/36144)
|
||||
* **localize:** expose `canParse()` diagnostics ([#37909](https://github.com/angular/angular/issues/37909)) ([ec32eba](https://github.com/angular/angular/commit/ec32eba)), closes [#37901](https://github.com/angular/angular/issues/37901)
|
||||
* **localize:** implement message extraction tool ([#32912](https://github.com/angular/angular/issues/32912)) ([190561d](https://github.com/angular/angular/commit/190561d))
|
||||
* **platform-browser:** Allow `sms`-URLs ([#31463](https://github.com/angular/angular/issues/31463)) ([fc5c34d](https://github.com/angular/angular/commit/fc5c34d)), closes [#31462](https://github.com/angular/angular/issues/31462)
|
||||
* **platform-server:** add option for absolute URL HTTP support ([#37539](https://github.com/angular/angular/issues/37539)) ([d37049a](https://github.com/angular/angular/commit/d37049a)), closes [#37071](https://github.com/angular/angular/issues/37071)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **compiler-cli:** fix regressions in incremental program reuse ([#37641](https://github.com/angular/angular/issues/37641)) ([5103d90](https://github.com/angular/angular/commit/5103d90))
|
||||
* **ngcc:** shortcircuit tokenizing in ESM dependency host ([#37639](https://github.com/angular/angular/issues/37639)) ([bd7f440](https://github.com/angular/angular/commit/bd7f440))
|
||||
* **ngcc:** use `EntryPointManifest` to speed up noop `ProgramBaseEntryPointFinder` ([#37665](https://github.com/angular/angular/issues/37665)) ([9318e23](https://github.com/angular/angular/commit/9318e23))
|
||||
* **router:** apply prioritizedGuardValue operator to optimize CanLoad guards ([#37523](https://github.com/angular/angular/issues/37523)) ([d7dd295](https://github.com/angular/angular/commit/d7dd295))
|
||||
|
||||
|
||||
|
||||
<a name="10.0.3"></a>
|
||||
## 10.0.3 (2020-07-08)
|
||||
|
||||
@ -447,12 +676,12 @@ https://github.com/microsoft/TypeScript/issues/38374 for more
|
||||
information and updates.
|
||||
|
||||
If you used Closure Compiler with Angular in the past, you will likely
|
||||
be better off consuming Angular packages built from sources directly
|
||||
be better off consuming Angular packages built from sources directly
|
||||
rather than consuming the version we publish on npm,
|
||||
which is primarily optimized for Webpack/Rollup + Terser build pipeline.
|
||||
|
||||
As a temporary workaround, you might consider using your current build
|
||||
pipeline with Closure flag `--compilation_level=SIMPLE`. This flag
|
||||
pipeline with Closure flag `--compilation_level=SIMPLE`. This flag
|
||||
will ensure that your build pipeline produces buildable and
|
||||
runnable artifacts, at the cost of increased payload size due to
|
||||
advanced optimizations being disabled.
|
||||
@ -460,17 +689,17 @@ advanced optimizations being disabled.
|
||||
If you were affected by this change, please help us understand your
|
||||
needs by leaving a comment on https://github.com/angular/angular/issues/37234.
|
||||
|
||||
* **core:** make generic mandatory for ModuleWithProviders
|
||||
* **core:** make generic mandatory for ModuleWithProviders
|
||||
|
||||
A generic type parameter has always been required for the `ModuleWithProviders` pattern to work with Ivy, but prior to this commit, View Engine allowed the generic type to be omitted (though support was officially deprecated).
|
||||
If you're using `ModuleWithProviders` without a generic type in your application code, a v10 migration will update your code for you.
|
||||
If you're using `ModuleWithProviders` without a generic type in your application code, a v10 migration will update your code for you.
|
||||
|
||||
However, if you are using View Engine and also depending on a library that omits the generic type, you will now get a build time error similar to:
|
||||
|
||||
```
|
||||
error TS2314: Generic type 'ModuleWithProviders<T>' requires 1 type argument(s).
|
||||
```
|
||||
|
||||
|
||||
In this case, ngcc won't help you (because it's Ivy-only) and the migration only covers application code.
|
||||
You should contact the library author to fix their library to provide a type parameter when they use this class.
|
||||
|
||||
@ -1798,7 +2027,7 @@ API surface going forward.
|
||||
* **core:** Injector.get now accepts abstract classes to return
|
||||
type-safe values. Previous implementation returned `any` through the
|
||||
deprecated implementation.
|
||||
* Angular now compiles with Ivy by default ([#32219](https://github.com/angular/angular/issues/32219)) ([ec4381d](https://github.com/angular/angular/commit/ec4381d)).
|
||||
* Angular now compiles with Ivy by default ([#32219](https://github.com/angular/angular/issues/32219)) ([ec4381d](https://github.com/angular/angular/commit/ec4381d)).
|
||||
|
||||
If you aren't familiar with Ivy, read our [blog post about the Ivy preview](https://blog.angular.io/its-time-for-the-compatibility-opt-in-preview-of-ivy-38f3542a282f?gi=8bfeb44b05c) and see the list of changes [here](https://docs.google.com/document/d/1Dije0AsJ0PxL3NaeNPxpYDeapj30b_QC0xfeIvIIzgg/preview).
|
||||
|
||||
|
@ -1,72 +1,12 @@
|
||||
# Código de Conducta
|
||||
# Contributor Code of Conduct
|
||||
## Version 0.3b-angular
|
||||
|
||||
## 1. Propósito
|
||||
As contributors and maintainers of the Angular project, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities.
|
||||
|
||||
“Prometemos brindar cortesía y respeto a cualquier persona involucrada en esta comunidad, sin importar el género con el que se identifique, su orientación sexual, limitación física, edad, raza, etnia, religión o nivel de conocimiento. Esperamos que cualquiera que desee contribuir en este proyecto brinde el mismo comportamiento”
|
||||
Communication through any of Angular's channels (GitHub, Gitter, IRC, mailing lists, Google+, Twitter, etc.) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
||||
|
||||
Bajo ese principio queremos enfocar esta comunidad, una comunidad de respeto por el otro, donde cualquiera que sienta pasión por Angular y desee involucrarse con cualquier tipo de actividad deberá ayudar a mantener una atmósfera de cortesía por el otro, respetando los pensamientos, acciones, ideales y propuestas del otro.
|
||||
We promise to extend courtesy and respect to everyone involved in this project regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to the Angular project to do the same.
|
||||
|
||||
## 2. Comportamiento esperado
|
||||
If any member of the community violates this code of conduct, the maintainers of the Angular project may take action, removing issues, comments, and PRs or blocking accounts as deemed appropriate.
|
||||
|
||||
- Evitar usar expresiones o gestos insultantes, humillantes o intimidatorios para referirnos a otros.
|
||||
- Ejercita la consideración y el respeto en tus comunicaciones y acciones.
|
||||
- Absténte de adoptar una conducta y un lenguaje degradantes, discriminatorios, abusivos o acosadores.
|
||||
- Evitar comportamientos que agredan las expresiones de identidad, género, creencias religiosas, acciones que lastimen o los aíslen a otros.
|
||||
- Evitar comentarios sobre ideas políticas.
|
||||
- No se toleran conductas físicas y actitudes dirigidas al descrédito personal, físico o emocional de cualquier persona.
|
||||
- No se toleran chistes y comentarios excluyentes, sexistas y racistas.
|
||||
- Se rechaza actitudes de hostigamiento.
|
||||
- Se rechaza el acoso: este se entiende como cualquier tipo de comentario verbal que refuerce discriminación por género, identidad y expresión de género, orientación sexual, discapacidad, apariencia física, tamaño corporal, raza, edad o religión en contextos laborales o sociales.
|
||||
- No se tolera el contacto físico y/o la atención sexual no deseada.
|
||||
- Promover la igualdad de oportunidades de formación, educación, intercambio y retroalimentación antes, durante y después de los eventos.
|
||||
- Intenta colaborar en lugar de generar conflicto.
|
||||
- Sé consciente de tu entorno y de tus compañeros participantes. Alerta a líderes de la comunidad si notas una situación peligrosa, alguien en apuros, o violaciones de este Código de Conducta, incluso si parecen intrascendentes.
|
||||
|
||||
## 3. Comportamiento inaceptable
|
||||
Comportamientos inaceptables incluyen: intimidación, acoso, abuso, discriminación, comunicación despectiva o degradante o acciones por cualquier participante en nuestra comunidad ya sea virtual, o en las comunicaciones uno-a-uno que se realizan en el contexto de la comunidad. Por favor ser respetuoso con todos.
|
||||
|
||||
El acoso incluye: comentarios nocivos o perjudiciales, verbales o escritos relacionados con el género, la orientación sexual, raza, religión, discapacidad; uso inadecuado de desnudos y / o imágenes sexuales en espacios públicos (incluyendo la presentación diapositivas); intimidación deliberada, acecho o seguimiento; fotografías o grabaciones acosadoras; interrupción sostenida de charlas y otros eventos; contacto físico inapropiado, y atención sexual no deseada.
|
||||
|
||||
## 4. Consecuencias de comportamiento inaceptable
|
||||
Se espera que personas a quienes se les solicite que detengan su comportamiento inaceptable lo hagan de manera inmediata esto será válido para cualquier miembro de la comunidad.
|
||||
|
||||
En caso de presentarse una violación al código de conducta de manera repetida se tendrá cero tolerancia a este comportamiento por parte de los organizadores.
|
||||
|
||||
Si un miembro de la comunidad participa en una conducta inaceptable, los organizadores pueden tomar cualquier acción que consideren apropiada, hasta e incluyendo una prohibición temporal o expulsión permanente de la comunidad, sin previo aviso.
|
||||
|
||||
Priorizamos la seguridad de las personas marginadas sobre la comodidad de las personas privilegiadas. Nos reservamos el derecho de no actuar sobre las quejas relacionadas con:
|
||||
|
||||
- El "racismo inverso", "sexismo inverso" y "cisfobia".
|
||||
- Comunicación razonable de límites, como "déjame en paz", "vete" o "no estoy discutiendo esto contigo".
|
||||
- Al comunicarse en un "tono", no se encuentra agradable.
|
||||
- Identificando comportamientos o suposiciones racistas, sexistas, cissexistas u opresivas.
|
||||
|
||||
## 5. ¿Qué hacer si se incumple el código de conducta?
|
||||
Si eres víctima o testigo de una conducta inaceptable, o tienes cualquier inquietud, por favor comunícate con el equipo organizador lo antes posible:
|
||||
|
||||
- Mensaje directo: Michael Prentice (@splaktar)
|
||||
- Mensaje directo: Jorge Cano (@jorgeucano)
|
||||
- Mensaje directo: Andrés Villanueva (@villanuevand)
|
||||
- Email: [soporte@angular.lat](mailto:soporte@angular.lat)
|
||||
|
||||
### ¿Qué pasa después?
|
||||
- Una vez haya sido notificada el no cumplimiento de la norma, el equipo de liderazgo se reunirán y analizarán el caso.
|
||||
- Los incidentes presentados se manejarán con discreción.
|
||||
- Los organizadores se comunicarán con la persona que incumplió la norma y tomarán las medidas respectivas.
|
||||
- Se realizará un acompañamiento a la persona agredida y se apoyará.
|
||||
- Si el incidente se hace público, Angular Hispano no se hace responsable de los perjuicios que esto pueda ocasionar en el agresor o el agredido.
|
||||
|
||||
## 6. Alcance
|
||||
Esperamos que todos los participantes de la comunidad (organizadores, voluntarios, contribuyentes pagados o de otro modo; patrocinadores; y otros invitados) se atengan a este Código de Conducta en todos los espacios virtuales y presenciales, así como en todas las comunicaciones de uno-a-uno pertinentes la comunidad.
|
||||
|
||||
### Colaboradores
|
||||
|
||||
- Alejandra Giraldo
|
||||
- Vanessa Marely
|
||||
- Mariano Alvarez
|
||||
- Andrés Villanueva
|
||||
- Michael Prentice
|
||||
- javascript&friends
|
||||
- Angular
|
||||
- She Codes Angular
|
||||
- Colombia dev
|
||||
If you are subject to or witness unacceptable behavior, or have any other concerns, please email us at [conduct@angular.io](mailto:conduct@angular.io).
|
||||
|
@ -1,359 +0,0 @@
|
||||
# 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:
|
||||
|
||||
- [Code of Conduct](#coc)
|
||||
- [Question or Problem?](#question)
|
||||
- [Issues and Bugs](#issue)
|
||||
- [Feature Requests](#feature)
|
||||
- [Submission Guidelines](#submit)
|
||||
- [Coding Rules](#rules)
|
||||
- [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].
|
||||
|
||||
|
||||
## <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.
|
||||
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:
|
||||
|
||||
- there are thousands of people willing to help on Stack Overflow
|
||||
- questions and answers stay available for public viewing so your question/answer might help someone else
|
||||
- Stack Overflow's voting system assures that the best answers are prominently visible.
|
||||
|
||||
To save your and our time, we will systematically close all issues that are requests for general support and redirect people to Stack Overflow.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
## <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 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.
|
||||
|
||||
* **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 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 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.
|
||||
|
||||
You can file new issues by selecting from our [new issue templates](https://github.com/angular/angular/issues/new/choose) and filling out the issue template.
|
||||
|
||||
|
||||
### <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 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
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
10. Push your branch to GitHub:
|
||||
|
||||
```shell
|
||||
git push origin my-fix-branch
|
||||
```
|
||||
|
||||
11. In GitHub, send a pull request to `angular:master`.
|
||||
|
||||
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:
|
||||
|
||||
* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
|
||||
|
||||
```shell
|
||||
git push origin --delete my-fix-branch
|
||||
```
|
||||
|
||||
* Check out the master branch:
|
||||
|
||||
```shell
|
||||
git checkout master -f
|
||||
```
|
||||
|
||||
* Delete the local branch:
|
||||
|
||||
```shell
|
||||
git branch -D my-fix-branch
|
||||
```
|
||||
|
||||
* Update your master with the latest upstream version:
|
||||
|
||||
```shell
|
||||
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**.
|
||||
* 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).
|
||||
|
||||
|
||||
## <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**.
|
||||
|
||||
|
||||
```
|
||||
<header>
|
||||
<BLANK LINE>
|
||||
<body>
|
||||
<BLANK LINE>
|
||||
<footer>
|
||||
```
|
||||
|
||||
The `header` is mandatory and must conform to the [Commit Message Header](#commit-header) format.
|
||||
|
||||
The `body` is mandatory for all commits except for those of scope "docs".
|
||||
When the body is required it must be at least 20 characters long.
|
||||
|
||||
The `footer` is optional.
|
||||
|
||||
Any line of the commit message cannot be longer than 100 characters.
|
||||
|
||||
|
||||
#### <a href="commit-header"></a>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
|
||||
│
|
||||
└─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
|
||||
```
|
||||
|
||||
The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is optional.
|
||||
|
||||
|
||||
##### Type
|
||||
|
||||
Must be one of the following:
|
||||
|
||||
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
|
||||
* **ci**: Changes to our CI configuration files and scripts (example scopes: Circle, BrowserStack, SauceLabs)
|
||||
* **docs**: Documentation only changes
|
||||
* **feat**: A new feature
|
||||
* **fix**: A bug fix
|
||||
* **perf**: A code change that improves performance
|
||||
* **refactor**: A code change that neither fixes a bug nor adds a feature
|
||||
* **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
|
||||
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`
|
||||
|
||||
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
|
||||
|
||||
* `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
|
||||
|
||||
|
||||
#### 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.
|
||||
|
||||
|
||||
### 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 name="cla"></a> Signing the CLA
|
||||
|
||||
Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code
|
||||
changes to be accepted, the CLA must be signed. It's a quick process, we promise!
|
||||
|
||||
* For individuals, we have a [simple click-through form][individual-cla].
|
||||
* For corporations, we'll need you to
|
||||
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
|
||||
|
||||
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.
|
||||
|
||||
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/
|
||||
|
||||
|
||||
|
||||
|
||||
[angular-group]: https://groups.google.com/forum/#!forum/angular
|
||||
[coc]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md
|
||||
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
|
||||
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
|
||||
[dev-doc]: https://github.com/angular/angular/blob/master/docs/DEVELOPER.md
|
||||
[github]: https://github.com/angular/angular
|
||||
[gitter]: https://gitter.im/angular/angular
|
||||
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
|
||||
[js-style-guide]: https://google.github.io/styleguide/jsguide.html
|
||||
[jsfiddle]: http://jsfiddle.net
|
||||
[plunker]: http://plnkr.co/edit
|
||||
[runnable]: http://runnable.com
|
||||
[stackoverflow]: http://stackoverflow.com/questions/tagged/angular
|
302
CONTRIBUTING.md
302
CONTRIBUTING.md
@ -1,243 +1,242 @@
|
||||
# Contribuye a Angular
|
||||
# Contributing to Angular
|
||||
|
||||
¡Nos encantaría que contribuyeras a Angular y que ayudaras a hacerlo aún mejor de lo que es hoy!
|
||||
Como colaborador, estos son los lineamientos que nos gustaría que siguieras:
|
||||
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:
|
||||
|
||||
- [Código de conducta](#coc)
|
||||
- [¿Preguntas o problemas?](#question)
|
||||
- [_Issues_ y _bugs_](#issue)
|
||||
- [Solicitud de funcionalidades](#feature)
|
||||
- [Guía para la creación de issues y PRs](#submit)
|
||||
- [Reglas del código](#rules)
|
||||
- [Convención para el mensaje de los _commits_](#commit)
|
||||
- [Firma del Acuerdo de Licencia de Colaborador (CLA)](#cla)
|
||||
- [Code of Conduct](#coc)
|
||||
- [Question or Problem?](#question)
|
||||
- [Issues and Bugs](#issue)
|
||||
- [Feature Requests](#feature)
|
||||
- [Submission Guidelines](#submit)
|
||||
- [Coding Rules](#rules)
|
||||
- [Commit Message Guidelines](#commit)
|
||||
- [Signing the CLA](#cla)
|
||||
|
||||
|
||||
## <a name="coc"></a> Código de conducta
|
||||
## <a name="coc"></a> Code of Conduct
|
||||
|
||||
Ayúdanos a mantener Angular abierto e inclusivo.
|
||||
Por favor lee y sigue nuestro [Código de conducta][coc].
|
||||
Help us keep Angular open and inclusive.
|
||||
Please read and follow our [Code of Conduct][coc].
|
||||
|
||||
|
||||
## <a name="question"></a> ¿Tienes alguna pregunta o problema?
|
||||
## <a name="question"></a> Got a Question or Problem?
|
||||
|
||||
No abras *issues* para preguntas de soporte general ya que queremos mantener los *issues* de GitHub para reporte de *bugs* y solicitud de funcionalidades.
|
||||
En su lugar, recomendamos utilizar [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) para hacer preguntas relacionadas con soporte. Al crear una nueva pregunta en Stack Overflow, asegúrate de agregar el etiqueta (tag) de `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 es mucho mejor para hacer preguntas ya que:
|
||||
Stack Overflow is a much better place to ask questions since:
|
||||
|
||||
- Hay miles de personas dispuestas a ayudar en preguntas y respuestas de Stack Overflow
|
||||
que permanecen disponibles para el público, por lo que tu pregunta o respuesta podría ayudar a otra persona.
|
||||
- El sistema de votación de Stack Overflow asegura que las mejores respuestas sobresalgan y sean visibles.
|
||||
- there are thousands of people willing to help on Stack Overflow
|
||||
- questions and answers stay available for public viewing so your question/answer might help someone else
|
||||
- Stack Overflow's voting system assures that the best answers are prominently visible.
|
||||
|
||||
Para ahorrar tu tiempo y el nuestro, cerraremos sistemáticamente todos los *issues* que sean solicitudes de soporte general y redirigiremos a las personas a Stack Overflow.
|
||||
To save your and our time, we will systematically close all issues that are requests for general support and redirect people to Stack Overflow.
|
||||
|
||||
Si deseas chatear sobre alguna pregunta en tiempo real, puedes hacerlo a través de nuestro [canal de Gitter][gitter].
|
||||
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> ¿Encontraste un Bug?
|
||||
## <a name="issue"></a> Found a Bug?
|
||||
|
||||
Si encontraste un error en el código fuente, puedes ayudarnos [creando un *issue*](#submit-issue) en nuestro [repositorio de GitHub][github].
|
||||
O incluso mejor, puedes [crear un *Pull Request*](#submit-pr) con la solución.
|
||||
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> ¿Falta alguna funcionalidad?
|
||||
Puedes solicitar una nueva funcionalidad [creando un *issue*](#submit-issue) en nuestro repositorio de GitHub.
|
||||
Si deseas implementar una nueva funcionalidad, por favor considera el tamaño del cambio para determinar los pasos correctos para continuar:
|
||||
## <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 consider the size of the change in order to determine the right steps to proceed:
|
||||
|
||||
* Para un **cambio significativo**, primero abre un *issue* y describe tu propuesta para que pueda ser discutida.
|
||||
Este proceso nos permite coordinar mejor nuestros esfuerzos, evitar trabajo duplicado y ayudarte a diseñar el cambio para que sea aceptado con éxito en el proyecto.
|
||||
* 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.
|
||||
|
||||
**Nota**: Agregar un nuevo tema a la documentación o reescribir significativamente un tema, también cuenta como *cambio significativo*.
|
||||
**Note**: Adding a new topic to the documentation, or significantly re-writing a topic, counts as a major feature.
|
||||
|
||||
* **Cambios pequeños** pueden ser elaborados y directamente [creados como un _pull request_](#submit-pr).
|
||||
* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
|
||||
|
||||
|
||||
## <a name="submit"></a> Guía para la creación de issues y PRs
|
||||
## <a name="submit"></a> Submission Guidelines
|
||||
|
||||
|
||||
### <a name="submit-issue"></a> Creación de _issues_
|
||||
### <a name="submit-issue"></a> Submitting an Issue
|
||||
|
||||
Antes de crear un *issue*, por favor busca en el el *issue tracker*, quizá un *issue* para tu problema ya existe y la discusión puede informarte sobre soluciones alternativas disponibles.
|
||||
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.
|
||||
|
||||
Queremos solucionar todos los problemas lo antes posible, pero antes de corregir un bug necesitamos reproducirlo y confirmarlo.
|
||||
Para reproducir errores, requerimos que proporciones una reproducción mínima.
|
||||
Tener un escenario reproducible mínimo nos brinda una gran cantidad de información importante sin tener que ir y venir con preguntas adicionales.
|
||||
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.
|
||||
|
||||
Una reproducción mínima nos permite confirmar rápidamente un bug (o señalar un problema de código), así también confirmar que estamos solucionando el problema correcto.
|
||||
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.
|
||||
|
||||
Requerimos una reproducción mínima para ahorrar tiempo a los encargados del mantenimiento y en última instancia, poder corregir más bugs.
|
||||
A menudo los desarrolladores encuentran problemas de código mientras preparan una reproducción mínima.
|
||||
Entendemos que a veces puede ser difícil extraer porciones esenciales de código de un código más grande, pero realmente necesitamos aislar el problema antes de poder solucionarlo.
|
||||
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.
|
||||
|
||||
Desafortunadamente no podemos investigar/corregir errores sin una reproducción mínima, por lo que si no tenemos tu retroalimentación del bug, vamos a cerrar el *issue* ya que no tiene suficiente información para reproducirse.
|
||||
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.
|
||||
|
||||
Puedes presentar nuevos *issues* seleccionando nuestra [plantilla de _issues_](https://github.com/angular/angular/issues/new/choose) y complentando la plantilla.
|
||||
You can file new issues by selecting from our [new issue templates](https://github.com/angular/angular/issues/new/choose) and filling out the issue template.
|
||||
|
||||
|
||||
### <a name="submit-pr"></a> Creación de un Pull Requests (PR)
|
||||
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
|
||||
|
||||
Antes de crear tu Pull Request (PR) considera los siguientes lineamientos:
|
||||
Before you submit your Pull Request (PR) consider the following guidelines:
|
||||
|
||||
1. Busca en [GitHub](https://github.com/angular/angular/pulls) PRs que estén abiertos o cerrados y que estén relacionados con el que vas a crear.
|
||||
No deseas duplicar los esfuerzos existentes.
|
||||
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. Asegúrate de que el PR describa el problema que estás solucionando o que documente el diseño de la funcionalidad que deseas agregar.
|
||||
Discutir el diseño por adelantado ayuda a garantizar que estemos listos para aceptar tu trabajo.
|
||||
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. Por favor firma nuestro [Acuerdo de Licencia de Colaborador (CLA)](#cla) antes de crear PRs.
|
||||
No podemos aceptar el código sin el Acuerdo de Licencia de Colaborador (CLA) firmado.
|
||||
Asegúrate de crear todas las contribuciones de Git con la dirección de correo electrónico asociada con tu firma del Acuerdo de Licencia de Colaborador (CLA).
|
||||
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. Haz *fork* del repositorio angular/angular.
|
||||
4. Fork the angular/angular repo.
|
||||
|
||||
5. Haz tus cambios en una nueva rama de Git:
|
||||
5. Make your changes in a new git branch:
|
||||
|
||||
```shell
|
||||
git checkout -b my-fix-branch master
|
||||
```
|
||||
|
||||
6. Crea tu correción, **incluyendo casos de prueba apropiados**.
|
||||
6. Create your patch, **including appropriate test cases**.
|
||||
|
||||
7. Sigue nuestras [Reglas de código](#rules).
|
||||
7. Follow our [Coding Rules](#rules).
|
||||
|
||||
8. Ejecuta todo el conjunto de pruebas de Angular, tal como está descrito en la [documentación del desarrollador][dev-doc], y asegúrate de que todas las pruebas pasen.
|
||||
8. Run the full Angular test suite, as described in the [developer documentation][dev-doc], and ensure that all tests pass.
|
||||
|
||||
9. Crea un commit de tus cambios utilizando un mensaje de commit descriptivo que siga nuestra [convención para el mensaje de los commits](#commit).
|
||||
Es necesario cumplir con estas convenciones porque las notas de las versiones se generan automáticamente a partir de estos mensajes.
|
||||
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
|
||||
```
|
||||
Nota: la opción de la línea de comandos de Git `-a` automaticamente hará "add" y "rm" a los archivos editados.
|
||||
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
|
||||
|
||||
10. Haz push de tu rama a GitHub:
|
||||
10. Push your branch to GitHub:
|
||||
|
||||
```shell
|
||||
git push origin my-fix-branch
|
||||
```
|
||||
|
||||
11. En GitHub, crea un pull request a `angular:master`.
|
||||
11. In GitHub, send a pull request to `angular:master`.
|
||||
|
||||
Si solicitamos cambios a través de revisiones de código, sigue las siguientes indicaciones:
|
||||
If we ask for changes via code reviews then:
|
||||
|
||||
* Haz los cambios requeridos.
|
||||
* Ejecuta nuevamente el conjunto de pruebas de Angular para asegurar que todas las pruebas aún están pasando.
|
||||
* Haz rebase de tu rama a la rama master y haz push con la opción `-f` a tu repositorio de Github (esto actualizará tu Pull Request):
|
||||
* 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
|
||||
```
|
||||
|
||||
¡Es todo! ¡Muchas gracias por tu contribución!
|
||||
That's it! Thank you for your contribution!
|
||||
|
||||
|
||||
#### Después del merge de tu pull request
|
||||
#### After your pull request is merged
|
||||
|
||||
Después de que se hizo merge de tu pull request, puedes eliminar de forma segura tu rama y hacer pull de los cambios del repositorio principal (upstream):
|
||||
After your pull request is merged, you can safely delete your branch and pull the changes from the main (upstream) repository:
|
||||
|
||||
* Elimina la rama remota en GitHub a través de la interfaz de usuario web de GitHub o en tu línea de comandos de la siguiente manera:
|
||||
* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
|
||||
|
||||
```shell
|
||||
git push origin --delete my-fix-branch
|
||||
```
|
||||
|
||||
* Muévete a la rama master:
|
||||
* Check out the master branch:
|
||||
|
||||
```shell
|
||||
git checkout master -f
|
||||
```
|
||||
|
||||
* Elimina tu rama local:
|
||||
* Delete the local branch:
|
||||
|
||||
```shell
|
||||
git branch -D my-fix-branch
|
||||
```
|
||||
|
||||
* Actualiza tu rama master con la última versión del fork (upstream):
|
||||
* Update your master with the latest upstream version:
|
||||
|
||||
```shell
|
||||
git pull --ff upstream master
|
||||
```
|
||||
|
||||
|
||||
## <a name="rules"></a> Reglas del código
|
||||
Para garantizar la coherencia en todo el código fuente, ten en cuenta estas reglas mientras trabajas:
|
||||
## <a name="rules"></a> Coding Rules
|
||||
To ensure consistency throughout the source code, keep these rules in mind as you are working:
|
||||
|
||||
* Todas las funcionalidades o solución de bugs **deben ser probadas** por una o más pruebas (pruebas unitarias).
|
||||
* Todos los métodos públicos del API **deben ser documentados**.
|
||||
* Seguimos la [guía de estilo JavaScript de Google][js-style-guide], pero cada línea no debe exceder **100 caracteres**.
|
||||
* All features or bug fixes **must be tested** by one or more specs (unit-tests).
|
||||
* All public API methods **must be documented**.
|
||||
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at **100 characters**.
|
||||
|
||||
Un formateador automatizado está disponible, revisar [DEVELOPER.md](docs/DEVELOPER.md#clang-format).
|
||||
An automated formatter is available, see [DEVELOPER.md](docs/DEVELOPER.md#clang-format).
|
||||
|
||||
|
||||
## <a name="commit"></a> Formato para el mensaje de los commits
|
||||
## <a name="commit"></a> Commit Message Format
|
||||
|
||||
*Esta especificación está inspirada y reemplaza el [Formato de mensaje de commits de AngularJS][commit-message-format].*
|
||||
*This specification is inspired and supersedes the [AngularJS commit message format][commit-message-format].*
|
||||
|
||||
Tenemos reglas muy precisas sobre cómo deben formatearse nuestros mensajes de los commits de Git.
|
||||
Este formato permite tener **un historial de commits más facil de leer**.
|
||||
We have very precise rules over how our Git commit messages must be formatted.
|
||||
This format leads to **easier to read commit history**.
|
||||
|
||||
Cada mensaje de un commit consta del **header**, el **body**, y el **footer**.
|
||||
Each commit message consists of a **header**, a **body**, and a **footer**.
|
||||
|
||||
|
||||
```
|
||||
<header>
|
||||
<LINEA VACIA>
|
||||
<BLANK LINE>
|
||||
<body>
|
||||
<LINEA VACIA>
|
||||
<BLANK LINE>
|
||||
<footer>
|
||||
```
|
||||
|
||||
El `header` es obligatorio y debe ajustarse al formato del [mensaje del header del commit](#commit-header).
|
||||
The `header` is mandatory and must conform to the [Commit Message Header](#commit-header) format.
|
||||
|
||||
El `body` es obligatorio para todos los commits excepto los que tenga scope "docs".
|
||||
Cuando el body es requerido debe tener al menos 20 caracteres.
|
||||
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.
|
||||
|
||||
El `footer` es opcional.
|
||||
The `footer` is optional.
|
||||
|
||||
Cualquier línea del mensaje del commit no puede tener más de 100 caracteres.
|
||||
Any line of the commit message cannot be longer than 100 characters.
|
||||
|
||||
|
||||
#### <a href="commit-header"></a>Mensaje del header del commit
|
||||
#### <a href="commit-header"></a>Commit Message Header
|
||||
|
||||
```
|
||||
<tipo>(<alcance>): <resumen>
|
||||
<type>(<scope>): <short summary>
|
||||
│ │ │
|
||||
│ │ └─⫸ Resumen corto escrito en modo imperativo, tiempo presente. Sin mayúsculas. Sin punto final.
|
||||
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
|
||||
│ │
|
||||
│ └─⫸ Alcance del commit: animations|bazel|benchpress|common|compiler|compiler-cli|core|
|
||||
│ └─⫸ 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
|
||||
│
|
||||
└─⫸ Tipo de commit: build|ci|docs|feat|fix|perf|refactor|style|test
|
||||
└─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
|
||||
```
|
||||
|
||||
El `<tipo>` y `<resumen>` son obligatorios, el `(<alcance>)` es opcional.
|
||||
The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is optional.
|
||||
|
||||
|
||||
##### Tipo
|
||||
##### Type
|
||||
|
||||
El tipo debe ser uno de los siguientes:
|
||||
Must be one of the following:
|
||||
|
||||
* **build**: cambios que afectan el sistema de compilación o dependencias externas (ejemplos de scopes: gulp, broccoli, npm)
|
||||
* **ci**: cambios en nuestros archivos y scripts de configuración de CI (ejemplos de scopes: Circle, BrowserStack, SauceLabs)
|
||||
* **docs**: cambios en la documentación
|
||||
* **feat**: una nueva funcionalidad
|
||||
* **fix**: una solución de un bug
|
||||
* **perf**: un cambio de código que mejora el rendimiento.
|
||||
* **refactor**: un cambio de código que no corrige ningún error ni agrega ninguna funcionalidad
|
||||
* **style**: cambios que no afectan el significado del código (espacios en blanco, formato, falta de punto y coma, etc.)
|
||||
* **test**: se agregan pruebas faltantes o se corrigen pruebas existentes
|
||||
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
|
||||
* **ci**: Changes to our CI configuration files and scripts (example scopes: Circle, BrowserStack, SauceLabs)
|
||||
* **docs**: Documentation only changes
|
||||
* **feat**: A new feature
|
||||
* **fix**: A bug fix
|
||||
* **perf**: A code change that improves performance
|
||||
* **refactor**: A code change that neither fixes a bug nor adds a feature
|
||||
* **test**: Adding missing tests or correcting existing tests
|
||||
|
||||
|
||||
##### Alcance
|
||||
El alcance debe ser el nombre del paquete npm afectado (tal como lo percibe la persona que lee el registro de cambios generado a partir de los mensajes de commit).
|
||||
##### Scope
|
||||
The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages).
|
||||
|
||||
La siguiente es la lista de alcances permitidos:
|
||||
The following is the list of supported scopes:
|
||||
|
||||
* `animations`
|
||||
* `bazel`
|
||||
@ -261,73 +260,80 @@ La siguiente es la lista de alcances permitidos:
|
||||
* `upgrade`
|
||||
* `zone.js`
|
||||
|
||||
Actualmente hay algunas excepciones a la regla "usar el nombre de paquete":
|
||||
There are currently a few exceptions to the "use package name" rule:
|
||||
|
||||
* `packaging`: usado para cambios que cambian el diseño de los paquetes de npm en todos nuestros paquetes. Ejemplos: cambios de la ruta públic, package.json cambios hechos a todos los paquetes, cambios a archivos o formatos d.ts, cambios a bundles, etc.
|
||||
* `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`: utilizado para actualizar las notas de la versión en CHANGELOG.md
|
||||
* `changelog`: used for updating the release notes in CHANGELOG.md
|
||||
|
||||
* `dev-infra`: utilizado para cambios relacionados con dev-infra dentro de los directorios /scripts, /tools y /dev-infra
|
||||
* `dev-infra`: used for dev-infra related changes within the directories /scripts, /tools and /dev-infra
|
||||
|
||||
* `docs-infra`: utilizado para cambios relacionados con la documentación (angular.io) dentro del directorio /aio del repositorio
|
||||
* `docs-infra`: used for docs-app (angular.io) related changes within the /aio directory of the repo
|
||||
|
||||
* `migrations`: utilizado para los cambios en las migraciones `ng update`.
|
||||
* `migrations`: used for changes to the `ng update` migrations.
|
||||
|
||||
* `ngcc`: usado para los cambios del [Compilador de compatibilidad de Angular](./packages/compiler-cli/ngcc/README.md)
|
||||
* `ngcc`: used for changes to the [Angular Compatibility Compiler](./packages/compiler-cli/ngcc/README.md)
|
||||
|
||||
* `ve`: utilizado para cambios específicos de ViewEngine (legacy compiler/renderer).
|
||||
* `ve`: used for changes specific to ViewEngine (legacy compiler/renderer).
|
||||
|
||||
* alcance vacío: útil para cambios de `style`, `test` y `refactor` que se realizan en todos los paquetes (ejemplo: `style: add missing semicolons`) y para cambios de la documentación que no están relacionados a un paquete en específico(ejemplo: `docs: corrige error gramatical en el tutorial`).
|
||||
* 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`).
|
||||
|
||||
|
||||
##### Resumen
|
||||
##### Summary
|
||||
|
||||
Usa el campo resumen para proporcionar una descripción breve del cambio:
|
||||
Use the summary field to provide a succinct description of the change:
|
||||
|
||||
* usa el modo imperativo, tiempo presente: "cambia" no "cambió" o "cambios"
|
||||
* no debe de contener ninguna letra mayúscula
|
||||
* no debe de conter punto (.) al final
|
||||
* use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
* don't capitalize the first letter
|
||||
* no dot (.) at the end
|
||||
|
||||
|
||||
#### Mensaje del cuerpo del commit
|
||||
#### Commit Message Body
|
||||
|
||||
Tal como en el resumen, usa el modo imperativo, tiempo presente: "cambia" no "cambió" o "cambios".
|
||||
Just as in the summary, use the imperative, present tense: "fix" not "fixed" nor "fixes".
|
||||
|
||||
Explica la razón del cambio en el el mensaje del cuerpo del commit. Este mensaje de confirmación debe explicar _por qué_ está realizando el cambio.
|
||||
Puedes incluir una comparación del comportamiento anterior con el nuevo comportamiento para ilustrar el impacto del cambio.
|
||||
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.
|
||||
|
||||
|
||||
#### Mensaje del footer del commit
|
||||
#### Commit Message Footer
|
||||
|
||||
El footer puede contener información sobre cambios significativos y también es el lugar para hacer referencia a issues de GitHub, tickets de Jira y otros PRs que están relacionados con el commit.
|
||||
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.
|
||||
|
||||
```
|
||||
CAMBIO SIGNIFICATIVO: <resumen del cambio significativo>
|
||||
<LINEA VACIA>
|
||||
<descripción del cambio significativo + instrucciones para la migración>
|
||||
<LINEA VACIA>
|
||||
<LINEA VACIA>
|
||||
Fix #<issue número>
|
||||
BREAKING CHANGE: <breaking change summary>
|
||||
<BLANK LINE>
|
||||
<breaking change description + migration instructions>
|
||||
<BLANK LINE>
|
||||
<BLANK LINE>
|
||||
Fixes #<issue number>
|
||||
```
|
||||
|
||||
La sección de cambios significativos debería comenzar con la frase "CAMBIO SIGNIFICATIVO: " seguido de un resumen del cambio significativo, una línea en blanco y una descripción detallada del cambio significativo que también incluya instrucciones de migración.
|
||||
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.
|
||||
|
||||
|
||||
### Revirtiendo commits
|
||||
### Revert commits
|
||||
|
||||
Si el commit revierte un commit previo, el commit debería comenzar con `revert: `, seguido por el header del commit revertido.
|
||||
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit.
|
||||
|
||||
El contenido del mensaje del commit debería contener:
|
||||
The content of the commit message body should contain:
|
||||
|
||||
- Información sobre el SHA del commit que se revierte en el siguiente formato: `Esto revierte el commit <SHA>`,
|
||||
- Una descripción clara de la razón para revertir el mensaje del _commit_.
|
||||
- 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 name="cla"></a> Firma del Acuerdo de Licencia de Colaborador (CLA)
|
||||
## <a name="cla"></a> Signing the CLA
|
||||
|
||||
Por favor firma nuestro Acuerdo de Licencia de Colaborador (CLA) cuando creas tu primer pull request. Para que cualquier cambio de código sea aceptado, el Acuerdo de Licencia de Colaborador (CLA) debe ser firmado. Es un proceso rápido con nuestro CLA assistant que está integrado con nuestro CI.
|
||||
Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code
|
||||
changes to be accepted, the CLA must be signed. It's a quick process, we promise!
|
||||
|
||||
Los siguientes documentos pueden ayudarte a resolver problemas con cuentas de GitHub y múltiples direcciones de correo electrónico:
|
||||
* For individuals, we have a [simple click-through form][individual-cla].
|
||||
* For corporations, we'll need you to
|
||||
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
|
26
README.en.md
26
README.en.md
@ -1,26 +0,0 @@
|
||||
[](https://circleci.com/gh/angular/workflows/angular/tree/master)
|
||||
[](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://www.npmjs.com/@angular/core)
|
||||
|
||||
|
||||
# Angular
|
||||
|
||||
Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages.
|
||||
|
||||
## Quickstart
|
||||
|
||||
[Get started in 5 minutes][quickstart].
|
||||
|
||||
## Changelog
|
||||
|
||||
[Learn about the latest improvements][changelog].
|
||||
|
||||
## Want to help?
|
||||
|
||||
Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our
|
||||
guidelines for [contributing][contributing] and then check out one of our issues in the [hotlist: community-help](https://github.com/angular/angular/labels/hotlist%3A%20community-help).
|
||||
|
||||
[contributing]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md
|
||||
[quickstart]: https://angular.io/start
|
||||
[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md
|
||||
[ng]: https://angular.io
|
31
README.md
31
README.md
@ -1,25 +1,26 @@
|
||||
# Angular en español
|
||||
[](https://circleci.com/gh/angular/workflows/angular/tree/master)
|
||||
[](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://www.npmjs.com/@angular/core)
|
||||
|
||||
Angular es una plataforma de desarrollo para construir aplicaciones web y móviles que usa
|
||||
TypeScript/JavaScript y otros lenguajes de programación.
|
||||
|
||||
## ¿Quieres ayudar?
|
||||
# Angular
|
||||
|
||||
### Documentación en español
|
||||
Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages.
|
||||
|
||||
¿Quieres mejorar la documentación? ¡Excelente! Lee nuestras pautas para
|
||||
[colaborar](CONTRIBUTING.md) y luego revisa algunos de nuestras
|
||||
[issues](https://github.com/angular-hispano/angular/issues).
|
||||
## Quickstart
|
||||
|
||||
### El framework
|
||||
[Get started in 5 minutes][quickstart].
|
||||
|
||||
La colaboración para corregir errores y agregar funciones en el framework debe realizarse en inglés a través
|
||||
del repositorio [angular/angular](https://github.com/angular/angular) upstream.
|
||||
## Changelog
|
||||
|
||||
## Guía rápida
|
||||
[Learn about the latest improvements][changelog].
|
||||
|
||||
[Comienza a usarlo en 5 minutos](https://docs.angular.lat/start).
|
||||
## Want to help?
|
||||
|
||||
## Registro de cambios (Changelog)
|
||||
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).
|
||||
|
||||
[Últimas mejoras realizadas](CHANGELOG.md).
|
||||
[contributing]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md
|
||||
[quickstart]: https://angular.io/start
|
||||
[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md
|
||||
[ng]: https://angular.io
|
||||
|
167
aio/README.md
167
aio/README.md
@ -1,131 +1,140 @@
|
||||
# Proyecto de documentación Angular (https://docs.angular.lat)
|
||||
# Angular documentation project (https://angular.io)
|
||||
|
||||
Todo en esta carpeta es parte del proyecto de documentación. Esto incluye:
|
||||
Everything in this folder is part of the documentation project. This includes
|
||||
|
||||
* El sitio web para mostrar la documentación
|
||||
* La configuración de dgeni para convertir los archivos de origen a archivos renderizados que se pueden vizualizar en el sitio web.
|
||||
* Las herramientas para establecer ejemplos para el desarrollo; y generar archivos en tiempo real y archivos zip desde los ejemplos.
|
||||
* the web site for displaying the documentation
|
||||
* the dgeni configuration for converting source files to rendered files that can be viewed in the web site.
|
||||
* the tooling for setting up examples for development; and generating live-example and zip files from the examples.
|
||||
|
||||
## Tareas de desarrollador
|
||||
## Developer tasks
|
||||
|
||||
Nosotros usamos [Yarn](https://yarnpkg.com) para gestionar las dependencias y crear tareas de compilación.
|
||||
Debes ejecutar todas estas tareas desde la carpeta `angular/aio`.
|
||||
Aquí están las tareas más importantes que podrías necesitar usar:
|
||||
We use [Yarn](https://yarnpkg.com) to manage the dependencies and to run build tasks.
|
||||
You should run all these tasks from the `angular/aio` folder.
|
||||
Here are the most important tasks you might need to use:
|
||||
|
||||
* `yarn` - instalar todas las dependencias.
|
||||
* `yarn setup` - instalar todas las dependencias, boilerplate, stackblitz, zips y ejecuta dgeni en los documentos.
|
||||
* `yarn setup-local` - igual que `setup`, pero crea los paquetes de Angular a partir del código y usa estas versiones construidas localmente (en lugar de las recuperadas desde npm) para aio y ejemplos de documentos boilerplate.
|
||||
* `yarn` - install all the dependencies.
|
||||
* `yarn setup` - install all the dependencies, boilerplate, stackblitz, zips and run dgeni on the docs.
|
||||
* `yarn setup-local` - same as `setup`, but build the Angular packages from the source code and use these locally built versions (instead of the ones fetched from npm) for aio and docs examples boilerplate.
|
||||
|
||||
* `yarn build` - crear una compilación de producción de la aplicación (después de instalar dependencias, boilerplate, etc).
|
||||
* `yarn build-local` - igual que `build`, pero usa `setup-local` en lugar de `setup`.
|
||||
* `yarn build-local-with-viewengine` - igual que `build-local`, pero además también enciende el modo `ViewEngine` (pre-Ivy) en aio.
|
||||
(Nota: Encender el modo `ViewEngine` en ejemplos de documentos, ver `yarn boilerplate:add:viewengine` abajo.)
|
||||
* `yarn build` - create a production build of the application (after installing dependencies, boilerplate, etc).
|
||||
* `yarn build-local` - same as `build`, but use `setup-local` instead of `setup`.
|
||||
* `yarn build-local-with-viewengine` - same as `build-local`, but in addition also turns on `ViewEngine` (pre-Ivy) mode in aio.
|
||||
(Note: To turn on `ViewEngine` mode in docs examples, see `yarn boilerplate:add:viewengine` below.)
|
||||
|
||||
* `yarn start` - ejecutar un servidor web de desarrollo que observa los archivos; luego crea el doc-viewer y vuelve a cargar la página, según sea necesario.
|
||||
* `yarn serve-and-sync` - ejecutar ambos, el `docs-watch` y `start` en la misma consola.
|
||||
* `yarn lint` - comprobar que el código del doc-viewer sigue nuestras reglas de estilo.
|
||||
* `yarn test` - observar todos los archivos de origen, para el doc-viewer, y ejecuta todas las pruebas unitarias cuando haya algún cambio.
|
||||
* `yarn test --watch=false` -ejecutar todas las pruebas unitarias una sola vez.
|
||||
* `yarn e2e` - ejecutar todas las pruebas de e2e para el doc-viewer.
|
||||
* `yarn start` - run a development web server that watches the files; then builds the doc-viewer and reloads the page, as necessary.
|
||||
* `yarn serve-and-sync` - run both the `docs-watch` and `start` in the same console.
|
||||
* `yarn lint` - check that the doc-viewer code follows our style rules.
|
||||
* `yarn test` - watch all the source files, for the doc-viewer, and run all the unit tests when any change.
|
||||
* `yarn test --watch=false` - run all the unit tests once.
|
||||
* `yarn e2e` - run all the e2e tests for the doc-viewer.
|
||||
|
||||
* `yarn docs` - generar toda la documentación desde los archivos fuente.
|
||||
* `yarn docs-watch` - observar el código Angular, los archivos de documentación y ejecutar un 'doc-gen' en corto circuito para los documentos que fueron cambiados.
|
||||
* `yarn docs-lint` - comprobar que el código del documento generado sigue nuestras reglas de estilo.
|
||||
* `yarn docs-test` - ejecutar las pruebas unitarias para el código de generación de doc.
|
||||
* `yarn docs` - generate all the docs from the source files.
|
||||
* `yarn docs-watch` - watch the Angular source and the docs files and run a short-circuited doc-gen for the docs that changed.
|
||||
* `yarn docs-lint` - check that the doc gen code follows our style rules.
|
||||
* `yarn docs-test` - run the unit tests for the doc generation code.
|
||||
|
||||
* `yarn boilerplate:add` - generar todo el código boilerplate para los ejemplos, para que puedan ejecutarse localmente.
|
||||
* `yarn boilerplate:add:viewengine` - igual que `boilerplate:add` pero también enciende el modo `ViewEngine` (pre-Ivy).
|
||||
* `yarn boilerplate:add` - generate all the boilerplate code for the examples, so that they can be run locally.
|
||||
* `yarn boilerplate:add:viewengine` - same as `boilerplate:add` but also turns on `ViewEngine` (pre-Ivy) mode.
|
||||
|
||||
* `yarn boilerplate:remove` - eliminar todo el código boilerplate que fue añadido a través`yarn boilerplate:add`.
|
||||
* `yarn generate-stackblitz` - generar los archivos stackblitz que están usados por la etiqueta `live-example` en documentos.
|
||||
* `yarn generate-zips` - generar los archivos zip desde los ejemplos. Zip está disponible a través de la etiqueta `live-example` en los documentos.
|
||||
* `yarn boilerplate:remove` - remove all the boilerplate code that was added via `yarn boilerplate:add`.
|
||||
* `yarn generate-stackblitz` - generate the stackblitz files that are used by the `live-example` tags in the docs.
|
||||
* `yarn generate-zips` - generate the zip files from the examples. Zip available via the `live-example` tags in the docs.
|
||||
|
||||
* `yarn example-e2e` - ejecutar todas las pruebas e2e para ejemplos. Opciones disponibles:
|
||||
- `--setup`: generar boilerplate, forzar la actualización del controlador web y otras configuraciones, luego ejecutar las pruebas.
|
||||
- `--local`: ejecutar pruebas e2e con la versión local de Angular contenida en la carpeta "dist".
|
||||
_Requiere `--setup` para que surta efecto._
|
||||
- `--viewengine`: ejecutar pruebas e2e en modo `ViewEngine` (pre-Ivy).
|
||||
- `--filter=foo`: limitar pruebas e2e a las que contienen la palabra "foo".
|
||||
* `yarn example-e2e` - run all e2e tests for examples. Available options:
|
||||
- `--setup`: generate boilerplate, force webdriver update & other setup, then run tests.
|
||||
- `--local`: run e2e tests with the local version of Angular contained in the "dist" folder.
|
||||
_Requires `--setup` in order to take effect._
|
||||
- `--viewengine`: run e2e tests in `ViewEngine` (pre-Ivy) mode.
|
||||
- `--filter=foo`: limit e2e tests to those containing the word "foo".
|
||||
|
||||
> **Nota para usuarios Windows**
|
||||
> **Note for Windows users**
|
||||
>
|
||||
> Configurar los ejemplos implica crear algunos [enlaces simbólicos](https://es.wikipedia.org/wiki/Enlace_simb%C3%B3lico) (ver [Aquí](./tools/examples/README.md#symlinked-node_modules) para más detalles). En Windows, esto requiere tener [Habilitado el Modo de desarrollador ](https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10) (compatible con Windows 10 o más reciente) o ejecutar los comandos de configuración cómo administrador.
|
||||
> Setting up the examples involves creating some [symbolic links](https://en.wikipedia.org/wiki/Symbolic_link) (see [here](./tools/examples/README.md#symlinked-node_modules) for details). On Windows, this requires to either have [Developer Mode enabled](https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10) (supported on Windows 10 or newer) or run the setup commands as administrator.
|
||||
>
|
||||
> Los comandos afectados son:
|
||||
> The affected commands are:
|
||||
> - `yarn setup` / `yarn setup-*`
|
||||
> - `yarn build` / `yarn build-*`
|
||||
> - `yarn boilerplate:add`
|
||||
> - `yarn example-e2e --setup`
|
||||
|
||||
## Usando ServiceWorker localmente
|
||||
## Using ServiceWorker locally
|
||||
|
||||
Ejecutando `yarn start` (incluso cuando se apunta explícitamente al modo de producción) no configura el
|
||||
ServiceWorker. Si quieres probar el ServiceWorker localmente, puedes usar `yarn build` y luego
|
||||
ejecutar los archivos en `dist/` con `yarn http-server dist -p 4200`.
|
||||
Running `yarn start` (even when explicitly targeting production mode) does not set up the
|
||||
ServiceWorker. If you want to test the ServiceWorker locally, you can use `yarn build` and then
|
||||
serve the files in `dist/` with `yarn http-server dist -p 4200`.
|
||||
|
||||
|
||||
## Guía de autoría
|
||||
Existen dos tipos de contenido en la documentación:
|
||||
## Guide to authoring
|
||||
|
||||
* **Documentación de API**: descripciones de los módulos, clases, interfaces, decoradores, etc que son parte de la plataforma Angular.
|
||||
La documentacion de API está generada directamente desde el código fuente.
|
||||
El código fuente está contenido en archivos TypeScript , almacenados en la carpeta `angular/packages`.
|
||||
Cada elemento de la API puede tener un comentario anterior, el cual contiene etiquetas y contenido de estilos JSDoc.
|
||||
El contenido está escrito en markdown.
|
||||
There are two types of content in the documentation:
|
||||
|
||||
* **Otro contenido**: guias, tutoriales, y otro material de marketing.
|
||||
Todos los demás contenidos se escriben utilizando markdown en archivos de texto, ubicados en la carpeta `angular/aio/content`.
|
||||
Más específicamente, hay subcarpetas que contienen tipos particulares de contenido: guías, tutoriales y marketing.
|
||||
* **API docs**: descriptions of the modules, classes, interfaces, decorators, etc that make up the Angular platform.
|
||||
API docs are generated directly from the source code.
|
||||
The source code is contained in TypeScript files, located in the `angular/packages` folder.
|
||||
Each API item may have a preceding comment, which contains JSDoc style tags and content.
|
||||
The content is written in markdown.
|
||||
|
||||
* **Ejempos de código**: los ejemplos de código deben ser comprobables para garantizar su precisión.
|
||||
Además, nuestros ejemplos tienen un aspecto específico y permiten al usuario copiar el código fuente. Para mayor
|
||||
ejemplos se representan en una interfaz con pestañas (e.g. template, HTML, y TypeScript en pestañas separadas). Adicionalmente, algunos son ejemplos en acción, que proporcionan enlaces donde se puede editar el código, ejecutar, y/o descargar. Para obtener más detalles sobre cómo trabajar con ejemplos de código, lea los [fragmentos de código](https://docs.angular.lat/guide/docs-style-guide#code-snippets), [código fuente de marcado ](https://docs.angular.lat/guide/docs-style-guide#source-code-markup), y [ ejemplos en acción ](https://docs.angular.lat/guide/docs-style-guide#live-examples) paginas de los [ autores de guías de estilo ](https://docs.angular.lat/guide/docs-style-guide).
|
||||
* **Other content**: guides, tutorials, and other marketing material.
|
||||
All other content is written using markdown in text files, located in the `angular/aio/content` folder.
|
||||
More specifically, there are sub-folders that contain particular types of content: guides, tutorial and marketing.
|
||||
|
||||
Usamos la herramienta [dgeni](https://github.com/angular/dgeni) para convertir estos archivos en docs que se pueden ver en el doc-viewer.
|
||||
Las [guías de estilo para Autores](https://docs.angular.lat/guide/docs-style-guide) prescriben pautas para
|
||||
escribir páginas de guía, explica cómo usar la documentación de clases y componentes, y cómo marcar el código fuente para producir fragmentos de código.
|
||||
* **Code examples**: code examples need to be testable to ensure their accuracy.
|
||||
Also, our examples have a specific look and feel and allow the user to copy the source code. For larger
|
||||
examples they are rendered in a tabbed interface (e.g. template, HTML, and TypeScript on separate
|
||||
tabs). Additionally, some are live examples, which provide links where the code can be edited, executed, and/or downloaded. For details on working with code examples, please read the [Code snippets](https://angular.io/guide/docs-style-guide#code-snippets), [Source code markup](https://angular.io/guide/docs-style-guide#source-code-markup), and [Live examples](https://angular.io/guide/docs-style-guide#live-examples) pages of the [Authors Style Guide](https://angular.io/guide/docs-style-guide).
|
||||
|
||||
### Generando documentos completos
|
||||
We use the [dgeni](https://github.com/angular/dgeni) tool to convert these files into docs that can be viewed in the doc-viewer.
|
||||
|
||||
La principal tarea para generar los documentos es `yarn docs`. Esto procesará todos los archivos fuente (API y otros), extrayendo la documentación y generando archivos JSON que pueden ser consumidos por el doc-viewer.
|
||||
The [Authors Style Guide](https://angular.io/guide/docs-style-guide) prescribes guidelines for
|
||||
writing guide pages, explains how to use the documentation classes and components, and how to markup sample source code to produce code snippets.
|
||||
|
||||
### Generación parcial de doc para editores
|
||||
### Generating the complete docs
|
||||
|
||||
La generación completa de documentos puede llevar hasta un minuto. Eso es demasiado lento para la creación y edición eficiente de documentos.
|
||||
The main task for generating the docs is `yarn docs`. This will process all the source files (API and other),
|
||||
extracting the documentation and generating JSON files that can be consumed by the doc-viewer.
|
||||
|
||||
Puedes ealizar pequeños cambios en un editor inteligente que muestre un markdown con formato:
|
||||
>En VS Code, _Cmd-K, V_ abre la vista previa de markdown en el panel lateral; _Cmd-B_ alterna la barra izquierda
|
||||
### Partial doc generation for editors
|
||||
|
||||
Puedes también mirar los cambios que se muestran correctamente en el doc-viewer
|
||||
con un tiempo de ciclo rápido de edición / visualización.
|
||||
Full doc generation can take up to one minute. That's too slow for efficient document creation and editing.
|
||||
|
||||
Para este propósito, usa la tarea `yarn docs-watch`, que observa los cambios en los archivos de origen y solo vuelve a procesar los archivos necesarios para generar los documentos relacionados con el archivo que ha cambiado.
|
||||
Dado que esta tarea tiene accesos directos, es mucho más rápido (a menudo menos de 1 segundo) pero no producirá contenido de fidelidad completa. Por ejemplo, los enlaces a otros documentoss y ejemplos de código pueden no mostrarse correctamente. Esto se nota especialmente en los enlaces a otros documentos y en los ejemplos incrustados, que no siempre se representan correctamente.
|
||||
You can make small changes in a smart editor that displays formatted markdown:
|
||||
>In VS Code, _Cmd-K, V_ opens markdown preview in side pane; _Cmd-B_ toggles left sidebar
|
||||
|
||||
La configuración general es la siguiente:
|
||||
You also want to see those changes displayed properly in the doc viewer
|
||||
with a quick, edit/view cycle time.
|
||||
|
||||
* Abrir una terminal, estar seguro que las dependencias están instaladas; ejecutar una generación inicial del doc; luego iniciar el doc-viewer:
|
||||
For this purpose, use the `yarn docs-watch` task, which watches for changes to source files and only
|
||||
re-processes the files necessary to generate the docs that are related to the file that has changed.
|
||||
Since this task takes shortcuts, it is much faster (often less than 1 second) but it won't produce full
|
||||
fidelity content. For example, links to other docs and code examples may not render correctly. This is
|
||||
most particularly noticed in links to other docs and in the embedded examples, which may not always render
|
||||
correctly.
|
||||
|
||||
The general setup is as follows:
|
||||
|
||||
* Open a terminal, ensure the dependencies are installed; run an initial doc generation; then start the doc-viewer:
|
||||
|
||||
```bash
|
||||
yarn setup
|
||||
yarn start
|
||||
```
|
||||
|
||||
* Abrir una segunda terminal e iniciar el observador de documentos.
|
||||
* Open a second terminal and start watching the docs
|
||||
|
||||
```bash
|
||||
yarn docs-watch
|
||||
```
|
||||
|
||||
>Alternativamente, prueba el comando fusionado `serve-and-sync` que crea, observa y ejecuta en la misma ventana de la terminal
|
||||
>Alternatively, try the consolidated `serve-and-sync` command that builds, watches and serves in the same terminal window
|
||||
```bash
|
||||
yarn serve-and-sync
|
||||
```
|
||||
|
||||
* Abre un navegador con la siguiente dirección https://localhost:4200/ y navega hasta el documento en el que quieras trabajar.
|
||||
Puedes automáticamente abrir el navegador utilizando `yarn start -o` en la primera terminal.
|
||||
* Open a browser at https://localhost:4200/ and navigate to the document on which you want to work.
|
||||
You can automatically open the browser by using `yarn start -o` in the first terminal.
|
||||
|
||||
* Realiza cambios en la página de documentación asociada o en los archivos de ejemplo. Cada vez que un archivo es guardado, la documentación se regenerará, la aplicación se reconstruirá y la página se volverá a cargar.
|
||||
* Make changes to the page's associated doc or example files. Every time a file is saved, the doc will
|
||||
be regenerated, the app will rebuild and the page will reload.
|
||||
|
||||
*Si recibes un error de compilación acerca de los ejemplos o cualquier otro error, asegúrate de consultar las
|
||||
[guías de estilo para Autores](https://angular.io/guide/docs-style-guide) para más información.
|
||||
* If you get a build error complaining about examples or any other odd behavior, be sure to consult
|
||||
the [Authors Style Guide](https://angular.io/guide/docs-style-guide).
|
||||
|
@ -16,13 +16,6 @@ import {BuildNums, PrNums, SHA} from './constants';
|
||||
|
||||
const logger = new Logger('mock-external-apis');
|
||||
|
||||
const log = (...args: any[]) => {
|
||||
// Filter out non-matching URL checks
|
||||
if (!/^matching.+: false$/.test(args[0])) {
|
||||
logger.log(...args);
|
||||
}
|
||||
};
|
||||
|
||||
const AIO_CIRCLE_CI_TOKEN = getEnvVar('AIO_CIRCLE_CI_TOKEN');
|
||||
const AIO_GITHUB_TOKEN = getEnvVar('AIO_GITHUB_TOKEN');
|
||||
|
||||
@ -91,8 +84,8 @@ const createArchive = (buildNum: number, prNum: number, sha: string) => {
|
||||
};
|
||||
|
||||
// Create request scopes
|
||||
const circleCiApi = nock(CIRCLE_CI_API_HOST).log(log).persist();
|
||||
const githubApi = nock(GITHUB_API_HOST).log(log).persist().matchHeader('Authorization', `token ${AIO_GITHUB_TOKEN}`);
|
||||
const circleCiApi = nock(CIRCLE_CI_API_HOST).persist();
|
||||
const githubApi = nock(GITHUB_API_HOST).persist().matchHeader('Authorization', `token ${AIO_GITHUB_TOKEN}`);
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
|
@ -27,28 +27,28 @@
|
||||
"body-parser": "^1.19.0",
|
||||
"delete-empty": "^3.0.0",
|
||||
"express": "^4.17.1",
|
||||
"jasmine": "^3.5.0",
|
||||
"nock": "^12.0.3",
|
||||
"node-fetch": "^2.6.0",
|
||||
"jasmine": "^3.6.1",
|
||||
"nock": "^13.0.4",
|
||||
"node-fetch": "^2.6.1",
|
||||
"shelljs": "^0.8.4",
|
||||
"source-map-support": "^0.5.19",
|
||||
"tar-stream": "^2.1.2",
|
||||
"tslib": "^1.11.1"
|
||||
"tar-stream": "^2.1.3",
|
||||
"tslib": "^2.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/body-parser": "^1.19.0",
|
||||
"@types/express": "^4.17.6",
|
||||
"@types/jasmine": "^3.5.10",
|
||||
"@types/express": "^4.17.8",
|
||||
"@types/jasmine": "^3.5.14",
|
||||
"@types/nock": "^11.1.0",
|
||||
"@types/node": "^13.13.2",
|
||||
"@types/node": "^14.6.4",
|
||||
"@types/node-fetch": "^2.5.7",
|
||||
"@types/shelljs": "^0.8.7",
|
||||
"@types/supertest": "^2.0.8",
|
||||
"nodemon": "^2.0.3",
|
||||
"@types/shelljs": "^0.8.8",
|
||||
"@types/supertest": "^2.0.10",
|
||||
"nodemon": "^2.0.4",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"supertest": "^4.0.2",
|
||||
"tslint": "^6.1.1",
|
||||
"tslint": "^6.1.3",
|
||||
"tslint-jasmine-noSkipOrFocus": "^1.0.9",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^4.0.2"
|
||||
}
|
||||
}
|
||||
|
@ -214,23 +214,24 @@ describe('GithubApi', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should call \'https.request()\' with the correct options', () => {
|
||||
it('should call \'https.request()\' with the correct options', async () => {
|
||||
const requestHandler = nock('https://api.github.com')
|
||||
.intercept('/path', 'method')
|
||||
.reply(200);
|
||||
|
||||
(api as any).request('method', '/path');
|
||||
await (api as any).request('method', '/path');
|
||||
requestHandler.done();
|
||||
});
|
||||
|
||||
|
||||
it('should add the \'Authorization\' header containing the \'githubToken\'', () => {
|
||||
it('should add the \'Authorization\' header containing the \'githubToken\'', async () => {
|
||||
const requestHandler = nock('https://api.github.com')
|
||||
.intercept('/path', 'method', undefined, {
|
||||
reqheaders: {Authorization: 'token 12345'},
|
||||
})
|
||||
.reply(200);
|
||||
(api as any).request('method', '/path');
|
||||
|
||||
await (api as any).request('method', '/path');
|
||||
requestHandler.done();
|
||||
});
|
||||
|
||||
@ -244,12 +245,13 @@ describe('GithubApi', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should \'JSON.stringify\' and send the data along with the request', () => {
|
||||
it('should \'JSON.stringify\' and send the data along with the request', async () => {
|
||||
const data = {key: 'value'};
|
||||
const requestHandler = nock('https://api.github.com')
|
||||
.intercept('/path', 'method', JSON.stringify(data))
|
||||
.reply(200);
|
||||
(api as any).request('method', '/path', data);
|
||||
|
||||
await (api as any).request('method', '/path', data);
|
||||
requestHandler.done();
|
||||
});
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,11 +21,13 @@ import { ItemDirective } from './item.directive';
|
||||
ItemDirective
|
||||
],
|
||||
// #enddocregion declarations
|
||||
// #docregion imports
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
HttpClientModule
|
||||
],
|
||||
// #enddocregion imports
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
|
@ -0,0 +1,9 @@
|
||||
/*
|
||||
* This example project is special in that it is not a cli app. To run tests appropriate for this
|
||||
* project, the test command is overwritten in `aio/content/examples/observables/example-config.json`.
|
||||
*
|
||||
* This is an empty placeholder file to ensure that `aio/tools/examples/run-example-e2e.js` runs
|
||||
* tests for this project.
|
||||
*
|
||||
* TODO: Fix our infrastructure/tooling, so that this hack is not necessary.
|
||||
*/
|
@ -0,0 +1,12 @@
|
||||
{
|
||||
"tests": [
|
||||
{
|
||||
"cmd": "yarn",
|
||||
"args": ["tsc", "--project", "tsconfig.spec.json", "--module", "commonjs"]
|
||||
},
|
||||
{
|
||||
"cmd": "yarn",
|
||||
"args": ["jasmine", "out-tsc/**/*.spec.js"]
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
import { docRegionChain, docRegionObservable, docRegionUnsubscribe } from './observables';
|
||||
|
||||
describe('observables', () => {
|
||||
it('should print 2', (doneFn: DoneFn) => {
|
||||
const consoleLogSpy = spyOn(console, 'log');
|
||||
const observable = docRegionObservable(console);
|
||||
observable.subscribe(() => {
|
||||
expect(consoleLogSpy).toHaveBeenCalledTimes(1);
|
||||
expect(consoleLogSpy).toHaveBeenCalledWith(2);
|
||||
doneFn();
|
||||
});
|
||||
});
|
||||
|
||||
it('should close the subscription', () => {
|
||||
const subscription = docRegionUnsubscribe();
|
||||
expect(subscription.closed).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should chain an observable', (doneFn: DoneFn) => {
|
||||
const observable = docRegionChain();
|
||||
observable.subscribe(value => {
|
||||
expect(value).toBe(4);
|
||||
doneFn();
|
||||
});
|
||||
});
|
||||
});
|
@ -1,40 +1,72 @@
|
||||
import { map } from 'rxjs/operators';
|
||||
// #docplaster
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
// #docregion observable
|
||||
export function docRegionObservable(console: Console) {
|
||||
// #docregion observable
|
||||
|
||||
// declare a publishing operation
|
||||
const observable = new Observable<number>(observer => {
|
||||
// Subscriber fn...
|
||||
});
|
||||
// declare a publishing operation
|
||||
const observable = new Observable<number>(observer => {
|
||||
// Subscriber fn...
|
||||
// #enddocregion observable
|
||||
// The below code is used for unit testing only
|
||||
observer.next(2);
|
||||
// #docregion observable
|
||||
});
|
||||
|
||||
// initiate execution
|
||||
observable.subscribe(() => {
|
||||
// observer handles notifications
|
||||
});
|
||||
// initiate execution
|
||||
observable.subscribe(value => {
|
||||
// observer handles notifications
|
||||
// #enddocregion observable
|
||||
// The below code is used for unit testing only
|
||||
console.log(value);
|
||||
// #docregion observable
|
||||
});
|
||||
|
||||
// #enddocregion observable
|
||||
// #enddocregion observable
|
||||
return observable;
|
||||
}
|
||||
|
||||
// #docregion unsubscribe
|
||||
export function docRegionUnsubscribe() {
|
||||
const observable = new Observable<number>(() => {
|
||||
// Subscriber fn...
|
||||
});
|
||||
// #docregion unsubscribe
|
||||
|
||||
const subscription = observable.subscribe(() => {
|
||||
// observer handles notifications
|
||||
});
|
||||
const subscription = observable.subscribe(() => {
|
||||
// observer handles notifications
|
||||
});
|
||||
|
||||
subscription.unsubscribe();
|
||||
subscription.unsubscribe();
|
||||
|
||||
// #enddocregion unsubscribe
|
||||
// #enddocregion unsubscribe
|
||||
return subscription;
|
||||
}
|
||||
|
||||
// #docregion error
|
||||
export function docRegionError() {
|
||||
const observable = new Observable<number>(() => {
|
||||
// Subscriber fn...
|
||||
});
|
||||
|
||||
observable.subscribe(() => {
|
||||
throw Error('my error');
|
||||
});
|
||||
// #docregion error
|
||||
observable.subscribe(() => {
|
||||
throw new Error('my error');
|
||||
});
|
||||
// #enddocregion error
|
||||
}
|
||||
|
||||
// #enddocregion error
|
||||
export function docRegionChain() {
|
||||
let observable = new Observable<number>(observer => {
|
||||
// Subscriber fn...
|
||||
observer.next(2);
|
||||
});
|
||||
|
||||
// #docregion chain
|
||||
observable =
|
||||
// #docregion chain
|
||||
|
||||
observable.pipe(map(v => 2 * v));
|
||||
observable.pipe(map(v => 2 * v));
|
||||
|
||||
// #enddocregion chain
|
||||
// #enddocregion chain
|
||||
return observable;
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
import { docRegionError, docRegionPromise } from './promises';
|
||||
|
||||
describe('promises', () => {
|
||||
it('should print 2', (doneFn: DoneFn) => {
|
||||
const consoleLogSpy = spyOn(console, 'log');
|
||||
const pr = docRegionPromise(console, 2);
|
||||
pr.then((value) => {
|
||||
expect(consoleLogSpy).toHaveBeenCalledTimes(1);
|
||||
expect(consoleLogSpy).toHaveBeenCalledWith(2);
|
||||
expect(value).toBe(4);
|
||||
doneFn();
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw an error', (doneFn: DoneFn) => {
|
||||
const promise = docRegionError();
|
||||
promise
|
||||
.then(() => {
|
||||
throw new Error('Promise should be rejected.');
|
||||
},
|
||||
() => doneFn());
|
||||
});
|
||||
});
|
@ -1,25 +1,44 @@
|
||||
// #docregion promise
|
||||
// initiate execution
|
||||
const promise = new Promise<number>((resolve, reject) => {
|
||||
// Executer fn...
|
||||
});
|
||||
// #docplaster
|
||||
|
||||
promise.then(value => {
|
||||
// handle result here
|
||||
});
|
||||
export function docRegionPromise(console: Console, inputValue: number) {
|
||||
// #docregion promise
|
||||
// initiate execution
|
||||
let promise = new Promise<number>((resolve, reject) => {
|
||||
// Executer fn...
|
||||
// #enddocregion promise
|
||||
// The below is used in the unit tests.
|
||||
resolve(inputValue);
|
||||
// #docregion promise
|
||||
});
|
||||
// #enddocregion promise
|
||||
promise =
|
||||
// #docregion promise
|
||||
promise.then(value => {
|
||||
// handle result here
|
||||
// #enddocregion promise
|
||||
// The below is used in the unit tests.
|
||||
console.log(value);
|
||||
return value;
|
||||
// #docregion promise
|
||||
});
|
||||
// #enddocregion promise
|
||||
promise =
|
||||
// #docregion chain
|
||||
promise.then(v => 2 * v);
|
||||
// #enddocregion chain
|
||||
|
||||
// #enddocregion promise
|
||||
return promise;
|
||||
}
|
||||
|
||||
// #docregion chain
|
||||
export function docRegionError() {
|
||||
let promise = Promise.resolve();
|
||||
promise =
|
||||
// #docregion error
|
||||
|
||||
promise.then(v => 2 * v);
|
||||
promise.then(() => {
|
||||
throw new Error('my error');
|
||||
});
|
||||
|
||||
// #enddocregion chain
|
||||
|
||||
// #docregion error
|
||||
|
||||
promise.then(() => {
|
||||
throw Error('my error');
|
||||
});
|
||||
|
||||
// #enddocregion error
|
||||
// #enddocregion error
|
||||
return promise;
|
||||
}
|
||||
|
@ -41,7 +41,6 @@
|
||||
<!-- #enddocregion translated-plural -->
|
||||
<!-- #docregion translated-select -->
|
||||
<!-- #docregion translate-select-1 -->
|
||||
</trans-unit>
|
||||
<trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">
|
||||
<source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>
|
||||
<target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>
|
||||
|
@ -1,3 +1,4 @@
|
||||
// TODO: Add unit tests for this file.
|
||||
// tslint:disable: no-output-native
|
||||
// #docregion
|
||||
import { Component, Output, OnInit, EventEmitter, NgModule } from '@angular/core';
|
||||
|
@ -2,7 +2,11 @@
|
||||
"tests": [
|
||||
{
|
||||
"cmd": "yarn",
|
||||
"args": [ "tsc", "--project", "./tsconfig.app.json" ]
|
||||
"args": ["tsc", "--project", "tsconfig.spec.json", "--module", "commonjs"]
|
||||
},
|
||||
{
|
||||
"cmd": "yarn",
|
||||
"args": ["jasmine", "out-tsc/**/*.spec.js"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
55
aio/content/examples/observables/src/creating.spec.ts
Normal file
55
aio/content/examples/observables/src/creating.spec.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import { docRegionFromEvent, docRegionSubscriber } from './creating';
|
||||
|
||||
describe('observables', () => {
|
||||
it('should create an observable using the constructor', () => {
|
||||
const console = {log: jasmine.createSpy('log')};
|
||||
docRegionSubscriber(console);
|
||||
expect(console.log).toHaveBeenCalledTimes(4);
|
||||
expect(console.log.calls.allArgs()).toEqual([
|
||||
[1],
|
||||
[2],
|
||||
[3],
|
||||
['Finished sequence'],
|
||||
]);
|
||||
});
|
||||
|
||||
it('should listen to input changes', () => {
|
||||
let triggerInputChange;
|
||||
const input = {
|
||||
value: 'Test',
|
||||
addEventListener: jasmine
|
||||
.createSpy('addEvent')
|
||||
.and.callFake((eventName: string, cb: (e) => void) => {
|
||||
if (eventName === 'keydown') {
|
||||
triggerInputChange = cb;
|
||||
}
|
||||
}),
|
||||
removeEventListener: jasmine.createSpy('removeEventListener'),
|
||||
};
|
||||
|
||||
const document = { getElementById: () => input };
|
||||
docRegionFromEvent(document);
|
||||
triggerInputChange({keyCode: 65});
|
||||
expect(input.value).toBe('Test');
|
||||
|
||||
triggerInputChange({keyCode: 27});
|
||||
expect(input.value).toBe('');
|
||||
});
|
||||
|
||||
it('should call removeEventListener when unsubscribing', (doneFn: DoneFn) => {
|
||||
const input = {
|
||||
addEventListener: jasmine.createSpy('addEvent'),
|
||||
removeEventListener: jasmine
|
||||
.createSpy('removeEvent')
|
||||
.and.callFake((eventName: string, cb: (e) => void) => {
|
||||
if (eventName === 'keydown') {
|
||||
doneFn();
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
const document = { getElementById: () => input };
|
||||
const subscription = docRegionFromEvent(document);
|
||||
subscription.unsubscribe();
|
||||
});
|
||||
});
|
@ -1,38 +1,39 @@
|
||||
// #docplaster
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
// #docregion subscriber
|
||||
export function docRegionSubscriber(console) {
|
||||
// #docregion subscriber
|
||||
// This function runs when subscribe() is called
|
||||
function sequenceSubscriber(observer) {
|
||||
// synchronously deliver 1, 2, and 3, then complete
|
||||
observer.next(1);
|
||||
observer.next(2);
|
||||
observer.next(3);
|
||||
observer.complete();
|
||||
|
||||
// This function runs when subscribe() is called
|
||||
function sequenceSubscriber(observer) {
|
||||
// synchronously deliver 1, 2, and 3, then complete
|
||||
observer.next(1);
|
||||
observer.next(2);
|
||||
observer.next(3);
|
||||
observer.complete();
|
||||
// unsubscribe function doesn't need to do anything in this
|
||||
// because values are delivered synchronously
|
||||
return {unsubscribe() {}};
|
||||
}
|
||||
|
||||
// unsubscribe function doesn't need to do anything in this
|
||||
// because values are delivered synchronously
|
||||
return {unsubscribe() {}};
|
||||
// Create a new Observable that will deliver the above sequence
|
||||
const sequence = new Observable(sequenceSubscriber);
|
||||
|
||||
// execute the Observable and print the result of each notification
|
||||
sequence.subscribe({
|
||||
next(num) { console.log(num); },
|
||||
complete() { console.log('Finished sequence'); }
|
||||
});
|
||||
|
||||
// Logs:
|
||||
// 1
|
||||
// 2
|
||||
// 3
|
||||
// Finished sequence
|
||||
// #enddocregion subscriber
|
||||
}
|
||||
|
||||
// Create a new Observable that will deliver the above sequence
|
||||
const sequence = new Observable(sequenceSubscriber);
|
||||
|
||||
// execute the Observable and print the result of each notification
|
||||
sequence.subscribe({
|
||||
next(num) { console.log(num); },
|
||||
complete() { console.log('Finished sequence'); }
|
||||
});
|
||||
|
||||
// Logs:
|
||||
// 1
|
||||
// 2
|
||||
// 3
|
||||
// Finished sequence
|
||||
|
||||
// #enddocregion subscriber
|
||||
|
||||
// #docregion fromevent
|
||||
|
||||
function fromEvent(target, eventName) {
|
||||
@ -51,16 +52,18 @@ function fromEvent(target, eventName) {
|
||||
|
||||
// #enddocregion fromevent
|
||||
|
||||
// #docregion fromevent_use
|
||||
export function docRegionFromEvent(document) {
|
||||
// #docregion fromevent_use
|
||||
|
||||
const ESC_KEY = 27;
|
||||
const nameInput = document.getElementById('name') as HTMLInputElement;
|
||||
const ESC_KEY = 27;
|
||||
const nameInput = document.getElementById('name') as HTMLInputElement;
|
||||
|
||||
const subscription = fromEvent(nameInput, 'keydown')
|
||||
.subscribe((e: KeyboardEvent) => {
|
||||
const subscription = fromEvent(nameInput, 'keydown').subscribe((e: KeyboardEvent) => {
|
||||
if (e.keyCode === ESC_KEY) {
|
||||
nameInput.value = '';
|
||||
}
|
||||
});
|
||||
// #enddocregion fromevent_use
|
||||
return subscription;
|
||||
}
|
||||
|
||||
// #enddocregion fromevent_use
|
||||
|
@ -1,5 +1,5 @@
|
||||
// TODO: Add unit tests for this file.
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
// #docregion
|
||||
|
||||
// Create an Observable that will start listening to geolocation updates
|
||||
|
48
aio/content/examples/observables/src/multicasting.spec.ts
Normal file
48
aio/content/examples/observables/src/multicasting.spec.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { docRegionDelaySequence, docRegionMulticastSequence } from './multicasting';
|
||||
|
||||
describe('multicasting', () => {
|
||||
let console;
|
||||
beforeEach(() => {
|
||||
jasmine.clock().install();
|
||||
console = {log: jasmine.createSpy('log')};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jasmine.clock().uninstall();
|
||||
});
|
||||
|
||||
it('should create an observable and emit in sequence', () => {
|
||||
docRegionDelaySequence(console);
|
||||
jasmine.clock().tick(10000);
|
||||
expect(console.log).toHaveBeenCalledTimes(12);
|
||||
expect(console.log.calls.allArgs()).toEqual([
|
||||
[1],
|
||||
['1st subscribe: 1'],
|
||||
['2nd subscribe: 1'],
|
||||
[2],
|
||||
['1st subscribe: 2'],
|
||||
['2nd subscribe: 2'],
|
||||
[3],
|
||||
['Finished sequence'],
|
||||
['1st subscribe: 3'],
|
||||
['1st sequence finished.'],
|
||||
['2nd subscribe: 3'],
|
||||
['2nd sequence finished.']
|
||||
]);
|
||||
});
|
||||
|
||||
it('should create an observable and multicast the emissions', () => {
|
||||
docRegionMulticastSequence(console);
|
||||
jasmine.clock().tick(10000);
|
||||
expect(console.log).toHaveBeenCalledTimes(7);
|
||||
expect(console.log.calls.allArgs()).toEqual([
|
||||
['1st subscribe: 1'],
|
||||
['1st subscribe: 2'],
|
||||
['2nd subscribe: 2'],
|
||||
['1st subscribe: 3'],
|
||||
['2nd subscribe: 3'],
|
||||
['1st sequence finished.'],
|
||||
['2nd sequence finished.']
|
||||
]);
|
||||
});
|
||||
});
|
@ -1,155 +1,160 @@
|
||||
// #docplaster
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
// #docregion delay_sequence
|
||||
export function docRegionDelaySequence(console) {
|
||||
// #docregion delay_sequence
|
||||
function sequenceSubscriber(observer) {
|
||||
const seq = [1, 2, 3];
|
||||
let timeoutId;
|
||||
|
||||
function sequenceSubscriber(observer) {
|
||||
const seq = [1, 2, 3];
|
||||
let timeoutId;
|
||||
// Will run through an array of numbers, emitting one value
|
||||
// per second until it gets to the end of the array.
|
||||
function doInSequence(arr, idx) {
|
||||
timeoutId = setTimeout(() => {
|
||||
observer.next(arr[idx]);
|
||||
if (idx === arr.length - 1) {
|
||||
observer.complete();
|
||||
} else {
|
||||
doInSequence(arr, ++idx);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// Will run through an array of numbers, emitting one value
|
||||
doInSequence(seq, 0);
|
||||
|
||||
// Unsubscribe should clear the timeout to stop execution
|
||||
return {
|
||||
unsubscribe() {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Create a new Observable that will deliver the above sequence
|
||||
const sequence = new Observable(sequenceSubscriber);
|
||||
|
||||
sequence.subscribe({
|
||||
next(num) { console.log(num); },
|
||||
complete() { console.log('Finished sequence'); }
|
||||
});
|
||||
|
||||
// Logs:
|
||||
// (at 1 second): 1
|
||||
// (at 2 seconds): 2
|
||||
// (at 3 seconds): 3
|
||||
// (at 3 seconds): Finished sequence
|
||||
|
||||
// #enddocregion delay_sequence
|
||||
|
||||
// #docregion subscribe_twice
|
||||
|
||||
// Subscribe starts the clock, and will emit after 1 second
|
||||
sequence.subscribe({
|
||||
next(num) { console.log('1st subscribe: ' + num); },
|
||||
complete() { console.log('1st sequence finished.'); }
|
||||
});
|
||||
|
||||
// After 1/2 second, subscribe again.
|
||||
setTimeout(() => {
|
||||
sequence.subscribe({
|
||||
next(num) { console.log('2nd subscribe: ' + num); },
|
||||
complete() { console.log('2nd sequence finished.'); }
|
||||
});
|
||||
}, 500);
|
||||
|
||||
// Logs:
|
||||
// (at 1 second): 1st subscribe: 1
|
||||
// (at 1.5 seconds): 2nd subscribe: 1
|
||||
// (at 2 seconds): 1st subscribe: 2
|
||||
// (at 2.5 seconds): 2nd subscribe: 2
|
||||
// (at 3 seconds): 1st subscribe: 3
|
||||
// (at 3 seconds): 1st sequence finished
|
||||
// (at 3.5 seconds): 2nd subscribe: 3
|
||||
// (at 3.5 seconds): 2nd sequence finished
|
||||
|
||||
// #enddocregion subscribe_twice
|
||||
}
|
||||
|
||||
export function docRegionMulticastSequence(console) {
|
||||
// #docregion multicast_sequence
|
||||
function multicastSequenceSubscriber() {
|
||||
const seq = [1, 2, 3];
|
||||
// Keep track of each observer (one for every active subscription)
|
||||
const observers = [];
|
||||
// Still a single timeoutId because there will only ever be one
|
||||
// set of values being generated, multicasted to each subscriber
|
||||
let timeoutId;
|
||||
|
||||
// Return the subscriber function (runs when subscribe()
|
||||
// function is invoked)
|
||||
return observer => {
|
||||
observers.push(observer);
|
||||
// When this is the first subscription, start the sequence
|
||||
if (observers.length === 1) {
|
||||
timeoutId = doSequence({
|
||||
next(val) {
|
||||
// Iterate through observers and notify all subscriptions
|
||||
observers.forEach(obs => obs.next(val));
|
||||
},
|
||||
complete() {
|
||||
// Notify all complete callbacks
|
||||
observers.slice(0).forEach(obs => obs.complete());
|
||||
}
|
||||
}, seq, 0);
|
||||
}
|
||||
|
||||
return {
|
||||
unsubscribe() {
|
||||
// Remove from the observers array so it's no longer notified
|
||||
observers.splice(observers.indexOf(observer), 1);
|
||||
// If there's no more listeners, do cleanup
|
||||
if (observers.length === 0) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// Run through an array of numbers, emitting one value
|
||||
// per second until it gets to the end of the array.
|
||||
function doInSequence(arr, idx) {
|
||||
timeoutId = setTimeout(() => {
|
||||
function doSequence(observer, arr, idx) {
|
||||
return setTimeout(() => {
|
||||
observer.next(arr[idx]);
|
||||
if (idx === arr.length - 1) {
|
||||
observer.complete();
|
||||
} else {
|
||||
doInSequence(arr, ++idx);
|
||||
doSequence(observer, arr, ++idx);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
doInSequence(seq, 0);
|
||||
// Create a new Observable that will deliver the above sequence
|
||||
const multicastSequence = new Observable(multicastSequenceSubscriber());
|
||||
|
||||
// Unsubscribe should clear the timeout to stop execution
|
||||
return {unsubscribe() {
|
||||
clearTimeout(timeoutId);
|
||||
}};
|
||||
}
|
||||
|
||||
// Create a new Observable that will deliver the above sequence
|
||||
const sequence = new Observable(sequenceSubscriber);
|
||||
|
||||
sequence.subscribe({
|
||||
next(num) { console.log(num); },
|
||||
complete() { console.log('Finished sequence'); }
|
||||
});
|
||||
|
||||
// Logs:
|
||||
// (at 1 second): 1
|
||||
// (at 2 seconds): 2
|
||||
// (at 3 seconds): 3
|
||||
// (at 3 seconds): Finished sequence
|
||||
|
||||
// #enddocregion delay_sequence
|
||||
|
||||
// #docregion subscribe_twice
|
||||
|
||||
// Subscribe starts the clock, and will emit after 1 second
|
||||
sequence.subscribe({
|
||||
next(num) { console.log('1st subscribe: ' + num); },
|
||||
complete() { console.log('1st sequence finished.'); }
|
||||
});
|
||||
|
||||
// After 1/2 second, subscribe again.
|
||||
setTimeout(() => {
|
||||
sequence.subscribe({
|
||||
next(num) { console.log('2nd subscribe: ' + num); },
|
||||
complete() { console.log('2nd sequence finished.'); }
|
||||
});
|
||||
}, 500);
|
||||
|
||||
// Logs:
|
||||
// (at 1 second): 1st subscribe: 1
|
||||
// (at 1.5 seconds): 2nd subscribe: 1
|
||||
// (at 2 seconds): 1st subscribe: 2
|
||||
// (at 2.5 seconds): 2nd subscribe: 2
|
||||
// (at 3 seconds): 1st subscribe: 3
|
||||
// (at 3 seconds): 1st sequence finished
|
||||
// (at 3.5 seconds): 2nd subscribe: 3
|
||||
// (at 3.5 seconds): 2nd sequence finished
|
||||
|
||||
// #enddocregion subscribe_twice
|
||||
|
||||
// #docregion multicast_sequence
|
||||
|
||||
function multicastSequenceSubscriber() {
|
||||
const seq = [1, 2, 3];
|
||||
// Keep track of each observer (one for every active subscription)
|
||||
const observers = [];
|
||||
// Still a single timeoutId because there will only ever be one
|
||||
// set of values being generated, multicasted to each subscriber
|
||||
let timeoutId;
|
||||
|
||||
// Return the subscriber function (runs when subscribe()
|
||||
// function is invoked)
|
||||
return (observer) => {
|
||||
observers.push(observer);
|
||||
// When this is the first subscription, start the sequence
|
||||
if (observers.length === 1) {
|
||||
timeoutId = doSequence({
|
||||
next(val) {
|
||||
// Iterate through observers and notify all subscriptions
|
||||
observers.forEach(obs => obs.next(val));
|
||||
},
|
||||
complete() {
|
||||
// Notify all complete callbacks
|
||||
observers.slice(0).forEach(obs => obs.complete());
|
||||
}
|
||||
}, seq, 0);
|
||||
}
|
||||
|
||||
return {
|
||||
unsubscribe() {
|
||||
// Remove from the observers array so it's no longer notified
|
||||
observers.splice(observers.indexOf(observer), 1);
|
||||
// If there's no more listeners, do cleanup
|
||||
if (observers.length === 0) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// Run through an array of numbers, emitting one value
|
||||
// per second until it gets to the end of the array.
|
||||
function doSequence(observer, arr, idx) {
|
||||
return setTimeout(() => {
|
||||
observer.next(arr[idx]);
|
||||
if (idx === arr.length - 1) {
|
||||
observer.complete();
|
||||
} else {
|
||||
doSequence(observer, arr, ++idx);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// Create a new Observable that will deliver the above sequence
|
||||
const multicastSequence = new Observable(multicastSequenceSubscriber());
|
||||
|
||||
// Subscribe starts the clock, and begins to emit after 1 second
|
||||
multicastSequence.subscribe({
|
||||
next(num) { console.log('1st subscribe: ' + num); },
|
||||
complete() { console.log('1st sequence finished.'); }
|
||||
});
|
||||
|
||||
// After 1 1/2 seconds, subscribe again (should "miss" the first value).
|
||||
setTimeout(() => {
|
||||
// Subscribe starts the clock, and begins to emit after 1 second
|
||||
multicastSequence.subscribe({
|
||||
next(num) { console.log('2nd subscribe: ' + num); },
|
||||
complete() { console.log('2nd sequence finished.'); }
|
||||
next(num) { console.log('1st subscribe: ' + num); },
|
||||
complete() { console.log('1st sequence finished.'); }
|
||||
});
|
||||
}, 1500);
|
||||
|
||||
// Logs:
|
||||
// (at 1 second): 1st subscribe: 1
|
||||
// (at 2 seconds): 1st subscribe: 2
|
||||
// (at 2 seconds): 2nd subscribe: 2
|
||||
// (at 3 seconds): 1st subscribe: 3
|
||||
// (at 3 seconds): 1st sequence finished
|
||||
// (at 3 seconds): 2nd subscribe: 3
|
||||
// (at 3 seconds): 2nd sequence finished
|
||||
// After 1 1/2 seconds, subscribe again (should "miss" the first value).
|
||||
setTimeout(() => {
|
||||
multicastSequence.subscribe({
|
||||
next(num) { console.log('2nd subscribe: ' + num); },
|
||||
complete() { console.log('2nd sequence finished.'); }
|
||||
});
|
||||
}, 1500);
|
||||
|
||||
// #enddocregion multicast_sequence
|
||||
// Logs:
|
||||
// (at 1 second): 1st subscribe: 1
|
||||
// (at 2 seconds): 1st subscribe: 2
|
||||
// (at 2 seconds): 2nd subscribe: 2
|
||||
// (at 3 seconds): 1st subscribe: 3
|
||||
// (at 3 seconds): 1st sequence finished
|
||||
// (at 3 seconds): 2nd subscribe: 3
|
||||
// (at 3 seconds): 2nd sequence finished
|
||||
|
||||
// #enddocregion multicast_sequence
|
||||
}
|
||||
|
19
aio/content/examples/observables/src/subscribing.spec.ts
Normal file
19
aio/content/examples/observables/src/subscribing.spec.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { docRegionObserver } from './subscribing';
|
||||
|
||||
describe('subscribing', () => {
|
||||
it('should subscribe and emit', () => {
|
||||
const console = {log: jasmine.createSpy('log')};
|
||||
docRegionObserver(console);
|
||||
expect(console.log).toHaveBeenCalledTimes(8);
|
||||
expect(console.log.calls.allArgs()).toEqual([
|
||||
['Observer got a next value: 1'],
|
||||
['Observer got a next value: 2'],
|
||||
['Observer got a next value: 3'],
|
||||
['Observer got a complete notification'],
|
||||
['Observer got a next value: 1'],
|
||||
['Observer got a next value: 2'],
|
||||
['Observer got a next value: 3'],
|
||||
['Observer got a complete notification'],
|
||||
]);
|
||||
});
|
||||
});
|
@ -1,32 +1,35 @@
|
||||
// #docplaster
|
||||
import { of } from 'rxjs';
|
||||
|
||||
import { Observable, of } from 'rxjs';
|
||||
export function docRegionObserver(console) {
|
||||
// #docregion observer
|
||||
|
||||
// #docregion observer
|
||||
// Create simple observable that emits three values
|
||||
const myObservable = of(1, 2, 3);
|
||||
|
||||
// Create simple observable that emits three values
|
||||
const myObservable = of(1, 2, 3);
|
||||
// Create observer object
|
||||
const myObserver = {
|
||||
next: x => console.log('Observer got a next value: ' + x),
|
||||
error: err => console.error('Observer got an error: ' + err),
|
||||
complete: () => console.log('Observer got a complete notification'),
|
||||
};
|
||||
|
||||
// Create observer object
|
||||
const myObserver = {
|
||||
next: x => console.log('Observer got a next value: ' + x),
|
||||
error: err => console.error('Observer got an error: ' + err),
|
||||
complete: () => console.log('Observer got a complete notification'),
|
||||
};
|
||||
// Execute with the observer object
|
||||
myObservable.subscribe(myObserver);
|
||||
|
||||
// Execute with the observer object
|
||||
myObservable.subscribe(myObserver);
|
||||
// Logs:
|
||||
// Observer got a next value: 1
|
||||
// Observer got a next value: 2
|
||||
// Observer got a next value: 3
|
||||
// Observer got a complete notification
|
||||
// Logs:
|
||||
// Observer got a next value: 1
|
||||
// Observer got a next value: 2
|
||||
// Observer got a next value: 3
|
||||
// Observer got a complete notification
|
||||
|
||||
// #enddocregion observer
|
||||
// #enddocregion observer
|
||||
|
||||
// #docregion sub_fn
|
||||
myObservable.subscribe(
|
||||
x => console.log('Observer got a next value: ' + x),
|
||||
err => console.error('Observer got an error: ' + err),
|
||||
() => console.log('Observer got a complete notification')
|
||||
);
|
||||
// #enddocregion sub_fn
|
||||
// #docregion sub_fn
|
||||
myObservable.subscribe(
|
||||
x => console.log('Observer got a next value: ' + x),
|
||||
err => console.error('Observer got an error: ' + err),
|
||||
() => console.log('Observer got a complete notification')
|
||||
);
|
||||
// #enddocregion sub_fn
|
||||
}
|
||||
|
@ -2,7 +2,11 @@
|
||||
"tests": [
|
||||
{
|
||||
"cmd": "yarn",
|
||||
"args": [ "tsc", "--project", "./tsconfig.app.json" ]
|
||||
"args": ["tsc", "--project", "tsconfig.spec.json", "--module", "commonjs"]
|
||||
},
|
||||
{
|
||||
"cmd": "yarn",
|
||||
"args": ["jasmine", "out-tsc/**/*.spec.js"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
// TODO: Add unit tests for this file.
|
||||
import { pipe, range, timer, zip } from 'rxjs';
|
||||
import { ajax } from 'rxjs/ajax';
|
||||
import { retryWhen, map, mergeMap } from 'rxjs/operators';
|
||||
|
@ -0,0 +1,72 @@
|
||||
import { of } from 'rxjs';
|
||||
import { docRegionTypeahead } from './typeahead';
|
||||
|
||||
describe('typeahead', () => {
|
||||
let document;
|
||||
let ajax;
|
||||
let triggertInputChange;
|
||||
|
||||
beforeEach(() => {
|
||||
jasmine.clock().install();
|
||||
const input = {
|
||||
addEventListener: jasmine
|
||||
.createSpy('addEvent')
|
||||
.and.callFake((eventName: string, cb: (e) => void) => {
|
||||
if (eventName === 'input') {
|
||||
triggertInputChange = cb;
|
||||
}
|
||||
}),
|
||||
removeEventListener: jasmine.createSpy('removeEvent'),
|
||||
};
|
||||
|
||||
document = { getElementById: (id: string) => input };
|
||||
ajax = jasmine.createSpy('ajax').and.callFake((url: string) => of('foo bar'));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jasmine.clock().uninstall();
|
||||
});
|
||||
|
||||
it('should make an ajax call to the corrent endpoint', () => {
|
||||
docRegionTypeahead(document, ajax);
|
||||
triggertInputChange({ target: { value: 'foo' } });
|
||||
jasmine.clock().tick(11);
|
||||
expect(ajax).toHaveBeenCalledWith('/api/endpoint?search=foo');
|
||||
});
|
||||
|
||||
it('should not make an ajax call, when the input length < 3', () => {
|
||||
docRegionTypeahead(document, ajax);
|
||||
triggertInputChange({ target: { value: '' } });
|
||||
jasmine.clock().tick(11);
|
||||
expect(ajax).not.toHaveBeenCalled();
|
||||
triggertInputChange({ target: { value: 'fo' } });
|
||||
jasmine.clock().tick(11);
|
||||
expect(ajax).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not make an ajax call for intermediate values when debouncing', () => {
|
||||
docRegionTypeahead(document, ajax);
|
||||
triggertInputChange({ target: { value: 'foo' } });
|
||||
jasmine.clock().tick(9);
|
||||
triggertInputChange({ target: { value: 'bar' } });
|
||||
jasmine.clock().tick(9);
|
||||
triggertInputChange({ target: { value: 'baz' } });
|
||||
jasmine.clock().tick(9);
|
||||
triggertInputChange({ target: { value: 'qux' } });
|
||||
expect(ajax).not.toHaveBeenCalled();
|
||||
jasmine.clock().tick(10);
|
||||
expect(ajax).toHaveBeenCalledTimes(1);
|
||||
expect(ajax).toHaveBeenCalledWith('/api/endpoint?search=qux');
|
||||
});
|
||||
|
||||
it('should not make an ajax call, when the input value has not changed', () => {
|
||||
docRegionTypeahead(document, ajax);
|
||||
triggertInputChange({ target: { value: 'foo' } });
|
||||
jasmine.clock().tick(11);
|
||||
expect(ajax).toHaveBeenCalled();
|
||||
ajax.calls.reset();
|
||||
triggertInputChange({ target: { value: 'foo' } });
|
||||
jasmine.clock().tick(11);
|
||||
expect(ajax).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
@ -1,18 +1,32 @@
|
||||
import { fromEvent } from 'rxjs';
|
||||
import { ajax } from 'rxjs/ajax';
|
||||
import { debounceTime, distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators';
|
||||
/*
|
||||
Because of how the code is merged together using the doc regions,
|
||||
we need to indent the imports with the function below.
|
||||
*/
|
||||
// #docplaster
|
||||
// #docregion
|
||||
import { fromEvent } from 'rxjs';
|
||||
import { ajax } from 'rxjs/ajax';
|
||||
import { debounceTime, distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators';
|
||||
|
||||
// #enddocregion
|
||||
/* tslint:disable:no-shadowed-variable */
|
||||
/* tslint:disable:align */
|
||||
export function docRegionTypeahead(document, ajax) {
|
||||
// #docregion
|
||||
const searchBox = document.getElementById('search-box');
|
||||
|
||||
const searchBox = document.getElementById('search-box');
|
||||
const typeahead = fromEvent(searchBox, 'input').pipe(
|
||||
map((e: KeyboardEvent) => (e.target as HTMLInputElement).value),
|
||||
filter(text => text.length > 2),
|
||||
debounceTime(10),
|
||||
distinctUntilChanged(),
|
||||
switchMap(searchTerm => ajax(`/api/endpoint?search=${searchTerm}`))
|
||||
);
|
||||
|
||||
const typeahead = fromEvent(searchBox, 'input').pipe(
|
||||
map((e: KeyboardEvent) => (e.target as HTMLInputElement).value),
|
||||
filter(text => text.length > 2),
|
||||
debounceTime(10),
|
||||
distinctUntilChanged(),
|
||||
switchMap(() => ajax('/api/endpoint'))
|
||||
);
|
||||
typeahead.subscribe(data => {
|
||||
// Handle the data from the API
|
||||
});
|
||||
|
||||
typeahead.subscribe(data => {
|
||||
// Handle the data from the API
|
||||
});
|
||||
// #enddocregion
|
||||
return typeahead;
|
||||
}
|
||||
|
@ -0,0 +1,17 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { SwUpdate } from '@angular/service-worker';
|
||||
|
||||
function notifyUser(message: string): void { }
|
||||
|
||||
// #docregion sw-unrecoverable-state
|
||||
@Injectable()
|
||||
export class HandleUnrecoverableStateService {
|
||||
constructor(updates: SwUpdate) {
|
||||
updates.unrecoverable.subscribe(event => {
|
||||
notifyUser(
|
||||
`An error occurred that we cannot recover from:\n${event.reason}\n\n` +
|
||||
'Please reload the page.');
|
||||
});
|
||||
}
|
||||
}
|
||||
// #enddocregion sw-unrecoverable-state
|
@ -10,8 +10,8 @@ import { Hero } from '../shared/hero.model';
|
||||
template: `
|
||||
<section>
|
||||
Our list of heroes:
|
||||
<hero-profile *ngFor="let hero of heroes" [hero]="hero">
|
||||
</hero-profile>
|
||||
<toh-hero *ngFor="let hero of heroes" [hero]="hero">
|
||||
</toh-hero>
|
||||
Total powers: {{totalPowers}}<br>
|
||||
Average power: {{totalPowers / heroes.length}}
|
||||
</section>
|
||||
|
@ -28,7 +28,7 @@ import {
|
||||
ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync
|
||||
} from '@angular/core/testing';
|
||||
|
||||
import { addMatchers, newEvent, click } from '../../testing';
|
||||
import { addMatchers, click } from '../../testing';
|
||||
|
||||
export class NotProvided extends ValueService { /* example below */ }
|
||||
beforeEach(addMatchers);
|
||||
@ -274,9 +274,11 @@ describe('demo (with TestBed):', () => {
|
||||
expect(comp.name).toBe(expectedOrigName,
|
||||
`comp.name should still be ${expectedOrigName} after value change, before binding happens`);
|
||||
|
||||
// dispatch a DOM event so that Angular learns of input value change.
|
||||
// Dispatch a DOM event so that Angular learns of input value change.
|
||||
// then wait while ngModel pushes input.box value to comp.name
|
||||
input.dispatchEvent(newEvent('input'));
|
||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
||||
input.dispatchEvent(new Event('input'));
|
||||
return fixture.whenStable();
|
||||
})
|
||||
.then(() => {
|
||||
@ -312,9 +314,11 @@ describe('demo (with TestBed):', () => {
|
||||
expect(comp.name).toBe(expectedOrigName,
|
||||
`comp.name should still be ${expectedOrigName} after value change, before binding happens`);
|
||||
|
||||
// dispatch a DOM event so that Angular learns of input value change.
|
||||
// Dispatch a DOM event so that Angular learns of input value change.
|
||||
// then wait a tick while ngModel pushes input.box value to comp.name
|
||||
input.dispatchEvent(newEvent('input'));
|
||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
||||
input.dispatchEvent(new Event('input'));
|
||||
tick();
|
||||
expect(comp.name).toBe(expectedNewName,
|
||||
`After ngModel updates the model, comp.name should be ${expectedNewName} `);
|
||||
@ -335,10 +339,12 @@ describe('demo (with TestBed):', () => {
|
||||
// simulate user entering new name in input
|
||||
input.value = inputText;
|
||||
|
||||
// dispatch a DOM event so that Angular learns of input value change.
|
||||
// Dispatch a DOM event so that Angular learns of input value change.
|
||||
// then wait a tick while ngModel pushes input.box value to comp.text
|
||||
// and Angular updates the output span
|
||||
input.dispatchEvent(newEvent('input'));
|
||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
||||
input.dispatchEvent(new Event('input'));
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
expect(span.textContent).toBe(expectedText, 'output span');
|
||||
|
@ -3,7 +3,7 @@ import { ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync } from
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import {
|
||||
ActivatedRoute, ActivatedRouteStub, asyncData, click, newEvent
|
||||
ActivatedRoute, ActivatedRouteStub, asyncData, click
|
||||
} from '../../testing';
|
||||
|
||||
import { Hero } from '../model/hero';
|
||||
@ -99,7 +99,10 @@ function overrideSetup() {
|
||||
const newName = 'New Name';
|
||||
|
||||
page.nameInput.value = newName;
|
||||
page.nameInput.dispatchEvent(newEvent('input')); // tell Angular
|
||||
|
||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
||||
page.nameInput.dispatchEvent(new Event('input')); // tell Angular
|
||||
|
||||
expect(component.hero.name).toBe(newName, 'component hero has new name');
|
||||
expect(hdsSpy.testHero.name).toBe(origName, 'service hero unchanged before save');
|
||||
@ -197,9 +200,10 @@ function heroModuleSetup() {
|
||||
// simulate user entering a new name into the input box
|
||||
nameInput.value = 'quick BROWN fOx';
|
||||
|
||||
// dispatch a DOM event so that Angular learns of input value change.
|
||||
// use newEvent utility function (not provided by Angular) for better browser compatibility
|
||||
nameInput.dispatchEvent(newEvent('input'));
|
||||
// Dispatch a DOM event so that Angular learns of input value change.
|
||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
||||
nameInput.dispatchEvent(new Event('input'));
|
||||
|
||||
// Tell Angular to update the display binding through the title pipe
|
||||
fixture.detectChanges();
|
||||
|
@ -6,7 +6,7 @@ import { DebugElement } from '@angular/core';
|
||||
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { addMatchers, newEvent } from '../../testing';
|
||||
import { addMatchers } from '../../testing';
|
||||
import { HeroService } from '../model/hero.service';
|
||||
import { getTestHeroes, TestHeroService } from '../model/testing/test-hero.service';
|
||||
|
||||
@ -53,7 +53,10 @@ describe('HeroListComponent', () => {
|
||||
it('should select hero on click', fakeAsync(() => {
|
||||
const expectedHero = HEROES[1];
|
||||
const li = page.heroRows[1];
|
||||
li.dispatchEvent(newEvent('click'));
|
||||
|
||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
||||
li.dispatchEvent(new Event('click'));
|
||||
tick();
|
||||
// `.toEqual` because selectedHero is clone of expectedHero; see FakeHeroService
|
||||
expect(comp.selectedHero).toEqual(expectedHero);
|
||||
@ -62,7 +65,10 @@ describe('HeroListComponent', () => {
|
||||
it('should navigate to selected hero detail on click', fakeAsync(() => {
|
||||
const expectedHero = HEROES[1];
|
||||
const li = page.heroRows[1];
|
||||
li.dispatchEvent(newEvent('click'));
|
||||
|
||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
||||
li.dispatchEvent(new Event('click'));
|
||||
tick();
|
||||
|
||||
// should have navigated
|
||||
|
@ -3,7 +3,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
import { HighlightDirective } from './highlight.directive';
|
||||
import { newEvent } from '../../testing';
|
||||
|
||||
// #docregion test-component
|
||||
@Component({
|
||||
@ -59,9 +58,12 @@ describe('HighlightDirective', () => {
|
||||
const input = des[2].nativeElement as HTMLInputElement;
|
||||
expect(input.style.backgroundColor).toBe('cyan', 'initial backgroundColor');
|
||||
|
||||
// dispatch a DOM event so that Angular responds to the input value change.
|
||||
input.value = 'green';
|
||||
input.dispatchEvent(newEvent('input'));
|
||||
|
||||
// Dispatch a DOM event so that Angular responds to the input value change.
|
||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
||||
input.dispatchEvent(new Event('input'));
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(input.style.backgroundColor).toBe('green', 'changed backgroundColor');
|
||||
|
@ -14,18 +14,6 @@ export function advance(f: ComponentFixture<any>): void {
|
||||
f.detectChanges();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create custom DOM event the old fashioned way
|
||||
*
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/Event/initEvent
|
||||
* Although officially deprecated, some browsers (phantom) don't accept the preferred "new Event(eventName)"
|
||||
*/
|
||||
export function newEvent(eventName: string, bubbles = false, cancelable = false) {
|
||||
const evt = document.createEvent('CustomEvent'); // MUST be 'CustomEvent'
|
||||
evt.initCustomEvent(eventName, bubbles, cancelable, null);
|
||||
return evt;
|
||||
}
|
||||
|
||||
// See https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
|
||||
// #docregion click-event
|
||||
/** Button events to pass to `DebugElement.triggerEventHandler` for RouterLink event handler */
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Location } from '@angular/common';
|
||||
|
||||
@ -11,7 +11,7 @@ import { HeroService } from '../hero.service';
|
||||
styleUrls: [ './hero-detail.component.css' ]
|
||||
})
|
||||
export class HeroDetailComponent implements OnInit {
|
||||
@Input() hero: Hero;
|
||||
hero: Hero;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
|
@ -1,112 +1,111 @@
|
||||
# Accesibilidad en Angular
|
||||
# Accessibility in Angular
|
||||
|
||||
Hay una amplia variedad de personas que utilizan la web, algunas de ellas con discapacidad visual o motora.
|
||||
Existen diferentes tecnologías de apoyo que hacen que sea mucho más fácil para estos grupos
|
||||
interactuar con aplicaciones de software basadas en la web.
|
||||
Además, diseñar una aplicación para que sea más accesible, normalmente mejora la experiencia de usuario en general.
|
||||
The web is used by a wide variety of people, including those who have visual or motor impairments.
|
||||
A variety of assistive technologies are available that make it much easier for these groups to
|
||||
interact with web-based software applications.
|
||||
In addition, designing an application to be more accessible generally improves the user experience for all users.
|
||||
|
||||
Para una introducción en profundidad a los problemas y técnicas sobre el diseño de aplicaciones accesibles, puede consultar la sección de [Accesibilidad](https://developers.google.com/web/fundamentals/accessibility/#what_is_accessibility) de Google [Fundamentos Web](https://developers.google.com/web/fundamentals/).
|
||||
For an in-depth introduction to issues and techniques for designing accessible applications, see the [Accessibility](https://developers.google.com/web/fundamentals/accessibility/#what_is_accessibility) section of the Google's [Web Fundamentals](https://developers.google.com/web/fundamentals/).
|
||||
|
||||
Esta página habla de las mejores prácticas para diseñar aplicaciones en Angular que funcionan
|
||||
bien para todos los usuarios, incluyendo aquéllos que necesitan tecnologías de apoyo.
|
||||
This page discusses best practices for designing Angular applications that
|
||||
work well for all users, including those who rely on assistive technologies.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Para ver la aplicación de ejemplo que describe esta página, ir a <live-example></live-example>.
|
||||
For the sample app that this page describes, see the <live-example></live-example>.
|
||||
|
||||
</div>
|
||||
|
||||
## Atributos de accesibilidad
|
||||
## Accessibility attributes
|
||||
|
||||
Crear una web accesible a menudo implica establecer los [atributos ARIA](https://developers.google.com/web/fundamentals/accessibility/semantics-aria)
|
||||
para proporcionar la semántica que, de otro modo, podría no estar presente.
|
||||
Usa la plantilla de sintaxis del [enlace de atributos](attribute binding) (guide/attribute-binding) para controlar los valores de los atributos relacionados con la accesibilidad.
|
||||
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/attribute-binding) template syntax to control the values of accessibility-related attributes.
|
||||
|
||||
Para enlazar los atributos ARIA en Angular, debes usar el prefijo `attr.`, ya que la especificación ARIA
|
||||
depende de los atributos HTML y no de las propiedades de los elementos del DOM.
|
||||
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.
|
||||
|
||||
```html
|
||||
<!-- Use attr. when binding to an ARIA attribute -->
|
||||
<button [attr.aria-label]="myActionLabel">...</button>
|
||||
```
|
||||
|
||||
Observa que esta sintaxis solo es necesaria para los _enlaces_ de atributos.
|
||||
Los atributos ARIA estáticos no requieren de ninguna sintaxis adicional.
|
||||
Note that this syntax is only necessary for attribute _bindings_.
|
||||
Static ARIA attributes require no extra syntax.
|
||||
|
||||
```html
|
||||
<!-- Static ARIA attributes require no extra syntax -->
|
||||
<button aria-label="Save document">...</button>
|
||||
```
|
||||
|
||||
NOTA:
|
||||
NOTE:
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Por convenio, los atributos HTML se escriben en minúscula (`tabindex`), mientras que para las propiedades se usa *camelCase* (`tabIndex`).
|
||||
By convention, HTML attributes use lowercase names (`tabindex`), while properties use camelCase names (`tabIndex`).
|
||||
|
||||
Consulta la guía [Sintaxis del enlace](guide/binding-syntax#html-attribute-vs-dom-property) para saber más sobre las diferencias entre atributos y propiedades.
|
||||
See the [Binding syntax](guide/binding-syntax#html-attribute-vs-dom-property) guide for more background on the difference between attributes and properties.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
## Componentes del interfaz de usuario de Angular
|
||||
## Angular UI components
|
||||
|
||||
La librería [Angular Material](https://material.angular.io/), que es mantenida por el equipo Angular, es un conjunto de componentes reutilizables para la interfaz de usuario que pretende ser totalmente accesible.
|
||||
El [Kit de Desarrollo de Componentes (CDK)](https://material.angular.io/cdk/categories) (Component Development Kit) incluye el paquete `a11y` que proporciona herramientas para dar soporte a distintos aspectos de la accesibilidad.
|
||||
Por ejemplo:
|
||||
The [Angular Material](https://material.angular.io/) library, which is maintained by the Angular team, is a suite of reusable UI components that aims to be fully accessible.
|
||||
The [Component Development Kit (CDK)](https://material.angular.io/cdk/categories) includes the `a11y` package that provides tools to support various areas of accessibility.
|
||||
For example:
|
||||
|
||||
* `LiveAnnouncer` se utiliza para comunicar mensajes a los usuarios de lectores de pantalla que usan la region `aria-live`. Se puede consultar la documentación de la W3C para obtener más información sobre [regiones aria-live](https://www.w3.org/WAI/PF/aria-1.1/states_and_properties#aria-live).
|
||||
* `LiveAnnouncer` is used to announce messages for screen-reader users using an `aria-live` region. See the W3C documentation for more information on [aria-live regions](https://www.w3.org/WAI/PF/aria-1.1/states_and_properties#aria-live).
|
||||
|
||||
* La directiva `cdkTrapFocus` limita el foco de la tecla de tabulación para que se quede dentro de un elemento. Úsala para crear una experiencia accesible en componentes como las ventanas modales, donde el foco debe estar limitado.
|
||||
* The `cdkTrapFocus` directive traps Tab-key focus within an element. Use it to create accessible experience for components like modal dialogs, where focus must be constrained.
|
||||
|
||||
Para obtener más detalles sobre esta y otras herramientas, consulta el [resumen de accesibilidad del Angular CDK](https://material.angular.io/cdk/a11y/overview).
|
||||
For full details of these and other tools, see the [Angular CDK accessibility overview](https://material.angular.io/cdk/a11y/overview).
|
||||
|
||||
|
||||
### Aumento de elementos nativos
|
||||
### Augmenting native elements
|
||||
|
||||
Los elementos HTML nativos capturan una serie de patrones de interacción estándar que son importantes para la accesibilidad.
|
||||
Al crear componentes de Angular, deberías reutilizar estos elementos nativos directamente cuando sea posible, en lugar de volver a implementar comportamientos bien soportados.
|
||||
Native HTML elements capture a number of standard interaction patterns that are important to accessibility.
|
||||
When authoring Angular components, you should re-use these native elements directly when possible, rather than re-implementing well-supported behaviors.
|
||||
|
||||
Por ejemplo, en lugar de crear un elemento personalizado para un nuevo tipo de botón, puedes crear un componente que use un selector de atributos con un elemento nativo `<button>`.
|
||||
Esto se aplica sobre todo a `<button>` y `<a>`, pero se puede usar con muchos otros tipos de elementos.
|
||||
For example, instead of creating a custom element for a new variety of button, you can create a component that uses an attribute selector with a native `<button>` element.
|
||||
This most commonly applies to `<button>` and `<a>`, but can be used with many other types of element.
|
||||
|
||||
You can see examples of this pattern in Angular Material: [`MatButton`](https://github.com/angular/components/blob/master/src/material/button/button.ts#L66-L68), [`MatTabNav`](https://github.com/angular/components/blob/master/src/material/tabs/tab-nav-bar/tab-nav-bar.ts#L67), [`MatTable`](https://github.com/angular/components/blob/master/src/material/table/table.ts#L17).
|
||||
|
||||
### Uso de contenedores para elementos nativos
|
||||
### Using containers for native elements
|
||||
|
||||
A veces, para usar el elemento nativo apropiado hace falta un contenedor.
|
||||
Por ejemplo, el elemento nativo `<input>` no puede tener hijos, por lo que cualquier componente de entrada de texto personalizado necesita envolver un `<input>` con elementos adicionales.
|
||||
Sometimes using the appropriate native element requires a container element.
|
||||
For example, the native `<input>` element cannot have children, so any custom text entry components need
|
||||
to wrap an `<input>` with additional elements.
|
||||
While you might just include the `<input>` in your custom component's template,
|
||||
this makes it impossible for users of the component to set arbitrary properties and attributes to the input element.
|
||||
Instead, you can create a container component that uses content projection to include the native control in the
|
||||
component's API.
|
||||
|
||||
Si bien puedes incluir el `<input>` en la plantilla de tu componente personalizado,
|
||||
esto hace que sea imposible para los usuarios de dicho componente establecer propiedades y atributos arbitrarios para el elemento de entrada.
|
||||
En su lugar, puedes crear un componente contenedor que utilice la proyección de contenido para incluir el control nativo en el
|
||||
API del componente.
|
||||
You can see [`MatFormField`](https://material.angular.io/components/form-field/overview) as an example of this pattern.
|
||||
|
||||
Puedes consultar [`MatFormField`](https://material.angular.io/components/form-field/overview) para ver un ejemplo de este patrón.
|
||||
## Case study: Building a custom progress bar
|
||||
|
||||
## Caso práctico: creación de una barra de progreso personalizada
|
||||
The following example shows how to make a simple progress bar accessible by using host binding to control accessibility-related attributes.
|
||||
|
||||
El siguiente ejemplo muestra cómo hacer que una barra de progreso simple sea accesible utilizando el *host binding* para controlar los atributos relacionados con la accesibilidad.
|
||||
|
||||
* El componente define un elemento habilitado para accesibilidad con el atributo HTML estándar `role` y los atributos ARIA. El atributo ARIA `aria-valuenow` está vinculado a la entrada del usuario.
|
||||
* The component defines an accessibility-enabled element with both the standard HTML attribute `role`, and ARIA attributes. The ARIA attribute `aria-valuenow` is bound to the user's input.
|
||||
|
||||
<code-example path="accessibility/src/app/progress-bar.component.ts" header="src/app/progress-bar.component.ts" region="progressbar-component"></code-example>
|
||||
|
||||
|
||||
* En la plantilla, el atributo `aria-label` asegura que el control sea accesible para los lectores de pantalla.
|
||||
* In the template, the `aria-label` attribute ensures that the control is accessible to screen readers.
|
||||
|
||||
<code-example path="accessibility/src/app/app.component.html" header="src/app/app.component.html" region="template"></code-example>
|
||||
|
||||
|
||||
## Enrutamiento y gestión del foco
|
||||
## Routing and focus management
|
||||
|
||||
El seguimiento y el control del [foco](https://developers.google.com/web/fundamentals/accessibility/focus/) en una interfaz de usuario son aspectos muy importantes en el diseño si queremos tener en cuenta la accesibilidad.
|
||||
Al usar el enrutamiento de Angular, debes decidir dónde va el foco de la página al navegar.
|
||||
Tracking and controlling [focus](https://developers.google.com/web/fundamentals/accessibility/focus/) in a UI is an important consideration in designing for accessibility.
|
||||
When using Angular routing, you should decide where page focus goes upon navigation.
|
||||
|
||||
Para evitar depender únicamente de señales visuales, te debes asegurar de que el código de enrutamiento actualiza el foco después de la navegación de la página.
|
||||
Usa el evento `NavigationEnd` del servicio` Router` para saber cuándo actualizar el foco.
|
||||
|
||||
El siguiente ejemplo muestra cómo encontrar y poner el foco en el contenido principal de la cabecera (el elemento `#main-content-header`) dentro del DOM después de la navegación.
|
||||
To avoid relying solely on visual cues, you need to make sure your routing code updates focus after page navigation.
|
||||
Use the `NavigationEnd` event from the `Router` service to know when to update
|
||||
focus.
|
||||
|
||||
The following example shows how to find and focus the main content header in the DOM after navigation.
|
||||
|
||||
@ -120,12 +119,13 @@ router.events.pipe(filter(e => e instanceof NavigationEnd)).subscribe(() => {
|
||||
});
|
||||
|
||||
```
|
||||
En una aplicación real, el elemento que recibe el foco dependerá de la estructura específica y del diseño que tenga tu aplicación.
|
||||
El elemento enfocado debe colocar a los usuarios en una posición en la que pasen inmediatamente al contenido principal que acaba de ser visualizado.
|
||||
Debe evitar situaciones en las que el foco vuelva al elemento `body` después de un cambio de ruta.
|
||||
In a real application, the element that receives focus will depend on your specific
|
||||
application structure and layout.
|
||||
The focused element should put users in a position to immediately move into the main content that has just been routed into view.
|
||||
You should avoid situations where focus returns to the `body` element after a route change.
|
||||
|
||||
|
||||
## Recursos adicionales
|
||||
## Additional resources
|
||||
|
||||
* [Accessibility - Google Web Fundamentals](https://developers.google.com/web/fundamentals/accessibility)
|
||||
|
||||
@ -145,13 +145,13 @@ Debe evitar situaciones en las que el foco vuelva al elemento `body` después de
|
||||
|
||||
* [Codelyzer](http://codelyzer.com/rules/) provides linting rules that can help you make sure your code meets accessibility standards.
|
||||
|
||||
Libros
|
||||
Books
|
||||
|
||||
* "A Web for Everyone: Designing Accessible User Experiences", Sarah Horton and Whitney Quesenbery
|
||||
|
||||
* "Inclusive Design Patterns", Heydon Pickering
|
||||
|
||||
## Más sobre accesibilidad
|
||||
## More on accessibility
|
||||
|
||||
Podrías estar interesado en lo siguiente:
|
||||
You may also be interested in the following:
|
||||
* [Audit your Angular app's accessibility with codelyzer](https://web.dev/accessible-angular-with-codelyzer/).
|
||||
|
@ -341,7 +341,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
||||
In Angular, the template no longer specifies its associated controller.
|
||||
Rather, the component specifies its associated template as part of the component class decorator.
|
||||
|
||||
For more information, see [Architecture Overview](guide/architecture#componentes).
|
||||
For more information, see [Architecture Overview](guide/architecture#components).
|
||||
|
||||
</td>
|
||||
|
||||
@ -1035,7 +1035,7 @@ The Angular code is shown using TypeScript.
|
||||
This is a nonissue in Angular because ES 2015 modules
|
||||
handle the namespacing for you.
|
||||
|
||||
For more information on modules, see the [Modules](guide/architecture#módulos) section of the
|
||||
For more information on modules, see the [Modules](guide/architecture#modules) section of the
|
||||
[Architecture Overview](guide/architecture).
|
||||
</td>
|
||||
|
||||
@ -1112,7 +1112,7 @@ The Angular code is shown using TypeScript.
|
||||
|
||||
This is how you associate a template with logic, which is defined in the component class.
|
||||
|
||||
For more information, see the [Components](guide/architecture#componentes)
|
||||
For more information, see the [Components](guide/architecture#components)
|
||||
section of the [Architecture Overview](guide/architecture) page.
|
||||
</td>
|
||||
|
||||
@ -1144,7 +1144,7 @@ The Angular code is shown using TypeScript.
|
||||
|
||||
In Angular, you create a component class to contain the data model and control methods. Use the TypeScript <code>export</code> keyword to export the class so that the functionality can be imported into NgModules.
|
||||
|
||||
For more information, see the [Components](guide/architecture#componentes)
|
||||
For more information, see the [Components](guide/architecture#components)
|
||||
section of the [Architecture Overview](guide/architecture) page.
|
||||
</td>
|
||||
|
||||
|
@ -31,7 +31,7 @@ For example:
|
||||
|
||||
```json
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true,
|
||||
...
|
||||
|
@ -1,665 +0,0 @@
|
||||
# Ahead-of-time (AOT) compilation
|
||||
|
||||
An Angular application consists mainly of components and their HTML templates. Because the components and templates provided by Angular cannot be understood by the browser directly, Angular applications require a compilation process before they can run in a browser.
|
||||
|
||||
The Angular [ahead-of-time (AOT) compiler](guide/glossary#aot) converts your Angular HTML and TypeScript code into efficient JavaScript code during the build phase _before_ the browser downloads and runs that code. Compiling your application during the build process provides a faster rendering in the browser.
|
||||
|
||||
This guide explains how to specify metadata and apply available compiler options to compile your applications efficiently using the AOT compiler.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
<a href="https://www.youtube.com/watch?v=anphffaCZrQ">Watch Alex Rickabaugh explain the Angular compiler</a> at AngularConnect 2019.
|
||||
|
||||
</div>
|
||||
|
||||
{@a why-aot}
|
||||
|
||||
Here are some reasons you might want to use AOT.
|
||||
|
||||
* *Faster rendering*
|
||||
With AOT, the browser downloads a pre-compiled version of the application.
|
||||
The browser loads executable code so it can render the application immediately, without waiting to compile the app first.
|
||||
|
||||
* *Fewer asynchronous requests*
|
||||
The compiler _inlines_ external HTML templates and CSS style sheets within the application JavaScript,
|
||||
eliminating separate ajax requests for those source files.
|
||||
|
||||
* *Smaller Angular framework download size*
|
||||
There's no need to download the Angular compiler if the app is already compiled.
|
||||
The compiler is roughly half of Angular itself, so omitting it dramatically reduces the application payload.
|
||||
|
||||
* *Detect template errors earlier*
|
||||
The AOT compiler detects and reports template binding errors during the build step
|
||||
before users can see them.
|
||||
|
||||
* *Better security*
|
||||
AOT compiles HTML templates and components into JavaScript files long before they are served to the client.
|
||||
With no templates to read and no risky client-side HTML or JavaScript evaluation,
|
||||
there are fewer opportunities for injection attacks.
|
||||
|
||||
{@a overview}
|
||||
|
||||
## Choosing a compiler
|
||||
|
||||
Angular offers two ways to compile your application:
|
||||
|
||||
* **_Just-in-Time_ (JIT)**, which compiles your app in the browser at runtime. This was the default until Angular 8.
|
||||
* **_Ahead-of-Time_ (AOT)**, which compiles your app and libraries at build time. This is the default since Angular 9.
|
||||
|
||||
When you run the [`ng build`](cli/build) (build only) or [`ng serve`](cli/serve) (build and serve locally) CLI commands, the type of compilation (JIT or AOT) depends on the value of the `aot` property in your build configuration specified in `angular.json`. By default, `aot` is set to `true` for new CLI apps.
|
||||
|
||||
See the [CLI command reference](cli) and [Building and serving Angular apps](guide/build) for more information.
|
||||
|
||||
## How AOT works
|
||||
|
||||
The Angular AOT compiler extracts **metadata** to interpret the parts of the application that Angular is supposed to manage.
|
||||
You can specify the metadata explicitly in **decorators** such as `@Component()` and `@Input()`, or implicitly in the constructor declarations of the decorated classes.
|
||||
The metadata tells Angular how to construct instances of your application classes and interact with them at runtime.
|
||||
|
||||
In the following example, the `@Component()` metadata object and the class constructor tell Angular how to create and display an instance of `TypicalComponent`.
|
||||
|
||||
```typescript
|
||||
@Component({
|
||||
selector: 'app-typical',
|
||||
template: '<div>A typical component for {{data.name}}</div>'
|
||||
)}
|
||||
export class TypicalComponent {
|
||||
@Input() data: TypicalData;
|
||||
constructor(private someService: SomeService) { ... }
|
||||
}
|
||||
```
|
||||
|
||||
The Angular compiler extracts the metadata _once_ and generates a _factory_ for `TypicalComponent`.
|
||||
When it needs to create a `TypicalComponent` instance, Angular calls the factory, which produces a new visual element, bound to a new instance of the component class with its injected dependency.
|
||||
|
||||
### Compilation phases
|
||||
|
||||
There are three phases of AOT compilation.
|
||||
* Phase 1 is *code analysis*.
|
||||
In this phase, the TypeScript compiler and *AOT collector* create a representation of the source. The collector does not attempt to interpret the metadata it collects. It represents the metadata as best it can and records errors when it detects a metadata syntax violation.
|
||||
|
||||
* Phase 2 is *code generation*.
|
||||
In this phase, the compiler's `StaticReflector` interprets the metadata collected in phase 1, performs additional validation of the metadata, and throws an error if it detects a metadata restriction violation.
|
||||
|
||||
* Phase 3 is *template type checking*.
|
||||
In this optional phase, the Angular *template compiler* uses the TypeScript compiler to validate the binding expressions in templates. You can enable this phase explicitly by setting the `fullTemplateTypeCheck` configuration option; see [Angular compiler options](guide/angular-compiler-options).
|
||||
|
||||
|
||||
### Metadata restrictions
|
||||
|
||||
You write metadata in a _subset_ of TypeScript that must conform to the following general constraints:
|
||||
|
||||
* Limit [expression syntax](#expression-syntax) to the supported subset of JavaScript.
|
||||
* Only reference exported symbols after [code folding](#code-folding).
|
||||
* Only call [functions supported](#supported-functions) by the compiler.
|
||||
* Decorated and data-bound class members must be public.
|
||||
|
||||
For additional guidelines and instructions on preparing an application for AOT compilation, see [Angular: Writing AOT-friendly applications](https://medium.com/sparkles-blog/angular-writing-aot-friendly-applications-7b64c8afbe3f).
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Errors in AOT compilation commonly occur because of metadata that does not conform to the compiler's requirements (as described more fully below).
|
||||
For help in understanding and resolving these problems, see [AOT Metadata Errors](guide/aot-metadata-errors).
|
||||
|
||||
</div>
|
||||
|
||||
### Configuring AOT compilation
|
||||
|
||||
You can provide options in the [TypeScript configuration file](guide/typescript-configuration) that controls the compilation process. See [Angular compiler options](guide/angular-compiler-options) for a complete list of available options.
|
||||
|
||||
## Phase 1: Code analysis
|
||||
|
||||
The TypeScript compiler does some of the analytic work of the first phase. It emits the `.d.ts` _type definition files_ with type information that the AOT compiler needs to generate application code.
|
||||
At the same time, the AOT **collector** analyzes the metadata recorded in the Angular decorators and outputs metadata information in **`.metadata.json`** files, one per `.d.ts` file.
|
||||
|
||||
You can think of `.metadata.json` as a diagram of the overall structure of a decorator's metadata, represented as an [abstract syntax tree (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree).
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Angular's [schema.ts](https://github.com/angular/angular/blob/master/packages/compiler-cli/src/metadata/schema.ts)
|
||||
describes the JSON format as a collection of TypeScript interfaces.
|
||||
|
||||
</div>
|
||||
|
||||
{@a expression-syntax}
|
||||
### Expression syntax limitations
|
||||
|
||||
The AOT collector only understands a subset of JavaScript.
|
||||
Define metadata objects with the following limited syntax:
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
</style>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Syntax</th>
|
||||
<th>Example</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Literal object </td>
|
||||
<td><code>{cherry: true, apple: true, mincemeat: false}</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Literal array </td>
|
||||
<td><code>['cherries', 'flour', 'sugar']</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Spread in literal array</td>
|
||||
<td><code>['apples', 'flour', ...the_rest]</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Calls</td>
|
||||
<td><code>bake(ingredients)</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>New</td>
|
||||
<td><code>new Oven()</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Property access</td>
|
||||
<td><code>pie.slice</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Array index</td>
|
||||
<td><code>ingredients[0]</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Identity reference</td>
|
||||
<td><code>Component</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>A template string</td>
|
||||
<td><code>`pie is ${multiplier} times better than cake`</code></td>
|
||||
<tr>
|
||||
<td>Literal string</td>
|
||||
<td><code>pi</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Literal number</td>
|
||||
<td><code>3.14153265</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Literal boolean</td>
|
||||
<td><code>true</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Literal null</td>
|
||||
<td><code>null</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Supported prefix operator </td>
|
||||
<td><code>!cake</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Supported binary operator </td>
|
||||
<td><code>a+b</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Conditional operator</td>
|
||||
<td><code>a ? b : c</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Parentheses</td>
|
||||
<td><code>(a+b)</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
If an expression uses unsupported syntax, the collector writes an error node to the `.metadata.json` file.
|
||||
The compiler later reports the error if it needs that piece of metadata to generate the application code.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
If you want `ngc` to report syntax errors immediately rather than produce a `.metadata.json` file with errors, set the `strictMetadataEmit` option in the TypeScript configuration file.
|
||||
|
||||
```
|
||||
"angularCompilerOptions": {
|
||||
...
|
||||
"strictMetadataEmit" : true
|
||||
}
|
||||
```
|
||||
|
||||
Angular libraries have this option to ensure that all Angular `.metadata.json` files are clean and it is a best practice to do the same when building your own libraries.
|
||||
|
||||
</div>
|
||||
|
||||
{@a function-expression}
|
||||
{@a arrow-functions}
|
||||
### No arrow functions
|
||||
|
||||
The AOT compiler does not support [function expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function)
|
||||
and [arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions), also called _lambda_ functions.
|
||||
|
||||
Consider the following component decorator:
|
||||
|
||||
```typescript
|
||||
@Component({
|
||||
...
|
||||
providers: [{provide: server, useFactory: () => new Server()}]
|
||||
})
|
||||
```
|
||||
|
||||
The AOT collector does not support the arrow function, `() => new Server()`, in a metadata expression.
|
||||
It generates an error node in place of the function.
|
||||
When the compiler later interprets this node, it reports an error that invites you to turn the arrow function into an _exported function_.
|
||||
|
||||
You can fix the error by converting to this:
|
||||
|
||||
```typescript
|
||||
export function serverFactory() {
|
||||
return new Server();
|
||||
}
|
||||
|
||||
@Component({
|
||||
...
|
||||
providers: [{provide: server, useFactory: serverFactory}]
|
||||
})
|
||||
```
|
||||
|
||||
In version 5 and later, the compiler automatically performs this rewriting while emitting the `.js` file.
|
||||
|
||||
{@a exported-symbols}
|
||||
{@a code-folding}
|
||||
### Code folding
|
||||
|
||||
The compiler can only resolve references to **_exported_** symbols.
|
||||
The collector, however, can evaluate an expression during collection and record the result in the `.metadata.json`, rather than the original expression.
|
||||
This allows you to make limited use of non-exported symbols within expressions.
|
||||
|
||||
For example, the collector can evaluate the expression `1 + 2 + 3 + 4` and replace it with the result, `10`.
|
||||
This process is called _folding_. An expression that can be reduced in this manner is _foldable_.
|
||||
|
||||
{@a var-declaration}
|
||||
The collector can evaluate references to module-local `const` declarations and initialized `var` and `let` declarations, effectively removing them from the `.metadata.json` file.
|
||||
|
||||
Consider the following component definition:
|
||||
|
||||
```typescript
|
||||
const template = '<div>{{hero.name}}</div>';
|
||||
|
||||
@Component({
|
||||
selector: 'app-hero',
|
||||
template: template
|
||||
})
|
||||
export class HeroComponent {
|
||||
@Input() hero: Hero;
|
||||
}
|
||||
```
|
||||
|
||||
The compiler could not refer to the `template` constant because it isn't exported.
|
||||
The collector, however, can fold the `template` constant into the metadata definition by in-lining its contents.
|
||||
The effect is the same as if you had written:
|
||||
|
||||
```typescript
|
||||
@Component({
|
||||
selector: 'app-hero',
|
||||
template: '<div>{{hero.name}}</div>'
|
||||
})
|
||||
export class HeroComponent {
|
||||
@Input() hero: Hero;
|
||||
}
|
||||
```
|
||||
|
||||
There is no longer a reference to `template` and, therefore, nothing to trouble the compiler when it later interprets the _collector's_ output in `.metadata.json`.
|
||||
|
||||
You can take this example a step further by including the `template` constant in another expression:
|
||||
|
||||
```typescript
|
||||
const template = '<div>{{hero.name}}</div>';
|
||||
|
||||
@Component({
|
||||
selector: 'app-hero',
|
||||
template: template + '<div>{{hero.title}}</div>'
|
||||
})
|
||||
export class HeroComponent {
|
||||
@Input() hero: Hero;
|
||||
}
|
||||
```
|
||||
|
||||
The collector reduces this expression to its equivalent _folded_ string:
|
||||
|
||||
```
|
||||
'<div>{{hero.name}}</div><div>{{hero.title}}</div>'
|
||||
```
|
||||
|
||||
#### Foldable syntax
|
||||
|
||||
The following table describes which expressions the collector can and cannot fold:
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
</style>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Syntax</th>
|
||||
<th>Foldable</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Literal object </td>
|
||||
<td>yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Literal array </td>
|
||||
<td>yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Spread in literal array</td>
|
||||
<td>no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Calls</td>
|
||||
<td>no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>New</td>
|
||||
<td>no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Property access</td>
|
||||
<td>yes, if target is foldable</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Array index</td>
|
||||
<td> yes, if target and index are foldable</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Identity reference</td>
|
||||
<td>yes, if it is a reference to a local</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>A template with no substitutions</td>
|
||||
<td>yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>A template with substitutions</td>
|
||||
<td>yes, if the substitutions are foldable</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Literal string</td>
|
||||
<td>yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Literal number</td>
|
||||
<td>yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Literal boolean</td>
|
||||
<td>yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Literal null</td>
|
||||
<td>yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Supported prefix operator </td>
|
||||
<td>yes, if operand is foldable</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Supported binary operator </td>
|
||||
<td>yes, if both left and right are foldable</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Conditional operator</td>
|
||||
<td>yes, if condition is foldable </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Parentheses</td>
|
||||
<td>yes, if the expression is foldable</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
If an expression is not foldable, the collector writes it to `.metadata.json` as an [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) for the compiler to resolve.
|
||||
|
||||
|
||||
## Phase 2: code generation
|
||||
|
||||
The collector makes no attempt to understand the metadata that it collects and outputs to `.metadata.json`.
|
||||
It represents the metadata as best it can and records errors when it detects a metadata syntax violation.
|
||||
It's the compiler's job to interpret the `.metadata.json` in the code generation phase.
|
||||
|
||||
The compiler understands all syntax forms that the collector supports, but it may reject _syntactically_ correct metadata if the _semantics_ violate compiler rules.
|
||||
|
||||
### Public symbols
|
||||
|
||||
The compiler can only reference _exported symbols_.
|
||||
|
||||
* Decorated component class members must be public. You cannot make an `@Input()` property private or protected.
|
||||
* Data bound properties must also be public.
|
||||
|
||||
```typescript
|
||||
// BAD CODE - title is private
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
template: '<h1>{{title}}</h1>'
|
||||
})
|
||||
export class AppComponent {
|
||||
private title = 'My App'; // Bad
|
||||
}
|
||||
```
|
||||
|
||||
{@a supported-functions}
|
||||
|
||||
### Supported classes and functions
|
||||
|
||||
The collector can represent a function call or object creation with `new` as long as the syntax is valid.
|
||||
The compiler, however, can later refuse to generate a call to a _particular_ function or creation of a _particular_ object.
|
||||
|
||||
The compiler can only create instances of certain classes, supports only core decorators, and only supports calls to macros (functions or static methods) that return expressions.
|
||||
* New instances
|
||||
|
||||
The compiler only allows metadata that create instances of the class `InjectionToken` from `@angular/core`.
|
||||
|
||||
* Supported decorators
|
||||
|
||||
The compiler only supports metadata for the [Angular decorators in the `@angular/core` module](api/core#decorators).
|
||||
|
||||
* Function calls
|
||||
|
||||
Factory functions must be exported, named functions.
|
||||
The AOT compiler does not support lambda expressions ("arrow functions") for factory functions.
|
||||
|
||||
{@a function-calls}
|
||||
### Functions and static method calls
|
||||
|
||||
The collector accepts any function or static method that contains a single `return` statement.
|
||||
The compiler, however, only supports macros in the form of functions or static methods that return an *expression*.
|
||||
|
||||
For example, consider the following function:
|
||||
|
||||
```typescript
|
||||
export function wrapInArray<T>(value: T): T[] {
|
||||
return [value];
|
||||
}
|
||||
```
|
||||
|
||||
You can call the `wrapInArray` in a metadata definition because it returns the value of an expression that conforms to the compiler's restrictive JavaScript subset.
|
||||
|
||||
You might use `wrapInArray()` like this:
|
||||
|
||||
```typescript
|
||||
@NgModule({
|
||||
declarations: wrapInArray(TypicalComponent)
|
||||
})
|
||||
export class TypicalModule {}
|
||||
```
|
||||
|
||||
The compiler treats this usage as if you had written:
|
||||
|
||||
```typescript
|
||||
@NgModule({
|
||||
declarations: [TypicalComponent]
|
||||
})
|
||||
export class TypicalModule {}
|
||||
```
|
||||
The Angular [`RouterModule`](api/router/RouterModule) exports two macro static methods, `forRoot` and `forChild`, to help declare root and child routes.
|
||||
Review the [source code](https://github.com/angular/angular/blob/master/packages/router/src/router_module.ts#L139 "RouterModule.forRoot source code")
|
||||
for these methods to see how macros can simplify configuration of complex [NgModules](guide/ngmodules).
|
||||
|
||||
{@a metadata-rewriting}
|
||||
|
||||
### Metadata rewriting
|
||||
|
||||
The compiler treats object literals containing the fields `useClass`, `useValue`, `useFactory`, and `data` specially, converting the expression initializing one of these fields into an exported variable that replaces the expression.
|
||||
This process of rewriting these expressions removes all the restrictions on what can be in them because
|
||||
the compiler doesn't need to know the expression's value—it just needs to be able to generate a reference to the value.
|
||||
|
||||
You might write something like:
|
||||
|
||||
```typescript
|
||||
class TypicalServer {
|
||||
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
providers: [{provide: SERVER, useFactory: () => TypicalServer}]
|
||||
})
|
||||
export class TypicalModule {}
|
||||
```
|
||||
|
||||
Without rewriting, this would be invalid because lambdas are not supported and `TypicalServer` is not exported.
|
||||
To allow this, the compiler automatically rewrites this to something like:
|
||||
|
||||
```typescript
|
||||
class TypicalServer {
|
||||
|
||||
}
|
||||
|
||||
export const ɵ0 = () => new TypicalServer();
|
||||
|
||||
@NgModule({
|
||||
providers: [{provide: SERVER, useFactory: ɵ0}]
|
||||
})
|
||||
export class TypicalModule {}
|
||||
```
|
||||
|
||||
This allows the compiler to generate a reference to `ɵ0` in the factory without having to know what the value of `ɵ0` contains.
|
||||
|
||||
The compiler does the rewriting during the emit of the `.js` file.
|
||||
It does not, however, rewrite the `.d.ts` file, so TypeScript doesn't recognize it as being an export. and it does not interfere with the ES module's exported API.
|
||||
|
||||
|
||||
{@a binding-expression-validation}
|
||||
|
||||
## Phase 3: Template type checking
|
||||
|
||||
One of the Angular compiler's most helpful features is the ability to type-check expressions within templates, and catch any errors before they cause crashes at runtime.
|
||||
In the template type-checking phase, the Angular template compiler uses the TypeScript compiler to validate the binding expressions in templates.
|
||||
|
||||
Enable this phase explicitly by adding the compiler option `"fullTemplateTypeCheck"` in the `"angularCompilerOptions"` of the project's TypeScript configuration file
|
||||
(see [Angular Compiler Options](guide/angular-compiler-options)).
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
In [Angular Ivy](guide/ivy), the template type checker has been completely rewritten to be more capable as well as stricter, meaning it can catch a variety of new errors that the previous type checker would not detect.
|
||||
|
||||
As a result, templates that previously compiled under View Engine can fail type checking under Ivy. This can happen because Ivy's stricter checking catches genuine errors, or because application code is not typed correctly, or because the application uses libraries in which typings are inaccurate or not specific enough.
|
||||
|
||||
This stricter type checking is not enabled by default in version 9, but can be enabled by setting the `strictTemplates` configuration option.
|
||||
We do expect to make strict type checking the default in the future.
|
||||
|
||||
For more information about type-checking options, and about improvements to template type checking in version 9 and above, see [Template type checking](guide/template-typecheck).
|
||||
|
||||
</div>
|
||||
|
||||
Template validation produces error messages when a type error is detected in a template binding
|
||||
expression, similar to how type errors are reported by the TypeScript compiler against code in a `.ts`
|
||||
file.
|
||||
|
||||
For example, consider the following component:
|
||||
|
||||
```typescript
|
||||
@Component({
|
||||
selector: 'my-component',
|
||||
template: '{{person.addresss.street}}'
|
||||
})
|
||||
class MyComponent {
|
||||
person?: Person;
|
||||
}
|
||||
```
|
||||
|
||||
This produces the following error:
|
||||
|
||||
```
|
||||
my.component.ts.MyComponent.html(1,1): : Property 'addresss' does not exist on type 'Person'. Did you mean 'address'?
|
||||
```
|
||||
|
||||
The file name reported in the error message, `my.component.ts.MyComponent.html`, is a synthetic file
|
||||
generated by the template compiler that holds contents of the `MyComponent` class template.
|
||||
The compiler never writes this file to disk.
|
||||
The line and column numbers are relative to the template string in the `@Component` annotation of the class, `MyComponent` in this case.
|
||||
If a component uses `templateUrl` instead of `template`, the errors are reported in the HTML file referenced by the `templateUrl` instead of a synthetic file.
|
||||
|
||||
The error location is the beginning of the text node that contains the interpolation expression with the error.
|
||||
If the error is in an attribute binding such as `[value]="person.address.street"`, the error
|
||||
location is the location of the attribute that contains the error.
|
||||
|
||||
The validation uses the TypeScript type checker and the options supplied to the TypeScript compiler to control how detailed the type validation is.
|
||||
For example, if the `strictTypeChecks` is specified, the error
|
||||
```my.component.ts.MyComponent.html(1,1): : Object is possibly 'undefined'```
|
||||
is reported as well as the above error message.
|
||||
|
||||
### Type narrowing
|
||||
|
||||
The expression used in an `ngIf` directive is used to narrow type unions in the Angular
|
||||
template compiler, the same way the `if` expression does in TypeScript.
|
||||
For example, to avoid `Object is possibly 'undefined'` error in the template above, modify it to only emit the interpolation if the value of `person` is initialized as shown below:
|
||||
|
||||
```typescript
|
||||
@Component({
|
||||
selector: 'my-component',
|
||||
template: '<span *ngIf="person"> {{person.addresss.street}} </span>'
|
||||
})
|
||||
class MyComponent {
|
||||
person?: Person;
|
||||
}
|
||||
```
|
||||
|
||||
Using `*ngIf` allows the TypeScript compiler to infer that the `person` used in the binding expression will never be `undefined`.
|
||||
|
||||
For more information about input type narrowing, see [Input setter coercion](guide/template-typecheck#input-setter-coercion) and [Improving template type checking for custom directives](guide/structural-directives#directive-type-checks).
|
||||
|
||||
### Non-null type assertion operator
|
||||
|
||||
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`.
|
||||
|
||||
```typescript
|
||||
@Component({
|
||||
selector: 'my-component',
|
||||
template: '<span *ngIf="person"> {{person.name}} lives on {{address!.street}} </span>'
|
||||
})
|
||||
class MyComponent {
|
||||
person?: Person;
|
||||
address?: Address;
|
||||
|
||||
setData(person: Person, address: Address) {
|
||||
this.person = person;
|
||||
this.address = address;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The non-null assertion operator should be used sparingly as refactoring of the component might break this constraint.
|
||||
|
||||
In this example it is recommended to include the checking of `address` in the `*ngIf` as shown below:
|
||||
|
||||
```typescript
|
||||
@Component({
|
||||
selector: 'my-component',
|
||||
template: '<span *ngIf="person && address"> {{person.name}} lives on {{address.street}} </span>'
|
||||
})
|
||||
class MyComponent {
|
||||
person?: Person;
|
||||
address?: Address;
|
||||
|
||||
setData(person: Person, address: Address) {
|
||||
this.person = person;
|
||||
this.address = address;
|
||||
}
|
||||
}
|
||||
```
|
@ -1,128 +1,131 @@
|
||||
# Compilación anticipada (AOT)
|
||||
# Ahead-of-time (AOT) compilation
|
||||
|
||||
Una aplicación Angular consta principalmente de componentes y sus plantillas HTML. Los componentes y plantillas proporcionados por Angular no pueden ser entendidos por el navegador directamente, las aplicaciones en Angular requieren un proceso de compilación antes de que puedan correr en un navegador.
|
||||
An Angular application consists mainly of components and their HTML templates. Because the components and templates provided by Angular cannot be understood by the browser directly, Angular applications require a compilation process before they can run in a browser.
|
||||
|
||||
La [compilación anticipada de Angular (AOT)](guide/glossary#aot) convierte plantillas y código de TypeScript en eficiente código JavaScript durante la fase de construcción _antes_ de que el navegador descargue y corra el código. Compilando tu aplicación durante el proceso de construcción se proporciona una renderización más rápida en el navegador.
|
||||
The Angular [ahead-of-time (AOT) compiler](guide/glossary#aot) converts your Angular HTML and TypeScript code into efficient JavaScript code during the build phase _before_ the browser downloads and runs that code. Compiling your application during the build process provides a faster rendering in the browser.
|
||||
|
||||
Esta guía explica como especificar metadatos y aplicar las opciones del compilador disponibles para compilar aplicaciones eficientemente usando la compilación anticipada (AOT).
|
||||
This guide explains how to specify metadata and apply available compiler options to compile your applications efficiently using the AOT compiler.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
<a href="https://www.youtube.com/watch?v=anphffaCZrQ">Mira a Alex Rickabaugh explicando el compilador de Angular en AngularConnect 2019.
|
||||
<a href="https://www.youtube.com/watch?v=anphffaCZrQ">Watch Alex Rickabaugh explain the Angular compiler</a> at AngularConnect 2019.
|
||||
|
||||
</div>
|
||||
|
||||
{@a why-aot}
|
||||
|
||||
Aquí algunas razones por las qué podrías querer usar AOT.
|
||||
Here are some reasons you might want to use AOT.
|
||||
|
||||
* *Renderizado más rápido*
|
||||
Con AOT, el navegador descarga una versión pre compilada de una aplicación.
|
||||
El navegador carga el código ejecutable para que pueda renderizar la aplicación inmediatamente, sin esperar a compilar la aplicación primero.
|
||||
* *Faster rendering*
|
||||
With AOT, the browser downloads a pre-compiled version of the application.
|
||||
The browser loads executable code so it can render the application immediately, without waiting to compile the app first.
|
||||
|
||||
* *Menos solicitudes asincrónicas*
|
||||
El compilador _inserta_ plantillas HTML y hojas de estilo CSS externas dentro de la aplicación JavaScript, eliminando solicitudes ajax separadas para esos archivos fuente.
|
||||
* *Fewer asynchronous requests*
|
||||
The compiler _inlines_ external HTML templates and CSS style sheets within the application JavaScript,
|
||||
eliminating separate ajax requests for those source files.
|
||||
|
||||
* *Angular pesa menos*
|
||||
No existe necesidad de incluir el compilador de Angular si la aplicación ya esta compilada.
|
||||
El compilador es aproximadamente la mitad de Angular en si mismo, así que omitíendolo se reduce drásticamente el peso de la aplicación.
|
||||
* *Smaller Angular framework download size*
|
||||
There's no need to download the Angular compiler if the app is already compiled.
|
||||
The compiler is roughly half of Angular itself, so omitting it dramatically reduces the application payload.
|
||||
|
||||
* *Detecte errores en platillas antes*
|
||||
El compilador AOT detecta y reporta errores de enlace de datos en plantillas durante el paso de construcción antes que los usuarios puedan verlos.
|
||||
* *Detect template errors earlier*
|
||||
The AOT compiler detects and reports template binding errors during the build step
|
||||
before users can see them.
|
||||
|
||||
* *Mejor seguridad*
|
||||
AOT compila las plantillas HTML y componentes en archivos JavaScript mucho antes de que se sirvan a el cliente.
|
||||
Sin plantillas para leer y sin evaluaciones de JavaScript o HTML del lado del cliente riesgosas, existen pocas oportunidades para ataques de inyección.
|
||||
* *Better security*
|
||||
AOT compiles HTML templates and components into JavaScript files long before they are served to the client.
|
||||
With no templates to read and no risky client-side HTML or JavaScript evaluation,
|
||||
there are fewer opportunities for injection attacks.
|
||||
|
||||
{@a overview}
|
||||
|
||||
## Eligiendo un compilador.
|
||||
## Choosing a compiler
|
||||
|
||||
Angular ofrece dos formas para compilar tu aplicación:
|
||||
Angular offers two ways to compile your application:
|
||||
|
||||
* **_Just-in-Time_ (JIT)**, cuando compila tu aplicación en el navegador en tiempo de ejecución. Este fué el modo de compilación por defecto hasta Angular 8.
|
||||
* **_Ahead-of-Time_ (AOT)**, cuando compila tu aplicación y librerías en el tiempo de construcción. Este es el modo de compilación por defecto desde Angular 9.
|
||||
* **_Just-in-Time_ (JIT)**, which compiles your app in the browser at runtime. This was the default until Angular 8.
|
||||
* **_Ahead-of-Time_ (AOT)**, which compiles your app and libraries at build time. This is the default since Angular 9.
|
||||
|
||||
Cuando ejecutas los comandos del CLI [`ng build`](cli/build) (solo construcción) o [`ng serve`](cli/serve) (construye y sirve localmente), el tipo de compilación (JIT o AOT) depende del valor de la propiedad `aot` en tu configuración de construcción especificada en el archivo `angular.json`. Por defecto, `aot` esta establecido en `true` para nuevas aplicaciones.
|
||||
When you run the [`ng build`](cli/build) (build only) or [`ng serve`](cli/serve) (build and serve locally) CLI commands, the type of compilation (JIT or AOT) depends on the value of the `aot` property in your build configuration specified in `angular.json`. By default, `aot` is set to `true` for new CLI apps.
|
||||
|
||||
Mira la [referencia de comandos del CLI](cli) y [Construyendo y sirviendo Angular apps](guide/build) para más información.
|
||||
See the [CLI command reference](cli) and [Building and serving Angular apps](guide/build) for more information.
|
||||
|
||||
## Como funciona AOT
|
||||
## How AOT works
|
||||
|
||||
El compilador de Angular AOT extrae **metadatos** para interpretar las partes de la aplicación que se supone que Angular maneja.
|
||||
Puedes especificar los metadatos explícitamente en **decoradores** como `@Component()` y `@Input()`, o implícitamente en las declaraciones del constructor de las clases decoradas.
|
||||
Los metadatos le dicen a Angular como construir instancias de clases e interactuar con ellas en tiempo de ejecución.
|
||||
The Angular AOT compiler extracts **metadata** to interpret the parts of the application that Angular is supposed to manage.
|
||||
You can specify the metadata explicitly in **decorators** such as `@Component()` and `@Input()`, or implicitly in the constructor declarations of the decorated classes.
|
||||
The metadata tells Angular how to construct instances of your application classes and interact with them at runtime.
|
||||
|
||||
En el siguiente ejemplo, los metadatos de `@Component()` y el constructor le dicen a Angular como crear y mostrar una instancia de `TypicalComponent`.
|
||||
In the following example, the `@Component()` metadata object and the class constructor tell Angular how to create and display an instance of `TypicalComponent`.
|
||||
|
||||
```typescript
|
||||
@Component({
|
||||
selector: 'app-typical',
|
||||
template: '<div>A typical component for {{data.name}}</div>'
|
||||
)}
|
||||
})
|
||||
export class TypicalComponent {
|
||||
@Input() data: TypicalData;
|
||||
constructor(private someService: SomeService) { ... }
|
||||
}
|
||||
```
|
||||
|
||||
El compilador de Angular extrae los metadatos _una_ vez y genera una _fabrica_ para `TypicalComponent`.
|
||||
Cuando este necesita crear una instancia de `TypicalComponent`, Angular llama a la fabrica, el cuál produce un nuevo elemento visual, vinculado a una nueva instancia la clase del componente con su dependencia inyectada.
|
||||
The Angular compiler extracts the metadata _once_ and generates a _factory_ for `TypicalComponent`.
|
||||
When it needs to create a `TypicalComponent` instance, Angular calls the factory, which produces a new visual element, bound to a new instance of the component class with its injected dependency.
|
||||
|
||||
### Fases de compilación
|
||||
### Compilation phases
|
||||
|
||||
Existen tres fases de compilación en AOT.
|
||||
There are three phases of AOT compilation.
|
||||
* Phase 1 is *code analysis*.
|
||||
In this phase, the TypeScript compiler and *AOT collector* create a representation of the source. The collector does not attempt to interpret the metadata it collects. It represents the metadata as best it can and records errors when it detects a metadata syntax violation.
|
||||
|
||||
* Fase 1: *análisis de código*
|
||||
En esta fase, el compilador de TypeScript y el *recolector AOT* crea una representación de la fuente. El recolector no intenta interpretar los metadatos recopilados. Estos representan los metadatos lo mejor que pueden y registra errores cuando este detecta un violación de sintaxis en los metadatos.
|
||||
* Phase 2 is *code generation*.
|
||||
In this phase, the compiler's `StaticReflector` interprets the metadata collected in phase 1, performs additional validation of the metadata, and throws an error if it detects a metadata restriction violation.
|
||||
|
||||
* Fase 2: *generación de código*
|
||||
En esta fase, el `StaticReflector` del compilador interpreta los metadatos recolectados en la fase 1, realiza validaciones adicionales de los metadatos y lanza un error si este detecta una violación de la restricción de metadatos.
|
||||
|
||||
* Fase 3: *verificación de tipos en plantillas*
|
||||
Esta fase es opcional, el *compilador de plantillas* de Angular usa el compilador de Typescript para validar las expresiones de enlaces de datos en las plantillas. Puedes habilitar esta fase explícitamente configurando la opción `fullTemplateTypeCheck`; revisa [Opciones del Compilador Angular](guide/angular-compiler-options).
|
||||
* Phase 3 is *template type checking*.
|
||||
In this optional phase, the Angular *template compiler* uses the TypeScript compiler to validate the binding expressions in templates. You can enable this phase explicitly by setting the `fullTemplateTypeCheck` configuration option; see [Angular compiler options](guide/angular-compiler-options).
|
||||
|
||||
|
||||
### Restricciones de los metadatos
|
||||
### Metadata restrictions
|
||||
|
||||
Escribe metadatos en un _subconjunto_ de TypeScript que debe cumplir las siguientes restricciones generales:
|
||||
You write metadata in a _subset_ of TypeScript that must conform to the following general constraints:
|
||||
|
||||
* Limita la [sintaxis de expresiones](#expression-syntax) al subconjunto soportado de JavaScript.
|
||||
* Solo haz referencia a los símbolos exportados después del [plegado de código](#code-folding).
|
||||
* Solo llame [funciones compátibles](#supported-functions) por el compilador.
|
||||
* Miembros de clase decorados y con enlaces de datos deben ser públicos.
|
||||
* Limit [expression syntax](#expression-syntax) to the supported subset of JavaScript.
|
||||
* Only reference exported symbols after [code folding](#code-folding).
|
||||
* Only call [functions supported](#supported-functions) by the compiler.
|
||||
* Decorated and data-bound class members must be public.
|
||||
|
||||
Para guías e instrucciones adicionales al preparar una aplicación para compilación anticipada (AOT), revise [Angular: Writing AOT-friendly applications](https://medium.com/sparkles-blog/angular-writing-aot-friendly-applications-7b64c8afbe3f).
|
||||
For additional guidelines and instructions on preparing an application for AOT compilation, see [Angular: Writing AOT-friendly applications](https://medium.com/sparkles-blog/angular-writing-aot-friendly-applications-7b64c8afbe3f).
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Los errores en compilación anticipada (AOT) comúnmente ocurren debido a que los metadatos no se ajustan a los requisitos del compilador (como se describen con más detalle a continuación).
|
||||
Para ayudar a entender y resolver estos problemas, revisa [Errores de metadatos en AOT](guide/aot-metadata-errors).
|
||||
Errors in AOT compilation commonly occur because of metadata that does not conform to the compiler's requirements (as described more fully below).
|
||||
For help in understanding and resolving these problems, see [AOT Metadata Errors](guide/aot-metadata-errors).
|
||||
|
||||
</div>
|
||||
|
||||
### Configurando la compilación anticipada (AOT).
|
||||
### Configuring AOT compilation
|
||||
|
||||
Puedes proporcionar opciones en el [archivo de configuración de TypeScript](guide/typescript-configuration) que controlan el proceso de compilación. Revisa [las opciones de compilación de Angular](guide/angular-compiler-options) para una lista completa de opciones disponibles.
|
||||
You can provide options in the [TypeScript configuration file](guide/typescript-configuration) that controls the compilation process. See [Angular compiler options](guide/angular-compiler-options) for a complete list of available options.
|
||||
|
||||
## Fase 1: Análisis de código.
|
||||
## Phase 1: Code analysis
|
||||
|
||||
El compilador de TypeScript realiza parte del trabajo analítico en la primer fase. Este emite los _archivos de definición de tipos_ `.d.ts` con el tipo de información que el compilador AOT necesita para generar el código de la aplicación.
|
||||
Al mismo tiempo, el **recolector** AOT analiza los metadatos registrados en los decoradores de Angular y genera información de metadatos en archivos **`.metadata.json`**, uno por archivo `.d.ts`.
|
||||
The TypeScript compiler does some of the analytic work of the first phase. It emits the `.d.ts` _type definition files_ with type information that the AOT compiler needs to generate application code.
|
||||
At the same time, the AOT **collector** analyzes the metadata recorded in the Angular decorators and outputs metadata information in **`.metadata.json`** files, one per `.d.ts` file.
|
||||
|
||||
Puedes pensar en `.metadata.json` como un diagrama de la estructura general de los metadatos de un decorador, representados como un [árbol de sintaxis abstracta (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree).
|
||||
You can think of `.metadata.json` as a diagram of the overall structure of a decorator's metadata, represented as an [abstract syntax tree (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree).
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
El [schema.ts](https://github.com/angular/angular/blob/master/packages/compiler-cli/src/metadata/schema.ts) de Angular describe el formato JSON como una colección de interfaces de TypeScript.
|
||||
Angular's [schema.ts](https://github.com/angular/angular/blob/master/packages/compiler-cli/src/metadata/schema.ts)
|
||||
describes the JSON format as a collection of TypeScript interfaces.
|
||||
|
||||
</div>
|
||||
|
||||
{@a expression-syntax}
|
||||
### Limitaciones del sintaxis de expresión.
|
||||
### Expression syntax limitations
|
||||
|
||||
El recolector de AOT solo entiende un subconjunto de JavaScript.
|
||||
Defina objetos de metadatos con la siguiente sintaxis limitada:
|
||||
The AOT collector only understands a subset of JavaScript.
|
||||
Define metadata objects with the following limited syntax:
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
@ -130,84 +133,85 @@ Defina objetos de metadatos con la siguiente sintaxis limitada:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Sintaxis</th>
|
||||
<th>Ejemplo</th>
|
||||
<th>Syntax</th>
|
||||
<th>Example</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Objeto literal </td>
|
||||
<td>Literal object </td>
|
||||
<td><code>{cherry: true, apple: true, mincemeat: false}</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Colección literal </td>
|
||||
<td>Literal array </td>
|
||||
<td><code>['cherries', 'flour', 'sugar']</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Operador spread en colección literal</td>
|
||||
<td>Spread in literal array</td>
|
||||
<td><code>['apples', 'flour', ...the_rest]</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Llamadas</td>
|
||||
<td>Calls</td>
|
||||
<td><code>bake(ingredients)</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Nuevo</td>
|
||||
<td>New</td>
|
||||
<td><code>new Oven()</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Acceso a propiedades</td>
|
||||
<td>Property access</td>
|
||||
<td><code>pie.slice</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Indices de colección</td>
|
||||
<td>Array index</td>
|
||||
<td><code>ingredients[0]</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Referencia de identidad</td>
|
||||
<td>Identity reference</td>
|
||||
<td><code>Component</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Una plantilla de cadena</td>
|
||||
<td>A template string</td>
|
||||
<td><code>`pie is ${multiplier} times better than cake`</code></td>
|
||||
<tr>
|
||||
<td>Cadena literal</td>
|
||||
<td>Literal string</td>
|
||||
<td><code>pi</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Numero literal</td>
|
||||
<td>Literal number</td>
|
||||
<td><code>3.14153265</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Booleano literal</td>
|
||||
<td>Literal boolean</td>
|
||||
<td><code>true</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Nulo literal</td>
|
||||
<td>Literal null</td>
|
||||
<td><code>null</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Soporte a operador prefijo</td>
|
||||
<td>Supported prefix operator </td>
|
||||
<td><code>!cake</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Soporte a operaciones binarias</td>
|
||||
<td>Supported binary operator </td>
|
||||
<td><code>a+b</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Operador condicional</td>
|
||||
<td>Conditional operator</td>
|
||||
<td><code>a ? b : c</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Paréntesis</td>
|
||||
<td>Parentheses</td>
|
||||
<td><code>(a+b)</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Si una expresión usa sintaxis no compatible, el recolector escribe un error de nodo en el archivo `.metadata.json`.
|
||||
El compilador luego reporta el error si necesita esa pieza de metadatos para generar el código de la aplicación.
|
||||
|
||||
If an expression uses unsupported syntax, the collector writes an error node to the `.metadata.json` file.
|
||||
The compiler later reports the error if it needs that piece of metadata to generate the application code.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Si quieres que `ngc` reporte errores de sintaxis inmediatamente en lugar de producir un archivo `.metadata.json` con errores, configurá la opción `strictMetadataEmit` en el archivo de configuración de TypeScript.
|
||||
If you want `ngc` to report syntax errors immediately rather than produce a `.metadata.json` file with errors, set the `strictMetadataEmit` option in the TypeScript configuration file.
|
||||
|
||||
```
|
||||
"angularCompilerOptions": {
|
||||
@ -216,17 +220,18 @@ El compilador luego reporta el error si necesita esa pieza de metadatos para gen
|
||||
}
|
||||
```
|
||||
|
||||
Las librerías de Angular tienen esta opción para asegurar que todo los archivos `.metadata.json` están limpios y es una buena practica hacer lo mismo cuando construimos nuestras propias librerías.
|
||||
Angular libraries have this option to ensure that all Angular `.metadata.json` files are clean and it is a best practice to do the same when building your own libraries.
|
||||
|
||||
</div>
|
||||
|
||||
{@a function-expression}
|
||||
{@a arrow-functions}
|
||||
### Sin funciones flecha
|
||||
### No arrow functions
|
||||
|
||||
El compilador AOT no soporta [expresiones de función](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function) y [funciones flecha](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function), tampoco las funciones llamadas _lambda_.
|
||||
The AOT compiler does not support [function expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function)
|
||||
and [arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions), also called _lambda_ functions.
|
||||
|
||||
Considere el siguiente decorador del componente:
|
||||
Consider the following component decorator:
|
||||
|
||||
```typescript
|
||||
@Component({
|
||||
@ -235,11 +240,11 @@ Considere el siguiente decorador del componente:
|
||||
})
|
||||
```
|
||||
|
||||
El recolector de AOT no soporta la función tipo flecha, `() => new Server()`, en una expression de los metadatos.
|
||||
Esto genera un error de nodo en lugar de la función.
|
||||
Cuando el compilador posteriormente interpreta este nodo, este reporta un error que invita a convertir la función flecha en una _función exportada_.
|
||||
The AOT collector does not support the arrow function, `() => new Server()`, in a metadata expression.
|
||||
It generates an error node in place of the function.
|
||||
When the compiler later interprets this node, it reports an error that invites you to turn the arrow function into an _exported function_.
|
||||
|
||||
Puedes arreglar este error convirtiendo a esto:
|
||||
You can fix the error by converting to this:
|
||||
|
||||
```typescript
|
||||
export function serverFactory() {
|
||||
@ -252,23 +257,23 @@ export function serverFactory() {
|
||||
})
|
||||
```
|
||||
|
||||
En la version 5 y posterior, el compilador realiza automáticamente esta re escritura mientras emite el archivo `.js`.
|
||||
In version 5 and later, the compiler automatically performs this rewriting while emitting the `.js` file.
|
||||
|
||||
{@a exported-symbols}
|
||||
{@a code-folding}
|
||||
### Plegado de código (code folding)
|
||||
### Code folding
|
||||
|
||||
El compilador puede solo resolver referencias a símbolos **_exportados_**.
|
||||
El recolector sin embargo, puede evaluar una expresión durante la recolección y registrar el resultado en el `.metadata.json`, en vez de la expresión original.
|
||||
Esto permite hacer un uso limitado de símbolos no exportados dentro de expresiones.
|
||||
The compiler can only resolve references to **_exported_** symbols.
|
||||
The collector, however, can evaluate an expression during collection and record the result in the `.metadata.json`, rather than the original expression.
|
||||
This allows you to make limited use of non-exported symbols within expressions.
|
||||
|
||||
Por ejemplo, el recolector puede evaluar la expresión `1 + 2 + 3 + 4` y remplazarlo con el resultado, `10`.
|
||||
El proceso es llamado _plegado_. Una expresión que puede se reducida de esta manera es _plegable_.
|
||||
For example, the collector can evaluate the expression `1 + 2 + 3 + 4` and replace it with the result, `10`.
|
||||
This process is called _folding_. An expression that can be reduced in this manner is _foldable_.
|
||||
|
||||
{@a var-declaration}
|
||||
El recolector puede evaluar referencias hacia el modulo local, declaraciones `const` e inicializadas en `var` y `let` efectivamente son removidas del archivo `.metadata.json`.
|
||||
The collector can evaluate references to module-local `const` declarations and initialized `var` and `let` declarations, effectively removing them from the `.metadata.json` file.
|
||||
|
||||
Considere la siguiente definición del componente:
|
||||
Consider the following component definition:
|
||||
|
||||
```typescript
|
||||
const template = '<div>{{hero.name}}</div>';
|
||||
@ -282,9 +287,9 @@ export class HeroComponent {
|
||||
}
|
||||
```
|
||||
|
||||
El compilador no podría referirse hacia la constante `template` por que esta no ha sido exportada.
|
||||
El recolector sim embargo, puede encontrar la constante `template` dentro de la definición de metadatos insertando su contenido.
|
||||
El efecto es el mismo como si hubieras escrito:
|
||||
The compiler could not refer to the `template` constant because it isn't exported.
|
||||
The collector, however, can fold the `template` constant into the metadata definition by in-lining its contents.
|
||||
The effect is the same as if you had written:
|
||||
|
||||
```typescript
|
||||
@Component({
|
||||
@ -296,9 +301,9 @@ export class HeroComponent {
|
||||
}
|
||||
```
|
||||
|
||||
No hay una referencia a `template` y por lo tanto nada que moleste al compilador cuando posteriormente interprete las salidas del recolector en el archivo `.metadata.json`.
|
||||
There is no longer a reference to `template` and, therefore, nothing to trouble the compiler when it later interprets the _collector's_ output in `.metadata.json`.
|
||||
|
||||
Puedes tomar este ejemplo un paso más allá para incluir la constante `template` en otra expresión:
|
||||
You can take this example a step further by including the `template` constant in another expression:
|
||||
|
||||
```typescript
|
||||
const template = '<div>{{hero.name}}</div>';
|
||||
@ -312,15 +317,15 @@ export class HeroComponent {
|
||||
}
|
||||
```
|
||||
|
||||
El recolector reduce esta expresión a su equivalente cadena _plegada_:
|
||||
The collector reduces this expression to its equivalent _folded_ string:
|
||||
|
||||
```
|
||||
'<div>{{hero.name}}</div><div>{{hero.title}}</div>'
|
||||
```
|
||||
|
||||
#### Sintaxis plegable
|
||||
#### Foldable syntax
|
||||
|
||||
La siguiente tabla describe cuales expresiones el recolector puede y no puede encontrar:
|
||||
The following table describes which expressions the collector can and cannot fold:
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
@ -328,101 +333,101 @@ La siguiente tabla describe cuales expresiones el recolector puede y no puede en
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Sintaxis</th>
|
||||
<th>Plegable</th>
|
||||
<th>Syntax</th>
|
||||
<th>Foldable</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Objeto literal </td>
|
||||
<td>si</td>
|
||||
<td>Literal object </td>
|
||||
<td>yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Colección literal </td>
|
||||
<td>si</td>
|
||||
<td>Literal array </td>
|
||||
<td>yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Operador spread en colección literal</td>
|
||||
<td>Spread in literal array</td>
|
||||
<td>no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Llamadas</td>
|
||||
<td>Calls</td>
|
||||
<td>no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Nuevo</td>
|
||||
<td>New</td>
|
||||
<td>no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Acceso a propiedades<</td>
|
||||
<td>si, si el objetivo es plegable</td>
|
||||
<td>Property access</td>
|
||||
<td>yes, if target is foldable</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Indices de colección</td>
|
||||
<td>si, si el objetivo y el indice es plegable</td>
|
||||
<td>Array index</td>
|
||||
<td> yes, if target and index are foldable</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Referencia de identidad</td>
|
||||
<td>si, si es una referencia a una local</td>
|
||||
<td>Identity reference</td>
|
||||
<td>yes, if it is a reference to a local</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Una plantilla sin sustituciones</td>
|
||||
<td>si</td>
|
||||
<td>A template with no substitutions</td>
|
||||
<td>yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Una plantilla con sustituciones</td>
|
||||
<td>si, si las sustituciones son plegables</td>
|
||||
<td>A template with substitutions</td>
|
||||
<td>yes, if the substitutions are foldable</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Cadena literal</td>
|
||||
<td>si</td>
|
||||
<td>Literal string</td>
|
||||
<td>yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Numero literal</td>
|
||||
<td>si</td>
|
||||
<td>Literal number</td>
|
||||
<td>yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Booleano literal</td>
|
||||
<td>si</td>
|
||||
<td>Literal boolean</td>
|
||||
<td>yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Nulo literal</td>
|
||||
<td>si</td>
|
||||
<td>Literal null</td>
|
||||
<td>yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Soporte a operador prefijo </td>
|
||||
<td>si, si el operador es plegable</td>
|
||||
<td>Supported prefix operator </td>
|
||||
<td>yes, if operand is foldable</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Soporte a operador binario </td>
|
||||
<td>si, si ambos tanto el izquierda y derecha con plegables</td>
|
||||
<td>Supported binary operator </td>
|
||||
<td>yes, if both left and right are foldable</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Operador condicional</td>
|
||||
<td>si, si la condición es plegable </td>
|
||||
<td>Conditional operator</td>
|
||||
<td>yes, if condition is foldable </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Paréntesis</td>
|
||||
<td>si, si la expresión es plegable</td>
|
||||
<td>Parentheses</td>
|
||||
<td>yes, if the expression is foldable</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
Si es una expresión no plegable, el recolector lo escribe a `.metadata.json` como un [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) para que el compilador lo resuelva.
|
||||
If an expression is not foldable, the collector writes it to `.metadata.json` as an [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) for the compiler to resolve.
|
||||
|
||||
|
||||
## Fase 2: generación de código
|
||||
## Phase 2: code generation
|
||||
|
||||
El recolector no hace ningún intento para entender los metadatos que se recolectarón y las envía a `.metadata.json`.
|
||||
Esto representa los metadatos lo mejor que puede y registra errores cuando detecta una violación de sintaxis en los metadatos.
|
||||
Es el trabajo del compilador interpretar el `.metadata.json` en la fase de generación de código.
|
||||
The collector makes no attempt to understand the metadata that it collects and outputs to `.metadata.json`.
|
||||
It represents the metadata as best it can and records errors when it detects a metadata syntax violation.
|
||||
It's the compiler's job to interpret the `.metadata.json` in the code generation phase.
|
||||
|
||||
El compilador entiende toda las formas de sintaxis que el recolector soporta pero puede rechazar metadatos _sintácticamente_ correctos si la _semántica_ viola reglas del compilador.
|
||||
The compiler understands all syntax forms that the collector supports, but it may reject _syntactically_ correct metadata if the _semantics_ violate compiler rules.
|
||||
|
||||
### Símbolos públicos
|
||||
### Public symbols
|
||||
|
||||
El compilador puede solo referirse a _símbolos exportados_.
|
||||
The compiler can only reference _exported symbols_.
|
||||
|
||||
* Los atributos de la clase que tienen un decorador deben ser públicos. No puedes hacer que una propiedad `@Input()` sea privada o protegida.
|
||||
* Las propiedades enlazadas a datos también deben ser publicas.
|
||||
* Decorated component class members must be public. You cannot make an `@Input()` property private or protected.
|
||||
* Data bound properties must also be public.
|
||||
|
||||
```typescript
|
||||
// BAD CODE - title is private
|
||||
@ -437,32 +442,32 @@ export class AppComponent {
|
||||
|
||||
{@a supported-functions}
|
||||
|
||||
### Clases y funciones compatibles
|
||||
### Supported classes and functions
|
||||
|
||||
El recolector puede representar una función o la creación de un objeto con `new` mientras la sintaxis sea valida.
|
||||
El compilador, sin embargo, puede posteriormente rechazar a generar una llamada hacia una función _particular_ o la creación de un objeto _particular_.
|
||||
The collector can represent a function call or object creation with `new` as long as the syntax is valid.
|
||||
The compiler, however, can later refuse to generate a call to a _particular_ function or creation of a _particular_ object.
|
||||
|
||||
El compilador puede solo crea instancias de ciertas clases, compatibles solo con decoradores centrales y solo compatibles con llamadas a macros (funciones o métodos estáticos) que retornan expresiones.
|
||||
The compiler can only create instances of certain classes, supports only core decorators, and only supports calls to macros (functions or static methods) that return expressions.
|
||||
* New instances
|
||||
|
||||
* Nuevas instancias
|
||||
El compilador solo permite metadatos que crean instancias de las clases `InjectionToken` de `@angular/core`.
|
||||
The compiler only allows metadata that create instances of the class `InjectionToken` from `@angular/core`.
|
||||
|
||||
* Decoradores soportados
|
||||
El compilador solo soporta metadatos del [Modulo de decoradores de Angular en `@angular/core`](api/core#decorators).
|
||||
* Supported decorators
|
||||
|
||||
* Llamadas a funciones
|
||||
The compiler only supports metadata for the [Angular decorators in the `@angular/core` module](api/core#decorators).
|
||||
|
||||
Las funciones de fabrica deben ser exportadas.
|
||||
El compilador AOT no soporta expresiones lambda ("funciones flecha") para las funciones de fabrica.
|
||||
* Function calls
|
||||
|
||||
Factory functions must be exported, named functions.
|
||||
The AOT compiler does not support lambda expressions ("arrow functions") for factory functions.
|
||||
|
||||
{@a function-calls}
|
||||
### Functions and static method calls
|
||||
|
||||
### Llamadas a funciones y métodos estáticos.
|
||||
The collector accepts any function or static method that contains a single `return` statement.
|
||||
The compiler, however, only supports macros in the form of functions or static methods that return an *expression*.
|
||||
|
||||
El recolector acepta cualquier función o método estático que contenga una sola declaración de `return`.
|
||||
El compilador sin embargo, solo soporta macros (funciones o métodos estáticos) en la forma de funciones y métodos estáticos que retornan una *expression*.
|
||||
|
||||
Por ejemplo, considere la siguiente función:
|
||||
For example, consider the following function:
|
||||
|
||||
```typescript
|
||||
export function wrapInArray<T>(value: T): T[] {
|
||||
@ -470,9 +475,9 @@ export function wrapInArray<T>(value: T): T[] {
|
||||
}
|
||||
```
|
||||
|
||||
Puedes llamar a `wrapInArray` en una definición de metadatos porque este retorna el valor de una expresiones qué se ajusta al subconjunto de Javascript restringido del compilador.
|
||||
You can call the `wrapInArray` in a metadata definition because it returns the value of an expression that conforms to the compiler's restrictive JavaScript subset.
|
||||
|
||||
Puede usar `wrapInArray()` así:
|
||||
You might use `wrapInArray()` like this:
|
||||
|
||||
```typescript
|
||||
@NgModule({
|
||||
@ -481,7 +486,7 @@ Puede usar `wrapInArray()` así:
|
||||
export class TypicalModule {}
|
||||
```
|
||||
|
||||
El compilador trata este uso como si hubieras escrito:
|
||||
The compiler treats this usage as if you had written:
|
||||
|
||||
```typescript
|
||||
@NgModule({
|
||||
@ -489,19 +494,19 @@ El compilador trata este uso como si hubieras escrito:
|
||||
})
|
||||
export class TypicalModule {}
|
||||
```
|
||||
|
||||
El [`RouterModule`](api/router/RouterModule) de Angular exporta dos métodos estáticos, `forRoot` y `forChild` para ayudar a declarar rutas raíz e hijas.
|
||||
Revisa el [código fuente](https://github.com/angular/angular/blob/master/packages/router/src/router_module.ts#L139 "RouterModule.forRoot source code") para estos métodos para ver como los macros puede simplificar la configuración de complejos [NgModules](guide/ngmodules).
|
||||
The Angular [`RouterModule`](api/router/RouterModule) exports two macro static methods, `forRoot` and `forChild`, to help declare root and child routes.
|
||||
Review the [source code](https://github.com/angular/angular/blob/master/packages/router/src/router_module.ts#L139 "RouterModule.forRoot source code")
|
||||
for these methods to see how macros can simplify configuration of complex [NgModules](guide/ngmodules).
|
||||
|
||||
{@a metadata-rewriting}
|
||||
|
||||
### Re escribiendo metadatos
|
||||
### Metadata rewriting
|
||||
|
||||
El compilador trata a los objetos literales que contengan los campos `useClass`, `useValue`, `useFactory` y `data` específicamente, convirtiendo la expresión inicializando uno de estos campos en una variable exportada que reemplaza la expresión
|
||||
The compiler treats object literals containing the fields `useClass`, `useValue`, `useFactory`, and `data` specially, converting the expression initializing one of these fields into an exported variable that replaces the expression.
|
||||
This process of rewriting these expressions removes all the restrictions on what can be in them because
|
||||
the compiler doesn't need to know the expression's value—it just needs to be able to generate a reference to the value.
|
||||
|
||||
Este proceso de rescribir estas expresiones remueve todo las restricciones que pueden estar en el, porque el compilador no necesita conocer el valor de las expresiones solo necesita poder generar una referencia al valor.
|
||||
|
||||
Puedes escribir algo como:
|
||||
You might write something like:
|
||||
|
||||
```typescript
|
||||
class TypicalServer {
|
||||
@ -514,8 +519,8 @@ class TypicalServer {
|
||||
export class TypicalModule {}
|
||||
```
|
||||
|
||||
Sin la reescritura, esto sería invalido por que las lambdas no son soportadas y `TypicalServer` no esta exportada.
|
||||
Para permitirlo, el compilador automáticamente re escribe esto a algo como:
|
||||
Without rewriting, this would be invalid because lambdas are not supported and `TypicalServer` is not exported.
|
||||
To allow this, the compiler automatically rewrites this to something like:
|
||||
|
||||
```typescript
|
||||
class TypicalServer {
|
||||
@ -530,38 +535,40 @@ export const ɵ0 = () => new TypicalServer();
|
||||
export class TypicalModule {}
|
||||
```
|
||||
|
||||
Esto permite que el compilador genere una referencia hacia `ɵ0` en la fabrica sin tener que conocer cual es el valor de `ɵ0`.
|
||||
This allows the compiler to generate a reference to `ɵ0` in the factory without having to know what the value of `ɵ0` contains.
|
||||
|
||||
El compilador hace la reescritura durante la emisión de el archivo `.js`.
|
||||
Sin embargo, no reescribe el archivo `.d.ts`, entonces TypeScript no lo reconoce como una exportación y esto no interfiere con la API exportada de los módulos ES.
|
||||
The compiler does the rewriting during the emit of the `.js` file.
|
||||
It does not, however, rewrite the `.d.ts` file, so TypeScript doesn't recognize it as being an export. and it does not interfere with the ES module's exported API.
|
||||
|
||||
|
||||
{@a binding-expression-validation}
|
||||
|
||||
## Fase 3: Verificación de tipos en las plantillas
|
||||
## Phase 3: Template type checking
|
||||
|
||||
Una de las características más útiles del compilador de Angular es la habilidad de comprobar el tipado de las expresiones dentro de las plantillas y capturar cualquier error antes de que ellos causen fallas en tiempo de ejecución.
|
||||
One of the Angular compiler's most helpful features is the ability to type-check expressions within templates, and catch any errors before they cause crashes at runtime.
|
||||
In the template type-checking phase, the Angular template compiler uses the TypeScript compiler to validate the binding expressions in templates.
|
||||
|
||||
En la fase de verificación de tipos en las plantillas, el compilador de plantillas de Angular usa a el compilador de TypeScript para validar las expresiones con enlazadas a datos en las plantillas.
|
||||
|
||||
Habilite esta fase explícitamente agregando la opción del compilador `"fullTemplateTypeCheck"` en las `"angularCompilerOptions"` del archivo de configuración del proyecto TypeScript (mira [Opciones del compilador de Angular](guide/angular-compiler-options)).
|
||||
Enable this phase explicitly by adding the compiler option `"fullTemplateTypeCheck"` in the `"angularCompilerOptions"` of the project's TypeScript configuration file
|
||||
(see [Angular Compiler Options](guide/angular-compiler-options)).
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
En [Angular Ivy](guide/ivy), la verificación de tipos para las plantillas a sido completamente reescrita para ser más capaz así como más estricto, esto significa poder capturar una variedad de nuevos errores que antes el verificador de tipos no podia detectar.
|
||||
In [Angular Ivy](guide/ivy), the template type checker has been completely rewritten to be more capable as well as stricter, meaning it can catch a variety of new errors that the previous type checker would not detect.
|
||||
|
||||
Como resultado, las plantillas que previamente se compilarón bajo `View Engine` pueden fallar con el verificador de tipos bajo `Ivy`. Esto puede pasar por que el verificador de Ivy captura errores genuinos o porque el código de la aplicación no esta tipado correctamente o porque la aplicación usa librerías en las cuales el tipado es incorrecto o no es lo suficientemente especifico.
|
||||
As a result, templates that previously compiled under View Engine can fail type checking under Ivy. This can happen because Ivy's stricter checking catches genuine errors, or because application code is not typed correctly, or because the application uses libraries in which typings are inaccurate or not specific enough.
|
||||
|
||||
Este verificador de tipos estricto no esta habilitado por defecto el la version 9 pero puedes habilitarlo configurando la opción `strictTemplates`.
|
||||
Nosotros esperamos hacer que el verificador de tipos estricto este habilitado por defecto en el futuro.
|
||||
This stricter type checking is not enabled by default in version 9, but can be enabled by setting the `strictTemplates` configuration option.
|
||||
We do expect to make strict type checking the default in the future.
|
||||
|
||||
Para más información acerca de las opciones del verificador de tipos y más acerca de mejoras hacia la verificación de tipos en plantillas en la version 9 en adelante, mira [Verificando tipos en plantillas](guide/template-typecheck).
|
||||
For more information about type-checking options, and about improvements to template type checking in version 9 and above, see [Template type checking](guide/template-typecheck).
|
||||
|
||||
</div>
|
||||
|
||||
La validación de templates produce mensajes de error cuando un error de tipo es detectado en una plantilla con una expresión con enlace de datos, similar a como los errores de tipado son reportados por el compilador de TypeScript contra el código en un archivo `.ts`.
|
||||
Template validation produces error messages when a type error is detected in a template binding
|
||||
expression, similar to how type errors are reported by the TypeScript compiler against code in a `.ts`
|
||||
file.
|
||||
|
||||
Por ejemplo, considere el siguiente componente:
|
||||
For example, consider the following component:
|
||||
|
||||
```typescript
|
||||
@Component({
|
||||
@ -573,29 +580,32 @@ Por ejemplo, considere el siguiente componente:
|
||||
}
|
||||
```
|
||||
|
||||
Esto produce el siguiente error:
|
||||
This produces the following error:
|
||||
|
||||
```
|
||||
my.component.ts.MyComponent.html(1,1): : Property 'addresss' does not exist on type 'Person'. Did you mean 'address'?
|
||||
```
|
||||
|
||||
El archivo reporta el mensaje de error, `my.component.ts.MyComponent.html`, es un archivo sintético generado por el compilador de plantillas que espera que tenga contenido de la clase `MyComponent`.
|
||||
El compilador nunca escribe un archivo en el disco.
|
||||
Los números de línea y columna son relativos a la plantilla de cadena en el anotación `@Component` de la clase, `MyComponent` en este caso.
|
||||
Si un componente usa `templateUrl` en vez de `template`, los errores son reportados en el archivo HTML referenciado por el `templateUrl` en vez de un archivo sintético.
|
||||
The file name reported in the error message, `my.component.ts.MyComponent.html`, is a synthetic file
|
||||
generated by the template compiler that holds contents of the `MyComponent` class template.
|
||||
The compiler never writes this file to disk.
|
||||
The line and column numbers are relative to the template string in the `@Component` annotation of the class, `MyComponent` in this case.
|
||||
If a component uses `templateUrl` instead of `template`, the errors are reported in the HTML file referenced by the `templateUrl` instead of a synthetic file.
|
||||
|
||||
La ubicación del error esta en el inicio del nodo de texto que contiene la expresión interpolada con el error.
|
||||
Si el error esta en un atributo con enlace de datos como `[value]="person.address.street"`, la ubicación del error es la ubicación del atributo que contiene el error.
|
||||
|
||||
La validación usa el verificador de tipos de TypeScript y las opciones suministradas hacia el compilador de TypeScript para controlar qué tan detallada es la validación de tipos.
|
||||
Por ejemplo, si el `strictTypeChecks` es especificado, el error ```my.component.ts.MyComponent.html(1,1): : Object is possibly 'undefined'``` es reportado así como el mensaje de error anterior.
|
||||
The error location is the beginning of the text node that contains the interpolation expression with the error.
|
||||
If the error is in an attribute binding such as `[value]="person.address.street"`, the error
|
||||
location is the location of the attribute that contains the error.
|
||||
|
||||
The validation uses the TypeScript type checker and the options supplied to the TypeScript compiler to control how detailed the type validation is.
|
||||
For example, if the `strictTypeChecks` is specified, the error
|
||||
```my.component.ts.MyComponent.html(1,1): : Object is possibly 'undefined'```
|
||||
is reported as well as the above error message.
|
||||
|
||||
### Type narrowing
|
||||
|
||||
La expresión usada en un directiva `ngIf` es usada para estrechar uniones de tipo en el compilador de plantillas de Angular, de la misma manera que la expresión `if` lo hace en TypeScript.
|
||||
Por ejemplo, para evitar el error `Object is possibly 'undefined'` en la plantilla de arriba, modifícalo para que solo emita la interpolación si el valor de `person` esta inicializado como se muestra en seguida:
|
||||
|
||||
The expression used in an `ngIf` directive is used to narrow type unions in the Angular
|
||||
template compiler, the same way the `if` expression does in TypeScript.
|
||||
For example, to avoid `Object is possibly 'undefined'` error in the template above, modify it to only emit the interpolation if the value of `person` is initialized as shown below:
|
||||
|
||||
```typescript
|
||||
@Component({
|
||||
@ -607,17 +617,16 @@ Por ejemplo, para evitar el error `Object is possibly 'undefined'` en la plantil
|
||||
}
|
||||
```
|
||||
|
||||
Usando `*ngIf` permite que el compilador de TypeScript infiera que el atributo `person` usado en la expresión enlanzada nunca séra `undefined`.
|
||||
Using `*ngIf` allows the TypeScript compiler to infer that the `person` used in the binding expression will never be `undefined`.
|
||||
|
||||
Para más información acerca del estrechamiento de tipos de entrada, mira [Coerción del establecedor de entrada](guide/template-typecheck#input-setter-coercion) y [Mejorando el verificar de tipos para directivas personalizadas](guide/structural-directives#directive-type-checks).
|
||||
For more information about input type narrowing, see [Input setter coercion](guide/template-typecheck#input-setter-coercion) and [Improving template type checking for custom directives](guide/structural-directives#directive-type-checks).
|
||||
|
||||
### Operador de aserción de tipo nulo
|
||||
### Non-null type assertion operator
|
||||
|
||||
Use el [operador de aserción de tipo nulo](guide/template-expression-operators#non-null-assertion-operator) para reprimir el error `Object is possibly 'undefined'` cuando es inconveniente usar `*ngIf` o cuando alguna restricción en el componente asegura que la expresión siempre es no nula cuando la expresión con enlace de datos es interpolada.
|
||||
|
||||
En el siguiente ejemplo, las propiedades `person` y `address` son siempre configuradas juntas, implicando que `address` siempre es no nula si `person` es no nula.
|
||||
No existe una forma conveniente de describir esta restricción a TypeScript y a el compilador de plantillas pero el error es suprimido en el ejemplo por usar `address!.street`.
|
||||
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`.
|
||||
|
||||
```typescript
|
||||
@Component({
|
||||
@ -635,9 +644,9 @@ No existe una forma conveniente de describir esta restricción a TypeScript y a
|
||||
}
|
||||
```
|
||||
|
||||
El operador de aserción de tipo nulo debería usarse con moderación ya que la refactorización del componente podría romper esta restricción.
|
||||
The non-null assertion operator should be used sparingly as refactoring of the component might break this constraint.
|
||||
|
||||
En este ejemplo es recomendable incluir la verificación de `address` en el `*ngIf` como se muestra a continuación:
|
||||
In this example it is recommended to include the checking of `address` in the `*ngIf` as shown below:
|
||||
|
||||
```typescript
|
||||
@Component({
|
||||
|
@ -1,32 +1,32 @@
|
||||
# App shell
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
Obténga más información en [El modelo de aplicación Shell](https://developers.google.com/web/fundamentals/architecture/app-shell).
|
||||
Learn more in [The App Shell Model](https://developers.google.com/web/fundamentals/architecture/app-shell).
|
||||
|
||||
## Paso 1: Prepara la aplicación
|
||||
## Step 1: Prepare the application
|
||||
|
||||
Puedes hacer esto con el siguiente comando CLI:
|
||||
You can do this with the following CLI command:
|
||||
<code-example language="bash">
|
||||
ng new my-app --routing
|
||||
</code-example>
|
||||
|
||||
Para una aplicación existente, debes agregar manualmente el `RouterModule` y definir un` <router-outlet> `dentro de tu aplicación.
|
||||
For an existing application, you have to manually add the `RouterModule` and defining a `<router-outlet>` within your application.
|
||||
|
||||
## Paso 2: Crea el shell de la aplicación
|
||||
## Step 2: Create the app shell
|
||||
|
||||
Usa la CLI para crear automáticamente el shell de la aplicación.
|
||||
Use the CLI to automatically create the app shell.
|
||||
|
||||
<code-example language="bash">
|
||||
ng generate app-shell
|
||||
</code-example>
|
||||
|
||||
* `client-project` toma el nombre de tu aplicación cliente.
|
||||
* `client-project` takes the name of your client application.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
<code-example language="json">
|
||||
"server": {
|
||||
@ -53,18 +53,20 @@ Después de ejecutar este comando, notará que el archivo de configuración `ang
|
||||
}
|
||||
</code-example>
|
||||
|
||||
## Paso 3: Verifica que la aplicación está construida con el contenido del shell
|
||||
## Step 3: Verify the app is built with the shell content
|
||||
|
||||
Usa la CLI para construir el `app-shell` target.
|
||||
Use the CLI to build the `app-shell` target.
|
||||
|
||||
<code-example language="bash">
|
||||
ng run my-app:app-shell
|
||||
</code-example>
|
||||
|
||||
O usa la configuración de producción.
|
||||
Or to use the production configuration.
|
||||
|
||||
<code-example language="bash">
|
||||
ng run my-app:app-shell:production
|
||||
</code-example>
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
|
||||
|
@ -1,104 +0,0 @@
|
||||
# Introduction to modules
|
||||
|
||||
Angular apps are modular and Angular has its own modularity system called *NgModules*.
|
||||
NgModules are containers for a cohesive block of code dedicated to an application domain, a workflow, or a closely related set of capabilities. They can contain components, service providers, and other code files whose scope is defined by the containing NgModule. They can import functionality that is exported from other NgModules, and export selected functionality for use by other NgModules.
|
||||
|
||||
Every Angular app has at least one NgModule class, [the *root module*](guide/bootstrapping), which is conventionally named `AppModule` and resides in a file named `app.module.ts`. You launch your app by *bootstrapping* the root NgModule.
|
||||
|
||||
While a small application might have only one NgModule, most apps have many more *feature modules*. The *root* NgModule for an app is so named because it can include child NgModules in a hierarchy of any depth.
|
||||
|
||||
## NgModule metadata
|
||||
|
||||
An NgModule is defined by a class decorated with `@NgModule()`. The `@NgModule()` decorator is a function that takes a single metadata object, whose properties describe the module. The most important properties are as follows.
|
||||
|
||||
* `declarations`: The [components](guide/architecture-components), *directives*, and *pipes* that belong to this NgModule.
|
||||
|
||||
* `exports`: The subset of declarations that should be visible and usable in the *component templates* of other NgModules.
|
||||
|
||||
* `imports`: Other modules whose exported classes are needed by component templates declared in *this* NgModule.
|
||||
|
||||
* `providers`: Creators of [services](guide/architecture-services) that this NgModule contributes to the global collection of services; they become accessible in all parts of the app. (You can also specify providers at the component level, which is often preferred.)
|
||||
|
||||
* `bootstrap`: The main application view, called the *root component*, which hosts all other app views. Only the *root NgModule* should set the `bootstrap` property.
|
||||
|
||||
Here's a simple root NgModule definition.
|
||||
|
||||
<code-example path="architecture/src/app/mini-app.ts" region="module" header="src/app/app.module.ts"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
`AppComponent` is included in the `exports` list here for illustration; it isn't actually necessary in this example. A root NgModule has no reason to *export* anything because other modules don't need to *import* the root NgModule.
|
||||
|
||||
</div>
|
||||
|
||||
## NgModules and components
|
||||
|
||||
NgModules provide a *compilation context* for their components. A root NgModule always has a root component that is created during bootstrap, but any NgModule can include any number of additional components, which can be loaded through the router or created through the template. The components that belong to an NgModule share a compilation context.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/architecture/compilation-context.png" alt="Component compilation context" class="left">
|
||||
</div>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
A component and its template together define a *view*. A component can contain a *view hierarchy*, which allows you to define arbitrarily complex areas of the screen that can be created, modified, and destroyed as a unit. A view hierarchy can mix views defined in components that belong to different NgModules. This is often the case, especially for UI libraries.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/architecture/view-hierarchy.png" alt="View hierarchy" class="left">
|
||||
</div>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
When you create a component, it's associated directly with a single view, called the *host view*. The host view can be the root of a view hierarchy, which can contain *embedded views*, which are in turn the host views of other components. Those components can be in the same NgModule, or can be imported from other NgModules. Views in the tree can be nested to any depth.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
**Note:** The hierarchical structure of views is a key factor in the way Angular detects and responds to changes in the DOM and app data.
|
||||
|
||||
</div>
|
||||
|
||||
## NgModules and JavaScript modules
|
||||
|
||||
The NgModule system is different from and unrelated to the JavaScript (ES2015) module system for managing collections of JavaScript objects. These are *complementary* module systems that you can use together to write your apps.
|
||||
|
||||
In JavaScript each *file* is a module and all objects defined in the file belong to that module.
|
||||
The module declares some objects to be public by marking them with the `export` key word.
|
||||
Other JavaScript modules use *import statements* to access public objects from other modules.
|
||||
|
||||
<code-example path="architecture/src/app/app.module.ts" region="imports"></code-example>
|
||||
|
||||
<code-example path="architecture/src/app/app.module.ts" region="export"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
<a href="http://exploringjs.com/es6/ch_modules.html">Learn more about the JavaScript module system on the web.</a>
|
||||
</div>
|
||||
|
||||
## Angular libraries
|
||||
|
||||
<img src="generated/images/guide/architecture/library-module.png" alt="Component" class="left">
|
||||
|
||||
Angular loads as a collection of JavaScript modules. You can think of them as library modules. Each Angular library name begins with the `@angular` prefix. Install them with the node package manager `npm` and import parts of them with JavaScript `import` statements.
|
||||
|
||||
<br class="clear">
|
||||
|
||||
For example, import Angular's `Component` decorator from the `@angular/core` library like this.
|
||||
|
||||
<code-example path="architecture/src/app/app.component.ts" region="import"></code-example>
|
||||
|
||||
You also import NgModules from Angular *libraries* using JavaScript import statements.
|
||||
For example, the following code imports the `BrowserModule` NgModule from the `platform-browser` library.
|
||||
|
||||
<code-example path="architecture/src/app/mini-app.ts" region="import-browser-module"></code-example>
|
||||
|
||||
In the example of the simple root module above, the application module needs material from within
|
||||
`BrowserModule`. To access that material, add it to the `@NgModule` metadata `imports` like this.
|
||||
|
||||
<code-example path="architecture/src/app/mini-app.ts" region="ngmodule-imports"></code-example>
|
||||
|
||||
In this way you're using the Angular and JavaScript module systems *together*. Although it's easy to confuse the two systems, which share the common vocabulary of "imports" and "exports", you will become familiar with the different contexts in which they are used.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Learn more from the [NgModules](guide/ngmodules) guide.
|
||||
|
||||
</div>
|
@ -1,39 +1,39 @@
|
||||
# Introducción a módulos
|
||||
# Introduction to modules
|
||||
|
||||
Las aplicaciones Angular son modulares y Angular tiene su propio sistema de modularidad llamado *NgModules*.
|
||||
Los NgModules son contenedores para un bloque cohesivo de código dedicado a un dominio de aplicación, un flujo de trabajo o un conjunto de capacidades estrechamente relacionadas. Pueden contener componentes, proveedores de servicios y otros archivos de código cuyo alcance está definido por el NgModule que los contiene. Pueden importar la funcionalidad que se exporta desde otros NgModules y exportar la funcionalidad seleccionada para que la utilicen otros NgModules.
|
||||
Angular apps are modular and Angular has its own modularity system called *NgModules*.
|
||||
NgModules are containers for a cohesive block of code dedicated to an application domain, a workflow, or a closely related set of capabilities. They can contain components, service providers, and other code files whose scope is defined by the containing NgModule. They can import functionality that is exported from other NgModules, and export selected functionality for use by other NgModules.
|
||||
|
||||
Cada aplicación Angular tiene al menos una clase NgModule, [el *módulo raíz*](guide/bootstrapping), que se llama convencionalmente `AppModule` y reside en un archivo llamado `app.module.ts`. Inicia tu aplicación *cargando* el NgModule raíz.
|
||||
Every Angular app has at least one NgModule class, [the *root module*](guide/bootstrapping), which is conventionally named `AppModule` and resides in a file named `app.module.ts`. You launch your app by *bootstrapping* the root NgModule.
|
||||
|
||||
Si bien una aplicación pequeña puede tener sólo un NgModule, la mayoría de las aplicaciones tienen muchos más *módulos de funcionalidad*. El NgModule *raíz* para una aplicación se llama así porque puede incluir NgModules secundarios en una jerarquía de cualquier profundidad.
|
||||
While a small application might have only one NgModule, most apps have many more *feature modules*. The *root* NgModule for an app is so named because it can include child NgModules in a hierarchy of any depth.
|
||||
|
||||
## Metadatos de NgModule
|
||||
## NgModule metadata
|
||||
|
||||
Un NgModule está definido por una clase decorada con `@NgModule()`. El decorador `@NgModule()` es una función que toma un único objeto de metadatos, cuyas propiedades describen el módulo. Las propiedades más importantes son las siguientes.
|
||||
An NgModule is defined by a class decorated with `@NgModule()`. The `@NgModule()` decorator is a function that takes a single metadata object, whose properties describe the module. The most important properties are as follows.
|
||||
|
||||
* `declarations`: Los [componentes](guide/architecture-components), *directivas*, y *pipes* que pertenecen a este NgModule.
|
||||
* `declarations`: The [components](guide/architecture-components), *directives*, and *pipes* that belong to this NgModule.
|
||||
|
||||
* `exports`: El subconjunto de declaraciones que deberían ser visibles y utilizables en las *plantillas de componentes* de otros NgModules.
|
||||
* `exports`: The subset of declarations that should be visible and usable in the *component templates* of other NgModules.
|
||||
|
||||
* `imports`: Otros módulos cuyas clases exportadas son necesarias para las plantillas de componentes declaradas en *este* NgModule.
|
||||
* `imports`: Other modules whose exported classes are needed by component templates declared in *this* NgModule.
|
||||
|
||||
* `providers`: Creadores de [servicios](guide/architecture-services) que este NgModule aporta a la colección global de servicios; se vuelven accesibles en todas las partes de la aplicación. (También puedes especificar proveedores a nivel de componente, que a menudo es preferido).
|
||||
* `providers`: Creators of [services](guide/architecture-services) that this NgModule contributes to the global collection of services; they become accessible in all parts of the app. (You can also specify providers at the component level.)
|
||||
|
||||
* `bootstrap`: La vista principal de la aplicación, llamado el *componente raíz*, que aloja todas las demás vistas de la aplicación. Sólo el *NgModule raíz* debe establecer la propiedad `bootstrap`.
|
||||
* `bootstrap`: The main application view, called the *root component*, which hosts all other app views. Only the *root NgModule* should set the `bootstrap` property.
|
||||
|
||||
Aquí hay una definición simple del NgModule raíz.
|
||||
Here's a simple root NgModule definition.
|
||||
|
||||
<code-example path="architecture/src/app/mini-app.ts" region="module" header="src/app/app.module.ts"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Aquí se incluye `AppComponent` en la lista de `exports` como ilustración; en realidad no es necesario en este ejemplo. Un NgModule raíz no tiene ninguna razón para *exportar* nada porque otros módulos no necesitan *importar* el NgModule raíz.
|
||||
`AppComponent` is included in the `exports` list here for illustration; it isn't actually necessary in this example. A root NgModule has no reason to *export* anything because other modules don't need to *import* the root NgModule.
|
||||
|
||||
</div>
|
||||
|
||||
## NgModules y componentes
|
||||
## NgModules and components
|
||||
|
||||
NgModules proporciona un *contexto de compilación* para sus componentes. Un NgModule raíz siempre tiene un componente raíz que se crea durante el arranque, pero cualquier NgModule puede incluir cualquier cantidad de componentes adicionales, que se pueden cargar a través del enrutador o crear a través de la plantilla. Los componentes que pertenecen a un NgModule comparten un contexto de compilación.
|
||||
NgModules provide a *compilation context* for their components. A root NgModule always has a root component that is created during bootstrap, but any NgModule can include any number of additional components, which can be loaded through the router or created through the template. The components that belong to an NgModule share a compilation context.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/architecture/compilation-context.png" alt="Component compilation context" class="left">
|
||||
@ -41,7 +41,7 @@ NgModules proporciona un *contexto de compilación* para sus componentes. Un NgM
|
||||
|
||||
<br class="clear">
|
||||
|
||||
Juntos, un componente y su plantilla definen una *vista*. Un componente puede contener una *jerarquía de vista*, que te permiten definir áreas arbitrariamente complejas de la pantalla que se pueden crear, modificar y destruir como una unidad. Una jerarquía de vistas puede mezclar vistas definidas en componentes que pertenecen a diferentes NgModules. Este suele ser el caso, especialmente para las bibliotecas de interfaz de usuario.
|
||||
A component and its template together define a *view*. A component can contain a *view hierarchy*, which allows you to define arbitrarily complex areas of the screen that can be created, modified, and destroyed as a unit. A view hierarchy can mix views defined in components that belong to different NgModules. This is often the case, especially for UI libraries.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/architecture/view-hierarchy.png" alt="View hierarchy" class="left">
|
||||
@ -49,56 +49,56 @@ Juntos, un componente y su plantilla definen una *vista*. Un componente puede co
|
||||
|
||||
<br class="clear">
|
||||
|
||||
Cuando creas un componente, se asocia directamente con una sola vista, llamada *vista host*. La vista host puede ser la raíz de una jerarquía de vistas, que puede contener *vistas incrustadas*, que a su vez son las vistas de host de otros componentes. Esos componentes pueden estar en el mismo NgModule o pueden importarse desde otros NgModules. Las vistas en el árbol se pueden anidar a cualquier profundidad.
|
||||
When you create a component, it's associated directly with a single view, called the *host view*. The host view can be the root of a view hierarchy, which can contain *embedded views*, which are in turn the host views of other components. Those components can be in the same NgModule, or can be imported from other NgModules. Views in the tree can be nested to any depth.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
**Nota:** La estructura jerárquica de las vistas es un factor clave en la forma en que Angular detecta y responde a los cambios en el DOM y los datos de la aplicación.
|
||||
**Note:** The hierarchical structure of views is a key factor in the way Angular detects and responds to changes in the DOM and app data.
|
||||
|
||||
</div>
|
||||
|
||||
## NgModules y módulos JavaScript
|
||||
## NgModules and JavaScript modules
|
||||
|
||||
El sistema NgModule es diferente y no está relacionado con el sistema de módulos JavaScript (ES2015) para administrar colecciones de objetos JavaScript. Estos son sistemas de módulos *complementarios* que puedes usar juntos para escribir tus aplicaciones.
|
||||
The NgModule system is different from and unrelated to the JavaScript (ES2015) module system for managing collections of JavaScript objects. These are *complementary* module systems that you can use together to write your apps.
|
||||
|
||||
En JavaScript, cada *archivo* es un módulo y todos los objetos definidos en el archivo pertenecen a ese módulo.
|
||||
El módulo declara que algunos objetos son públicos marcándolos con la palabra clave `export`.
|
||||
Otros módulos de JavaScript usan *declaraciones de importación* para acceder a objetos públicos de otros módulos.
|
||||
In JavaScript each *file* is a module and all objects defined in the file belong to that module.
|
||||
The module declares some objects to be public by marking them with the `export` key word.
|
||||
Other JavaScript modules use *import statements* to access public objects from other modules.
|
||||
|
||||
<code-example path="architecture/src/app/app.module.ts" region="imports"></code-example>
|
||||
|
||||
<code-example path="architecture/src/app/app.module.ts" region="export"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
<a href="http://exploringjs.com/es6/ch_modules.html">Obtén más información sobre el sistema de módulos de JavaScript en la web.</a>
|
||||
<a href="http://exploringjs.com/es6/ch_modules.html">Learn more about the JavaScript module system on the web.</a>
|
||||
</div>
|
||||
|
||||
## Bibliotecas Angular
|
||||
## Angular libraries
|
||||
|
||||
<img src="generated/images/guide/architecture/library-module.png" alt="Component" class="left">
|
||||
|
||||
Angular se carga como una colección de módulos JavaScript. Puedes pensar en ellos como módulos de biblioteca. Cada nombre de biblioteca de Angular comienza con el prefijo `@angular`. Instálalos con el gestor de paquetes `npm` e importa partes de ellos con declaraciones `import` de JavaScript.
|
||||
Angular loads as a collection of JavaScript modules. You can think of them as library modules. Each Angular library name begins with the `@angular` prefix. Install them with the node package manager `npm` and import parts of them with JavaScript `import` statements.
|
||||
|
||||
<br class="clear">
|
||||
|
||||
Por ejemplo, importa el decorador `Component` de Angular de la biblioteca `@angular/core` como esta.
|
||||
For example, import Angular's `Component` decorator from the `@angular/core` library like this.
|
||||
|
||||
<code-example path="architecture/src/app/app.component.ts" region="import"></code-example>
|
||||
|
||||
También importa NgModules desde las *bibliotecas* Angular usando declaraciones de importación de JavaScript.
|
||||
Por ejemplo, el siguiente código importa el NgModule `BrowserModule` de la biblioteca `platform-browser`.
|
||||
You also import NgModules from Angular *libraries* using JavaScript import statements.
|
||||
For example, the following code imports the `BrowserModule` NgModule from the `platform-browser` library.
|
||||
|
||||
<code-example path="architecture/src/app/mini-app.ts" region="import-browser-module"></code-example>
|
||||
|
||||
En el ejemplo del módulo raíz simple anterior, el módulo de la aplicación necesita material de
|
||||
`BrowserModule`. Para acceder a ese material, agrégalo a los metadatos `imports` de `@NgModule` de esta manera.
|
||||
In the example of the simple root module above, the application module needs material from within
|
||||
`BrowserModule`. To access that material, add it to the `@NgModule` metadata `imports` like this.
|
||||
|
||||
<code-example path="architecture/src/app/mini-app.ts" region="ngmodule-imports"></code-example>
|
||||
|
||||
De esta manera, estás utilizando los sistemas de módulos Angular y JavaScript *juntos*. Aunque es fácil confundir los dos sistemas, que comparten el vocabulario común de "importaciones" y "exportaciones", te familiarizarás con los diferentes contextos en los que se utilizan.
|
||||
In this way you're using the Angular and JavaScript module systems *together*. Although it's easy to confuse the two systems, which share the common vocabulary of "imports" and "exports", you will become familiar with the different contexts in which they are used.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Obtén más información en la guía [NgModules](guide/ngmodules).
|
||||
Learn more from the [NgModules](guide/ngmodules) guide.
|
||||
|
||||
</div>
|
||||
|
@ -1,90 +0,0 @@
|
||||
# Next steps: tools and techniques
|
||||
|
||||
After you understand the basic Angular building blocks, you can learn more
|
||||
about the features and tools that can help you develop and deliver Angular applications.
|
||||
|
||||
* Work through the [Tour of Heroes](tutorial) tutorial to get a feel for how to fit the basic building blocks together to create a well-designed application.
|
||||
|
||||
* Check out the [Glossary](guide/glossary) to understand Angular-specific terms and usage.
|
||||
|
||||
* Use the documentation to learn about key features in more depth, according to your stage of development and areas of interest.
|
||||
|
||||
## Application architecture
|
||||
|
||||
* The [Components and templates](guide/displaying-data) guide explains how to connect the application data in your [components](guide/glossary#component) to your page-display [templates](guide/glossary#template), to create a complete interactive application.
|
||||
|
||||
* The [NgModules](guide/ngmodules) guide provides in-depth information on the modular structure of an Angular application.
|
||||
|
||||
* The [Routing and navigation](guide/router) guide provides in-depth information on how to construct applications that allow a user to navigate to different [views](guide/glossary#view) within your single-page app.
|
||||
|
||||
* The [Dependency injection](guide/dependency-injection) guide provides in-depth information on how to construct an application such that each component class can acquire the services and objects it needs to perform its function.
|
||||
|
||||
## Responsive programming
|
||||
|
||||
The **Components and Templates** guide provides guidance and details of the [template syntax](guide/template-syntax) that you use to display your component data when and where you want it within a view, and to collect input from users that you can respond to.
|
||||
|
||||
Additional pages and sections describe some basic programming techniques for Angular apps.
|
||||
|
||||
* [Lifecycle hooks](guide/lifecycle-hooks): Tap into key moments in the lifetime of a component, from its creation to its destruction, by implementing the lifecycle hook interfaces.
|
||||
|
||||
* [Observables and event processing](guide/observables): How to use observables with components and services to publish and subscribe to messages of any type, such as user-interaction events and asynchronous operation results.
|
||||
|
||||
* [Angular elements](guide/elements): How to package components as *custom elements* using Web Components, a web standard for defining new HTML elements in a framework-agnostic way.
|
||||
|
||||
* [Forms](guide/forms-overview): Support complex data entry scenarios with HTML-based input validation.
|
||||
|
||||
* [Animations](guide/animations): Use Angular's animation library to animate component behavior
|
||||
without deep knowledge of animation techniques or CSS.
|
||||
|
||||
## Client-server interaction
|
||||
|
||||
Angular provides a framework for single-page apps, where most of the logic and data resides on the client.
|
||||
Most apps still need to access a server using the `HttpClient` to access and save data.
|
||||
For some platforms and applications, you might also want to use the PWA (Progressive Web App) model to improve the user experience.
|
||||
|
||||
* [HTTP](guide/http): Communicate with a server to get data, save data, and invoke server-side actions with an HTTP client.
|
||||
|
||||
* [Server-side rendering](guide/universal): Angular Universal generates static application pages on the server through server-side rendering (SSR). This allows you to run your Angular app on the server in order to improve performance and show the first page quickly on mobile and low-powered devices, and also facilitate web crawlers.
|
||||
|
||||
* [Service workers and PWA](guide/service-worker-intro): Use a service worker to reduce dependency on the network and significantly improve the user experience.
|
||||
|
||||
* [Web workers](guide/web-worker): Learn how to run CPU-intensive computations in a background thread.
|
||||
|
||||
## Support for the development cycle
|
||||
|
||||
The **Development Workflow** section describes the tools and processes you use to compile, test, and deploy Angular applications.
|
||||
|
||||
* [CLI Command Reference](cli): The Angular CLI is a command-line tool that you use to create projects, generate application and library code, and perform a variety of ongoing development tasks such as testing, bundling, and deployment.
|
||||
|
||||
* [Compilation](guide/aot-compiler): Angular provides just-in-time (JIT) compilation for the development environment, and ahead-of-time (AOT) compilation for the production environment.
|
||||
|
||||
* [Testing platform](guide/testing): Run unit tests on your application parts as they interact with the Angular framework.
|
||||
|
||||
* [Deployment](guide/deployment): Learn techniques for deploying your Angular application to a remote server.
|
||||
|
||||
* [Security guidelines](guide/security): Learn about Angular's built-in protections against common web-app vulnerabilities and attacks such as cross-site scripting attacks.
|
||||
|
||||
* [Internationalization](guide/i18n): Make your app available in multiple languages with Angular's internationalization (i18n) tools.
|
||||
|
||||
* [Accessibility](guide/accessibility): Make your app accessible to all users.
|
||||
|
||||
|
||||
## File structure, configuration, and dependencies
|
||||
|
||||
* [Workspace and file structure](guide/file-structure): Understand the structure of Angular workspace and project folders.
|
||||
|
||||
* [Building and serving](guide/build): Learn to define different build and proxy server configurations for your project, such as development, staging, and production.
|
||||
|
||||
* [npm packages](guide/npm-packages): The Angular Framework, Angular CLI, and components used by Angular applications are packaged as [npm](https://docs.npmjs.com/) packages and distributed via the npm registry. The Angular CLI creates a default `package.json` file, which specifies a starter set of packages that work well together and jointly support many common application scenarios.
|
||||
|
||||
* [TypeScript configuration](guide/typescript-configuration): TypeScript is the primary language for Angular application development.
|
||||
|
||||
* [Browser support](guide/browser-support): Make your apps compatible across a wide range of browsers.
|
||||
|
||||
## Extending Angular
|
||||
|
||||
* [Angular libraries](guide/libraries): Learn about using and creating re-usable libraries.
|
||||
|
||||
* [Schematics](guide/schematics): Learn about customizing and extending the CLI's generation capabilities.
|
||||
|
||||
* [CLI builders](guide/cli-builder): Learn about customizing and extending the CLI's ability to apply tools to perform complex tasks, such as building and testing applications.
|
@ -1,88 +1,90 @@
|
||||
# Próximos Pasos: Herramientas y Técnicas
|
||||
# Next steps: tools and techniques
|
||||
|
||||
Una vez que comprendas los conceptos básicos de Angular, puedes aprender más sobre las funcionalidades y herramientas que pueden ayudarte a desarrollar y entregar aplicaciones Angular.
|
||||
After you understand the basic Angular building blocks, you can learn more
|
||||
about the features and tools that can help you develop and deliver Angular applications.
|
||||
|
||||
* Realiza el tutorial [Tour de Héroes](tutorial) para familiarizarte con los conceptos básicos necesarios para crear una aplicación bien diseñada.
|
||||
* Work through the [Tour of Heroes](tutorial) tutorial to get a feel for how to fit the basic building blocks together to create a well-designed application.
|
||||
|
||||
* Consulta el [Glosario](guide/glossary) para comprender los términos específicos de Angular y su correspondiente utilización.
|
||||
* Check out the [Glossary](guide/glossary) to understand Angular-specific terms and usage.
|
||||
|
||||
* Utiliza la documentación te permite conocer en detalle las funcionalidades claves, según tu etapa de desarrollo y tus áreas de interés.
|
||||
* Use the documentation to learn about key features in more depth, according to your stage of development and areas of interest.
|
||||
|
||||
## Arquitectura de la aplicación
|
||||
## Application architecture
|
||||
|
||||
* La guía de [Componentes y Plantillas](guide/displaying-data) explica como conectar los datos de la aplicación de sus [componentes](guide/glossary#componente) con las [plantillas](guide/glossary#plantilla) de las pantallas, para crear una aplicación completamente interactiva.
|
||||
* The [Components and templates](guide/displaying-data) guide explains how to connect the application data in your [components](guide/glossary#component) to your page-display [templates](guide/glossary#template), to create a complete interactive application.
|
||||
|
||||
* La guía de [NgModules](guide/ngmodules) proporciona información detallada sobre la estructura de módulos utilizada en una aplicación Angular.
|
||||
* The [NgModules](guide/ngmodules) guide provides in-depth information on the modular structure of an Angular application.
|
||||
|
||||
* La guía de [Enrutamiento y navigación](guide/router) describe como crear aplicaciones que permitan al usuario navegar entre las diferentes [vistas](guide/glossary#vista) dentro de su aplicación de una sola página (SPA).
|
||||
* The [Routing and navigation](guide/router) guide provides in-depth information on how to construct applications that allow a user to navigate to different [views](guide/glossary#view) within your single-page app.
|
||||
|
||||
* La guía de [Injección de dependencias](guide/dependency-injection) brinda información detallada sobre cómo construir una aplicación de modo que cada clase de componente pueda adquirir los servicios y objetos que necesita para realizar su función.
|
||||
* The [Dependency injection](guide/dependency-injection) guide provides in-depth information on how to construct an application such that each component class can acquire the services and objects it needs to perform its function.
|
||||
|
||||
## Programación responsive
|
||||
## Responsive programming
|
||||
|
||||
La guía de **Componentes y Plantillas** brinda orientación y detalles de la [sintaxis de plantilla](guide/template-syntax) que se utilizan para mostrar la información de sus componentes, cuando y donde lo desees dentro de una vista y para obtener entradas (inputs) de los usuarios a las que puedas responder.
|
||||
The **Components and Templates** guide provides guidance and details of the [template syntax](guide/template-syntax) that you use to display your component data when and where you want it within a view, and to collect input from users that you can respond to.
|
||||
|
||||
Las páginas y secciones adicionales describen algunas técnicas básicas de programación para aplicaciones Angular.
|
||||
Additional pages and sections describe some basic programming techniques for Angular apps.
|
||||
|
||||
* [Lifecycle Hooks](guide/lifecycle-hooks): Aprovecha los momentos claves de la vida de un componente, desde su creación hasta su destrucción, implementando las interfaces de los `lifecycle hooks`.
|
||||
* [Lifecycle hooks](guide/lifecycle-hooks): Tap into key moments in the lifetime of a component, from its creation to its destruction, by implementing the lifecycle hook interfaces.
|
||||
|
||||
* [Observables y procesamiento de eventos](guide/observables): Cómo utilizar observables con componentes y servicios para publicar y suscribirse a mensajes de cualquier tipo, tales como los eventos de interacción del usuario y los resultados de operaciones asincrónicas.
|
||||
* [Observables and event processing](guide/observables): How to use observables with components and services to publish and subscribe to messages of any type, such as user-interaction events and asynchronous operation results.
|
||||
|
||||
* [Elementos Angular](guide/elements): Cómo empaquetar componentes como *elementos personalizados* utilizando Web Components, un estándar web para definir nuevos elementos HTML de una manera agnóstica a cualquier framework.
|
||||
* [Angular elements](guide/elements): How to package components as *custom elements* using Web Components, a web standard for defining new HTML elements in a framework-agnostic way.
|
||||
|
||||
* [Formularios](guide/forms-overview): Soporta escenarios complejos de entrada de datos con validación de entradas (inputs) basadas en HTML.
|
||||
* [Forms](guide/forms-overview): Support complex data entry scenarios with HTML-based input validation.
|
||||
|
||||
* [Animaciones](guide/animations): Utiliza la librería de animación de Angular para animar el comportamiento de los componentes sin necesidad de conocer en profundidad las técnicas de animación o CSS.
|
||||
* [Animations](guide/animations): Use Angular's animation library to animate component behavior
|
||||
without deep knowledge of animation techniques or CSS.
|
||||
|
||||
## Interacción Cliente-Servidor
|
||||
## Client-server interaction
|
||||
|
||||
Angular ofrece un framework para aplicaciones de una sola página (SPA), donde la mayoría de la lógica y los datos se encuentran en el cliente.
|
||||
La mayoría de las aplicaciones todavía necesitan acceder a un servidor usando el `HttpClient` para acceder y guardar datos.
|
||||
Para algunas plataformas y aplicaciones, se puede también querer utilizar el modelo PWA (Aplicaciones Web Progresivas) para mejorar la experiencia de usuario.
|
||||
Angular provides a framework for single-page apps, where most of the logic and data resides on the client.
|
||||
Most apps still need to access a server using the `HttpClient` to access and save data.
|
||||
For some platforms and applications, you might also want to use the PWA (Progressive Web App) model to improve the user experience.
|
||||
|
||||
* [HTTP](guide/http): Comunícate con un servidor para obtener datos, guardarlos e invocar acciones del lado del servidor con un cliente HTTP.
|
||||
* [HTTP](guide/http): Communicate with a server to get data, save data, and invoke server-side actions with an HTTP client.
|
||||
|
||||
* [Renderizado del lado del servidor](guide/universal): Angular Universal genera páginas de aplicación estáticas en el servidor a través de la renderización del lado del servidor (SSR). Esto te permite ejecutar tu aplicación Angular en el servidor para mejorar el rendimiento y mostrar la primera página rápidamente en dispositivos móviles y de baja potencia, y también facilitar los rastreadores web.
|
||||
* [Server-side rendering](guide/universal): Angular Universal generates static application pages on the server through server-side rendering (SSR). This allows you to run your Angular app on the server in order to improve performance and show the first page quickly on mobile and low-powered devices, and also facilitate web crawlers.
|
||||
|
||||
* [Service workers y PWA](guide/service-worker-intro): Utiliza un service worker para reducir la dependencia de la red y mejorar significativamente la experiencia del usuario.
|
||||
* [Service workers and PWA](guide/service-worker-intro): Use a service worker to reduce dependency on the network and significantly improve the user experience.
|
||||
|
||||
* [Web workers](guide/web-worker): Aprende a ejecutar cálculos con uso intensivo de la CPU en un hilo en segundo plano.
|
||||
* [Web workers](guide/web-worker): Learn how to run CPU-intensive computations in a background thread.
|
||||
|
||||
## Soporte del Ciclo de Desarrollo
|
||||
## Support for the development cycle
|
||||
|
||||
La sección **Workflow de Desarrollo** detalla las herramientas y los procesos utilizados para compilar, probar y desplegar aplicaciones Angular.
|
||||
The **Development Workflow** section describes the tools and processes you use to compile, test, and deploy Angular applications.
|
||||
|
||||
* [CLI Referencia de Comando](cli): La CLI de Angular es una interfaz de línea de comandos utilizada para crear proyectos, generar código de aplicaciones y librerías y realizar un conjunto de tareas de desarrollo tales como pruebas, empaquetamiento y despliegue de aplicaciones.
|
||||
* [CLI Command Reference](cli): The Angular CLI is a command-line tool that you use to create projects, generate application and library code, and perform a variety of ongoing development tasks such as testing, bundling, and deployment.
|
||||
|
||||
* [Compilación](guide/aot-compiler): Angular proporciona compilación `just-in-time` (JIT) para el entorno de desarrollo y compilación `ahead-of-time` (AOT) para el entorno de producción.
|
||||
* [Compilation](guide/aot-compiler): Angular provides just-in-time (JIT) compilation for the development environment, and ahead-of-time (AOT) compilation for the production environment.
|
||||
|
||||
* [Plataforma de pruebas](guide/testing): Ejecuta pruebas unitarias sobre las distintas partes de tu aplicación a medida que interactúan con el framework de Angular.
|
||||
* [Testing platform](guide/testing): Run unit tests on your application parts as they interact with the Angular framework.
|
||||
|
||||
* [Despliegue](guide/deployment): Aprende técnicas para desplegar tu aplicación Angular en un servidor remoto.
|
||||
* [Deployment](guide/deployment): Learn techniques for deploying your Angular application to a remote server.
|
||||
|
||||
* [Lineamientos de Seguridad](guide/security): Aprende sobre las protecciones integradas por Angular contra las vulnerabilidades y los ataques comunes a las aplicaciones web, como por ejemplo, ataques de cross-site scripting.
|
||||
* [Security guidelines](guide/security): Learn about Angular's built-in protections against common web-app vulnerabilities and attacks such as cross-site scripting attacks.
|
||||
|
||||
* [Internacionalización](guide/i18n): Haz que tu aplicación soporte múltiples lenguajes con las herramientas de internacionalización de Angular (i18n).
|
||||
* [Internationalization](guide/i18n): Make your app available in multiple languages with Angular's internationalization (i18n) tools.
|
||||
|
||||
* [Accesibilidad](guide/accessibility): Haz que tu aplicación sea accesible a todos los usuarios.
|
||||
* [Accessibility](guide/accessibility): Make your app accessible to all users.
|
||||
|
||||
|
||||
## Estructura de Archivos, Configuración y Dependencias
|
||||
## File structure, configuration, and dependencies
|
||||
|
||||
* [Espacio de trabajo y estructura de archivos](guide/file-structure): Comprende la estructura del espacio de trabajo y las carpetas de proyectos en Angular.
|
||||
* [Workspace and file structure](guide/file-structure): Understand the structure of Angular workspace and project folders.
|
||||
|
||||
* [Construcción y servicio](guide/build): Aprende a definir diferentes configuraciones de servidores proxy y construcción para tu proyecto, como por ejemplo desarrollo, staging y producción.
|
||||
* [Building and serving](guide/build): Learn to define different build and proxy server configurations for your project, such as development, staging, and production.
|
||||
|
||||
* [Paquetes npm](guide/npm-packages): El Framework de Angular, la CLI de Angular y los componentes usados por las aplicaciones Angular se empaquetan como paquetes [npm](https://docs.npmjs.com/) y se distribuyen a través del registro de `npm`. La CLI de Angular crea por defecto un archivo `package.json`, que especifica un conjunto inicial de paquetes que funcionan bien en conjunto y dan soporte a muchos escenarios de aplicaciones comunes.
|
||||
* [npm packages](guide/npm-packages): The Angular Framework, Angular CLI, and components used by Angular applications are packaged as [npm](https://docs.npmjs.com/) packages and distributed via the npm registry. The Angular CLI creates a default `package.json` file, which specifies a starter set of packages that work well together and jointly support many common application scenarios.
|
||||
|
||||
* [Configuración de Typescript](guide/typescript-configuration): TypeScript es el lenguaje principal utilizado para el desarrollo de aplicaciones Angular.
|
||||
* [TypeScript configuration](guide/typescript-configuration): TypeScript is the primary language for Angular application development.
|
||||
|
||||
* [Soporte de Navegadores](guide/browser-support): Haz que tus aplicaciones sean compatibles en una amplia gama de navegadores.
|
||||
* [Browser support](guide/browser-support): Make your apps compatible across a wide range of browsers.
|
||||
|
||||
## Extendiendo Angular
|
||||
## Extending Angular
|
||||
|
||||
* [Librerías Angular](guide/libraries): Aprende a usar y crear librerías reutilizables.
|
||||
* [Angular libraries](guide/libraries): Learn about using and creating re-usable libraries.
|
||||
|
||||
* [Esquemas](guide/schematics): Aprende como personalizar y extender las capacidades de generación de la CLI.
|
||||
* [Schematics](guide/schematics): Learn about customizing and extending the CLI's generation capabilities.
|
||||
|
||||
* [Constructores de la CLI](guide/cli-builder): Aprende a personalizar y extender la capacidad de la CLI de aplicar herramientas para realizar tareas complejas, como la construcción y pruebas de aplicaciones.
|
||||
* [CLI builders](guide/cli-builder): Learn about customizing and extending the CLI's ability to apply tools to perform complex tasks, such as building and testing applications.
|
||||
|
@ -1,116 +0,0 @@
|
||||
# Introduction to services and dependency injection
|
||||
|
||||
*Service* is a broad category encompassing any value, function, or feature that an app needs.
|
||||
A service is typically a class with a narrow, well-defined purpose.
|
||||
It should do something specific and do it well.
|
||||
|
||||
Angular distinguishes components from services to increase modularity and reusability.
|
||||
By separating a component's view-related functionality from other kinds of processing,
|
||||
you can make your component classes lean and efficient.
|
||||
|
||||
Ideally, a component's job is to enable the user experience and nothing more.
|
||||
A component should present properties and methods for data binding,
|
||||
in order to mediate between the view (rendered by the template)
|
||||
and the application logic (which often includes some notion of a *model*).
|
||||
|
||||
A component can delegate certain tasks to services, such as fetching data from the server,
|
||||
validating user input, or logging directly to the console.
|
||||
By defining such processing tasks in an *injectable service class*, you make those tasks
|
||||
available to any component.
|
||||
You can also make your app more adaptable by injecting different providers of the same kind of service,
|
||||
as appropriate in different circumstances.
|
||||
|
||||
Angular doesn't *enforce* these principles. Angular does help you *follow* these principles
|
||||
by making it easy to factor your application logic into services and make those services
|
||||
available to components through *dependency injection*.
|
||||
|
||||
## Service examples
|
||||
|
||||
Here's an example of a service class that logs to the browser console.
|
||||
|
||||
<code-example path="architecture/src/app/logger.service.ts" header="src/app/logger.service.ts (class)" region="class"></code-example>
|
||||
|
||||
Services can depend on other services. For example, here's a `HeroService` that depends on the `Logger` service, and also uses `BackendService` to get heroes. That service in turn might depend on the `HttpClient` service to fetch heroes asynchronously from a server.
|
||||
|
||||
<code-example path="architecture/src/app/hero.service.ts" header="src/app/hero.service.ts (class)" region="class"></code-example>
|
||||
|
||||
## Dependency injection (DI)
|
||||
|
||||
<img src="generated/images/guide/architecture/dependency-injection.png" alt="Service" class="left">
|
||||
|
||||
DI is wired into the Angular framework and used everywhere to provide new components with the services or other things they need.
|
||||
Components consume services; that is, you can *inject* a service into a component, giving the component access to that service class.
|
||||
|
||||
To define a class as a service in Angular, use the `@Injectable()` decorator to provide the metadata that allows Angular to inject it into a component as a *dependency*.
|
||||
Similarly, use the `@Injectable()` decorator to indicate that a component or other class (such as another service, a pipe, or an NgModule) *has* a dependency.
|
||||
|
||||
* The *injector* is the main mechanism. Angular creates an application-wide injector for you during the bootstrap process, and additional injectors as needed. You don't have to create injectors.
|
||||
|
||||
* An injector creates dependencies, and maintains a *container* of dependency instances that it reuses if possible.
|
||||
|
||||
* A *provider* is an object that tells an injector how to obtain or create a dependency.
|
||||
|
||||
For any dependency that you need in your app, you must register a provider with the app's injector,
|
||||
so that the injector can use the provider to create new instances.
|
||||
For a service, the provider is typically the service class itself.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
A dependency doesn't have to be a service—it could be a function, for example, or a value.
|
||||
|
||||
</div>
|
||||
|
||||
When Angular creates a new instance of a component class, it determines which services or other dependencies that component needs by looking at the constructor parameter types. For example, the constructor of `HeroListComponent` needs `HeroService`.
|
||||
|
||||
<code-example path="architecture/src/app/hero-list.component.ts" header="src/app/hero-list.component.ts (constructor)" region="ctor"></code-example>
|
||||
|
||||
When Angular discovers that a component depends on a service, it first checks if the injector has any existing instances of that service. If a requested service instance doesn't yet exist, the injector makes one using the registered provider, and adds it to the injector before returning the service to Angular.
|
||||
|
||||
When all requested services have been resolved and returned, Angular can call the component's constructor with those services as arguments.
|
||||
|
||||
The process of `HeroService` injection looks something like this.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/architecture/injector-injects.png" alt="Service" class="left">
|
||||
</div>
|
||||
|
||||
### Providing services
|
||||
|
||||
You must register at least one *provider* of any service you are going to use.
|
||||
The provider can be part of the service's own metadata, making that service available everywhere,
|
||||
or you can register providers with specific modules or components.
|
||||
You register providers in the metadata of the service (in the `@Injectable()` decorator),
|
||||
or in the `@NgModule()` or `@Component()` metadata
|
||||
|
||||
* By default, the Angular CLI command [`ng generate service`](cli/generate) registers a provider with the root injector for your service by including provider metadata in the `@Injectable()` decorator. The tutorial uses this method to register the provider of HeroService class definition.
|
||||
|
||||
```
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
```
|
||||
|
||||
When you provide the service at the root level, Angular creates a single, shared instance of `HeroService`
|
||||
and injects it into any class that asks for it.
|
||||
Registering the provider in the `@Injectable()` metadata also allows Angular to optimize an app
|
||||
by removing the service from the compiled app if it isn't used.
|
||||
|
||||
* When you register a provider with a [specific NgModule](guide/architecture-modules), the same instance of a service is available to all components in that NgModule. To register at this level, use the `providers` property of the `@NgModule()` decorator,
|
||||
|
||||
```
|
||||
@NgModule({
|
||||
providers: [
|
||||
BackendService,
|
||||
Logger
|
||||
],
|
||||
...
|
||||
})
|
||||
```
|
||||
|
||||
* When you register a provider at the component level, you get a new instance of the
|
||||
service with each new instance of that component.
|
||||
At the component level, register a service provider in the `providers` property of the `@Component()` metadata.
|
||||
|
||||
<code-example path="architecture/src/app/hero-list.component.ts" header="src/app/hero-list.component.ts (component providers)" region="providers"></code-example>
|
||||
|
||||
For more detailed information, see the [Dependency Injection](guide/dependency-injection) section.
|
@ -1,81 +1,88 @@
|
||||
# Introducción a servicios e inyección de dependencias
|
||||
# Introduction to services and dependency injection
|
||||
|
||||
*Servicio* es una categoría amplia que abarca cualquier valor, función o característica que necesite una aplicación.
|
||||
Un servicio es típicamente una clase con un propósito limitado y bien definido.
|
||||
Debe hacer algo específico y hacerlo bien.
|
||||
*Service* is a broad category encompassing any value, function, or feature that an app needs.
|
||||
A service is typically a class with a narrow, well-defined purpose.
|
||||
It should do something specific and do it well.
|
||||
|
||||
Angular distingue los componentes de los servicios para aumentar la modularidad y la reutilización.
|
||||
Al separar la funcionalidad relacionada con la vista de un componente de otros tipos de procesamiento, puedes hacer que tus componentes sean ágiles y eficientes.
|
||||
Angular distinguishes components from services to increase modularity and reusability.
|
||||
By separating a component's view-related functionality from other kinds of processing,
|
||||
you can make your component classes lean and efficient.
|
||||
|
||||
Idealmente, el trabajo de un componente es permitir la experiencia del usuario y nada más.
|
||||
Un componente debe presentar propiedades y métodos para el enlace de datos,
|
||||
para mediar entre la vista (representada por la plantilla)
|
||||
y la lógica de la aplicación (que a menudo incluye alguna noción de * modelo *).
|
||||
Ideally, a component's job is to enable the user experience and nothing more.
|
||||
A component should present properties and methods for data binding,
|
||||
in order to mediate between the view (rendered by the template)
|
||||
and the application logic (which often includes some notion of a *model*).
|
||||
|
||||
Un componente puede delegar ciertas tareas a los servicios, como obtener datos del servidor, validar la entrada del usuario o registrar información directamente en la consola.
|
||||
Al definir tales tareas de procesamiento en una * clase de servicio inyectable *, hace que esas tareas sean disponibles para cualquier componente.
|
||||
También puedes hacer que tu aplicación sea más adaptable inyectando diferentes proveedores del mismo tipo de servicio, según corresponda en diferentes circunstancias.
|
||||
A component can delegate certain tasks to services, such as fetching data from the server,
|
||||
validating user input, or logging directly to the console.
|
||||
By defining such processing tasks in an *injectable service class*, you make those tasks
|
||||
available to any component.
|
||||
You can also make your app more adaptable by injecting different providers of the same kind of service,
|
||||
as appropriate in different circumstances.
|
||||
|
||||
Angular no * impone * estos principios. Angular te ayuda a * seguir * estos principios
|
||||
al facilitar la integración de la lógica de tu aplicación en los servicios y hacer que esos servicios sean disponibles para los componentes a través de * inyección de dependencia *.
|
||||
Angular doesn't *enforce* these principles. Angular does help you *follow* these principles
|
||||
by making it easy to factor your application logic into services and make those services
|
||||
available to components through *dependency injection*.
|
||||
|
||||
## Ejemplos de servicios
|
||||
## Service examples
|
||||
|
||||
A continuación, se muestra un ejemplo de una clase de servicio que registra información en la consola del navegador.
|
||||
Here's an example of a service class that logs to the browser console.
|
||||
|
||||
<code-example path="architecture/src/app/logger.service.ts" header="src/app/logger.service.ts (class)" region="class"></code-example>
|
||||
|
||||
Los servicios pueden depender de otros servicios. Por ejemplo, hay un `HeroService` que depende del `Logger` service, y también usa `BackendService` para obtener héroes. Ese servicio, a su vez, podría depender del servicio `HttpClient` para buscar héroes de forma asíncrona desde un servidor.
|
||||
Services can depend on other services. For example, here's a `HeroService` that depends on the `Logger` service, and also uses `BackendService` to get heroes. That service in turn might depend on the `HttpClient` service to fetch heroes asynchronously from a server.
|
||||
|
||||
<code-example path="architecture/src/app/hero.service.ts" header="src/app/hero.service.ts (class)" region="class"></code-example>
|
||||
|
||||
## Inyección de dependencia (ID)
|
||||
## Dependency injection (DI)
|
||||
|
||||
<img src="generated/images/guide/architecture/dependency-injection.png" alt="Service" class="left">
|
||||
|
||||
Inyección de dependencia está conectado al framework de Angular y se usa en todas partes para proporcionar nuevos componentes con los servicios u otras cosas que necesitan.
|
||||
Los componentes consumen servicios; es decir, puede * inyectar * un servicio en un componente, dándole acceso al componente a ese servicio.
|
||||
DI is wired into the Angular framework and used everywhere to provide new components with the services or other things they need.
|
||||
Components consume services; that is, you can *inject* a service into a component, giving the component access to that service class.
|
||||
|
||||
Para definir una clase como un servicio en Angular, usa el decorador `@Injectable ()` para proporcionar los metadatos que le permitan a Angular inyectarlo en un componente como una * dependencia *.
|
||||
De manera similar, usa el decorador `@Injectable()` para indicar que un componente u otra clase (como otro servicio, un pipeline o un NgModule) * tiene * una dependencia.
|
||||
To define a class as a service in Angular, use the `@Injectable()` decorator to provide the metadata that allows Angular to inject it into a component as a *dependency*.
|
||||
Similarly, use the `@Injectable()` decorator to indicate that a component or other class (such as another service, a pipe, or an NgModule) *has* a dependency.
|
||||
|
||||
* El * inyector * es el mecanismo principal. Angular crea un inyector para toda la aplicación durante el proceso de arranque e inyectores adicionales según sea necesario. No es necesario crear inyectores.
|
||||
* The *injector* is the main mechanism. Angular creates an application-wide injector for you during the bootstrap process, and additional injectors as needed. You don't have to create injectors.
|
||||
|
||||
* Un inyector crea dependencias y mantiene un * contenedor * de instancias de dependencia que reutiliza si es posible.
|
||||
* An injector creates dependencies, and maintains a *container* of dependency instances that it reuses if possible.
|
||||
|
||||
* Un * proveedor * es un objeto que le dice a un inyector cómo obtener o crear una dependencia.
|
||||
* A *provider* is an object that tells an injector how to obtain or create a dependency.
|
||||
|
||||
Para cualquier dependencia que necesites en tu aplicación, debes registrar un proveedor con el inyector de la aplicación, con el fin de que el inyector pueda utilizar el proveedor para crear nuevas instancias.
|
||||
Para un servicio, el proveedor suele ser la propia clase de servicio.
|
||||
For any dependency that you need in your app, you must register a provider with the app's injector,
|
||||
so that the injector can use the provider to create new instances.
|
||||
For a service, the provider is typically the service class itself.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Una dependencia no tiene que ser solamente un servicio—podría ser una función, por ejemplo, o un valor.
|
||||
A dependency doesn't have to be a service—it could be a function, for example, or a value.
|
||||
|
||||
</div>
|
||||
|
||||
Cuando Angular crea una nueva instancia de una clase de componente, determina qué servicios u otras dependencias necesita ese componente al observar los tipos de parámetros del constructor. Por ejemplo, el constructor de `HeroListComponent` necesita `HeroService`.
|
||||
When Angular creates a new instance of a component class, it determines which services or other dependencies that component needs by looking at the constructor parameter types. For example, the constructor of `HeroListComponent` needs `HeroService`.
|
||||
|
||||
<code-example path="architecture/src/app/hero-list.component.ts" header="src/app/hero-list.component.ts (constructor)" region="ctor"></code-example>
|
||||
|
||||
Cuando Angular descubre que un componente depende de un servicio, primero verifica si el inyector tiene instancias existentes de ese servicio. Si una instancia de servicio solicitada aún no existe, el inyector crea una utilizando el proveedor registrado y la agrega al inyector antes de devolver el servicio a Angular.
|
||||
When Angular discovers that a component depends on a service, it first checks if the injector has any existing instances of that service. If a requested service instance doesn't yet exist, the injector makes one using the registered provider, and adds it to the injector before returning the service to Angular.
|
||||
|
||||
Cuando todos los servicios solicitados se han resuelto y devuelto, Angular puede llamar al constructor del componente con esos servicios como argumentos.
|
||||
When all requested services have been resolved and returned, Angular can call the component's constructor with those services as arguments.
|
||||
|
||||
El proceso de inyección de "HeroService" se parece a esto.
|
||||
The process of `HeroService` injection looks something like this.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/architecture/injector-injects.png" alt="Service" class="left">
|
||||
</div>
|
||||
|
||||
### Proporcionar servicios
|
||||
### Providing services
|
||||
|
||||
Deberías registrar al menos un * proveedor * de cualquier servicio que vayas a utilizar.
|
||||
El proveedor puede formar parte de los propios metadatos del servicio, haciendo que ese servicio esté disponible en todas partes, o puede registrar proveedores con módulos o componentes específicos.
|
||||
Debes registrar proveedores en los metadatos del servicio (en el decorador `@Injectable()`),
|
||||
o en los metadatos `@NgModule()` o `@Component()`
|
||||
You must register at least one *provider* of any service you are going to use.
|
||||
The provider can be part of the service's own metadata, making that service available everywhere,
|
||||
or you can register providers with specific modules or components.
|
||||
You register providers in the metadata of the service (in the `@Injectable()` decorator),
|
||||
or in the `@NgModule()` or `@Component()` metadata
|
||||
|
||||
* Por defecto, el comando CLI de Angular [`ng generate service`](cli/generate) registra un proveedor con el inyector raíz para tu servicio al incluir metadatos del proveedor en el decorador `@Injectable()`. El tutorial utiliza este método para registrar el proveedor de la definición de clase HeroService.
|
||||
* By default, the Angular CLI command [`ng generate service`](cli/generate) registers a provider with the root injector for your service by including provider metadata in the `@Injectable()` decorator. The tutorial uses this method to register the provider of HeroService class definition.
|
||||
|
||||
```
|
||||
@Injectable({
|
||||
@ -83,10 +90,12 @@ o en los metadatos `@NgModule()` o `@Component()`
|
||||
})
|
||||
```
|
||||
|
||||
Cuando proporcionas el servicio en el nivel raíz, Angular crea una instancia única compartida de `HeroService` y lo inyecta en cualquier clase que lo solicite.
|
||||
El registro del proveedor en los metadatos `@Injectable()` también permite a Angular optimizar una aplicación eliminando el servicio de la aplicación compilada si no se utiliza.
|
||||
When you provide the service at the root level, Angular creates a single, shared instance of `HeroService`
|
||||
and injects it into any class that asks for it.
|
||||
Registering the provider in the `@Injectable()` metadata also allows Angular to optimize an app
|
||||
by removing the service from the compiled app if it isn't used.
|
||||
|
||||
* Cuando registras un proveedor con un [NgModule específico](guide/architecture-modules), la misma instancia de un servicio está disponible para todos los componentes en ese NgModule. Para registrar en este nivel, usa la propiedad `Provider` del decorador `@NgModule()`.
|
||||
* When you register a provider with a [specific NgModule](guide/architecture-modules), the same instance of a service is available to all components in that NgModule. To register at this level, use the `providers` property of the `@NgModule()` decorator,
|
||||
|
||||
```
|
||||
@NgModule({
|
||||
@ -98,10 +107,10 @@ o en los metadatos `@NgModule()` o `@Component()`
|
||||
})
|
||||
```
|
||||
|
||||
* Cuando registras un proveedor a nivel del componente, obtienes una nueva instancia del
|
||||
servicio con cada nueva instancia de ese componente.
|
||||
A nivel del componente, registra un proveedor de servicios en la propiedad `Providers` de los metadatos `@Component()`.
|
||||
* When you register a provider at the component level, you get a new instance of the
|
||||
service with each new instance of that component.
|
||||
At the component level, register a service provider in the `providers` property of the `@Component()` metadata.
|
||||
|
||||
<code-example path="architecture/src/app/hero-list.component.ts" header="src/app/hero-list.component.ts (component providers)" region="providers"></code-example>
|
||||
|
||||
Para obtener información más detallada, consulta la sección [Inyección de dependencia](guide/dependency-injection).
|
||||
For more detailed information, see the [Dependency Injection](guide/dependency-injection) section.
|
||||
|
@ -1,157 +0,0 @@
|
||||
# Introduction to Angular concepts
|
||||
|
||||
Angular is a platform and framework for building single-page client applications using HTML and TypeScript.
|
||||
Angular is written in TypeScript.
|
||||
It implements core and optional functionality as a set of TypeScript libraries that you import into your apps.
|
||||
|
||||
The architecture of an Angular application relies on certain fundamental concepts.
|
||||
The basic building blocks are *NgModules*, which provide a compilation context for *components*. NgModules collect related code into functional sets; an Angular app is defined by a set of NgModules. An app always has at least a *root module* that enables bootstrapping, and typically has many more *feature modules*.
|
||||
|
||||
* Components define *views*, which are sets of screen elements that Angular can choose among and modify according to your program logic and data.
|
||||
|
||||
* Components use *services*, which provide specific functionality not directly related to views. Service providers can be *injected* into components as *dependencies*, making your code modular, reusable, and efficient.
|
||||
|
||||
Modules, components and services are classes that use *decorators*. These decorators mark their type and provide metadata that tells Angular how to use them.
|
||||
|
||||
* The metadata for a component class associates it with a *template* that defines a view. A template combines ordinary HTML with Angular *directives* and *binding markup* that allow Angular to modify the HTML before rendering it for display.
|
||||
|
||||
* The metadata for a service class provides the information Angular needs to make it available to components through *dependency injection (DI)*.
|
||||
|
||||
An app's components typically define many views, arranged hierarchically. Angular provides the `Router` service to help you define navigation paths among views. The router provides sophisticated in-browser navigational capabilities.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the [Angular Glossary](guide/glossary) for basic definitions of important Angular terms and usage.
|
||||
|
||||
</div>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For the sample app that this page describes, see the <live-example></live-example>.
|
||||
</div>
|
||||
|
||||
## Modules
|
||||
|
||||
Angular *NgModules* differ from and complement JavaScript (ES2015) modules. An NgModule declares a compilation context for a set of components that is dedicated to an application domain, a workflow, or a closely related set of capabilities. An NgModule can associate its components with related code, such as services, to form functional units.
|
||||
|
||||
Every Angular app has a *root module*, conventionally named `AppModule`, which provides the bootstrap mechanism that launches the application. An app typically contains many functional modules.
|
||||
|
||||
Like JavaScript modules, NgModules can import functionality from other NgModules, and allow their own functionality to be exported and used by other NgModules. For example, to use the router service in your app, you import the `Router` NgModule.
|
||||
|
||||
Organizing your code into distinct functional modules helps in managing development of complex applications, and in designing for reusability. In addition, this technique lets you take advantage of *lazy-loading*—that is, loading modules on demand—to minimize the amount of code that needs to be loaded at startup.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For a more detailed discussion, see [Introduction to modules](guide/architecture-modules).
|
||||
|
||||
</div>
|
||||
|
||||
## Components
|
||||
|
||||
Every Angular application has at least one component, the *root component* that connects a component hierarchy with the page document object model (DOM). Each component defines a class that contains application data and logic, and is associated with an HTML *template* that defines a view to be displayed in a target environment.
|
||||
|
||||
The `@Component()` decorator identifies the class immediately below it as a component, and provides the template and related component-specific metadata.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Decorators are functions that modify JavaScript classes. Angular defines a number of decorators that attach specific kinds of metadata to classes, so that the system knows what those classes mean and how they should work.
|
||||
|
||||
<a href="https://medium.com/google-developers/exploring-es7-decorators-76ecb65fb841#.x5c2ndtx0">Learn more about decorators on the web.</a>
|
||||
|
||||
</div>
|
||||
|
||||
### Templates, directives, and data binding
|
||||
|
||||
A template combines HTML with Angular markup that can modify HTML elements before they are displayed.
|
||||
Template *directives* provide program logic, and *binding markup* connects your application data and the DOM.
|
||||
There are two types of data binding:
|
||||
|
||||
* *Event binding* lets your app respond to user input in the target environment by updating your application data.
|
||||
* *Property binding* lets you interpolate values that are computed from your application data into the HTML.
|
||||
|
||||
Before a view is displayed, Angular evaluates the directives and resolves the binding syntax in the template to modify the HTML elements and the DOM, according to your program data and logic. Angular supports *two-way data binding*, meaning that changes in the DOM, such as user choices, are also reflected in your program data.
|
||||
|
||||
Your templates can use *pipes* to improve the user experience by transforming values for display.
|
||||
For example, use pipes to display dates and currency values that are appropriate for a user's locale.
|
||||
Angular provides predefined pipes for common transformations, and you can also define your own pipes.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For a more detailed discussion of these concepts, see [Introduction to components](guide/architecture-components).
|
||||
|
||||
</div>
|
||||
|
||||
{@a dependency-injection}
|
||||
|
||||
|
||||
## Services and dependency injection
|
||||
|
||||
For data or logic that isn't associated with a specific view, and that you want to share across components, you create a *service* class. A service class definition is immediately preceded by the `@Injectable()` decorator. The decorator provides the metadata that allows other providers to be **injected** as dependencies into your class.
|
||||
|
||||
*Dependency injection* (DI) lets you keep your component classes lean and efficient. They don't fetch data from the server, validate user input, or log directly to the console; they delegate such tasks to services.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For a more detailed discussion, see [Introduction to services and DI](guide/architecture-services).
|
||||
|
||||
</div>
|
||||
|
||||
### Routing
|
||||
|
||||
The Angular `Router` NgModule provides a service that lets you define a navigation path among the different application states and view hierarchies in your app. It is modeled on the familiar browser navigation conventions:
|
||||
|
||||
* Enter a URL in the address bar and the browser navigates to a corresponding page.
|
||||
|
||||
* Click links on the page and the browser navigates to a new page.
|
||||
|
||||
* Click the browser's back and forward buttons and the browser navigates backward and forward through the history of pages you've seen.
|
||||
|
||||
The router maps URL-like paths to views instead of pages. When a user performs an action, such as clicking a link, that would load a new page in the browser, the router intercepts the browser's behavior, and shows or hides view hierarchies.
|
||||
|
||||
If the router determines that the current application state requires particular functionality, and the module that defines it hasn't been loaded, the router can *lazy-load* the module on demand.
|
||||
|
||||
The router interprets a link URL according to your app's view navigation rules and data state. You can navigate to new views when the user clicks a button or selects from a drop box, or in response to some other stimulus from any source. The router logs activity in the browser's history, so the back and forward buttons work as well.
|
||||
|
||||
To define navigation rules, you associate *navigation paths* with your components. A path uses a URL-like syntax that integrates your program data, in much the same way that template syntax integrates your views with your program data. You can then apply program logic to choose which views to show or to hide, in response to user input and your own access rules.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For a more detailed discussion, see [Routing and navigation](guide/router).
|
||||
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
## What's next
|
||||
|
||||
You've learned the basics about the main building blocks of an Angular application. The following diagram shows how these basic pieces are related.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/architecture/overview2.png" alt="overview">
|
||||
</div>
|
||||
|
||||
* Together, a component and template define an Angular view.
|
||||
* A decorator on a component class adds the metadata, including a pointer to the associated template.
|
||||
* Directives and binding markup in a component's template modify views based on program data and logic.
|
||||
* The dependency injector provides services to a component, such as the router service that lets you define navigation among views.
|
||||
|
||||
Each of these subjects is introduced in more detail in the following pages.
|
||||
|
||||
* [Introduction to Modules](guide/architecture-modules)
|
||||
|
||||
* [Introduction to Components](guide/architecture-components)
|
||||
|
||||
* [Templates and views](guide/architecture-components#templates-and-views)
|
||||
|
||||
* [Component metadata](guide/architecture-components#component-metadata)
|
||||
|
||||
* [Data binding](guide/architecture-components#data-binding)
|
||||
|
||||
* [Directives](guide/architecture-components#directives)
|
||||
|
||||
* [Pipes](guide/architecture-components#pipes)
|
||||
|
||||
* [Introduction to services and dependency injection](guide/architecture-services)
|
||||
|
||||
When you're familiar with these fundamental building blocks, you can explore them in more detail in the documentation. To learn about more tools and techniques that are available to help you build and deploy Angular applications, see [Next steps: tools and techniques](guide/architecture-next-steps).
|
||||
</div>
|
@ -1,157 +1,157 @@
|
||||
# Introducción a los conceptos de Angular
|
||||
# Introduction to Angular concepts
|
||||
|
||||
Angular es una plataforma y un framework para crear aplicaciones de una sola página en el lado del cliente usando HTML y TypeScript.
|
||||
Angular está escrito en TypeScript.
|
||||
Implementa la funcionalidad básica y opcional como un conjunto de bibliotecas TypeScript que importas en tus aplicaciones.
|
||||
Angular is a platform and framework for building single-page client applications using HTML and TypeScript.
|
||||
Angular is written in TypeScript.
|
||||
It implements core and optional functionality as a set of TypeScript libraries that you import into your apps.
|
||||
|
||||
La arquitectura de una aplicación en Angular se basa en ciertos conceptos fundamentales.
|
||||
Los bloques de construcción básicos son los *NgModules*, que proporcionan un contexto de compilación para los *componentes*. Los NgModules recopilan código relacionado en conjuntos funcionales; una aplicación de Angular se define por un conjunto de NgModules. Una aplicación siempre tiene al menos un *módulo raíz* que permite el arranque y generalmente tiene muchos más *módulos de funcionalidad*.
|
||||
The architecture of an Angular application relies on certain fundamental concepts.
|
||||
The basic building blocks are *NgModules*, which provide a compilation context for *components*. NgModules collect related code into functional sets; an Angular app is defined by a set of NgModules. An app always has at least a *root module* that enables bootstrapping, and typically has many more *feature modules*.
|
||||
|
||||
* Los componentes definen *vistas*, que son conjuntos de elementos de la pantalla que Angular puede elegir y modificar de acuerdo con la lógica y los datos de tu programa.
|
||||
* Components define *views*, which are sets of screen elements that Angular can choose among and modify according to your program logic and data.
|
||||
|
||||
* Los componentes usan *servicios*, los cuales proporcionan una funcionalidad específica que no está directamente relacionada con las vistas. Los proveedores de servicios pueden *inyectarse* en componentes como *dependencias*, haciendo que tu código sea modular, reutilizable y eficiente.
|
||||
* Components use *services*, which provide specific functionality not directly related to views. Service providers can be *injected* into components as *dependencies*, making your code modular, reusable, and efficient.
|
||||
|
||||
Los módulos, componentes y servicios son clases que usan *decoradores*. Estos decoradores indican su tipo y proporcionan metadatos que le indican a Angular cómo usarlos.
|
||||
Modules, components and services are classes that use *decorators*. These decorators mark their type and provide metadata that tells Angular how to use them.
|
||||
|
||||
* Los metadatos para una clase componente son asociados con una *plantilla* que define una vista. Una plantilla combina HTML ordinario con *directivas* de Angular y *enlace markup* que permiten a Angular modificar el HTML antes de mostrarlo para su visualización.
|
||||
* The metadata for a component class associates it with a *template* that defines a view. A template combines ordinary HTML with Angular *directives* and *binding markup* that allow Angular to modify the HTML before rendering it for display.
|
||||
|
||||
* Los metadatos para una clase servicio proporcionan la información que Angular necesita para que esté disponible para los componentes a través de la *Inyección de Dependencia (ID)*.
|
||||
* The metadata for a service class provides the information Angular needs to make it available to components through *dependency injection (DI)*.
|
||||
|
||||
Los componentes de una aplicación suelen definir muchas vistas, ordenadas jerárquicamente. Angular proporciona el servicio `Router` para ayudarte a definir rutas de navegación entre vistas. El enrutador proporciona capacidades de navegación sofisticadas en el navegador.
|
||||
An app's components typically define many views, arranged hierarchically. Angular provides the `Router` service to help you define navigation paths among views. The router provides sophisticated in-browser navigational capabilities.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Visita el [Glosario de Angular](guide/glossary) para ver las definiciones básicas de términos importantes en Angular y su uso.
|
||||
See the [Angular Glossary](guide/glossary) for basic definitions of important Angular terms and usage.
|
||||
|
||||
</div>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Para ver la aplicación de ejemplo que describe esta página, consulta el <live-example>ejemplo</live-example>.
|
||||
For the sample app that this page describes, see the <live-example></live-example>.
|
||||
</div>
|
||||
|
||||
## Módulos
|
||||
## Modules
|
||||
|
||||
Los *NgModules* de Angular difieren y complementan los módulos JavaScript (ES2015). Un NgModule declara un contexto de compilación para un conjunto de componentes que está dedicado a un dominio de aplicación, un flujo de trabajo o un conjunto de capacidades estrechamente relacionadas. Un NgModule puede asociar sus componentes con código relacionado, como servicios, para formar unidades funcionales.
|
||||
Angular *NgModules* differ from and complement JavaScript (ES2015) modules. An NgModule declares a compilation context for a set of components that is dedicated to an application domain, a workflow, or a closely related set of capabilities. An NgModule can associate its components with related code, such as services, to form functional units.
|
||||
|
||||
Cada aplicación en Angular tiene un *módulo raíz*, convencionalmente nombrado `AppModule`, que proporciona el mecanismo de arranque que inicia la aplicación. Una aplicación generalmente contiene muchos módulos funcionales.
|
||||
Every Angular app has a *root module*, conventionally named `AppModule`, which provides the bootstrap mechanism that launches the application. An app typically contains many functional modules.
|
||||
|
||||
Como en los módulos de JavaScript, los NgModules pueden importar la funcionalidad de otros, y permiten que su propia funcionalidad sea exportada y utilizada por otros NgModules. Por ejemplo, para utilizar el servicio de enrutamiento en su aplicación, importa el NgModule `Router`.
|
||||
Like JavaScript modules, NgModules can import functionality from other NgModules, and allow their own functionality to be exported and used by other NgModules. For example, to use the router service in your app, you import the `Router` NgModule.
|
||||
|
||||
Organizar tu código en distintos módulos funcionales ayuda a gestionar el desarrollo de aplicaciones complejas, y en el diseño para su reutilización. Además, esta técnica te permite aprovechar la *carga diferida*—es decir, cargar módulos bajo demanda—para minimizar la cantidad de código que debe cargarse al inicio.
|
||||
Organizing your code into distinct functional modules helps in managing development of complex applications, and in designing for reusability. In addition, this technique lets you take advantage of *lazy-loading*—that is, loading modules on demand—to minimize the amount of code that needs to be loaded at startup.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Para más información, visita [Introducción a los módulos](guide/architecture-modules).
|
||||
For a more detailed discussion, see [Introduction to modules](guide/architecture-modules).
|
||||
|
||||
</div>
|
||||
|
||||
## Componentes
|
||||
## Components
|
||||
|
||||
Cada aplicación de Angular tiene al menos un componente, el *componente raíz* que conecta una jerarquía de componentes con el modelo de objetos del documento de la página (DOM). Cada componente define una clase que contiene datos y lógica de la aplicación, y está asociado con una *plantilla* HTML que define una vista que se mostrará en un entorno de destino.
|
||||
Every Angular application has at least one component, the *root component* that connects a component hierarchy with the page document object model (DOM). Each component defines a class that contains application data and logic, and is associated with an HTML *template* that defines a view to be displayed in a target environment.
|
||||
|
||||
El decorador `@Component()` identifica la clase inmediatamente debajo de ella como un componente, y proporciona la plantilla y los metadatos específicos del componente relacionado.
|
||||
The `@Component()` decorator identifies the class immediately below it as a component, and provides the template and related component-specific metadata.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Los decoradores son funciones que modifican las clases de JavaScript. Angular define una serie de decoradores que adjuntan tipos específicos de metadatos a las clases, para que el sistema sepa qué significan esas clases y cómo deberían funcionar.
|
||||
Decorators are functions that modify JavaScript classes. Angular defines a number of decorators that attach specific kinds of metadata to classes, so that the system knows what those classes mean and how they should work.
|
||||
|
||||
<a href="https://medium.com/google-developers/exploring-es7-decorators-76ecb65fb841#.x5c2ndtx0">Obten más información sobre decoradores en la web.</a>
|
||||
<a href="https://medium.com/google-developers/exploring-es7-decorators-76ecb65fb841#.x5c2ndtx0">Learn more about decorators on the web.</a>
|
||||
|
||||
</div>
|
||||
|
||||
### Plantillas, directivas y enlace de datos
|
||||
### Templates, directives, and data binding
|
||||
|
||||
Una plantilla combina HTML con markup de Angular que puede modificar elementos HTML antes de que se muestren.
|
||||
Las *directivas* de la plantilla proporcionan la lógica de programa y el *enlace markup* conecta los datos de tu aplicación y el DOM.
|
||||
Hay dos tipos de enlace de datos:
|
||||
A template combines HTML with Angular markup that can modify HTML elements before they are displayed.
|
||||
Template *directives* provide program logic, and *binding markup* connects your application data and the DOM.
|
||||
There are two types of data binding:
|
||||
|
||||
* *Manejador de eventos* permite que tu aplicación responda a la entrada del usuario en el entorno objetivo actualizando los datos de tu aplicación.
|
||||
* *Vincular propiedades* te permite interpolar valores que se calculan a partir de los datos de tu aplicación en HTML.
|
||||
* *Event binding* lets your app respond to user input in the target environment by updating your application data.
|
||||
* *Property binding* lets you interpolate values that are computed from your application data into the HTML.
|
||||
|
||||
Antes de mostrar una vista, Angular evalúa las directivas y resuelve la sintaxis de enlace en la plantilla para modificar los elementos HTML y el DOM, de acuerdo con los datos y la lógica de tu programa. Angular soporta *enlace de datos en dos sentidos*, lo que significa que los cambios en el DOM, como las elecciones del usuario, también se reflejan en los datos de su programa.
|
||||
Before a view is displayed, Angular evaluates the directives and resolves the binding syntax in the template to modify the HTML elements and the DOM, according to your program data and logic. Angular supports *two-way data binding*, meaning that changes in the DOM, such as user choices, are also reflected in your program data.
|
||||
|
||||
Tus plantillas pueden usar *pipes* para mejorar la experiencia del usuario mediante la transformación de valores para mostrar.
|
||||
Por ejemplo, usa pipes para mostrar fechas y valores de moneda que sean apropiados para la configuración regional de un usuario.
|
||||
Angular proporciona pipes predefinidas para transformaciones comunes, y también puedes definir tus propias pipes.
|
||||
Your templates can use *pipes* to improve the user experience by transforming values for display.
|
||||
For example, use pipes to display dates and currency values that are appropriate for a user's locale.
|
||||
Angular provides predefined pipes for common transformations, and you can also define your own pipes.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Para más información sobre estos conceptos, visita [Introducción a los componentes](guide/architecture-components).
|
||||
For a more detailed discussion of these concepts, see [Introduction to components](guide/architecture-components).
|
||||
|
||||
</div>
|
||||
|
||||
{@a dependency-injection}
|
||||
|
||||
|
||||
## Servicios e inyección de dependencia
|
||||
## Services and dependency injection
|
||||
|
||||
Para los datos o la lógica que no están asociados con una vista específica y que deseas compartir entre componentes, crea una clase *servicio*. Una definición de clase servicio está inmediatamente precedida por el decorador `@Injectable()`. El decorador proporciona los metadatos que permiten **inyectar** otros proveedores como dependencias en su clase.
|
||||
For data or logic that isn't associated with a specific view, and that you want to share across components, you create a *service* class. A service class definition is immediately preceded by the `@Injectable()` decorator. The decorator provides the metadata that allows other providers to be **injected** as dependencies into your class.
|
||||
|
||||
*Inyección de Dependecia* (ID) te permite mantener sus clases componente ligeras y eficientes. No obtienen datos del servidor, validan la entrada del usuario o registra directamente en la consola; tales tareas son delegadas a los servicios.
|
||||
*Dependency injection* (DI) lets you keep your component classes lean and efficient. They don't fetch data from the server, validate user input, or log directly to the console; they delegate such tasks to services.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Para más información, visita [Introducción a los servicios e inyección de dependencia](guide/architecture-services).
|
||||
For a more detailed discussion, see [Introduction to services and DI](guide/architecture-services).
|
||||
|
||||
</div>
|
||||
|
||||
### Enrutamiento
|
||||
### Routing
|
||||
|
||||
El NgModule `Router` de Angular proporciona un servicio que te permite definir una ruta de navegación entre los diferentes estados de la aplicación y ver sus jerarquías. Se basa en las convenciones frecuentes de navegación del navegador:
|
||||
The Angular `Router` NgModule provides a service that lets you define a navigation path among the different application states and view hierarchies in your app. It is modeled on the familiar browser navigation conventions:
|
||||
|
||||
* Ingresa una URL en la barra de direcciones para que el navegador vaya a la página correspondiente.
|
||||
* Enter a URL in the address bar and the browser navigates to a corresponding page.
|
||||
|
||||
* Haz clic en los enlaces de la página para que el navegador vaya a una nueva página.
|
||||
* Click links on the page and the browser navigates to a new page.
|
||||
|
||||
* Haz clic en los botones atrás y adelante del navegador para que el navegador vaya hacia atrás y hacia adelante a través del historial de las páginas que has visto.
|
||||
* Click the browser's back and forward buttons and the browser navigates backward and forward through the history of pages you've seen.
|
||||
|
||||
El enrutador mapea rutas similares a URL para las vistas en lugar de páginas. Cuando un usuario realiza una acción, como hacer clic en un enlace, que cargaría una nueva página en el navegador, el enrutador intercepta el comportamiento del navegador y muestra u oculta las jerarquías de vista.
|
||||
The router maps URL-like paths to views instead of pages. When a user performs an action, such as clicking a link, that would load a new page in the browser, the router intercepts the browser's behavior, and shows or hides view hierarchies.
|
||||
|
||||
Si el enrutador determina que el estado actual de la aplicación requiere una funcionalidad particular, y el módulo que lo define no se ha cargado, el enrutador puede hacer *cargar diferida* sobre el módulo bajo demanda.
|
||||
If the router determines that the current application state requires particular functionality, and the module that defines it hasn't been loaded, the router can *lazy-load* the module on demand.
|
||||
|
||||
El enrutador interpreta una URL de enlace de acuerdo con las reglas de navegación de visualización de la aplicación y el estado de los datos. Puedes navegar a las nuevas vistas cuando el usuario hace clic en un botón o selecciona desde un cuadro desplegable, o en respuesta a algún otro estímulo de cualquier fuente. El enrutador registra la actividad en el historial del navegador, por lo que los botones de retroceso y avance también funcionan.
|
||||
The router interprets a link URL according to your app's view navigation rules and data state. You can navigate to new views when the user clicks a button or selects from a drop box, or in response to some other stimulus from any source. The router logs activity in the browser's history, so the back and forward buttons work as well.
|
||||
|
||||
Para definir reglas de navegación, asocia *rutas de navegación* a tus componentes. Una ruta utiliza una sintaxis similar a una URL que integra los datos de tu programa, de la misma manera que la sintaxis de la plantilla integra tus vistas con los datos de tu programa. Luego puedes aplicar la lógica del programa para elegir qué vistas mostrar u ocultar, en respuesta a la entrada del usuario y a tus propias reglas de acceso.
|
||||
To define navigation rules, you associate *navigation paths* with your components. A path uses a URL-like syntax that integrates your program data, in much the same way that template syntax integrates your views with your program data. You can then apply program logic to choose which views to show or to hide, in response to user input and your own access rules.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Para más información, visita [Enrutamiento y navegación](guide/router).
|
||||
For a more detailed discussion, see [Routing and navigation](guide/router).
|
||||
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
## ¿Qué sigue?
|
||||
## What's next
|
||||
|
||||
Has aprendido los conceptos básicos sobre los bloques de construcción de una aplicación en Angular. El siguiente diagrama muestra cómo se relacionan estos conceptos básicos.
|
||||
You've learned the basics about the main building blocks of an Angular application. The following diagram shows how these basic pieces are related.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/architecture/overview2.png" alt="overview">
|
||||
</div>
|
||||
|
||||
* Juntos, un componente y una plantilla definen una vista en Angular.
|
||||
* Un decorador en una clase componente agrega los metadatos, incluido un apuntador a la plantilla asociada.
|
||||
* Las directivas y el enlace markup en la plantilla de un componente modifican las vistas basadas en los datos y la lógica del programa.
|
||||
* El inyector de dependencia proporciona servicios a un componente, como el servicio de enrutamiento que le permite definir la navegación entre vistas.
|
||||
* Together, a component and template define an Angular view.
|
||||
* A decorator on a component class adds the metadata, including a pointer to the associated template.
|
||||
* Directives and binding markup in a component's template modify views based on program data and logic.
|
||||
* The dependency injector provides services to a component, such as the router service that lets you define navigation among views.
|
||||
|
||||
Cada uno de estos temas se presenta con más detalle en las siguientes páginas.
|
||||
Each of these subjects is introduced in more detail in the following pages.
|
||||
|
||||
* [Introducción a los Módulos](guide/architecture-modules)
|
||||
* [Introduction to Modules](guide/architecture-modules)
|
||||
|
||||
* [Introducción a los Componentes](guide/architecture-components)
|
||||
* [Introduction to Components](guide/architecture-components)
|
||||
|
||||
* [Plantillas y Vistas](guide/architecture-components#templates-and-views)
|
||||
* [Templates and views](guide/architecture-components#templates-and-views)
|
||||
|
||||
* [Metadatos de Componentes](guide/architecture-components#component-metadata)
|
||||
* [Component metadata](guide/architecture-components#component-metadata)
|
||||
|
||||
* [Enlace de Datos](guide/architecture-components#data-binding)
|
||||
* [Data binding](guide/architecture-components#data-binding)
|
||||
|
||||
* [Directivas](guide/architecture-components#directives)
|
||||
* [Directives](guide/architecture-components#directives)
|
||||
|
||||
* [Pipes](guide/architecture-components#pipes)
|
||||
|
||||
* [Introducción a los Servicios e Inyección de Dependencias.](guide/architecture-services)
|
||||
* [Introduction to services and dependency injection](guide/architecture-services)
|
||||
|
||||
Cuando estés familiarizado con estos bloques de construcción fundamentales, podrás explorarlos con más detalle en la documentación. Para saber más acerca de las herramientas y técnicas disponibles para ayudarte a crear y desplegar aplicaciones de Angular, visita [Próximos pasos: herramientas y técnicas](guide/architecture-next-steps).
|
||||
When you're familiar with these fundamental building blocks, you can explore them in more detail in the documentation. To learn about more tools and techniques that are available to help you build and deploy Angular applications, see [Next steps: tools and techniques](guide/architecture-next-steps).
|
||||
</div>
|
||||
|
@ -1,303 +0,0 @@
|
||||
# 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.
|
@ -1,28 +1,33 @@
|
||||
# Enlaces de atributos, clases y estilos
|
||||
# Attribute, class, and style bindings
|
||||
|
||||
La sintaxis de la plantilla proporciona enlaces one-way especializados para escenarios menos adecuados para el enlace de propiedades.
|
||||
The template syntax provides specialized one-way bindings for scenarios less well-suited to property binding.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Consulta el <live-example></live-example> para ver un ejemplo práctico que contiene los fragmentos de código de esta guía.
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
## Enlace de atributo
|
||||
## Attribute binding
|
||||
|
||||
Establece el valor de un atributo directamente con un **enlace de atributo**. Esta es la única excepción a la regla de que un enlace establece una propiedad de destino y el único enlace que crea y establece un atributo.
|
||||
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.
|
||||
|
||||
Por lo general, establecer una propiedad de elemento con un [enlace de propiedad](guide/property-binding) es preferible establecer el atributo con una string. Sin embargo, a veces
|
||||
no hay ninguna propiedad de elemento para vincular, por lo que la vinculación de atributos es la solución.
|
||||
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.
|
||||
|
||||
Considera el [ARIA](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) y
|
||||
[SVG](https://developer.mozilla.org/en-US/docs/Web/SVG). Son puramente atributos, no corresponden a las propiedades del elemento y no establecen las propiedades del elemento. En estos casos, no hay objetivos de propiedad a los que vincularse.
|
||||
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.
|
||||
|
||||
La sintaxis de enlace de atributo se parece al enlace de propiedad, pero en lugar de una propiedad de elemento entre paréntesis, comienza con el prefijo `attr`, seguido de un punto (`.`) y el nombre del atributo.
|
||||
Luego establece el valor del atributo, utilizando una expresión que se resuelve en una string, o elimina el atributo cuando la expresión se resuelva en `null`.
|
||||
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`.
|
||||
|
||||
Uno de los casos de uso principales para el enlace de atributos es establecer atributos ARIA, como en este ejemplo:
|
||||
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>
|
||||
|
||||
@ -30,27 +35,28 @@ Uno de los casos de uso principales para el enlace de atributos es establecer at
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
#### `colspan` y `colSpan`
|
||||
#### `colspan` and `colSpan`
|
||||
|
||||
Observa la diferencia entre el atributo `colspan` y la propiedad `colSpan`.
|
||||
Notice the difference between the `colspan` attribute and the `colSpan` property.
|
||||
|
||||
Si escribes algo como esto:
|
||||
If you wrote something like this:
|
||||
|
||||
<code-example language="html">
|
||||
<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
|
||||
</code-example>
|
||||
|
||||
Recibirías este error:
|
||||
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>
|
||||
|
||||
Como dice el mensaje, el elemento `<td>` no tiene una propiedad `colspan`. Esto es verdad
|
||||
porque `colspan` es un atributo—`colSpan`, con una `S` mayúscula, es la propiedad correspondiente. La interpolación y el enlace de propiedades solo pueden establecer *propiedades*, no atributos.
|
||||
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.
|
||||
|
||||
En su lugar, puedes usar el enlace de propiedad y lo escribirías así:
|
||||
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>
|
||||
|
||||
@ -60,28 +66,28 @@ En su lugar, puedes usar el enlace de propiedad y lo escribirías así:
|
||||
|
||||
{@a class-binding}
|
||||
|
||||
## Enlace de clase
|
||||
## Class binding
|
||||
|
||||
Aquí se explica cómo configurar el atributo `class` sin un enlace en HTML simple:
|
||||
Here's how to set the `class` attribute without a binding in plain HTML:
|
||||
|
||||
```html
|
||||
<!-- standard class attribute setting -->
|
||||
<div class="foo bar">Algún texto</div>
|
||||
<div class="foo bar">Some text</div>
|
||||
```
|
||||
|
||||
También puedes agregar y eliminar nombres de clase CSS del atributo `class` de un elemento con un **enlace de clase**.
|
||||
You can also add and remove CSS class names from an element's `class` attribute with a **class binding**.
|
||||
|
||||
Para crear un enlace de clase único, comienza con el prefijo `class` seguido de un punto (`.`) y el nombre de la clase CSS (por ejemplo, `[class.foo]="hasFoo"`).
|
||||
Angular agrega la clase cuando la expresión enlazada es verdadera y elimina la clase cuando la expresión es falsa (con la excepción de `undefined`, vea [delegación de estilo](#styling-delegation)).
|
||||
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)).
|
||||
|
||||
Para crear un enlace a varias clases, usa un enlace genérico `[class]` sin el punto (por ejemplo, `[class]="classExpr"`).
|
||||
La expresión puede ser una string de nombres de clase delimitada por espacios, o puede formatearla como un objeto con nombres de clase como claves y expresiones de verdad / falsedad como valores.
|
||||
Con el formato de objeto, Angular agregará una clase solo si su valor asociado es verdadero.
|
||||
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.
|
||||
|
||||
Es importante tener en cuenta que con cualquier expresión similar a un objeto (`object`,`Array`, `Map`, `Set`, etc.), la identidad del objeto debe cambiar para que se actualice la lista de clases.
|
||||
Actualizar la propiedad sin cambiar la identidad del objeto no tendrá ningún efecto.
|
||||
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.
|
||||
|
||||
Si hay varios enlaces al mismo nombre de clase, los conflictos se resuelven usando [precedencia de estilo](#styling-precedence).
|
||||
If there are multiple bindings to the same class name, conflicts are resolved using [styling precedence](#styling-precedence).
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
@ -98,26 +104,26 @@ Si hay varios enlaces al mismo nombre de clase, los conflictos se resuelven usan
|
||||
</col>
|
||||
<tr>
|
||||
<th>
|
||||
Tipo de enlace
|
||||
Binding Type
|
||||
</th>
|
||||
<th>
|
||||
Sintaxis
|
||||
Syntax
|
||||
</th>
|
||||
<th>
|
||||
Tipo de entrada
|
||||
Input Type
|
||||
</th>
|
||||
<th>
|
||||
Ejemplo de valores de entrada
|
||||
Example Input Values
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Enlace de clase única</td>
|
||||
<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>Enlace de clases múltiples</td>
|
||||
<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>
|
||||
@ -133,43 +139,43 @@ Si hay varios enlaces al mismo nombre de clase, los conflictos se resuelven usan
|
||||
</table>
|
||||
|
||||
|
||||
La directiva [NgClass](guide/built-in-directives/#ngclass) se puede utilizar como alternativa a los enlaces directos `[class]`.
|
||||
Sin embargo, se prefiere usar la sintaxis de enlace de clase anterior sin `NgClass` porque debido a las mejoras en el enlace de clase en Angular, `NgClass` ya no proporciona un valor significativo y podría eliminarse en el futuro.
|
||||
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/>
|
||||
|
||||
{@a style-binding}
|
||||
## Style binding
|
||||
|
||||
## Enlace de estilo
|
||||
|
||||
Aquí se explica cómo configurar el atributo `style` sin un enlace en HTML simple:
|
||||
Here's how to set the `style` attribute without a binding in plain HTML:
|
||||
|
||||
```html
|
||||
<!-- standard style attribute setting -->
|
||||
<div style="color: blue">Algún texto</div>
|
||||
<div style="color: blue">Some text</div>
|
||||
```
|
||||
|
||||
También se puede establecer estilos dinámicamente con un **enlace de estilo**.
|
||||
You can also set styles dynamically with a **style binding**.
|
||||
|
||||
Para crear un enlace de estilo único, comienza con el prefijo `style` seguido de un punto (`.`) y el nombre de la propiedad de estilo CSS (por ejemplo, `[style.width]="width"`).
|
||||
La propiedad se establecerá en el valor de la expresión enlazada, que normalmente es una string.
|
||||
Opcionalmente, se puede agregar una extensión de unidad como `em` o `%`, que requiere un tipo de número.
|
||||
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">
|
||||
|
||||
Ten en cuenta que se puede escribir una _propiedad de estilo_ en [dash-case](guide/glossary#dash-case), como se muestra arriba, o [camelCase](guide/glossary#camelcase), como `fontSize`.
|
||||
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>
|
||||
|
||||
Si deseas alternar múltiples estilos, puedes vincular la propiedad `[style]` directamente sin el punto (por ejemplo, `[style]="styleExpr"`).
|
||||
La expresión asociada al enlace `[style]` suele ser una lista de string de estilos como `"width: 100px; height: 100px;"`.
|
||||
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;"`.
|
||||
|
||||
También se puede formatear la expresión como un objeto con nombres de estilo como claves y valores de estilo como los valores, como `{width: '100px', height: '100px'}`.
|
||||
Es importante tener en cuenta que con cualquier expresión similar a un objeto (`object`, `Array`, `Map`, `Set`, etc), la identidad del objeto debe cambiar para que se actualice la lista de clases.
|
||||
Actualizar la propiedad sin cambiar la identidad del objeto no tendrá ningún efecto.
|
||||
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.
|
||||
|
||||
Si hay varios enlaces a la misma propiedad de estilo, los conflictos se resuelven usando [reglas de precedencia de estilo](#styling-precedence).
|
||||
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}
|
||||
@ -186,33 +192,33 @@ Si hay varios enlaces a la misma propiedad de estilo, los conflictos se resuelve
|
||||
</col>
|
||||
<tr>
|
||||
<th>
|
||||
Tipo de enlace
|
||||
Binding Type
|
||||
</th>
|
||||
<th>
|
||||
Sintaxis
|
||||
Syntax
|
||||
</th>
|
||||
<th>
|
||||
Tipo de entrada
|
||||
Input Type
|
||||
</th>
|
||||
<th>
|
||||
Ejemplo de valores de entrada
|
||||
Example Input Values
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Enlace de estilo único</td>
|
||||
<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>Enlace de estilo único con unidades</td>
|
||||
<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>Enlace de múltiples estilos</td>
|
||||
<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>
|
||||
@ -227,71 +233,71 @@ Si hay varios enlaces a la misma propiedad de estilo, los conflictos se resuelve
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
La directiva [NgStyle](guide/built-in-directives/#ngstyle) se puede utilizar como alternativa a los enlaces directos `[style]`.
|
||||
Sin embargo, se prefiere usar la sintaxis de enlace de estilos anterior sin `NgStyle` porque debido a las mejoras en el enlace de estilos en Angular, `NgStyle` ya no proporciona un valor significativo y podría eliminarse en el futuro.
|
||||
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}
|
||||
|
||||
## Precedencia de estilo
|
||||
## Styling Precedence
|
||||
|
||||
Un único elemento HTML puede tener su lista de clases CSS y valores de estilo vinculados a múltiples fuentes (por ejemplo, enlaces de host de múltiples directivas).
|
||||
A single HTML element can have its CSS class list and style values bound to multiple sources (for example, host bindings from multiple directives).
|
||||
|
||||
Cuando hay varios enlaces al mismo nombre de clase o propiedad de estilo, Angular usa un conjunto de reglas de precedencia para resolver conflictos y determinar qué clases o estilos se aplican finalmente al elemento.
|
||||
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>Precedencia de estilo (de mayor a menor)</h4>
|
||||
<h4>Styling precedence (highest to lowest)</h4>
|
||||
|
||||
1. Enlaces de plantillas
|
||||
1. Enlace de propiedad (por ejemplo, `<div [class.foo]="hasFoo">` o `<div [style.color]="color">`)
|
||||
1. Enlace de mapa (por ejemplo, `<div [class]="classExpr">` o `<div [style]="styleExpr">`)
|
||||
1. Valor estático (por ejemplo, `<div class="foo">` o `<div style="color: blue">`)
|
||||
1. Enlaces de directivas hosts
|
||||
1. Enlace de propiedad (por ejemplo, `host: {'[class.foo]': 'hasFoo'}` o `host: {'[style.color]': 'color'}`)
|
||||
1. Enlace de mapa (por ejemplo, `host: {'[class]': 'classExpr'}` o `host: {'[style]': 'styleExpr'}`)
|
||||
1. Valor estático (por ejemplo, `host: {'class': 'foo'}` o `host: {'style': 'color: blue'}`)
|
||||
1. Enlaces de componentes hosts
|
||||
1. Enlace de propiedad (por ejemplo, `host: {'[class.foo]': 'hasFoo'}` o `host: {'[style.color]': 'color'}`)
|
||||
1. Enlace de mapa (por ejemplo, `host: {'[class]': 'classExpr'}` o `host: {'[style]': 'styleExpr'}`)
|
||||
1. Valor estático (por ejemplo, `host: {'class': 'foo'}` o `host: {'style': 'color: blue'}`)
|
||||
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>
|
||||
|
||||
Cuanto más específico sea un enlace de clase o estilo, mayor será su precedencia.
|
||||
The more specific a class or style binding is, the higher its precedence.
|
||||
|
||||
Un enlace a una clase específica (por ejemplo, `[class.foo]`) tendrá prioridad sobre un enlace genérico `[class]`, y un enlace a un estilo específico (por ejemplo, `[style.bar]`) tendrá prioridad sobre un enlace genérico `[style]`.
|
||||
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>
|
||||
|
||||
Las reglas de especificidad también se aplican cuando se trata de enlaces que se originan de diferentes fuentes.
|
||||
Es posible que un elemento tenga enlaces en la plantilla donde se declara, desde enlaces de host en directivas coincidentes y desde enlaces de host en componentes coincidentes.
|
||||
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.
|
||||
|
||||
Los enlaces de plantilla son los más específicos porque se aplican al elemento directa y exclusivamente, por lo que tienen la mayor prioridad.
|
||||
Template bindings are the most specific because they apply to the element directly and exclusively, so they have the highest precedence.
|
||||
|
||||
Los enlaces de host de directiva se consideran menos específicos porque las directivas se pueden usar en varias ubicaciones, por lo que tienen una precedencia menor que los enlaces de plantilla.
|
||||
Directive host bindings are considered less specific because directives can be used in multiple locations, so they have a lower precedence than template bindings.
|
||||
|
||||
Las directivas a menudo aumentan el comportamiento de los componentes, por lo que los enlaces de host de los componentes tienen la prioridad más baja.
|
||||
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>
|
||||
|
||||
Además, los enlaces tienen prioridad sobre los atributos estáticos.
|
||||
In addition, bindings take precedence over static attributes.
|
||||
|
||||
En el siguiente caso, `class` y `[class]` tienen una especificidad similar, pero el enlace `[class]` tendrá prioridad porque es dinámico.
|
||||
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}
|
||||
### Delegar a estilos con menor prioridad
|
||||
### Delegating to styles with lower precedence
|
||||
|
||||
Es posible que los estilos de precedencia más alta "deleguen" a los estilos de precedencia más bajos utilizando valores `undefined`.
|
||||
Mientras que establecer una propiedad de estilo en `null` asegura que el estilo se elimine, establecerlo en `undefined` hará que Angular vuelva al siguiente enlace de precedencia más alto para ese estilo.
|
||||
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.
|
||||
|
||||
Por ejemplo, considera la siguiente plantilla:
|
||||
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>
|
||||
|
||||
Imagina que la directiva `dirWithHostBinding` y el componente `comp-with-host-binding` tienen un enlace de host `[style.width]`.
|
||||
En ese caso, si `dirWithHostBinding` establece su enlace en `undefined`, la propiedad `width` volverá al valor del enlace de host del componente `comp-with-host-binding`.
|
||||
Sin embargo, si `dirWithHostBinding` establece su enlace en `null`, la propiedad `width` se eliminará por completo.
|
||||
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.
|
||||
|
@ -1,318 +0,0 @@
|
||||
|
||||
# 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>
|
||||
|
@ -1,21 +1,23 @@
|
||||
|
||||
# Sintaxis de Enlace: una visión general
|
||||
# Binding syntax: an overview
|
||||
|
||||
El enlace de datos es un mecanismo utilizado para coordinar los valores de los datos que los usuarios visualizan en la aplicación.
|
||||
Aunque puedas insertar y actualizar valores en el HTML, la aplicación es más fácil de escribir, leer y mantener si tu le dejas esas tareas al framework de enlace.
|
||||
Por lo que simplemente debes declarar enlaces entre los datos del modelo y los elementos HTML y dejar al framework que haga el resto del trabajo.
|
||||
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">
|
||||
|
||||
Consulta la <live-example>aplicación de muestra</live-example> que es un ejemplo funcional que contiene los fragmentos de código utilizados en esta guía.
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
Angular proporciona muchas formas para manejar el enlace de datos. Los tipos de enlace se pueden agrupar en tres categorías que se distinguen de acuerdo a la dirección del flujo de datos:
|
||||
Angular provides many kinds of data-binding. Binding types can be grouped into three categories distinguished by the direction of data flow:
|
||||
|
||||
* Desde el _modelo-hacia-vista_
|
||||
* Desde la _vista-hacia-modelo_
|
||||
* Secuencia Bidireccional: _vista-hacia-modelo-hacia-vista_
|
||||
* From the _source-to-view_
|
||||
* From _view-to-source_
|
||||
* Two-way sequence: _view-to-source-to-view_
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
@ -30,23 +32,23 @@ Angular proporciona muchas formas para manejar el enlace de datos. Los tipos de
|
||||
</col>
|
||||
<tr>
|
||||
<th>
|
||||
Tipo
|
||||
Type
|
||||
</th>
|
||||
<th>
|
||||
Sintaxis
|
||||
Syntax
|
||||
</th>
|
||||
<th>
|
||||
Categoría
|
||||
Category
|
||||
</th>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Interpolación<br>
|
||||
Propiedad<br>
|
||||
Atributo<br>
|
||||
Clase<br>
|
||||
Estilos
|
||||
Interpolation<br>
|
||||
Property<br>
|
||||
Attribute<br>
|
||||
Class<br>
|
||||
Style
|
||||
</td>
|
||||
<td>
|
||||
|
||||
@ -59,11 +61,11 @@ Angular proporciona muchas formas para manejar el enlace de datos. Los tipos de
|
||||
</td>
|
||||
|
||||
<td>
|
||||
Una sola dirección<br>desde el modelo de datos<br>hacia la vista
|
||||
One-way<br>from data source<br>to view target
|
||||
</td>
|
||||
<tr>
|
||||
<td>
|
||||
Evento
|
||||
Event
|
||||
</td>
|
||||
<td>
|
||||
<code-example>
|
||||
@ -73,12 +75,12 @@ Angular proporciona muchas formas para manejar el enlace de datos. Los tipos de
|
||||
</td>
|
||||
|
||||
<td>
|
||||
Una sola dirección<br>desde la vista<br>hacia el modelo de datos
|
||||
One-way<br>from view target<br>to data source
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Bidireccional
|
||||
Two-way
|
||||
</td>
|
||||
<td>
|
||||
<code-example>
|
||||
@ -87,123 +89,132 @@ Angular proporciona muchas formas para manejar el enlace de datos. Los tipos de
|
||||
</code-example>
|
||||
</td>
|
||||
<td>
|
||||
Bidireccional
|
||||
Two-way
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Los tipos de enlace distintos a la interporlación tienen un **nombre de destino** hacia la izquierda del signo igual, están rodeados por los signos de puntación `[]` o `()`, o bien están precedidos por el prefijo: `bind-`, `on-`, `bindon-`.
|
||||
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-`.
|
||||
|
||||
El *destino* de un enlace es la propiedad o evento situado dentro de los signos de puntuación: `[]`, `()` or `[()]`.
|
||||
The *target* of a binding is the property or event inside the binding punctuation: `[]`, `()` or `[()]`.
|
||||
|
||||
Cada miembro <span class="x x-first x-last">público</span> de una directiva **fuente** <span class="x x-first x-last">está</span> disponible automaticamente para ser utilizada con los enlaces.
|
||||
No es necesario hacer nada especial para poder acceder al miembro de una directiva en una expresión o declaración de plantilla.
|
||||
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.
|
||||
|
||||
### Enlace de Datos y el HTML
|
||||
|
||||
En condiciones normales para un desarrollo HTML, primero se crea la estructura visual con los elementos HTML y luego se modifican dichos elementos estableciendo los atributos de dichos elementos utilizando una cadena de caracteres.
|
||||
### 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">HTML Simple</div>
|
||||
<div class="special">Plain old HTML</div>
|
||||
<img src="images/item.png">
|
||||
<button disabled>Guardar</button>
|
||||
<button disabled>Save</button>
|
||||
```
|
||||
|
||||
Usando el enlace de datos, puedes controlar cosas como el estado de un botón:
|
||||
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>
|
||||
|
||||
Puedes notar que el enlace se realiza a la propiedad `disabled` del elemento botón del DOM,
|
||||
**no** al atributo. Esto aplica al enlace de datos en general. El enlace de datos funciona con las *propiedades* de los elementos, componentes y directivas del DOM, no con los *atributos* HTML
|
||||
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}
|
||||
|
||||
### Atributos HTML vs. Propiedades del DOM
|
||||
### HTML attribute vs. DOM property
|
||||
|
||||
Distinguir la diferencia entre un atributo HTML y una propiedad del DOM es clave para comprender como funciona el enlace en Angular. **Los attributos son definidos por el HTML. Las propiedades se acceden desde los nodos del DOM (Document Object Model).**
|
||||
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.**
|
||||
|
||||
* Muy pocos atributos HTML tienen una relación 1:1 con las propiedades; por ejemplo el, `id`.
|
||||
* A few HTML attributes have 1:1 mapping to properties; for example, `id`.
|
||||
|
||||
* Algunos atributos HTML no tienen su correspondencia en propiedades; como por ejemplo, `aria-*`.
|
||||
* Some HTML attributes don't have corresponding properties; for example, `aria-*`.
|
||||
|
||||
* Algunas propiedades del DOM no tienen su correspondencia hacia atributos; como por ejemplo, `textContent`.
|
||||
* Some DOM properties don't have corresponding attributes; for example, `textContent`.
|
||||
|
||||
Es importante recordar que los *atributos HTML* y las *propiedades del DOM* son cosas muy diferentes, incluso cuando tienen el mismo nombre.
|
||||
En Angular, el único rol de los atributos HTML es el de inicializar el estado de los elementos y las directivas.
|
||||
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.
|
||||
|
||||
**El enlace de plantilla funciona con *propiedades* y *eventos*, no con *atributos*.**
|
||||
**Template binding works with *properties* and *events*, not *attributes*.**
|
||||
|
||||
Cuando escribes un enlace de datos, se trata exclusivamente sobre las *propiedades del DOM* and *eventos* del objeto de destino.
|
||||
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">
|
||||
|
||||
Esta regla general puede ayudarnos a crear un modelo mental de los atributos y las propiedades del DOM:
|
||||
**Los atributos inicializan las propiedades del DOM y cuando eso ya esta hecho, los valores de las propiedades pueden cambiar, mientras que los atributos no lo pueden hacer.**
|
||||
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.**
|
||||
|
||||
Solamente hay una excepción a la regla.
|
||||
Los atributos pueden cambiarse usando el método `setAttribute()`, el cual re-inicializa las propiedades del DOM correspondientes.
|
||||
There is one exception to this rule.
|
||||
Attributes can be changed by `setAttribute()`, which re-initializes corresponding DOM properties.
|
||||
|
||||
</div>
|
||||
|
||||
Para más información, consulta la [Documentación de Interfaces MDN](https://developer.mozilla.org/en-US/docs/Web/API#Interfaces) que contiene los documentos de la API para todos los elementos estándar del DOM y sus propiedades.
|
||||
Comparar los atributos [`<td>` atributos](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td) con las propiedades [`<td>` propiedades](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement) nos proporciona un ejemplo útil para poder diferenciar estos dos términos de una mejor manera.
|
||||
En particular, se puede navegar de la página de atributos a la página de propiedades por medio del enlace "Interfaz del DOM", y navegar la jerarquía de la herencia hasta `HTMLTableCellElement`.
|
||||
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) 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`.
|
||||
|
||||
|
||||
#### Ejemplo 1: un `<input>`
|
||||
#### Example 1: an `<input>`
|
||||
|
||||
Cuando el navegador renderiza `<input type="text" value="Sarah">`, este crea un nodo correspondiente en el DOM con la propiedad `value` inicializada con el valor de "Sarah".
|
||||
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">
|
||||
```
|
||||
|
||||
Cuando el usuario ingresa "Sally" dentro del `<input>`, la **propiedad** `value` del elemento del DOM se convierte en "Sally".
|
||||
Sin embargo, si tu revisas el atributo HTML `value` usando el método `input.getAttribute('value')`, puedes notar que el *atributo* no ha cambiado—por lo que returna el valor de "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".
|
||||
|
||||
El atributo HTML `value` especifica el valor *inicial*; la propiedad del DOM `value` es el valor *actual*.
|
||||
The HTML attribute `value` specifies the *initial* value; the DOM `value` property is the *current* value.
|
||||
|
||||
Para consultar los atributos vs las propiedades del DOM en una aplicación funcional, consulta la <live-example name="binding-syntax">aplicación</live-example> en especial para repasar la sintaxis de enlace.
|
||||
To see attributes versus DOM properties in a functioning app, see the <live-example name="binding-syntax"></live-example> especially for binding syntax.
|
||||
|
||||
#### Ejemplo 2: un botón desactivado
|
||||
#### Example 2: a disabled button
|
||||
|
||||
El atributo `disabled` es otro ejemplo. La *propiedad* del botón `disabled`
|
||||
*property* es `false` por defecto así que el botón esta activo.
|
||||
The `disabled` attribute is another example. A button's `disabled`
|
||||
*property* is `false` by default so the button is enabled.
|
||||
|
||||
Cuando añades el *atributo* `disabled`, su sola presencia inicializa la *propiedad* del botón `disabled` con el valor de `true` por lo que el botón esta desactivado.
|
||||
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>Botón de Ejemplo</button>
|
||||
<button disabled>Test Button</button>
|
||||
```
|
||||
|
||||
Añadir y eliminar el *atributo* `disabled` desactiva y activa el botón.
|
||||
Sin embargo, el valor del *atributo* es irrelevante,
|
||||
lo cual es la razón del por qué no puedes activar un botón escribiendo `<button disabled="false">Todavía Desactivado</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>`.
|
||||
|
||||
Para controlar el estado de un botón, establece la *propiedad* `disabled`.
|
||||
To control the state of the button, set the `disabled` *property*,
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Aunque técnicamente podrías establecer el enlace de atributo `[attr.disabled]`, los valores son diferentes ya que el enlace de propiedad necesita un valor booleano, mientras que el enlace de atributo correspondiente depende de que su valor sea `null` o no. Por lo que considera lo siguiente:
|
||||
Though you could technically set the `[attr.disabled]` attribute binding, the values are different in that the property binding requires to be 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">
|
||||
```
|
||||
|
||||
Por lo general usa enlace de propiedades sobre enlace de atributos ya que es más intuitivo (siendo un valor booleano), tienen una sintaxis corta y es más eficaz.
|
||||
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>
|
||||
|
||||
Para ver el ejemplo del botón `disabled`, consulta la <live-example name="binding-syntax">aplicación</live-example> en especial para revisar la sintaxis de enlace. Este ejemplo muestra como alternar la propiedad disabled desde el componente.
|
||||
|
||||
## Tipos de enlace y objetivos
|
||||
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.
|
||||
|
||||
El **objetivo de un enlace de datos** se relaciona con algo del DOM.
|
||||
Dependiendo del tipo de enlace, el objetivo puede ser una propiedad (elemento, componente, o directiva),
|
||||
un evento (elemento, componente o directiva), o incluso algunas veces el nombre de un atributo.
|
||||
La siguiente tabla recoge los objetivos para los diferentes tipos de enlace.
|
||||
## 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}
|
||||
@ -218,23 +229,23 @@ La siguiente tabla recoge los objetivos para los diferentes tipos de enlace.
|
||||
</col>
|
||||
<tr>
|
||||
<th>
|
||||
Tipo
|
||||
Type
|
||||
</th>
|
||||
<th>
|
||||
Objetivo
|
||||
Target
|
||||
</th>
|
||||
<th>
|
||||
Ejemplos
|
||||
Examples
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Propiedad
|
||||
Property
|
||||
</td>
|
||||
<td>
|
||||
Propiedad del elemento<br>
|
||||
Propiedad del componente<br>
|
||||
Propiedad de la directiva
|
||||
Element property<br>
|
||||
Component property<br>
|
||||
Directive property
|
||||
</td>
|
||||
<td>
|
||||
<code>src</code>, <code>hero</code>, and <code>ngClass</code> in the following:
|
||||
@ -244,12 +255,12 @@ La siguiente tabla recoge los objetivos para los diferentes tipos de enlace.
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Evento
|
||||
Event
|
||||
</td>
|
||||
<td>
|
||||
Evento del elemento<br>
|
||||
Evento del componente<br>
|
||||
Evento de la directiva
|
||||
Element event<br>
|
||||
Component event<br>
|
||||
Directive event
|
||||
</td>
|
||||
<td>
|
||||
<code>click</code>, <code>deleteRequest</code>, and <code>myClick</code> in the following:
|
||||
@ -260,10 +271,10 @@ La siguiente tabla recoge los objetivos para los diferentes tipos de enlace.
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Bidireccional
|
||||
Two-way
|
||||
</td>
|
||||
<td>
|
||||
Eventos y propiedades
|
||||
Event and property
|
||||
</td>
|
||||
<td>
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="2-way-binding-syntax-1"></code-example>
|
||||
@ -271,11 +282,11 @@ La siguiente tabla recoge los objetivos para los diferentes tipos de enlace.
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Atributo
|
||||
Attribute
|
||||
</td>
|
||||
<td>
|
||||
Atributo
|
||||
(la excepción)
|
||||
Attribute
|
||||
(the exception)
|
||||
</td>
|
||||
<td>
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="attribute-binding-syntax-1"></code-example>
|
||||
@ -283,10 +294,10 @@ La siguiente tabla recoge los objetivos para los diferentes tipos de enlace.
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Clase
|
||||
Class
|
||||
</td>
|
||||
<td>
|
||||
Propiedad de una <code>clase</code>
|
||||
<code>class</code> property
|
||||
</td>
|
||||
<td>
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="class-binding-syntax-1"></code-example>
|
||||
@ -294,13 +305,14 @@ La siguiente tabla recoge los objetivos para los diferentes tipos de enlace.
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Estilos
|
||||
Style
|
||||
</td>
|
||||
<td>
|
||||
Propiedad de un <code>estilo</code>
|
||||
<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>
|
||||
|
||||
|
@ -1,174 +0,0 @@
|
||||
# Launching your app with a root module
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
A basic understanding of the following:
|
||||
* [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule).
|
||||
|
||||
<hr />
|
||||
|
||||
An NgModule describes how the application parts fit together.
|
||||
Every application has at least one Angular module, the _root_ module,
|
||||
which must be present for bootstrapping the application on launch.
|
||||
By convention and by default, this NgModule is named `AppModule`.
|
||||
|
||||
When you use the [Angular CLI](cli) command `ng new` to generate an app, the default `AppModule` is as follows.
|
||||
|
||||
```typescript
|
||||
/* JavaScript imports */
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
/* the AppModule class with the @NgModule decorator */
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
HttpClientModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
||||
|
||||
```
|
||||
|
||||
After the import statements is a class with the
|
||||
**`@NgModule`** [decorator](guide/glossary#decorator '"Decorator" explained').
|
||||
|
||||
The `@NgModule` decorator identifies `AppModule` as an `NgModule` class.
|
||||
`@NgModule` takes a metadata object that tells Angular how to compile and launch the application.
|
||||
|
||||
* **_declarations_**—this application's lone component.
|
||||
* **_imports_**—import `BrowserModule` to have browser specific services such as DOM rendering, sanitization, and location.
|
||||
* **_providers_**—the service providers.
|
||||
* **_bootstrap_**—the _root_ component that Angular creates and inserts
|
||||
into the `index.html` host web page.
|
||||
|
||||
The default application created by the Angular CLI only has one component, `AppComponent`, so it
|
||||
is in both the `declarations` and the `bootstrap` arrays.
|
||||
|
||||
{@a declarations}
|
||||
|
||||
## The `declarations` array
|
||||
|
||||
The module's `declarations` array tells Angular which components belong to that module.
|
||||
As you create more components, add them to `declarations`.
|
||||
|
||||
You must declare every component in exactly one `NgModule` class.
|
||||
If you use a component without declaring it, Angular returns an
|
||||
error message.
|
||||
|
||||
The `declarations` array only takes declarables. Declarables
|
||||
are components, [directives](guide/attribute-directives) and [pipes](guide/pipes).
|
||||
All of a module's declarables must be in the `declarations` array.
|
||||
Declarables must belong to exactly one module. The compiler emits
|
||||
an error if you try to declare the same class in more than one module.
|
||||
|
||||
These declared classes are visible within the module but invisible
|
||||
to components in a different module unless they are exported from
|
||||
this module and the other module imports this one.
|
||||
|
||||
An example of what goes into a declarations array follows:
|
||||
|
||||
```typescript
|
||||
declarations: [
|
||||
YourComponent,
|
||||
YourPipe,
|
||||
YourDirective
|
||||
],
|
||||
```
|
||||
|
||||
A declarable can only belong to one module, so only declare it in
|
||||
one `@NgModule`. When you need it elsewhere,
|
||||
import the module that has the declarable you need in it.
|
||||
|
||||
**Only `@NgModule` references** go in the `imports` array.
|
||||
|
||||
|
||||
### Using directives with `@NgModule`
|
||||
|
||||
Use the `declarations` array for directives.
|
||||
To use a directive, component, or pipe in a module, you must do a few things:
|
||||
|
||||
1. Export it from the file where you wrote it.
|
||||
2. Import it into the appropriate module.
|
||||
3. Declare it in the `@NgModule` `declarations` array.
|
||||
|
||||
|
||||
Those three steps look like the following. In the file where you create your directive, export it.
|
||||
The following example, named `ItemDirective` is the default directive structure that the CLI generates in its own file, `item.directive.ts`:
|
||||
|
||||
<code-example path="bootstrapping/src/app/item.directive.ts" region="directive" header="src/app/item.directive.ts"></code-example>
|
||||
|
||||
The key point here is that you have to export it so you can import it elsewhere. Next, import it
|
||||
into the `NgModule`, in this example `app.module.ts`, with a JavaScript import statement:
|
||||
|
||||
<code-example path="bootstrapping/src/app/app.module.ts" region="directive-import" header="src/app/app.module.ts"></code-example>
|
||||
|
||||
And in the same file, add it to the `@NgModule` `declarations` array:
|
||||
|
||||
<code-example path="bootstrapping/src/app/app.module.ts" region="declarations" header="src/app/app.module.ts"></code-example>
|
||||
|
||||
|
||||
Now you could use your `ItemDirective` in a component. This example uses `AppModule`, but you'd do it the same way for a feature module. For more about directives, see [Attribute Directives](guide/attribute-directives) and [Structural Directives](guide/structural-directives). You'd also use the same technique for [pipes](guide/pipes) and components.
|
||||
|
||||
Remember, components, directives, and pipes belong to one module only. You only need to declare them once in your app because you share them by importing the necessary modules. This saves you time and helps keep your app lean.
|
||||
|
||||
|
||||
|
||||
|
||||
{@a imports}
|
||||
|
||||
## The `imports` array
|
||||
|
||||
The module's `imports` array appears exclusively in the `@NgModule` metadata object.
|
||||
It tells Angular about other NgModules that this particular module needs to function properly.
|
||||
|
||||
This list of modules are those that export components, directives, or pipes
|
||||
that the component templates in this module reference. In this case, the component is
|
||||
`AppComponent`, which references components, directives, or pipes in `BrowserModule`,
|
||||
`FormsModule`, or `HttpClientModule`.
|
||||
A component template can reference another component, directive,
|
||||
or pipe when the referenced class is declared in this module or
|
||||
the class was imported from another module.
|
||||
|
||||
{@a bootstrap-array}
|
||||
|
||||
## The `providers` array
|
||||
|
||||
The providers array is where you list the services the app needs. When
|
||||
you list services here, they are available app-wide. You can scope
|
||||
them when using feature modules and lazy loading. For more information, see
|
||||
[Providers](guide/providers).
|
||||
|
||||
## The `bootstrap` array
|
||||
|
||||
The application launches by bootstrapping the root `AppModule`, which is
|
||||
also referred to as an `entryComponent`.
|
||||
Among other things, the bootstrapping process creates the component(s) listed in the `bootstrap` array
|
||||
and inserts each one into the browser DOM.
|
||||
|
||||
Each bootstrapped component is the base of its own tree of components.
|
||||
Inserting a bootstrapped component usually triggers a cascade of
|
||||
component creations that fill out that tree.
|
||||
|
||||
While you can put more than one component tree on a host web page,
|
||||
most applications have only one component tree and bootstrap a single root component.
|
||||
|
||||
This one root component is usually called `AppComponent` and is in the
|
||||
root module's `bootstrap` array.
|
||||
|
||||
|
||||
|
||||
## More about Angular Modules
|
||||
|
||||
For more on NgModules you're likely to see frequently in apps,
|
||||
see [Frequently Used Modules](guide/frequent-ngmodules).
|
@ -1,25 +1,23 @@
|
||||
# Lanzando tu aplicación con un módulo raíz
|
||||
# Launching your app with a root module
|
||||
|
||||
#### Pre-requisitos
|
||||
#### Prerequisites
|
||||
|
||||
Una comprensión básica de lo siguiente:
|
||||
A basic understanding of the following:
|
||||
* [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule).
|
||||
|
||||
<hr />
|
||||
|
||||
Un NgModule describe cómo encajan las partes de la aplicación.
|
||||
Cada aplicación tiene al menos un módulo Angular, el módulo _root_,
|
||||
que debe estar presente para arrancar la aplicación en el lanzamiento inicial.
|
||||
Por convención y por defecto, este NgModule se llama `AppModule`.
|
||||
An NgModule describes how the application parts fit together.
|
||||
Every application has at least one Angular module, the _root_ module,
|
||||
which must be present for bootstrapping the application on launch.
|
||||
By convention and by default, this NgModule is named `AppModule`.
|
||||
|
||||
Cuando se usa el comando de [Angular CLI](cli) `ng new` para generar una aplicación, el `AppModule` predeterminado es el siguiente.
|
||||
When you use the [Angular CLI](cli) command `ng new` to generate an app, the default `AppModule` looks like the following:
|
||||
|
||||
```typescript
|
||||
/* JavaScript imports */
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
@ -29,9 +27,7 @@ import { AppComponent } from './app.component';
|
||||
AppComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
HttpClientModule
|
||||
BrowserModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
@ -40,44 +36,43 @@ export class AppModule { }
|
||||
|
||||
```
|
||||
|
||||
Después de las declaraciones de importación hay una clase con
|
||||
[decorador](guide/glossary#decorator 'Explicando "Decorator"') **`@NgModule`**.
|
||||
After the import statements is a class with the
|
||||
**`@NgModule`** [decorator](guide/glossary#decorator '"Decorator" explained').
|
||||
|
||||
El decorador `@NgModule` identifica `AppModule` como una clase `NgModule`.
|
||||
`@NgModule` toma un objeto de metadatos que le dice a Angular cómo compilar e iniciar la aplicación.
|
||||
The `@NgModule` decorator identifies `AppModule` as an `NgModule` class.
|
||||
`@NgModule` takes a metadata object that tells Angular how to compile and launch the application.
|
||||
|
||||
* **_declarations_**— el único componente de esta aplicación..
|
||||
* **_imports_**— importar `BrowserModule` para tener servicios específicos del navegador como renderizado DOM, sanitization y ubicación.
|
||||
* **_providers_**— los proveedores de servicios.
|
||||
* **_bootstrap_**— el componente raíz que Angular crea e inserta
|
||||
en la página web de host `index.html`.
|
||||
* **_declarations_**—this application's lone component.
|
||||
* **_imports_**—import `BrowserModule` to have browser specific services such as DOM rendering, sanitization, and location.
|
||||
* **_providers_**—the service providers.
|
||||
* **_bootstrap_**—the _root_ component that Angular creates and inserts
|
||||
into the `index.html` host web page.
|
||||
|
||||
La aplicación predeterminada creada por Angular CLI solo tiene un componente, `AppComponent`, por lo que
|
||||
está en los arrays de `declarations` y `bootstrap`.
|
||||
The default application created by the Angular CLI only has one component, `AppComponent`, so it
|
||||
is in both the `declarations` and the `bootstrap` arrays.
|
||||
|
||||
{@a the-declarations-array}
|
||||
{@a declarations}
|
||||
|
||||
## El array `declarations`
|
||||
## The `declarations` array
|
||||
|
||||
El array de `declarations` le dice a Angular qué componentes pertenecen a ese módulo.
|
||||
A medida que crees más componentes, agrégalos a las `declarations`.
|
||||
The module's `declarations` array tells Angular which components belong to that module.
|
||||
As you create more components, add them to `declarations`.
|
||||
|
||||
Debe declarar cada componente en exactamente una clase `NgModule`.
|
||||
Si se usa un componente sin declararlo, Angular devuelve un
|
||||
mensaje de error.
|
||||
You must declare every component in exactly one `NgModule` class.
|
||||
If you use a component without declaring it, Angular returns an
|
||||
error message.
|
||||
|
||||
El array `declarations` solo acepta declarables. Declarables pueden ser
|
||||
componentes, [directivas](guide/attribute-directives) y [pipes](guide/pipes).
|
||||
Todos los declarables de un módulo deben estar en el array de `declarations`.
|
||||
Los declarables deben pertenecer exactamente a un módulo. El compilador emite
|
||||
un error si se intenta declarar la misma clase en más de un módulo.
|
||||
The `declarations` array only takes declarables. Declarables
|
||||
are components, [directives](guide/attribute-directives) and [pipes](guide/pipes).
|
||||
All of a module's declarables must be in the `declarations` array.
|
||||
Declarables must belong to exactly one module. The compiler emits
|
||||
an error if you try to declare the same class in more than one module.
|
||||
|
||||
Estas clases declaradas son visibles dentro del módulo pero invisibles
|
||||
a componentes en un módulo diferente, a menos que se exporten desde
|
||||
éste módulo y el otro módulo importe éste mismo módulo.
|
||||
These declared classes are visible within the module but invisible
|
||||
to components in a different module unless they are exported from
|
||||
this module and the other module imports this one.
|
||||
|
||||
A continuación, se muestra un ejemplo de un array `declarations`:
|
||||
An example of what goes into a declarations array follows:
|
||||
|
||||
```typescript
|
||||
declarations: [
|
||||
@ -87,86 +82,92 @@ A continuación, se muestra un ejemplo de un array `declarations`:
|
||||
],
|
||||
```
|
||||
|
||||
Un declarable solo puede pertenecer a un módulo, por lo que solo debe ser declarado en
|
||||
un `@NgModule`. Cuando se necesite en otro lugar,
|
||||
importa el módulo que tiene el declarable que necesites.
|
||||
|
||||
**Solo las referencias de `@NgModule`** van en el array `imports`.
|
||||
A declarable can only belong to one module, so only declare it in
|
||||
one `@NgModule`. When you need it elsewhere,
|
||||
import the module that has the declarable you need in it.
|
||||
|
||||
|
||||
### Usando directivas con `@NgModule`
|
||||
### Using directives with `@NgModule`
|
||||
|
||||
Usa el array `declarations` para las directivas.
|
||||
Para usar una directiva, un componente o un pipe en un módulo, hay que hacer algunas cosas:
|
||||
Use the `declarations` array for directives.
|
||||
To use a directive, component, or pipe in a module, you must do a few things:
|
||||
|
||||
1. Exportarlo desde el archivo donde se escribió.
|
||||
2. Importarlo al módulo apropiado.
|
||||
3. Declararlo en el array `declarations` del `@NgModule`.
|
||||
1. Export it from the file where you wrote it.
|
||||
2. Import it into the appropriate module.
|
||||
3. Declare it in the `@NgModule` `declarations` array.
|
||||
|
||||
|
||||
Esos tres pasos se parecen a los siguientes. En el archivo donde se crea la directiva, expórtalo.
|
||||
El siguiente ejemplo, llamado `ItemDirective` es la estructura de directiva predeterminada que la CLI genera en su propio archivo, `item.directive.ts`:
|
||||
Those three steps look like the following. In the file where you create your directive, export it.
|
||||
The following example, named `ItemDirective` is the default directive structure that the CLI generates in its own file, `item.directive.ts`:
|
||||
|
||||
<code-example path="bootstrapping/src/app/item.directive.ts" region="directive" header="src/app/item.directive.ts"></code-example>
|
||||
|
||||
El punto clave aquí es que se debe exportar para poder importarlo en otro lugar. A continuación, importar
|
||||
en el `NgModule`, en este ejemplo, `app.module.ts` con una declaración de importación de JavaScript:
|
||||
The key point here is that you have to export it so you can import it elsewhere. Next, import it
|
||||
into the `NgModule`, in this example `app.module.ts`, with a JavaScript import statement:
|
||||
|
||||
<code-example path="bootstrapping/src/app/app.module.ts" region="directive-import" header="src/app/app.module.ts"></code-example>
|
||||
|
||||
Y en el mismo archivo, agregarlo al array `declarations` del `@ NgModule`:
|
||||
And in the same file, add it to the `@NgModule` `declarations` array:
|
||||
|
||||
<code-example path="bootstrapping/src/app/app.module.ts" region="declarations" header="src/app/app.module.ts"></code-example>
|
||||
|
||||
|
||||
Ahora puedes usar tu `ItemDirective` en un componente. Este ejemplo usa `AppModule`, pero se haría de la misma manera para un módulo de funciones. Para obtener más información sobre las directivas, consulta [Directivas de atributos](guide/attribute-directives) y [Directivas estructurales](guide/structural-directives). También se usaría la misma técnica para [pipes](guide/pipes) y componentes.
|
||||
|
||||
Recuerda, los componentes, directivas y pipes pertenecen a un solo módulo. Solo se necesita declararlos una vez en tu aplicación porque se comparten importando los módulos necesarios. Esto ahorra tiempo y ayuda a mantener la aplicación optimizada.
|
||||
Now you could use your `ItemDirective` in a component. This example uses `AppModule`, but you'd do it the same way for a feature module. For more about directives, see [Attribute Directives](guide/attribute-directives) and [Structural Directives](guide/structural-directives). You'd also use the same technique for [pipes](guide/pipes) and components.
|
||||
|
||||
Remember, components, directives, and pipes belong to one module only. You only need to declare them once in your app because you share them by importing the necessary modules. This saves you time and helps keep your app lean.
|
||||
|
||||
{@a imports}
|
||||
|
||||
## El array de `imports`
|
||||
## The `imports` array
|
||||
|
||||
The module's `imports` array appears exclusively in the `@NgModule` metadata object.
|
||||
It tells Angular about other NgModules that this particular module needs to function properly.
|
||||
|
||||
<code-example
|
||||
path="bootstrapping/src/app/app.module.ts"
|
||||
region="imports"
|
||||
header="src/app/app.module.ts (excerpt)">
|
||||
</code-example>
|
||||
|
||||
This list of modules are those that export components, directives, or pipes
|
||||
that component templates in this module reference. In this case, the component is
|
||||
`AppComponent`, which references components, directives, or pipes in `BrowserModule`,
|
||||
`FormsModule`, or `HttpClientModule`.
|
||||
A component template can reference another component, directive,
|
||||
or pipe when the referenced class is declared in this module or
|
||||
the class was imported from another module.
|
||||
|
||||
El array de `imports` del módulo aparece exclusivamente en el objeto de metadatos del `@NgModule`.
|
||||
Le dice a Angular sobre otros NgModules que este módulo en particular necesita para funcionar correctamente.
|
||||
|
||||
Esta lista de módulos son los que exportan componentes, directivas o pipes
|
||||
que las plantillas de componentes en este módulo hacen referencia. En este caso, el componente es
|
||||
`AppComponent`, que hace referencia a componentes, directivas o pipes en `BrowserModule`,
|
||||
`FormsModule`, o `HttpClientModule`.
|
||||
Una plantilla de componente puede hacer referencia a otro componente, directiva,
|
||||
o pipe cuando la clase referenciada se declara en este módulo o
|
||||
la clase se importó de otro módulo.
|
||||
|
||||
{@a bootstrap-array}
|
||||
|
||||
## El array `providers`
|
||||
## The `providers` array
|
||||
|
||||
El array `providers` es donde se enumeran los servicios que necesita la aplicación. Cuando
|
||||
enumera los servicios, están disponibles en toda la aplicación. Puedes reducir el scope
|
||||
al usar módulos de funciones y carga diferida. Para más información, ver
|
||||
[Proveedores](guide/providers).
|
||||
The providers array is where you list the services the app needs. When
|
||||
you list services here, they are available app-wide. You can scope
|
||||
them when using feature modules and lazy loading. For more information, see
|
||||
[Providers](guide/providers).
|
||||
|
||||
## El array `bootstrap`
|
||||
## The `bootstrap` array
|
||||
|
||||
La aplicación se inicia haciendo bootstraping desde la raíz `AppModule`, que es
|
||||
también conocido como `entryComponent`.
|
||||
Entre otras cosas, el proceso de carga crea los componentes enumerados en el array de `bootstrap`
|
||||
e inserta cada uno en el DOM del navegador.
|
||||
The application launches by bootstrapping the root `AppModule`, which is
|
||||
also referred to as an `entryComponent`.
|
||||
Among other things, the bootstrapping process creates the component(s) listed in the `bootstrap` array
|
||||
and inserts each one into the browser DOM.
|
||||
|
||||
Cada componente bootstrap es la base de su propio árbol de componentes.
|
||||
La inserción de un componente bootstrapped generalmente desencadena una cascada de
|
||||
creaciones de componentes que completan ese árbol.
|
||||
Each bootstrapped component is the base of its own tree of components.
|
||||
Inserting a bootstrapped component usually triggers a cascade of
|
||||
component creations that fill out that tree.
|
||||
|
||||
Si bien puedes colocar más de un árbol de componentes en una página web de host,
|
||||
la mayoría de las aplicaciones tienen solo un árbol de componentes y arrancan un solo componente raíz.
|
||||
While you can put more than one component tree on a host web page,
|
||||
most applications have only one component tree and bootstrap a single root component.
|
||||
|
||||
Este componente raíz se suele llamar `AppComponent` y se encuentra en el
|
||||
array `bootstrap` del módulo raíz.
|
||||
This one root component is usually called `AppComponent` and is in the
|
||||
root module's `bootstrap` array.
|
||||
|
||||
|
||||
## Más sobre módulos Angular
|
||||
|
||||
Para obtener más información sobre NgModules que probablemente veas con frecuencia en las aplicaciones,
|
||||
consulta [Módulos de uso frecuente](guide/frequent-ngmodules).
|
||||
## More about Angular Modules
|
||||
|
||||
For more on NgModules you're likely to see frequently in apps,
|
||||
see [Frequently Used Modules](guide/frequent-ngmodules).
|
||||
|
@ -10,7 +10,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><b>platformBrowserDynamic().bootstrapModule</b>(AppModule);</code></td>
|
||||
<td><p>Carga la app, usando el componente raíz del <code>NgModule</code> especificado.</p>
|
||||
<td><p>Bootstraps the app, using the root component from the specified <code>NgModule</code>. </p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
@ -24,371 +24,370 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>@<b>NgModule</b>({ declarations: ..., imports: ...,<br> exports: ..., providers: ..., bootstrap: ...})<br>class MyModule {}</code></td>
|
||||
<td><p>Define un módulo que contiene componentes, directivas, pipes y proveedores.</p>
|
||||
<td><p>Defines a module that contains components, directives, pipes, and providers.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>declarations:</b> [MyRedComponent, MyBlueComponent, MyDatePipe]</code></td>
|
||||
<td><p>Lista de componentes, directivas y pipes que pertenecen a este módulo.</p>
|
||||
<td><p>List of components, directives, and pipes that belong to this module.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>imports:</b> [BrowserModule, SomeOtherModule]</code></td>
|
||||
<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><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>
|
||||
</tr><tr>
|
||||
<td><code><b>exports:</b> [MyRedComponent, MyDatePipe]</code></td>
|
||||
<td><p>Lista de componentes, directivas y pipes visibles a los módulos que importan este módulo.</p>
|
||||
<td><p>List of components, directives, and pipes visible to modules that import this module.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>providers:</b> [MyService, { provide: ... }]</code></td>
|
||||
<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><p>List of dependency injection providers visible both to the contents of this module and to importers of this module.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>entryComponents:</b> [SomeComponent, OtherComponent]</code></td>
|
||||
<td><p>Lista de componentes no referenciados en cualquier plantilla accesible, por ejemplo, creada dinámicamente a partir de código.</p></td>
|
||||
<td><p>List of components not referenced in any reachable template, for example dynamically created from code.</p></td>
|
||||
</tr><tr>
|
||||
<td><code><b>bootstrap:</b> [MyAppComponent]</code></td>
|
||||
<td><p>Lista de componentes a empaquetar cuando este módulo se inicia.</p>
|
||||
<td><p>List of components to bootstrap when this module is bootstrapped.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
<th>Sintaxis de plantilla</th>
|
||||
<th>Template syntax</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><input <b>[value]</b>="firstName"></code></td>
|
||||
<td><p>Vincula la propiedad <code>value</code> al resultado de la expresión <code>firstName</code>.</p>
|
||||
<td><p>Binds property <code>value</code> to the result of expression <code>firstName</code>.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><div <b>[attr.role]</b>="myAriaRole"></code></td>
|
||||
<td><p>Vincula el atributo <code>role</code> al resultado de la expresión <code>myAriaRole</code>.</p>
|
||||
<td><p>Binds attribute <code>role</code> to the result of expression <code>myAriaRole</code>.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><div <b>[class.extra-sparkle]</b>="isDelightful"></code></td>
|
||||
<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><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>
|
||||
</tr><tr>
|
||||
<td><code><div <b>[style.width.px]</b>="mySize"></code></td>
|
||||
<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><p>Binds style property <code>width</code> to the result of expression <code>mySize</code> in pixels. Units are optional.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><button <b>(click)</b>="readRainbow($event)"></code></td>
|
||||
<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><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>
|
||||
</tr><tr>
|
||||
<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:
|
||||
<code><div [title]="'Hola ' + ponyName"></code></p>
|
||||
<td><code><div title="Hello <b>{{ponyName}}</b>"></code></td>
|
||||
<td><p>Binds a property to an interpolated string, for example, "Hello Seabiscuit". Equivalent to:
|
||||
<code><div [title]="'Hello ' + ponyName"></code></p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<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><code><p>Hello <b>{{ponyName}}</b></p></code></td>
|
||||
<td><p>Binds text content to an interpolated string, for example, "Hello Seabiscuit".</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><my-cmp <b>[(title)]</b>="name"></code></td>
|
||||
<td><p>Establece el two-way data binding. Equivalente a: <code><my-cmp [title]="name" (titleChange)="name=$event"></code></p>
|
||||
<td><p>Sets up two-way data binding. Equivalent to: <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>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><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>
|
||||
</tr><tr>
|
||||
<td><code><p <b>*myUnless</b>="myExpression">...</p></code></td>
|
||||
<td><p>El símbolo <code>*</code> convierte el elemento actual en una plantilla incrustada. Equivalente a:
|
||||
<td><p>The <code>*</code> symbol turns the current element into an embedded template. Equivalent to:
|
||||
<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>Transforma el valor actual de la expresión <code>cardNumber</code> a través de la pipe <code>myCardNumberFormatter</code>.</p>
|
||||
<td><p>Transforms the current value of expression <code>cardNumber</code> via the pipe called <code>myCardNumberFormatter</code>.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><p>Employer: <b>{{employer?.companyName}}</b></p></code></td>
|
||||
<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><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>
|
||||
</tr><tr>
|
||||
<td><code><<b>svg:</b>rect x="0" y="0" width="100" height="100"/></code></td>
|
||||
<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><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>
|
||||
</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>Un elemento raíz <code><svg></code> es detectado como un elemento SVG automáticamente, sin el prefijo.</p>
|
||||
<td><p>An <code><svg></code> root element is detected as an SVG element automatically, without the prefix.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
<th>Directivas incorporadas</th>
|
||||
<th>Built-in directives</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>Elimina o recrea una parte del árbol DOM basado en la expresión <code>showSection</code>.</p>
|
||||
<td><p>Removes or recreates a portion of the DOM tree based on the <code>showSection</code> expression.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><li <b>*ngFor</b>="let item of list"></code></td>
|
||||
<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><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>
|
||||
</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>Intercambia condicionalmente el contenido del div seleccionando una de las plantillas incrustadas en función del valor actual de <code>conditionExpression</code>.</p>
|
||||
<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>
|
||||
</tr><tr>
|
||||
<td><code><div <b>[ngClass]</b>="{'active': isActive, 'disabled': isDisabled}"></code></td>
|
||||
<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><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>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><div <b>[ngStyle]</b>="{'property': 'value'}"></code><br><code><div <b>[ngStyle]</b>="dynamicStyles()"></code></td>
|
||||
<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><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>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
<th>Formularios</th>
|
||||
<th>Forms</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>Provee two-way data-binding, conversión y validación para controles de formulario.</p>
|
||||
<td><p>Provides two-way data-binding, parsing, and validation for form controls.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
<th>Decoradores de clases</th>
|
||||
<th>Class decorators</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>Declara que una clase es un componente y proporciona metadatos sobre el componente.</p>
|
||||
<td><p>Declares that a class is a component and provides metadata about the component.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>@Directive({...})</b><br>class MyDirective() {}</code></td>
|
||||
<td><p>Declara que una clase es una directiva y proporciona metadatos sobre la directiva.</p>
|
||||
<td><p>Declares that a class is a directive and provides metadata about the directive.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>@Pipe({...})</b><br>class MyPipe() {}</code></td>
|
||||
<td><p>Declara que una clase es una pipe y proporciona metadatos sobre la pipe.</p>
|
||||
<td><p>Declares that a class is a pipe and provides metadata about the pipe.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>@Injectable()</b><br>class MyService() {}</code></td>
|
||||
<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><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>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
<th>Configuración de Directiva</th>
|
||||
<th>Directive configuration</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>Especifica un selector CSS que identifica esta directiva dentro de una plantilla. Los selectores compatibles incluyen <code>element</code>,
|
||||
<td><p>Specifies a CSS selector that identifies this directive within a template. Supported selectors include <code>element</code>,
|
||||
<code>[attribute]</code>, <code>.class</code>, and <code>:not()</code>.</p>
|
||||
<p>No soporta selectores de relación padre-hijo.</p>
|
||||
<p>Does not support parent-child relationship selectors.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>providers:</b> [MyService, { provide: ... }]</code></td>
|
||||
<td><p>Lista de proveedores de inyección de dependencia para esta directiva y sus hijos.</p>
|
||||
<td><p>List of dependency injection providers for this directive and its children.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
<th>Configuración de Componente</th>
|
||||
<th>Component configuration</th>
|
||||
<th><p>
|
||||
<code>@Component</code> extiende <code>@Directive</code>,
|
||||
entonces la configuración de <code>@Directive</code> se aplica también a los componentes</p>
|
||||
<code>@Component</code> extends <code>@Directive</code>,
|
||||
so the <code>@Directive</code> configuration applies to components as well</p>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><b>moduleId:</b> module.id</code></td>
|
||||
<td><p>Si está presente, el <code>templateUrl</code> y <code>styleUrl</code> se resuelven en relación con el componente.</p>
|
||||
<td><p>If set, the <code>templateUrl</code> and <code>styleUrl</code> are resolved relative to the component.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>viewProviders:</b> [MyService, { provide: ... }]</code></td>
|
||||
<td><p>Lista de proveedores de inyección de dependencias en la vista de este componente.</p>
|
||||
<td><p>List of dependency injection providers scoped to this component's view.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<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><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>
|
||||
</tr><tr>
|
||||
<td><code><b>styles:</b> ['.primary {color: red}']<br><b>styleUrls:</b> ['my-component.css']</code></td>
|
||||
<td><p>Lista de estilos CSS en línea o URL de hojas de estilo externas para estilar la vista del componente.</p>
|
||||
<td><p>List of inline CSS styles or external stylesheet URLs for styling the component’s view.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
<th>Decoradores para los campos de la clase para directivas y componentes.</th>
|
||||
<th>Class field decorators for directives and components</th>
|
||||
<th><p><code>import { Input, ... } from '@angular/core';</code>
|
||||
</p>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><b>@Input()</b> myProperty;</code></td>
|
||||
<td><p>Declara una propiedad de entrada (input) que puede actualizar mediante el enlace de propiedad (property binding) (ejemplo:
|
||||
<td><p>Declares an input property that you can update via property binding (example:
|
||||
<code><my-cmp [myProperty]="someExpression"></code>).</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>@Output()</b> myEvent = new EventEmitter();</code></td>
|
||||
<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><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>
|
||||
</tr><tr>
|
||||
<td><code><b>@HostBinding('class.valid')</b> isValid;</code></td>
|
||||
<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><p>Binds a host element property (here, the CSS class <code>valid</code>) to a directive/component property (<code>isValid</code>).</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>@HostListener('click', ['$event'])</b> onClick(e) {...}</code></td>
|
||||
<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><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>
|
||||
</tr><tr>
|
||||
<td><code><b>@ContentChild(myPredicate)</b> myChildComponent;</code></td>
|
||||
<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><p>Binds the first result of the component content query (<code>myPredicate</code>) to a property (<code>myChildComponent</code>) of the class.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>@ContentChildren(myPredicate)</b> myChildComponents;</code></td>
|
||||
<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><p>Binds the results of the component content query (<code>myPredicate</code>) to a property (<code>myChildComponents</code>) of the class.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>@ViewChild(myPredicate)</b> myChildComponent;</code></td>
|
||||
<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><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>
|
||||
</tr><tr>
|
||||
<td><code><b>@ViewChildren(myPredicate)</b> myChildComponents;</code></td>
|
||||
<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><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>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
|
||||
<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)
|
||||
<th>Directive and component change detection and lifecycle hooks</th>
|
||||
<th><p>(implemented as class methods)
|
||||
</p>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><b>constructor(myService: MyService, ...)</b> { ... }</code></td>
|
||||
<td><p>Se llama antes que cualquier ciclo de vida. Úselo para inyectar dependencias, pero evite cualquier trabajo serio aquí.</p>
|
||||
<td><p>Called before any other lifecycle hook. Use it to inject dependencies, but avoid any serious work here.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>ngOnChanges(changeRecord)</b> { ... }</code></td>
|
||||
<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><p>Called after every change to input properties and before processing content or child views.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>ngOnInit()</b> { ... }</code></td>
|
||||
<td><p>Se llama después del constructor, inicializando propiedades de entrada (input), y la primera llamada a <code>ngOnChanges</code>.</p>
|
||||
<td><p>Called after the constructor, initializing input properties, and the first call to <code>ngOnChanges</code>.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>ngDoCheck()</b> { ... }</code></td>
|
||||
<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><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>
|
||||
</tr><tr>
|
||||
<td><code><b>ngAfterContentInit()</b> { ... }</code></td>
|
||||
<td><p>Se llama después de <code>ngOnInit</code> cuando el contenido del componente o directiva ha sido inicializado.</p>
|
||||
<td><p>Called after <code>ngOnInit</code> when the component's or directive's content has been initialized.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>ngAfterContentChecked()</b> { ... }</code></td>
|
||||
<td><p>Se llama después de cada verificación del contenido del componente o directiva.</p>
|
||||
<td><p>Called after every check of the component's or directive's content.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>ngAfterViewInit()</b> { ... }</code></td>
|
||||
<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><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>
|
||||
</tr><tr>
|
||||
<td><code><b>ngAfterViewChecked()</b> { ... }</code></td>
|
||||
<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><p>Called after every check of the component's views and child views / the view that a directive is in.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code><b>ngOnDestroy()</b> { ... }</code></td>
|
||||
<td><p>Se llama una vez, antes de que la instancia se destruya.</p>
|
||||
<td><p>Called once, before the instance is destroyed.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
<th>Configuración de inyección de dependencia</th>
|
||||
<th>Dependency injection configuration</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>{ <b>provide</b>: MyService, <b>useClass</b>: MyMockService }</code></td>
|
||||
<td><p>Establece o sobre-escribe el proveedor para <code>MyService</code> en la clase <code>MyMockService</code>.</p>
|
||||
<td><p>Sets or overrides the provider for <code>MyService</code> to the <code>MyMockService</code> class.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code>{ <b>provide</b>: MyService, <b>useFactory</b>: myFactory }</code></td>
|
||||
<td><p>Establece o sobre-escribe el proveedor para <code>MyService</code> en la factoría de función <code>myFactory</code>.</p>
|
||||
<td><p>Sets or overrides the provider for <code>MyService</code> to the <code>myFactory</code> factory function.</p>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><code>{ <b>provide</b>: MyValue, <b>useValue</b>: 41 }</code></td>
|
||||
<td><p>Establece o sobre-escribe el proveedor para <code>MyValue</code> al valor <code>41</code>.</p>
|
||||
<td><p>Sets or overrides the provider for <code>MyValue</code> to the value <code>41</code>.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<table class="is-full-width is-fixed-layout">
|
||||
<tbody><tr>
|
||||
<th>Enrutamiento y navegación</th>
|
||||
<th>Routing and navigation</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>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><p>Configures routes for the application. Supports static, parameterized, redirect, and wildcard routes. Also supports custom route data and resolve.</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>Marca la ubicación para cargar el componente de la ruta activa.</p>
|
||||
<td><p>Marks the location to load the component of the active route.</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>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><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>
|
||||
</tr><tr>
|
||||
<td><code><a [routerLink]="[ '/path' ]" routerLinkActive="active"></code></td>
|
||||
<td><p>Las clases proporcionadas se agregan al elemento cuando el <code>routerLink</code> se convierte en la ruta activa actual.</p>
|
||||
<td><p>The provided classes are added to the element when the <code>routerLink</code> becomes the current active route.</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>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><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>
|
||||
</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>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><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>
|
||||
</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>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><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>
|
||||
</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>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><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>
|
||||
</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>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><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>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
@ -1,318 +0,0 @@
|
||||
# Observables compared to other techniques
|
||||
|
||||
You can often use observables instead of promises to deliver values asynchronously. Similarly, observables can take the place of event handlers. Finally, because observables deliver multiple values, you can use them where you might otherwise build and operate on arrays.
|
||||
|
||||
Observables behave somewhat differently from the alternative techniques in each of these situations, but offer some significant advantages. Here are detailed comparisons of the differences.
|
||||
|
||||
## Observables compared to promises
|
||||
|
||||
Observables are often compared to promises. Here are some key differences:
|
||||
|
||||
* Observables are declarative; computation does not start until subscription. Promises execute immediately on creation. This makes observables useful for defining recipes that can be run whenever you need the result.
|
||||
|
||||
* Observables provide many values. Promises provide one. This makes observables useful for getting multiple values over time.
|
||||
|
||||
* Observables differentiate between chaining and subscription. Promises only have `.then()` clauses. This makes observables useful for creating complex transformation recipes to be used by other part of the system, without causing the work to be executed.
|
||||
|
||||
* Observables `subscribe()` is responsible for handling errors. Promises push errors to the child promises. This makes observables useful for centralized and predictable error handling.
|
||||
|
||||
|
||||
### Creation and subscription
|
||||
|
||||
* Observables are not executed until a consumer subscribes. The `subscribe()` executes the defined behavior once, and it can be called again. Each subscription has its own computation. Resubscription causes recomputation of values.
|
||||
|
||||
<code-example
|
||||
path="comparing-observables/src/observables.ts"
|
||||
header="src/observables.ts (observable)"
|
||||
region="observable">
|
||||
</code-example>
|
||||
|
||||
* Promises execute immediately, and just once. The computation of the result is initiated when the promise is created. There is no way to restart work. All `then` clauses (subscriptions) share the same computation.
|
||||
|
||||
<code-example
|
||||
path="comparing-observables/src/promises.ts"
|
||||
header="src/promises.ts (promise)"
|
||||
region="promise">
|
||||
</code-example>
|
||||
|
||||
### Chaining
|
||||
|
||||
* Observables differentiate between transformation function such as a map and subscription. Only subscription activates the subscriber function to start computing the values.
|
||||
|
||||
<code-example
|
||||
path="comparing-observables/src/observables.ts"
|
||||
header="src/observables.ts (chain)"
|
||||
region="chain">
|
||||
</code-example>
|
||||
|
||||
* Promises do not differentiate between the last `.then` clauses (equivalent to subscription) and intermediate `.then` clauses (equivalent to map).
|
||||
|
||||
<code-example
|
||||
path="comparing-observables/src/promises.ts"
|
||||
header="src/promises.ts (chain)"
|
||||
region="chain">
|
||||
</code-example>
|
||||
|
||||
### Cancellation
|
||||
|
||||
* Observable subscriptions are cancellable. Unsubscribing removes the listener from receiving further values, and notifies the subscriber function to cancel work.
|
||||
|
||||
<code-example
|
||||
path="comparing-observables/src/observables.ts"
|
||||
header="src/observables.ts (unsubcribe)"
|
||||
region="unsubscribe">
|
||||
</code-example>
|
||||
|
||||
* Promises are not cancellable.
|
||||
|
||||
### Error handling
|
||||
|
||||
* Observable execution errors are delivered to the subscriber's error handler, and the subscriber automatically unsubscribes from the observable.
|
||||
|
||||
<code-example
|
||||
path="comparing-observables/src/observables.ts"
|
||||
header="src/observables.ts (error)"
|
||||
region="error">
|
||||
</code-example>
|
||||
|
||||
* Promises push errors to the child promises.
|
||||
|
||||
<code-example
|
||||
path="comparing-observables/src/promises.ts"
|
||||
header="src/promises.ts (error)"
|
||||
region="error">
|
||||
</code-example>
|
||||
|
||||
### Cheat sheet
|
||||
|
||||
The following code snippets illustrate how the same kind of operation is defined using observables and promises.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Operation</th>
|
||||
<th>Observable</th>
|
||||
<th>Promise</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Creation</td>
|
||||
<td>
|
||||
<pre>
|
||||
new Observable((observer) => {
|
||||
observer.next(123);
|
||||
});</pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre>
|
||||
new Promise((resolve, reject) => {
|
||||
resolve(123);
|
||||
});</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Transform</td>
|
||||
<td><pre>obs.pipe(map((value) => value * 2));</pre></td>
|
||||
<td><pre>promise.then((value) => value * 2);</pre></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Subscribe</td>
|
||||
<td>
|
||||
<pre>
|
||||
sub = obs.subscribe((value) => {
|
||||
console.log(value)
|
||||
});</pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre>
|
||||
promise.then((value) => {
|
||||
console.log(value);
|
||||
});</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Unsubscribe</td>
|
||||
<td><pre>sub.unsubscribe();</pre></td>
|
||||
<td>Implied by promise resolution.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Observables compared to events API
|
||||
|
||||
Observables are very similar to event handlers that use the events API. Both techniques define notification handlers, and use them to process multiple values delivered over time. Subscribing to an observable is equivalent to adding an event listener. One significant difference is that you can configure an observable to transform an event before passing the event to the handler.
|
||||
|
||||
Using observables to handle events and asynchronous operations can have the advantage of greater consistency in contexts such as HTTP requests.
|
||||
|
||||
Here are some code samples that illustrate how the same kind of operation is defined using observables and the events API.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Observable</th>
|
||||
<th>Events API</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Creation & cancellation</td>
|
||||
<td>
|
||||
<pre>// Setup
|
||||
let clicks$ = fromEvent(buttonEl, ‘click’);
|
||||
// Begin listening
|
||||
let subscription = clicks$
|
||||
.subscribe(e => console.log(‘Clicked’, e))
|
||||
// Stop listening
|
||||
subscription.unsubscribe();</pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre>function handler(e) {
|
||||
console.log(‘Clicked’, e);
|
||||
}
|
||||
// Setup & begin listening
|
||||
button.addEventListener(‘click’, handler);
|
||||
// Stop listening
|
||||
button.removeEventListener(‘click’, handler);
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Subscription</td>
|
||||
<td>
|
||||
<pre>observable.subscribe(() => {
|
||||
// notification handlers here
|
||||
});</pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre>element.addEventListener(eventName, (event) => {
|
||||
// notification handler here
|
||||
});</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Configuration</td>
|
||||
<td>Listen for keystrokes, but provide a stream representing the value in the input.
|
||||
<pre>fromEvent(inputEl, 'keydown').pipe(
|
||||
map(e => e.target.value)
|
||||
);</pre>
|
||||
</td>
|
||||
<td>Does not support configuration.
|
||||
<pre>element.addEventListener(eventName, (event) => {
|
||||
// Cannot change the passed Event into another
|
||||
// value before it gets to the handler
|
||||
});</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
## Observables compared to arrays
|
||||
|
||||
An observable produces values over time. An array is created as a static set of values. In a sense, observables are asynchronous where arrays are synchronous. In the following examples, ➞ implies asynchronous value delivery.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Observable</th>
|
||||
<th>Array</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Given</td>
|
||||
<td>
|
||||
<pre>obs: ➞1➞2➞3➞5➞7</pre>
|
||||
<pre>obsB: ➞'a'➞'b'➞'c'</pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre>arr: [1, 2, 3, 5, 7]</pre>
|
||||
<pre>arrB: ['a', 'b', 'c']</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><pre>concat()</pre></td>
|
||||
<td>
|
||||
<pre>concat(obs, obsB)</pre>
|
||||
<pre>➞1➞2➞3➞5➞7➞'a'➞'b'➞'c'</pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre>arr.concat(arrB)</pre>
|
||||
<pre>[1,2,3,5,7,'a','b','c']</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><pre>filter()</pre></td>
|
||||
<td>
|
||||
<pre>obs.pipe(filter((v) => v>3))</pre>
|
||||
<pre>➞5➞7</pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre>arr.filter((v) => v>3)</pre>
|
||||
<pre>[5, 7]</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><pre>find()</pre></td>
|
||||
<td>
|
||||
<pre>obs.pipe(find((v) => v>3))</pre>
|
||||
<pre>➞5</pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre>arr.find((v) => v>3)</pre>
|
||||
<pre>5</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><pre>findIndex()</pre></td>
|
||||
<td>
|
||||
<pre>obs.pipe(findIndex((v) => v>3))</pre>
|
||||
<pre>➞3</pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre>arr.findIndex((v) => v>3)</pre>
|
||||
<pre>3</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><pre>forEach()</pre></td>
|
||||
<td>
|
||||
<pre>obs.pipe(tap((v) => {
|
||||
console.log(v);
|
||||
}))
|
||||
1
|
||||
2
|
||||
3
|
||||
5
|
||||
7</pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre>arr.forEach((v) => {
|
||||
console.log(v);
|
||||
})
|
||||
1
|
||||
2
|
||||
3
|
||||
5
|
||||
7</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><pre>map()</pre></td>
|
||||
<td>
|
||||
<pre>obs.pipe(map((v) => -v))</pre>
|
||||
<pre>➞-1➞-2➞-3➞-5➞-7</pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre>arr.map((v) => -v)</pre>
|
||||
<pre>[-1, -2, -3, -5, -7]</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><pre>reduce()</pre></td>
|
||||
<td>
|
||||
<pre>obs.pipe(reduce((s,v)=> s+v, 0))</pre>
|
||||
<pre>➞18</pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre>arr.reduce((s,v) => s+v, 0)</pre>
|
||||
<pre>18</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
@ -1,24 +1,25 @@
|
||||
# Observables en comparación con otras técnicas
|
||||
# Observables compared to other techniques
|
||||
|
||||
A menudo puedes usar observables en lugar de promesas para entregar valores de forma asíncrona. Del mismo modo, los observables pueden reemplazar a los controladores de eventos. Finalmente, porque los observables entregan múltiples valores, puedes usarlos donde de otro modo podrías construir y operar con arrays.
|
||||
You can often use observables instead of promises to deliver values asynchronously. Similarly, observables can take the place of event handlers. Finally, because observables deliver multiple values, you can use them where you might otherwise build and operate on arrays.
|
||||
|
||||
Los observables se comportan de manera algo diferente a las técnicas alternativas en cada una de estas situaciones, pero ofrecen algunas ventajas significativas. Aquí hay comparaciones detalladas de las diferencias.
|
||||
Observables behave somewhat differently from the alternative techniques in each of these situations, but offer some significant advantages. Here are detailed comparisons of the differences.
|
||||
|
||||
## Observables en comparación con promesas
|
||||
## Observables compared to promises
|
||||
|
||||
Los observables a menudo se comparan con las promesas. Aquí hay algunas diferencias clave:
|
||||
Observables are often compared to promises. Here are some key differences:
|
||||
|
||||
* Los observables son declarativos; La ejecución no comienza hasta la suscripción. Las promesas se ejecutan inmediatamente después de la creación. Esto hace que los observables sean útiles para definir recetas que se pueden ejecutar cuando necesites el resultado.
|
||||
* Observables are declarative; computation does not start until subscription. Promises execute immediately on creation. This makes observables useful for defining recipes that can be run whenever you need the result.
|
||||
|
||||
* Los observables proporcionan muchos valores. Las promesas proporcionan un valor. Esto hace que los observables sean útiles para obtener múltiples valores a lo largo del tiempo.
|
||||
* Observables provide many values. Promises provide one. This makes observables useful for getting multiple values over time.
|
||||
|
||||
* Los observables diferencian entre encadenamiento y suscripción. Las promesas solo tienen cláusulas `.then ()`. Esto hace que los observables sean útiles para crear recetas de transformación complejas para ser utilizadas por otra parte del sistema, sin que el trabajo se ejecute.
|
||||
* Observables differentiate between chaining and subscription. Promises only have `.then()` clauses. This makes observables useful for creating complex transformation recipes to be used by other part of the system, without causing the work to be executed.
|
||||
|
||||
* Observables `subscribe()` es responsable de manejar los errores. Las promesas empujan los errores a promesas hijas. Esto hace que los observables sean útiles para el manejo centralizado y predecible de errores.
|
||||
* Observables `subscribe()` is responsible for handling errors. Promises push errors to the child promises. This makes observables useful for centralized and predictable error handling.
|
||||
|
||||
### Creación y suscripción
|
||||
|
||||
* Los observables no se ejecutan hasta que un consumidor se suscribe. El `subscribe()` ejecuta el comportamiento definido una vez, y se puede volver a llamar. Cada suscripción tiene su propia computación. La resuscripción provoca la recomputación de los valores.
|
||||
### Creation and subscription
|
||||
|
||||
* Observables are not executed until a consumer subscribes. The `subscribe()` executes the defined behavior once, and it can be called again. Each subscription has its own computation. Resubscription causes recomputation of values.
|
||||
|
||||
<code-example
|
||||
path="comparing-observables/src/observables.ts"
|
||||
@ -26,7 +27,7 @@ Los observables a menudo se comparan con las promesas. Aquí hay algunas diferen
|
||||
region="observable">
|
||||
</code-example>
|
||||
|
||||
* Las promesas se ejecutan de inmediato, y solo una vez. La computación del resultado se inicia cuando se crea la promesa. No hay forma de reiniciar el trabajo. Todas las cláusulas `then` (suscripciones) comparten la misma computación.
|
||||
* Promises execute immediately, and just once. The computation of the result is initiated when the promise is created. There is no way to restart work. All `then` clauses (subscriptions) share the same computation.
|
||||
|
||||
<code-example
|
||||
path="comparing-observables/src/promises.ts"
|
||||
@ -34,9 +35,9 @@ Los observables a menudo se comparan con las promesas. Aquí hay algunas diferen
|
||||
region="promise">
|
||||
</code-example>
|
||||
|
||||
### Encadenamiento
|
||||
### Chaining
|
||||
|
||||
* Los observables diferencian entre la función de transformación, como `map` y `subscription`. Solo la suscripción activa la función de suscriptor para comenzar a calcular los valores.
|
||||
* Observables differentiate between transformation function such as a map and subscription. Only subscription activates the subscriber function to start computing the values.
|
||||
|
||||
<code-example
|
||||
path="comparing-observables/src/observables.ts"
|
||||
@ -44,7 +45,7 @@ Los observables a menudo se comparan con las promesas. Aquí hay algunas diferen
|
||||
region="chain">
|
||||
</code-example>
|
||||
|
||||
* Las promesas no diferencian entre las últimas cláusulas `.then` (equivalentes al subscription) y las cláusulas intermedias `.then` (equivalentes al map).
|
||||
* Promises do not differentiate between the last `.then` clauses (equivalent to subscription) and intermediate `.then` clauses (equivalent to map).
|
||||
|
||||
<code-example
|
||||
path="comparing-observables/src/promises.ts"
|
||||
@ -52,9 +53,9 @@ Los observables a menudo se comparan con las promesas. Aquí hay algunas diferen
|
||||
region="chain">
|
||||
</code-example>
|
||||
|
||||
### Cancelación
|
||||
### Cancellation
|
||||
|
||||
* Las suscripciones de los observables son cancelables. La cancelación de la suscripción evita que el oyente reciba más valores y notifica a la función del suscriptor que cancele el trabajo.
|
||||
* Observable subscriptions are cancellable. Unsubscribing removes the listener from receiving further values, and notifies the subscriber function to cancel work.
|
||||
|
||||
<code-example
|
||||
path="comparing-observables/src/observables.ts"
|
||||
@ -62,11 +63,11 @@ Los observables a menudo se comparan con las promesas. Aquí hay algunas diferen
|
||||
region="unsubscribe">
|
||||
</code-example>
|
||||
|
||||
* Las promesas no son cancelables.
|
||||
* Promises are not cancellable.
|
||||
|
||||
### Manejo de errores
|
||||
### Error handling
|
||||
|
||||
* Los errores de ejecución en observables se entregan al controlador de errores del suscriptor, y el suscriptor cancela automáticamente la suscripción del observable.
|
||||
* Observable execution errors are delivered to the subscriber's error handler, and the subscriber automatically unsubscribes from the observable.
|
||||
|
||||
<code-example
|
||||
path="comparing-observables/src/observables.ts"
|
||||
@ -74,7 +75,7 @@ Los observables a menudo se comparan con las promesas. Aquí hay algunas diferen
|
||||
region="error">
|
||||
</code-example>
|
||||
|
||||
* Las promesas empujan los errores a las promesas hijas.
|
||||
* Promises push errors to the child promises.
|
||||
|
||||
<code-example
|
||||
path="comparing-observables/src/promises.ts"
|
||||
@ -82,9 +83,9 @@ Los observables a menudo se comparan con las promesas. Aquí hay algunas diferen
|
||||
region="error">
|
||||
</code-example>
|
||||
|
||||
### Hoja de trucos
|
||||
### Cheat sheet
|
||||
|
||||
Los siguientes fragmentos de código ilustran cómo se define el mismo tipo de operación utilizando observables y promesas.
|
||||
The following code snippets illustrate how the same kind of operation is defined using observables and promises.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
@ -138,13 +139,13 @@ promise.then((value) => {
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Observables en comparación con eventos API
|
||||
## Observables compared to events API
|
||||
|
||||
Los observables son muy similares a los controladores de eventos que usan la API de eventos. Ambas técnicas definen manejadores de notificaciones y las utilizan para procesar múltiples valores entregados a lo largo del tiempo. Suscribirse a un observable es equivalente a agregar un detector de eventos. Una diferencia significativa es que puedes configurar un observable para transformar un evento antes de pasar el evento al controlador.
|
||||
Observables are very similar to event handlers that use the events API. Both techniques define notification handlers, and use them to process multiple values delivered over time. Subscribing to an observable is equivalent to adding an event listener. One significant difference is that you can configure an observable to transform an event before passing the event to the handler.
|
||||
|
||||
El uso de observables para manejar eventos y operaciones asíncronas puede tener la ventaja de una mayor coherencia en contextos como las solicitudes HTTP.
|
||||
Using observables to handle events and asynchronous operations can have the advantage of greater consistency in contexts such as HTTP requests.
|
||||
|
||||
Aquí hay algunos ejemplos de código que ilustran cómo se define el mismo tipo de operación usando observables y la API de eventos.
|
||||
Here are some code samples that illustrate how the same kind of operation is defined using observables and the events API.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
@ -204,9 +205,9 @@ button.removeEventListener(‘click’, handler);
|
||||
</table>
|
||||
|
||||
|
||||
## Observables en comparación con arrays
|
||||
## Observables compared to arrays
|
||||
|
||||
Un observable produce valores a lo largo del tiempo. Se crea un array como un conjunto estático de valores. En cierto sentido, los observables son asíncronos mientras que los arrays son síncronos. En los siguientes ejemplos, ➞ implica entrega de valor asíncrono.
|
||||
An observable produces values over time. An array is created as a static set of values. In a sense, observables are asynchronous where arrays are synchronous. In the following examples, ➞ implies asynchronous value delivery.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
|
@ -1,104 +0,0 @@
|
||||
# Complex animation sequences
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
A basic understanding of the following concepts:
|
||||
|
||||
* [Introduction to Angular animations](guide/animations)
|
||||
* [Transition and triggers](guide/transition-and-triggers)
|
||||
|
||||
<hr>
|
||||
|
||||
So far, we've learned simple animations of single HTML elements. Angular also lets you animate coordinated sequences, such as an entire grid or list of elements as they enter and leave a page. You can choose to run multiple animations in parallel, or run discrete animations sequentially, one following another.
|
||||
|
||||
Functions that control complex animation sequences are as follows:
|
||||
|
||||
* `query()` finds one or more inner HTML elements.
|
||||
* `stagger()` applies a cascading delay to animations for multiple elements.
|
||||
* [`group()`](api/animations/group) runs multiple animation steps in parallel.
|
||||
* `sequence()` runs animation steps one after another.
|
||||
|
||||
{@a complex-sequence}
|
||||
|
||||
## Animate multiple elements using query() and stagger() functions
|
||||
|
||||
The `query()` function allows you to find inner elements within the element that is being animated. This function targets specific HTML elements within a parent component and applies animations to each element individually. Angular intelligently handles setup, teardown, and cleanup as it coordinates the elements across the page.
|
||||
|
||||
The `stagger()` function allows you to define a timing gap between each queried item that is animated and thus animates elements with a delay between them.
|
||||
|
||||
The Filter/Stagger tab in the live example shows a list of heroes with an introductory sequence. The entire list of heroes cascades in, with a slight delay from top to bottom.
|
||||
|
||||
The following example demonstrates how to use `query()` and `stagger()` functions on the entry of an animated element.
|
||||
|
||||
* Use `query()` to look for an element entering the page that meets certain criteria.
|
||||
|
||||
* For each of these elements, use `style()` to set the same initial style for the element. Make it invisible and use `transform` to move it out of position so that it can slide into place.
|
||||
|
||||
* Use `stagger()` to delay each animation by 30 milliseconds.
|
||||
|
||||
* Animate each element on screen for 0.5 seconds using a custom-defined easing curve, simultaneously fading it in and un-transforming it.
|
||||
|
||||
<code-example path="animations/src/app/hero-list-page.component.ts" header="src/app/hero-list-page.component.ts" region="page-animations" language="typescript"></code-example>
|
||||
|
||||
## Parallel animation using group() function
|
||||
|
||||
You've seen how to add a delay between each successive animation. But you may also want to configure animations that happen in parallel. For example, you may want to animate two CSS properties of the same element but use a different `easing` function for each one. For this, you can use the animation [`group()`](api/animations/group) function.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
**Note:** The [`group()`](api/animations/group) function is used to group animation *steps*, rather than animated elements.
|
||||
</div>
|
||||
|
||||
In the following example, using groups on both `:enter` and `:leave` allow for two different timing configurations. They're applied to the same element in parallel, but run independently.
|
||||
|
||||
<code-example path="animations/src/app/hero-list-groups.component.ts" region="animationdef" header="src/app/hero-list-groups.component.ts (excerpt)" language="typescript"></code-example>
|
||||
|
||||
## Sequential vs. parallel animations
|
||||
|
||||
Complex animations can have many things happening at once. But what if you want to create an animation involving several animations happening one after the other? Earlier we used [`group()`](api/animations/group) to run multiple animations all at the same time, in parallel.
|
||||
|
||||
A second function called `sequence()` lets you run those same animations one after the other. Within `sequence()`, the animation steps consist of either `style()` or `animate()` function calls.
|
||||
|
||||
* Use `style()` to apply the provided styling data immediately.
|
||||
* Use `animate()` to apply styling data over a given time interval.
|
||||
|
||||
## Filter animation example
|
||||
|
||||
Let's take a look at another animation on the live example page. Under the Filter/Stagger tab, enter some text into the **Search Heroes** text box, such as `Magnet` or `tornado`.
|
||||
|
||||
The filter works in real time as you type. Elements leave the page as you type each new letter and the filter gets progressively stricter. The heroes list gradually re-enters the page as you delete each letter in the filter box.
|
||||
|
||||
The HTML template contains a trigger called `filterAnimation`.
|
||||
|
||||
<code-example path="animations/src/app/hero-list-page.component.html" header="src/app/hero-list-page.component.html" region="filter-animations"></code-example>
|
||||
|
||||
The component file contains three transitions.
|
||||
|
||||
<code-example path="animations/src/app/hero-list-page.component.ts" header="src/app/hero-list-page.component.ts" region="filter-animations" language="typescript"></code-example>
|
||||
|
||||
The animation does the following:
|
||||
|
||||
* Ignores any animations that are performed when the user first opens or navigates to this page. The filter narrows what is already there, so it assumes that any HTML elements to be animated already exist in the DOM.
|
||||
|
||||
* Performs a filter match for matches.
|
||||
|
||||
For each match:
|
||||
|
||||
* Hides the element by making it completely transparent and infinitely narrow, by setting its opacity and width to 0.
|
||||
|
||||
* Animates in the element over 300 milliseconds. During the animation, the element assumes its default width and opacity.
|
||||
|
||||
* If there are multiple matching elements, staggers in each element starting at the top of the page, with a 50-millisecond delay between each element.
|
||||
|
||||
## Animation sequence summary
|
||||
|
||||
Angular functions for animating multiple elements start with `query()` to find inner elements, for example gathering all images within a `<div>`. The remaining functions, `stagger()`, [`group()`](api/animations/group), and `sequence()`, apply cascades or allow you to control how multiple animation steps are applied.
|
||||
|
||||
## More on Angular animations
|
||||
|
||||
You may also be interested in the following:
|
||||
|
||||
* [Introduction to Angular animations](guide/animations)
|
||||
* [Transition and triggers](guide/transition-and-triggers)
|
||||
* [Reusable animations](guide/reusable-animations)
|
||||
* [Route transition animations](guide/route-animations)
|
@ -1,105 +1,104 @@
|
||||
# Secuencias de animación complejas
|
||||
# Complex animation sequences
|
||||
|
||||
#### Requisitos
|
||||
#### Prerequisites
|
||||
|
||||
Una comprensión básica de los siguientes conceptos:
|
||||
A basic understanding of the following concepts:
|
||||
|
||||
- [Introducción a animaciones Angular](guide/animations)
|
||||
- [Transición y triggers](guide/transition-and-triggers)
|
||||
* [Introduction to Angular animations](guide/animations)
|
||||
* [Transition and triggers](guide/transition-and-triggers)
|
||||
|
||||
<hr>
|
||||
|
||||
Hasta ahora, hemos aprendido animaciones simples de elementos HTML individuales. Angular también te permite animar secuencias coordinadas, como un grid completo o una lista de elementos cuando entran y salen de una página. Puedes elegir ejecutar varias animaciones en paralelo, o ejecutar animaciones discretas secuencialmente, una tras otra.
|
||||
So far, we've learned simple animations of single HTML elements. Angular also lets you animate coordinated sequences, such as an entire grid or list of elements as they enter and leave a page. You can choose to run multiple animations in parallel, or run discrete animations sequentially, one following another.
|
||||
|
||||
Las funciones que controlan secuencias de animación complejas son las siguientes:
|
||||
Functions that control complex animation sequences are as follows:
|
||||
|
||||
- `query()` encuentra uno o más elementos HTML internos.
|
||||
- `stagger()` aplica un retraso en cascada a las animaciones para varios elementos.
|
||||
- [`group()`](api/animations/group) ejecuta varios pasos de animación en paralelo.
|
||||
- `sequence()` ejecuta pasos de animación uno tras otro.
|
||||
* `query()` finds one or more inner HTML elements.
|
||||
* `stagger()` applies a cascading delay to animations for multiple elements.
|
||||
* [`group()`](api/animations/group) runs multiple animation steps in parallel.
|
||||
* `sequence()` runs animation steps one after another.
|
||||
|
||||
{@a complex-sequence}
|
||||
|
||||
## Animar varios elementos usando las funciones query() y stagger()
|
||||
## Animate multiple elements using query() and stagger() functions
|
||||
|
||||
La función `query()` permite encontrar elementos internos dentro del elemento que estás animando. Esta función se dirige a elementos HTML específicos dentro de un componente principal y aplica animaciones a cada elemento individualmente. Angular maneja de manera inteligente la configuración, el desmontaje y la limpieza a medida que coordina los elementos en la página.
|
||||
The `query()` function allows you to find inner elements within the element that is being animated. This function targets specific HTML elements within a parent component and applies animations to each element individually. Angular intelligently handles setup, teardown, and cleanup as it coordinates the elements across the page.
|
||||
|
||||
La función `stagger()` permite definir un intervalo de tiempo entre cada elemento consultado que está animado y, por lo tanto, anima elementos con un retraso entre ellos.
|
||||
The `stagger()` function allows you to define a timing gap between each queried item that is animated and thus animates elements with a delay between them.
|
||||
|
||||
La pestaña Filter/Stagger en el ejemplo en vivo muestra una lista de héroes con una secuencia introductoria. La lista completa de héroes entra en cascada, con un ligero retraso de arriba a abajo.
|
||||
The Filter/Stagger tab in the live example shows a list of heroes with an introductory sequence. The entire list of heroes cascades in, with a slight delay from top to bottom.
|
||||
|
||||
El siguiente ejemplo demuestra cómo utilizar las funciones `query()` y `stagger()` en la entrada de un elemento animado.
|
||||
The following example demonstrates how to use `query()` and `stagger()` functions on the entry of an animated element.
|
||||
|
||||
- Usa `query()` para buscar un elemento que ingrese a la página que cumpla con ciertos criterios.
|
||||
* Use `query()` to look for an element entering the page that meets certain criteria.
|
||||
|
||||
- Para cada uno de estos elementos, usa `style()` para establecer el mismo estilo inicial para el elemento. Hazlo invisible y usa `transform` para moverlo fuera de su posición para que pueda deslizarse a su lugar.
|
||||
* For each of these elements, use `style()` to set the same initial style for the element. Make it invisible and use `transform` to move it out of position so that it can slide into place.
|
||||
|
||||
- Usa `stagger()` para retrasar cada animación en 30 milisegundos.
|
||||
* Use `stagger()` to delay each animation by 30 milliseconds.
|
||||
|
||||
- Anima cada elemento en la pantalla durante 0,5 segundos utilizando una curva de easing (suavizado) definida a medida, desvaneciéndolo y deshaciéndolo simultáneamente.
|
||||
* Animate each element on screen for 0.5 seconds using a custom-defined easing curve, simultaneously fading it in and un-transforming it.
|
||||
|
||||
<code-example path="animations/src/app/hero-list-page.component.ts" header="src/app/hero-list-page.component.ts" region="page-animations" language="typescript"></code-example>
|
||||
|
||||
## Animación paralela usando la función group()
|
||||
## Parallel animation using group() function
|
||||
|
||||
Has visto cómo agregar un retraso entre cada animación sucesiva. Pero es posible que también quieras configurar animaciones que suceden en paralelo. Por ejemplo, es posible que quieras animar dos propiedades CSS del mismo elemento pero utilizar una función de `easing` diferente para cada una. Para ello, puedes utilizar la función de animación [`group()`](api/animations/group).
|
||||
You've seen how to add a delay between each successive animation. But you may also want to configure animations that happen in parallel. For example, you may want to animate two CSS properties of the same element but use a different `easing` function for each one. For this, you can use the animation [`group()`](api/animations/group) function.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
**Nota:** La función [`group()`](api/animations/group) se usa para agrupar _pasos_ de animación, en lugar de elementos animados.
|
||||
|
||||
**Note:** The [`group()`](api/animations/group) function is used to group animation *steps*, rather than animated elements.
|
||||
</div>
|
||||
|
||||
En el siguiente ejemplo, el uso de grupos tanto en `:enter` como en `:leave` permite dos configuraciones de tiempo diferentes. Se aplican al mismo elemento en paralelo, pero se ejecutan de forma independiente.
|
||||
In the following example, using groups on both `:enter` and `:leave` allow for two different timing configurations. They're applied to the same element in parallel, but run independently.
|
||||
|
||||
<code-example path="animations/src/app/hero-list-groups.component.ts" region="animationdef" header="src/app/hero-list-groups.component.ts (excerpt)" language="typescript"></code-example>
|
||||
|
||||
## Animaciones secuenciales vs paralelas
|
||||
## Sequential vs. parallel animations
|
||||
|
||||
Las animaciones complejas pueden tener muchas cosas sucediendo a la vez. Pero, ¿qué sucede si quieres crear una animación que involucre varias animaciones sucediendo una tras otra? Anteriormente usamos [`group()`](api/animations/group) para ejecutar múltiples animaciones al mismo tiempo, en paralelo.
|
||||
Complex animations can have many things happening at once. But what if you want to create an animation involving several animations happening one after the other? Earlier we used [`group()`](api/animations/group) to run multiple animations all at the same time, in parallel.
|
||||
|
||||
Una segunda función llamada `sequence()` permite ejecutar esas mismas animaciones una tras otra. Dentro de `sequence()`, los pasos de la animación consisten en llamadas de función `style()` o `animate()`
|
||||
A second function called `sequence()` lets you run those same animations one after the other. Within `sequence()`, the animation steps consist of either `style()` or `animate()` function calls.
|
||||
|
||||
- Usa `style()` para aplicar los datos de estilo proporcionados inmediatamente.
|
||||
- Usa `animate()` para aplicar datos de estilo en un intervalo de tiempo determinado.
|
||||
* Use `style()` to apply the provided styling data immediately.
|
||||
* Use `animate()` to apply styling data over a given time interval.
|
||||
|
||||
## Ejemplo de animación de filtro
|
||||
## Filter animation example
|
||||
|
||||
Echemos un vistazo a otra animación en la página de ejemplo. En la pestaña Filter/Stagger, ingresa un texto en el cuadro de texto **Search Heroes**, como `Magnet` o `tornado`.
|
||||
Let's take a look at another animation on the live example page. Under the Filter/Stagger tab, enter some text into the **Search Heroes** text box, such as `Magnet` or `tornado`.
|
||||
|
||||
El filtro funciona en tiempo real a medida que escribe. Los elementos abandonan la página a medida que escribe cada nueva letra y el filtro se vuelve progresivamente más estricto. La lista de héroes vuelve a entrar gradualmente en la página a medida que eliminas cada letra en la caja de filtro.
|
||||
The filter works in real time as you type. Elements leave the page as you type each new letter and the filter gets progressively stricter. The heroes list gradually re-enters the page as you delete each letter in the filter box.
|
||||
|
||||
La plantilla HTML contiene un trigger llamado `filterAnimation`.
|
||||
The HTML template contains a trigger called `filterAnimation`.
|
||||
|
||||
<code-example path="animations/src/app/hero-list-page.component.html" header="src/app/hero-list-page.component.html" region="filter-animations"></code-example>
|
||||
|
||||
El archivo del componente contiene tres transiciones.
|
||||
The component file contains three transitions.
|
||||
|
||||
<code-example path="animations/src/app/hero-list-page.component.ts" header="src/app/hero-list-page.component.ts" region="filter-animations" language="typescript"></code-example>
|
||||
|
||||
La animación hace lo siguiente:
|
||||
The animation does the following:
|
||||
|
||||
- Ignora las animaciones que se realizan cuando el usuario abre o navega por primera vez a esta página. El filtro reduce lo que ya está allí, por lo que asume que los elementos HTML que se van a animar ya existen en el DOM.
|
||||
* Ignores any animations that are performed when the user first opens or navigates to this page. The filter narrows what is already there, so it assumes that any HTML elements to be animated already exist in the DOM.
|
||||
|
||||
- Realiza un filtro de coincidencia.
|
||||
* Performs a filter match for matches.
|
||||
|
||||
Para cada coincidencia:
|
||||
For each match:
|
||||
|
||||
- Oculta el elemento haciéndolo completamente transparente e infinitamente estrecho, estableciendo su opacidad y ancho en 0.
|
||||
* Hides the element by making it completely transparent and infinitely narrow, by setting its opacity and width to 0.
|
||||
|
||||
- Anima el elemento más de 300 milisegundos. Durante la animación, el elemento asume su ancho y opacidad predeterminados.
|
||||
* Animates in the element over 300 milliseconds. During the animation, the element assumes its default width and opacity.
|
||||
|
||||
- Si hay varios elementos coincidentes, se escalona en cada elemento comenzando en la parte superior de la página, con un retraso de 50 milisegundos entre cada elemento.
|
||||
* If there are multiple matching elements, staggers in each element starting at the top of the page, with a 50-millisecond delay between each element.
|
||||
|
||||
## Resumen de la secuencia de animación
|
||||
## Animation sequence summary
|
||||
|
||||
Las funciones Angular para animar múltiples elementos comienzan con `query()` para encontrar elementos internos, por ejemplo, reuniendo todas las imágenes dentro de un `<div>`. Las funciones restantes, `stagger()`, [`group()`](api/animations/group) y `sequence()`, aplican cascadas o te permiten controlar cómo se aplican múltiples pasos de animación.
|
||||
Angular functions for animating multiple elements start with `query()` to find inner elements, for example gathering all images within a `<div>`. The remaining functions, `stagger()`, [`group()`](api/animations/group), and `sequence()`, apply cascades or allow you to control how multiple animation steps are applied.
|
||||
|
||||
## Más sobre animaciones en Angular
|
||||
## More on Angular animations
|
||||
|
||||
También puedes estar interesado en lo siguiente:
|
||||
You may also be interested in the following:
|
||||
|
||||
- [Introducción a animaciones Angular](guide/animations)
|
||||
- [Transición y triggers](guide/transition-and-triggers)
|
||||
- [Animaicones reusables](guide/reusable-animations)
|
||||
- [Animaciones en transición de ruta](guide/route-animations)
|
||||
* [Introduction to Angular animations](guide/animations)
|
||||
* [Transition and triggers](guide/transition-and-triggers)
|
||||
* [Reusable animations](guide/reusable-animations)
|
||||
* [Route transition animations](guide/route-animations)
|
||||
|
@ -125,7 +125,7 @@ Emulated is the default and most commonly used view encapsulation. For more info
|
||||
|
||||
<div class="alert is-important">
|
||||
|
||||
The shadow-piercing descendant combinator is deprecated and [support is being removed from major browsers](https://www.chromestatus.com/features/6750456638341120) and tools.
|
||||
The shadow-piercing descendant combinator is deprecated and [support is being removed from major browsers](https://www.chromestatus.com/feature/6750456638341120) and tools.
|
||||
As such we plan to drop support in Angular (for all 3 of `/deep/`, `>>>` and `::ng-deep`).
|
||||
Until then `::ng-deep` should be preferred for a broader compatibility with the tools.
|
||||
|
||||
|
@ -1,245 +0,0 @@
|
||||
# Creating libraries
|
||||
|
||||
This page provides a conceptual overview of how you can create and publish new libraries to extend Angular functionality.
|
||||
|
||||
If you find that you need to solve the same problem in more than one app (or want to share your solution with other developers), you have a candidate for a library.
|
||||
A simple example might be a button that sends users to your company website, that would be included in all apps that your company builds.
|
||||
|
||||
## Getting started
|
||||
|
||||
Use the Angular CLI to generate a new library skeleton in a new workspace with the following commands.
|
||||
|
||||
<code-example language="bash">
|
||||
ng new my-workspace --create-application=false
|
||||
cd my-workspace
|
||||
ng generate library my-lib
|
||||
</code-example>
|
||||
|
||||
The `ng generate` command creates the `projects/my-lib` folder in your workspace, which contains a component and a service inside an NgModule.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For more details on how a library project is structured, refer to the [Library project files](guide/file-structure#library-project-files) section of the [Project File Structure guide](guide/file-structure).
|
||||
|
||||
You can use the monorepo model to use the same workspace for multiple projects.
|
||||
See [Setting up for a multi-project workspace](guide/file-structure#multiple-projects).
|
||||
|
||||
</div>
|
||||
|
||||
When you generate a new library, the workspace configuration file, `angular.json`, is updated with a project of type 'library'.
|
||||
|
||||
<code-example format="json">
|
||||
"projects": {
|
||||
...
|
||||
"my-lib": {
|
||||
"root": "projects/my-lib",
|
||||
"sourceRoot": "projects/my-lib/src",
|
||||
"projectType": "library",
|
||||
"prefix": "lib",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
...
|
||||
</code-example>
|
||||
|
||||
You can build, test, and lint the project with CLI commands:
|
||||
|
||||
<code-example language="bash">
|
||||
ng build my-lib
|
||||
ng test my-lib
|
||||
ng lint my-lib
|
||||
</code-example>
|
||||
|
||||
Notice that the configured builder for the project is different from the default builder for app projects.
|
||||
This builder, among other things, ensures that the library is always built with the [AOT compiler](guide/aot-compiler), without the need to specify the `--prod` flag.
|
||||
|
||||
To make library code reusable you must define a public API for it. This "user layer" defines what is available to consumers of your library. A user of your library should be able to access public functionality (such as NgModules, service providers and general utility functions) through a single import path.
|
||||
|
||||
The public API for your library is maintained in the `public-api.ts` file in your library folder.
|
||||
Anything exported from this file is made public when your library is imported into an application.
|
||||
Use an NgModule to expose services and components.
|
||||
|
||||
Your library should supply documentation (typically a README file) for installation and maintenance.
|
||||
|
||||
## Refactoring parts of an app into a library
|
||||
|
||||
To make your solution reusable, you need to adjust it so that it does not depend on app-specific code.
|
||||
Here are some things to consider in migrating application functionality to a library.
|
||||
|
||||
* Declarations such as components and pipes should be designed as stateless, meaning they don’t rely on or alter external variables. If you do rely on state, you need to evaluate every case and decide whether it is application state or state that the library would manage.
|
||||
|
||||
* Any observables that the components subscribe to internally should be cleaned up and disposed of during the lifecycle of those components.
|
||||
|
||||
* Components should expose their interactions through inputs for providing context, and outputs for communicating events to other components.
|
||||
|
||||
* Check all internal dependencies.
|
||||
* For custom classes or interfaces used in components or service, check whether they depend on additional classes or interfaces that also need to be migrated.
|
||||
* Similarly, if your library code depends on a service, that service needs to be migrated.
|
||||
* If your library code or its templates depend on other libraries (such as Angular Material, for instance), you must configure your library with those dependencies.
|
||||
|
||||
* Consider how you provide services to client applications.
|
||||
|
||||
* Services should declare their own providers (rather than declaring providers in the NgModule or a component), so that they are *tree-shakable*. This allows the compiler to leave the service out of the bundle if it never gets injected into the application that imports the library. For more about this, see [Tree-shakable providers](guide/dependency-injection-providers#tree-shakable-providers).
|
||||
|
||||
* If you register global service providers or share providers across multiple NgModules, use the [`forRoot()` and `forChild()` design patterns](guide/singleton-services) provided by the [RouterModule](api/router/RouterModule).
|
||||
|
||||
* If your library provides optional services that might not be used by all client applications, support proper tree-shaking for that case by using the [lightweight token design pattern](guide/lightweight-injection-tokens).
|
||||
|
||||
{@a integrating-with-the-cli}
|
||||
|
||||
## Integrating with the CLI using code-generation schematics
|
||||
|
||||
A library typically includes *reusable code* that defines components, services, and other Angular artifacts (pipes, directives, and so on) that you simply import into a project.
|
||||
A library is packaged into an npm package for publishing and sharing.
|
||||
This package can also include [schematics](guide/glossary#schematic) that provide instructions for generating or transforming code directly in your project, in the same way that the CLI creates a generic new component with `ng generate component`.
|
||||
A schematic that is packaged with a library can, for example, provide the Angular CLI with the information it needs to generate a component that configures and uses a particular feature, or set of features, defined in that library.
|
||||
One example of this is Angular Material's navigation schematic which configures the CDK's `BreakpointObserver` and uses it with Material's `MatSideNav` and `MatToolbar` components.
|
||||
|
||||
You can create and include the following kinds of schematics.
|
||||
|
||||
* Include an installation schematic so that `ng add` can add your library to a project.
|
||||
|
||||
* Include generation schematics in your library so that `ng generate` can scaffold your defined artifacts (components, services, tests, and so on) in a project.
|
||||
|
||||
* Include an update schematic so that `ng update` can update your library’s dependencies and provide migrations for breaking changes in new releases.
|
||||
|
||||
What you include in your library depends on your task.
|
||||
For example, you could define a schematic to create a dropdown that is pre-populated with canned data to show how to add it to an app.
|
||||
If you want a dropdown that would contain different passed-in values each time, your library could define a schematic to create it with a given configuration. Developers could then use `ng generate` to configure an instance for their own app.
|
||||
|
||||
Suppose you want to read a configuration file and then generate a form based on that configuration.
|
||||
If that form will need additional customization by the developer who is using your library, it might work best as a schematic.
|
||||
However, if the forms will always be the same and not need much customization by developers, then you could create a dynamic component that takes the configuration and generates the form.
|
||||
In general, the more complex the customization, the more useful the schematic approach.
|
||||
|
||||
To learn more, see [Schematics Overview](guide/schematics) and [Schematics for Libraries](guide/schematics-for-libraries).
|
||||
|
||||
## Publishing your library
|
||||
|
||||
Use the Angular CLI and the npm package manager to build and publish your library as an npm package.
|
||||
|
||||
Before publishing a library to NPM, build it using the `--prod` flag which will use the older compiler and runtime known as View Engine instead of Ivy.
|
||||
|
||||
<code-example language="bash">
|
||||
ng build my-lib --prod
|
||||
cd dist/my-lib
|
||||
npm publish
|
||||
</code-example>
|
||||
|
||||
If you've never published a package in npm before, you must create a user account. Read more in [Publishing npm Packages](https://docs.npmjs.com/getting-started/publishing-npm-packages).
|
||||
|
||||
<div class="alert is-important">
|
||||
|
||||
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, publishing your libraries using the View Engine compiler ensures that they can be transparently consumed by both View Engine and Ivy apps.
|
||||
|
||||
</div>
|
||||
|
||||
{@a lib-assets}
|
||||
|
||||
## Managing assets in a library
|
||||
|
||||
Starting with version 9.x of the [ng-packagr](https://github.com/ng-packagr/ng-packagr/blob/master/README.md) tool, you can configure the tool to automatically copy assets into your library package as part of the build process.
|
||||
You can use this feature when your library needs to publish optional theming files, Sass mixins, or documentation (like a changelog).
|
||||
|
||||
* Learn how to [copy assets into your library as part of the build](https://github.com/ng-packagr/ng-packagr/blob/master/docs/copy-assets.md).
|
||||
|
||||
* Learn more about how to use the tool to [embed assets in CSS](https://github.com/ng-packagr/ng-packagr/blob/master/docs/embed-assets-css.md).
|
||||
|
||||
|
||||
## Linked libraries
|
||||
|
||||
While working on a published library, you can use [npm link](https://docs.npmjs.com/cli/link) to avoid reinstalling the library on every build.
|
||||
|
||||
The library must be rebuilt on every change.
|
||||
When linking a library, make sure that the build step runs in watch mode, and that the library's `package.json` configuration points at the correct entry points.
|
||||
For example, `main` should point at a JavaScript file, not a TypeScript file.
|
||||
|
||||
## Use TypeScript path mapping for peer dependencies
|
||||
|
||||
Angular libraries should list all `@angular/*` dependencies as peer dependencies.
|
||||
This ensures that when modules ask for Angular, they all get the exact same module.
|
||||
If a library lists `@angular/core` in `dependencies` instead of `peerDependencies`, it might get a different Angular module instead, which would cause your application to break.
|
||||
|
||||
While developing a library, you must install all peer dependencies through `devDependencies` to ensure that the library compiles properly.
|
||||
A linked library will then have its own set of Angular libraries that it uses for building, located in its `node_modules` folder.
|
||||
However, this can cause problems while building or running your application.
|
||||
|
||||
To get around this problem you can use TypeScript path mapping to tell TypeScript that it should load some modules from a specific location.
|
||||
List all the peer dependencies that your library uses in the workspace TypeScript configuration file `./tsconfig.json`, and point them at the local copy in the app's `node_modules` folder.
|
||||
|
||||
```
|
||||
{
|
||||
"compilerOptions": {
|
||||
// ...
|
||||
// paths are relative to `baseUrl` path.
|
||||
"paths": {
|
||||
"@angular/*": [
|
||||
"./node_modules/@angular/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This mapping ensures that your library always loads the local copies of the modules it needs.
|
||||
|
||||
|
||||
## Using your own library in apps
|
||||
|
||||
You don't have to publish your library to the npm package manager in order to use it in your own apps, but you do have to build it first.
|
||||
|
||||
To use your own library in an app:
|
||||
|
||||
* Build the library. You cannot use a library before it is built.
|
||||
<code-example language="bash">
|
||||
ng build my-lib
|
||||
</code-example>
|
||||
|
||||
* In your apps, import from the library by name:
|
||||
```
|
||||
import { myExport } from 'my-lib';
|
||||
```
|
||||
|
||||
### Building and rebuilding your library
|
||||
|
||||
The build step is important if you haven't published your library as an npm package and then installed the package back into your app from npm.
|
||||
For instance, if you clone your git repository and run `npm install`, your editor will show the `my-lib` imports as missing if you haven't yet built your library.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
When you import something from a library in an Angular app, Angular looks for a mapping between the library name and a location on disk.
|
||||
When you install a library package, the mapping is in the `node_modules` folder. When you build your own library, it has to find the mapping in your `tsconfig` paths.
|
||||
|
||||
Generating a library with the Angular CLI automatically adds its path to the `tsconfig` file.
|
||||
The Angular CLI uses the `tsconfig` paths to tell the build system where to find the library.
|
||||
|
||||
</div>
|
||||
|
||||
If you find that changes to your library are not reflected in your app, your app is probably using an old build of the library.
|
||||
|
||||
You can rebuild your library whenever you make changes to it, but this extra step takes time.
|
||||
*Incremental builds* functionality improves the library-development experience.
|
||||
Every time a file is changed a partial build is performed that emits the amended files.
|
||||
|
||||
Incremental builds can be run as a background process in your dev environment. To take advantage of this feature add the `--watch` flag to the build command:
|
||||
|
||||
<code-example language="bash">
|
||||
ng build my-lib --watch
|
||||
</code-example>
|
||||
|
||||
<div class="alert is-important">
|
||||
|
||||
The CLI `build` command uses a different builder and invokes a different build tool for libraries than it does for applications.
|
||||
|
||||
* The build system for apps, `@angular-devkit/build-angular`, is based on `webpack`, and is included in all new Angular CLI projects.
|
||||
* The build system for libraries is based on `ng-packagr`. It is only added to your dependencies when you add a library using `ng generate library my-lib`.
|
||||
|
||||
The two build systems support different things, and even where they support the same things, they do those things differently.
|
||||
This means that the TypeScript source can result in different JavaScript code in a built library than it would in a built application.
|
||||
|
||||
For this reason, an app that depends on a library should only use TypeScript path mappings that point to the *built library*.
|
||||
TypeScript path mappings should *not* point to the library source `.ts` files.
|
||||
|
||||
</div>
|
@ -1,13 +1,13 @@
|
||||
# Creando librerías
|
||||
# Creating libraries
|
||||
|
||||
Está pagina provee una vista conceptual de como puedes crear y publicar nuevas librerías para extender las funcionalidades de Angular.
|
||||
This page provides a conceptual overview of how you can create and publish new libraries to extend Angular functionality.
|
||||
|
||||
Si necesitas resolver el mismo problema en mas de una aplicación (o quiere compartir tu solución con otros desarrolladores), tienes un candidato para una librería.
|
||||
Un ejemplo simple puede ser un botón que envía a los usuarios hacia el sitio web de tu empresa, que sería incluido en todas las aplicaciones que tu empresa crea.
|
||||
If you find that you need to solve the same problem in more than one app (or want to share your solution with other developers), you have a candidate for a library.
|
||||
A simple example might be a button that sends users to your company website, that would be included in all apps that your company builds.
|
||||
|
||||
## Empezando
|
||||
## Getting started
|
||||
|
||||
Usa el Angular CLI para generar un nuevo esqueleto de librería, en nuevo espacio de trabajo con los siguiente comandos.
|
||||
Use the Angular CLI to generate a new library skeleton in a new workspace with the following commands.
|
||||
|
||||
<code-example language="bash">
|
||||
ng new my-workspace --create-application=false
|
||||
@ -15,17 +15,18 @@ Usa el Angular CLI para generar un nuevo esqueleto de librería, en nuevo espaci
|
||||
ng generate library my-lib
|
||||
</code-example>
|
||||
|
||||
El comando `ng generate` crea la carpeta `projects/my-lib` en el espacio de trabajo, que contiene un componente y un servicio dentro de un NgModule.
|
||||
The `ng generate` command creates the `projects/my-lib` folder in your workspace, which contains a component and a service inside an NgModule.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Para más detalles sobre como una librería es estructurada, refiérase a los [Archivos de Librería](guide/file-structure#library-project-files) en la sección de [Guía de estructura de archivos](guide/file-structure).
|
||||
For more details on how a library project is structured, refer to the [Library project files](guide/file-structure#library-project-files) section of the [Project File Structure guide](guide/file-structure).
|
||||
|
||||
Puedes usar un modelo de monorepo para usar el mismo espacio de trabajo con multiples proyectos. Véase [Configuración para espacio de trabajo multiproyecto](guide/file-structure#multiple-projects).
|
||||
You can use the monorepo model to use the same workspace for multiple projects.
|
||||
See [Setting up for a multi-project workspace](guide/file-structure#multiple-projects).
|
||||
|
||||
</div>
|
||||
|
||||
Cuando se genera una nueva librería, el archivo de configuración del espacio de trabajo, `angular.json`, es actualizado con un proyecto de tipo 'library'.
|
||||
When you generate a new library, the workspace configuration file, `angular.json`, is updated with a project of type `library`.
|
||||
|
||||
<code-example format="json">
|
||||
"projects": {
|
||||
@ -41,7 +42,7 @@ Cuando se genera una nueva librería, el archivo de configuración del espacio d
|
||||
...
|
||||
</code-example>
|
||||
|
||||
Puedes crear, probar y comprobar con los comandos de CLI:
|
||||
You can build, test, and lint the project with CLI commands:
|
||||
|
||||
<code-example language="bash">
|
||||
ng build my-lib
|
||||
@ -49,78 +50,75 @@ Puedes crear, probar y comprobar con los comandos de CLI:
|
||||
ng lint my-lib
|
||||
</code-example>
|
||||
|
||||
Puedes notar que el constructor configurado para el proyecto es diferente que el constructor por defecto para proyectos.
|
||||
El constructor, entre otras cosas, asegura que la librería siempre este construida con el [compilador AOT](guide/aot-compiler), sin la necesidad de especificar la bandera `--prod`.
|
||||
Notice that the configured builder for the project is different from the default builder for app projects.
|
||||
This builder, among other things, ensures that the library is always built with the [AOT compiler](guide/aot-compiler), without the need to specify the `--prod` flag.
|
||||
|
||||
Para hacer el código de la librería reusable debes definir una API pública para ella. Esta "capa de usuario" define que esta disponible para los consumidores de tu librería. Un usuario de tu librería debería ser capaz de acceder a la funcionalidad publica (como NgModules, servicios, proveedores y en general funciones de utilidad) mediante una sola ruta.
|
||||
To make library code reusable you must define a public API for it. This "user layer" defines what is available to consumers of your library. A user of your library should be able to access public functionality (such as NgModules, service providers and general utility functions) through a single import path.
|
||||
|
||||
La API pública para tu librería es mantenida en el archivo `public-api.ts` en tu carpeta de librería.
|
||||
Cualquier cosa exportada desde este archivo se hace publica cuando tu librería es importada dentro de una aplicación.
|
||||
Usa un NgModule para exponer los servicios y componentes.
|
||||
The public API for your library is maintained in the `public-api.ts` file in your library folder.
|
||||
Anything exported from this file is made public when your library is imported into an application.
|
||||
Use an NgModule to expose services and components.
|
||||
|
||||
Tu libería debería suministrar documentatión (típicamente en el archivo README) para la instalación y mantenimiento.
|
||||
Your library should supply documentation (typically a README file) for installation and maintenance.
|
||||
|
||||
## Refactorizando partes de una app dentro de un librería
|
||||
## Refactoring parts of an app into a library
|
||||
|
||||
Para hacer tu solución reusable, necesitas ajustarla para que no dependa del código específico de la aplicación.
|
||||
Aquí algunas cosas para considerar al migrar la funcionalidad de la aplicación a una librería.
|
||||
To make your solution reusable, you need to adjust it so that it does not depend on app-specific code.
|
||||
Here are some things to consider in migrating application functionality to a library.
|
||||
|
||||
* Declaraciones tales como componentes y pipes deberían ser diseñados como 'stateless' (sin estado), lo que significa que no dependen ni alteran variables externas. Si tu dependes del estado, necesitas evaluar cada caso y decidir el estado de la aplicación o el estado que la aplicación administraría.
|
||||
* Declarations such as components and pipes should be designed as stateless, meaning they don’t rely on or alter external variables. If you do rely on state, you need to evaluate every case and decide whether it is application state or state that the library would manage.
|
||||
|
||||
* Cualquier observable al cual los componentes se suscriban internamente deberían ser limpiados y desechados durante el ciclo de vida de esos componentes.
|
||||
* Any observables that the components subscribe to internally should be cleaned up and disposed of during the lifecycle of those components.
|
||||
|
||||
* Los componentes deberían exponer sus interacciones a través de 'inputs' para proporcionar contexto y 'outputs' para comunicar los eventos hacia otros componentes.
|
||||
* Components should expose their interactions through inputs for providing context, and outputs for communicating events to other components.
|
||||
|
||||
* Verifique todas las dependencias internas.
|
||||
* Para clases personalizadas o interfaces usadas en componentes o servicios, verifique si dependen en clases adicionales o interfaces que también necesiten ser migradas.
|
||||
* Del mismo modo, si tu código de librería depende de un servicio, este servicio necesita ser migrado.
|
||||
* Si tu código de librería o sus plantillas dependen de otras librerías (como Angular Material), debes configurar tu librería con esas dependencias.
|
||||
* Check all internal dependencies.
|
||||
* For custom classes or interfaces used in components or service, check whether they depend on additional classes or interfaces that also need to be migrated.
|
||||
* Similarly, if your library code depends on a service, that service needs to be migrated.
|
||||
* If your library code or its templates depend on other libraries (such as Angular Material, for instance), you must configure your library with those dependencies.
|
||||
|
||||
* Considere como proporcionar servicios a las aplicaciones cliente.
|
||||
* Consider how you provide services to client applications.
|
||||
|
||||
* Los servicios deberían declarar sus propios proveedores (en lugar de declarar los proveedores en el NgModule o en un componente). Esto le permite al compilador dejar los servicios fuera del 'bundle' si este nunca fue inyectado dentro de la aplicación que importa la librería, véase [proveedores Tree-shakable](guide/dependency-injection-providers#tree-shakable-providers)
|
||||
* Si registras proveedores globales o compartes proveedores a través de múltiples NgModules, usa el [`forRoot()` y `forChild()` como patrones de diseño](guide/singleton-services) proporcionados por el [RouterModule](api/router/RouterModule).
|
||||
* Si tu librería proporciona servicios opcionales que podrían no ser usados por todos las aplicaciones cliente, soporte apropiadamente el 'tree-shaking' para esos casos usando el [patrón de diseño de token ligero](guide/lightweight-injection-tokens).
|
||||
* Services should declare their own providers (rather than declaring providers in the NgModule or a component), so that they are *tree-shakable*. This allows the compiler to leave the service out of the bundle if it never gets injected into the application that imports the library. For more about this, see [Tree-shakable providers](guide/dependency-injection-providers#tree-shakable-providers).
|
||||
|
||||
* If you register global service providers or share providers across multiple NgModules, use the [`forRoot()` and `forChild()` design patterns](guide/singleton-services) provided by the [RouterModule](api/router/RouterModule).
|
||||
|
||||
* If your library provides optional services that might not be used by all client applications, support proper tree-shaking for that case by using the [lightweight token design pattern](guide/lightweight-injection-tokens).
|
||||
|
||||
{@a integrating-with-the-cli}
|
||||
|
||||
## Integración con el CLI usando generación de código con los schematics.
|
||||
## Integrating with the CLI using code-generation schematics
|
||||
|
||||
Comúnmente una librería incluye *código reusable* que define componentes, servicios y otros Artefactos de Angular (pipes, directivas y etc.) que tu simplemente importas a un proyecto.
|
||||
Una librería es empaquetada dentro de un paquete npm para publicar y compartir.
|
||||
A library typically includes *reusable code* that defines components, services, and other Angular artifacts (pipes, directives, and so on) that you simply import into a project.
|
||||
A library is packaged into an npm package for publishing and sharing.
|
||||
This package can also include [schematics](guide/glossary#schematic) that provide instructions for generating or transforming code directly in your project, in the same way that the CLI creates a generic new component with `ng generate component`.
|
||||
A schematic that is packaged with a library can, for example, provide the Angular CLI with the information it needs to generate a component that configures and uses a particular feature, or set of features, defined in that library.
|
||||
One example of this is Angular Material's navigation schematic which configures the CDK's `BreakpointObserver` and uses it with Material's `MatSideNav` and `MatToolbar` components.
|
||||
|
||||
Este paquete también puede incluir [schematics](guide/glossary#schematic) que proporciona instrucciones para generar o transformar código directamente un tu proyecto, de la misma forma que el CLI crea un nuevo componente genérico con `ng generate component`.
|
||||
You can create and include the following kinds of schematics.
|
||||
|
||||
Un 'schematic' empaquetado con una librería puede por ejemplo proporcionar al Angular CLI la información que necesita para generar un componente que configura y usa una particular característica o conjunto de características, definido en la librería.
|
||||
* Include an installation schematic so that `ng add` can add your library to a project.
|
||||
|
||||
Un ejemplo de esto es el 'schematic' de navegación de Angular Material el cual configura los CDK's `BreakpointObserver` y lo usa con los componentes `MatSideNav` y `MatToolbar` de Angular Material.
|
||||
* Include generation schematics in your library so that `ng generate` can scaffold your defined artifacts (components, services, tests, and so on) in a project.
|
||||
|
||||
Puedes crear e incluir los siguientes tipos de 'schematics'.
|
||||
* Include an update schematic so that `ng update` can update your library’s dependencies and provide migrations for breaking changes in new releases.
|
||||
|
||||
* Incluye un 'schematic' de instalación para que con `ng add` puedas agregar tu libería a un proyecto.
|
||||
What you include in your library depends on your task.
|
||||
For example, you could define a schematic to create a dropdown that is pre-populated with canned data to show how to add it to an app.
|
||||
If you want a dropdown that would contain different passed-in values each time, your library could define a schematic to create it with a given configuration. Developers could then use `ng generate` to configure an instance for their own app.
|
||||
|
||||
* Incluye un 'schematic' de generación en tu librería para que con `ng generate` puedas hacer scaffolding de sus artefactos (componentes, servicios, pruebas y etc) en un proyecto.
|
||||
Suppose you want to read a configuration file and then generate a form based on that configuration.
|
||||
If that form will need additional customization by the developer who is using your library, it might work best as a schematic.
|
||||
However, if the form will always be the same and not need much customization by developers, then you could create a dynamic component that takes the configuration and generates the form.
|
||||
In general, the more complex the customization, the more useful the schematic approach.
|
||||
|
||||
* Incluye un 'schematic' de actualización para que con `ng update` puedas actualizar las dependencias de tu librería y proporcionar migraciones para cambios importantes en un nuevo release.
|
||||
To learn more, see [Schematics Overview](guide/schematics) and [Schematics for Libraries](guide/schematics-for-libraries).
|
||||
|
||||
Lo que incluya tu librería depende de tu tarea.
|
||||
Por ejemplo, podrías definir un 'schematic' para crear un desplegable (dropdown) que esta pre-poblado con datos para mostrar como agregarlo a una aplicación.
|
||||
Si quieres un desplegable (dropdown) que contendrá valores diferentes cada vez, tu librería podría definir un 'schematic' para crearlo con una configuración dada. Los desarrolladores podrán entonces usar `ng generate` para configurar una instancia para sus propias aplicaciones.
|
||||
## Publishing your library
|
||||
|
||||
Supón que quieres leer un archivo de configuración y entonces generar una formulario con base a la configuración.
|
||||
Si este formulario necesita personalización adicional por parte del desarrollador que esta usando tu librería, esto podría trabajar mejor como un 'schematic'.
|
||||
Sin embargo, si el formulario siempre será el mismo y no necesita de mucha personalización por parte de los desarrolladores, entonces podría crear un componente dinámico que tome la configuración y genere el formulario.
|
||||
En general, entre más compleja sea personalización, la más util será en enfoque de un 'schematic'.
|
||||
Use the Angular CLI and the npm package manager to build and publish your library as an npm package.
|
||||
|
||||
Para aprender más, véase [Vista general de Schematics](guide/schematics) y [Schematics para librerías](guide/schematics-for-libraries).
|
||||
|
||||
{@a publishing-your-library}
|
||||
|
||||
## Publicando tu librería
|
||||
|
||||
Usa el Angular CLI y el gestor de paquetes npm para construir y publicar tu librería como un paquete npm.
|
||||
|
||||
Antes de publicar una librería a NPM, constrúyela usando la bandera `--prod` la cúal usará el compilador y tiempo de ejecución (runtime) más antiguos como 'View Engine' en vez de 'Ivy'.
|
||||
Before publishing a library to NPM, build it using the `--prod` flag which will use the older compiler and runtime known as View Engine instead of Ivy.
|
||||
|
||||
<code-example language="bash">
|
||||
ng build my-lib --prod
|
||||
@ -128,50 +126,48 @@ cd dist/my-lib
|
||||
npm publish
|
||||
</code-example>
|
||||
|
||||
Si nunca has publicado un paquete en npm antes, tu debes crear un cuenta. Lee más en [Publicando paquetes npm](https://docs.npmjs.com/getting-started/publishing-npm-packages).
|
||||
If you've never published a package in npm before, you must create a user account. Read more in [Publishing npm Packages](https://docs.npmjs.com/getting-started/publishing-npm-packages).
|
||||
|
||||
<div class="alert is-important">
|
||||
|
||||
Por ahora, no es recomendando publicar librerías con Ivy hacia NPM por que Ivy genera código que no es retrocompatible con 'View Engine', entonces las aplicaciones usando 'View Engine' no podrán consumirlas. Además, las instrucciones internas de IVY no son estables aun, lo cual puede romper potencialmente a los consumidores que usan una diferente versión de Angular a la que uso para construir la libería.
|
||||
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.
|
||||
|
||||
Cuando una librería publicada es usada en una aplicación con Ivy, el Angular CLI automáticamente la convertirá a Ivy usando una herramienta conocida como el compilador de compatibilidad Angular (`ngcc`). Por lo tanto, publicar tus librerías usado el compilador 'View Engine' garantiza que ellas puede ser consumidas de forma transparente por ambos motores 'View Engine' y 'Ivy'.
|
||||
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>
|
||||
|
||||
{@a lib-assets}
|
||||
|
||||
## Gestionando activos (assets) en una librería.
|
||||
## Managing assets in a library
|
||||
|
||||
Desde la versión 9.x de la herramienta [ng-packagr](https://github.com/ng-packagr/ng-packagr/blob/master/README.md), puedes configurar la herramienta para que automáticamente copie los activos (assets) dentro de el paquete de librería como parte del proceso de construcción.
|
||||
Puedes usar esta característica cuando tu librería necesite publicar archivos de temas opcionales, funciones de Sass o documentación (como un registro de cambios 'changelog').
|
||||
Starting with version 9.x of the [ng-packagr](https://github.com/ng-packagr/ng-packagr/blob/master/README.md) tool, you can configure the tool to automatically copy assets into your library package as part of the build process.
|
||||
You can use this feature when your library needs to publish optional theming files, Sass mixins, or documentation (like a changelog).
|
||||
|
||||
* Aprende como [copiar activos (assets) dentro de tu librería como parte de la construcción](https://github.com/ng-packagr/ng-packagr/blob/master/docs/copy-assets.md).
|
||||
* Learn how to [copy assets into your library as part of the build](https://github.com/ng-packagr/ng-packagr/blob/master/docs/copy-assets.md).
|
||||
|
||||
* Aprende más acerca de como usar la herramienta para [incrustar activos (assets) de CSS](https://github.com/ng-packagr/ng-packagr/blob/master/docs/embed-assets-css.md).
|
||||
* Learn more about how to use the tool to [embed assets in CSS](https://github.com/ng-packagr/ng-packagr/blob/master/docs/embed-assets-css.md).
|
||||
|
||||
|
||||
## Vinculando librerías
|
||||
## Linked libraries
|
||||
|
||||
Mientras trabajas en un librería publicada, puedes usar [npm link](https://docs.npmjs.com/cli/link) para evitar re instalar la librería en cada construcción.
|
||||
While working on a published library, you can use [npm link](https://docs.npmjs.com/cli/link) to avoid reinstalling the library on every build.
|
||||
|
||||
La librería debe ser reconstruida en cada cambio.
|
||||
Cuando vinculas una librería, asegurate que el paso de construir corra en modo vigía (watch mode) y que el `package.json` de la librería configure los puntos de entrada correctos.
|
||||
Por ejemplo, `main` debería apuntar a un archivo JavaScript, no a un archivo TypeScript.
|
||||
The library must be rebuilt on every change.
|
||||
When linking a library, make sure that the build step runs in watch mode, and that the library's `package.json` configuration points at the correct entry points.
|
||||
For example, `main` should point at a JavaScript file, not a TypeScript file.
|
||||
|
||||
## Utiliza el mapeo de rutas de TypeScript por las dependencias de pares.
|
||||
## Use TypeScript path mapping for peer dependencies
|
||||
|
||||
Las librerías de Angular deben enumerar todas las dependencias `@angular/*` como dependencias de pares.
|
||||
Esto garantiza que cuando los módulos solicitan Angular, todos ellos obtienen exactamente el mismo módulo.
|
||||
Si tu librería lista `@angular/core` en `dependencies` en vez de en `peerDependencies`, podría obtener un módulo Angular diferente, lo qué haría que tu aplicación se rompiera.
|
||||
Angular libraries should list all `@angular/*` dependencies as peer dependencies.
|
||||
This ensures that when modules ask for Angular, they all get the exact same module.
|
||||
If a library lists `@angular/core` in `dependencies` instead of `peerDependencies`, it might get a different Angular module instead, which would cause your application to break.
|
||||
|
||||
Cuando desarrollas una librería, tu debes instalar todas las dependencias de pares mediante `devDependencies` para garantizar que la librería compile apropiadamente.
|
||||
Una librería vinculada tendrá su propio conjunto de librerías Angular que usa para construir, ubicados en su carpeta `node_modules`.
|
||||
While developing a library, you must install all peer dependencies through `devDependencies` to ensure that the library compiles properly.
|
||||
A linked library will then have its own set of Angular libraries that it uses for building, located in its `node_modules` folder.
|
||||
However, this can cause problems while building or running your application.
|
||||
|
||||
Sin embargo, esto puede causar problemas mientras construyes o corres tu aplicación.
|
||||
|
||||
Para evitar este problema tu puedes usar el mapeo de rutas de TypeScript para indicarle a TypeScript que este debería cargar algunos módulos desde una ubicación especifica.
|
||||
|
||||
Enumera todas las dependencias de pares que tu librería usa en el archivo de configuración `./tsconfig.json` del espacio de trabajo de TypeScript, y apúntalos a la copia local en la carpeta `node_modules` de la aplicación.
|
||||
To get around this problem you can use TypeScript path mapping to tell TypeScript that it should load some modules from a specific location.
|
||||
List all the peer dependencies that your library uses in the workspace TypeScript configuration file `./tsconfig.json`, and point them at the local copy in the app's `node_modules` folder.
|
||||
|
||||
```
|
||||
{
|
||||
@ -187,47 +183,47 @@ Enumera todas las dependencias de pares que tu librería usa en el archivo de co
|
||||
}
|
||||
```
|
||||
|
||||
Este mapeador garantiza que tu librería siempre cargue las copias locales del módulo que necesita.
|
||||
This mapping ensures that your library always loads the local copies of the modules it needs.
|
||||
|
||||
|
||||
## Usando tu propia librería en aplicaciones.
|
||||
## Using your own library in apps
|
||||
|
||||
No tienes que publicar tu librería hacia el gestor de paquetes npm para usarla en tus propias aplicaciones, pero tienes que construirla primero.
|
||||
You don't have to publish your library to the npm package manager in order to use it in your own apps, but you do have to build it first.
|
||||
|
||||
Para usar tu propia librería en tu aplicación:
|
||||
To use your own library in an app:
|
||||
|
||||
* Construye la librería. No puedes usar una librería antes que se construya.
|
||||
* Build the library. You cannot use a library before it is built.
|
||||
<code-example language="bash">
|
||||
ng build my-lib
|
||||
</code-example>
|
||||
|
||||
* En tus aplicaciones, importa la librería por el nombre:
|
||||
* In your apps, import from the library by name:
|
||||
```
|
||||
import { myExport } from 'my-lib';
|
||||
```
|
||||
|
||||
### Construyendo y re construyendo tu librería.
|
||||
### Building and rebuilding your library
|
||||
|
||||
El paso de construir es importante si no tienes publicada tu librería como un paquete npm y luego ha instalado el paquete de nuevo dentro tu aplicación desde npm.
|
||||
Por ejemplo, si clonas tu repositorio git y corres `npm install`, tu editor mostrará la importación de `my-lib` como perdida si no tienes aun construida tu librería.
|
||||
The build step is important if you haven't published your library as an npm package and then installed the package back into your app from npm.
|
||||
For instance, if you clone your git repository and run `npm install`, your editor will show the `my-lib` imports as missing if you haven't yet built your library.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Cuando importas algo desde una librería en una aplicación Angular, Angular busca un mapeo entre el nombre de librería y una ubicación en disco.
|
||||
Cuando instalas un paquete de librería, el mapeo esta en la carpeta `node_modules`. Cuando construyes tu propia librería, tiene que encontrar el mapeo en tus rutas de `tsconfig`.
|
||||
When you import something from a library in an Angular app, Angular looks for a mapping between the library name and a location on disk.
|
||||
When you install a library package, the mapping is in the `node_modules` folder. When you build your own library, it has to find the mapping in your `tsconfig` paths.
|
||||
|
||||
Generando una librería con el Angular CLI automáticamente agrega su ruta en el archivo `tsconfig`.
|
||||
El Angular CLI usa las rutas `tsconfig` para indicarle al sistema construido donde encontrar la librería.
|
||||
Generating a library with the Angular CLI automatically adds its path to the `tsconfig` file.
|
||||
The Angular CLI uses the `tsconfig` paths to tell the build system where to find the library.
|
||||
|
||||
</div>
|
||||
|
||||
Si descubres que los cambios en tu librería no son reflejados en tu aplicación, tu aplicación probablemente esta usando una construcción antigua de la librería.
|
||||
If you find that changes to your library are not reflected in your app, your app is probably using an old build of the library.
|
||||
|
||||
Puedes re construir tu librería cada vez que hagas cambios en esta, pero este paso extra toma tiempo.
|
||||
Las *construcciones incrementales* funcionalmente mejoran la experiencia de desarrollo de librerías.
|
||||
Cada vez que un archivo es cambiando una construcción parcial es realizada y esta emite los archivos modificados.
|
||||
You can rebuild your library whenever you make changes to it, but this extra step takes time.
|
||||
*Incremental builds* functionality improves the library-development experience.
|
||||
Every time a file is changed a partial build is performed that emits the amended files.
|
||||
|
||||
Las *Construcciones incrementales* puede ser ejecutadas como un proceso en segundo plano en tu entorno de desarrollo. Para aprovechar esta característica agrega la bandera `--watch` al comando de construcción:
|
||||
Incremental builds can be run as a background process in your dev environment. To take advantage of this feature add the `--watch` flag to the build command:
|
||||
|
||||
<code-example language="bash">
|
||||
ng build my-lib --watch
|
||||
@ -235,15 +231,15 @@ ng build my-lib --watch
|
||||
|
||||
<div class="alert is-important">
|
||||
|
||||
El comando `build` del CLI utiliza un constructor diferente e invoca una herramienta de construcción diferente para las librerías que para las aplicaciones.
|
||||
The CLI `build` command uses a different builder and invokes a different build tool for libraries than it does for applications.
|
||||
|
||||
* El sistema de construcción para aplicaciones, `@angular-devkit/build-angular`, esta basado en `webpack`, y esta incluida en todos los nuevos proyectos de Angular CLI.
|
||||
* El sistema de construcción esta basado en `ng-packagr`. Este es solo agregado en tus dependencias cuando agregas una librería usando `ng generate library my-lib`.
|
||||
* The build system for apps, `@angular-devkit/build-angular`, is based on `webpack`, and is included in all new Angular CLI projects.
|
||||
* The build system for libraries is based on `ng-packagr`. It is only added to your dependencies when you add a library using `ng generate library my-lib`.
|
||||
|
||||
Los dos sistemas de construcción soportan diferentes cosas e incluso si ellos soportan las mismas cosas, ellos hacen esas cosas de forma diferente.
|
||||
Esto quiere decir que la fuente de TypeScript puede generar en código JavaScript diferente en una librería construida que en una aplicación construida.
|
||||
The two build systems support different things, and even where they support the same things, they do those things differently.
|
||||
This means that the TypeScript source can result in different JavaScript code in a built library than it would in a built application.
|
||||
|
||||
Por esta razón, una aplicación que depende de una librería debería solo usar el mapeo de rutas de TypeScript que apunte a la *librería construida*.
|
||||
El mapeo de rutas de TypeScript no debería apuntar hacia los archivos `.ts` fuente de la librería.
|
||||
For this reason, an app that depends on a library should only use TypeScript path mappings that point to the *built library*.
|
||||
TypeScript path mappings should *not* point to the library source `.ts` files.
|
||||
|
||||
</div>
|
||||
|
@ -14,7 +14,7 @@ established through the components' [view objects](guide/glossary#view).
|
||||
Each component has a *host view*, and can have additional *embedded views*.
|
||||
An embedded view in component A is the
|
||||
host view of component B, which can in turn have embedded view.
|
||||
This means that there is a [view hierarchy](guide/glossary#view-tree) for each component,
|
||||
This means that there is a [view hierarchy](guide/glossary#view-hierarchy) for each component,
|
||||
of which that component's host view is the root.
|
||||
|
||||
There is an API for navigating *down* the view hierarchy.
|
||||
|
@ -511,9 +511,9 @@ Each script tag has a `type="module"` or `nomodule` attribute. Browsers with nat
|
||||
|
||||
To include differential loading in your application builds, you must configure the Browserslist and TypeScript configuration files in your application project.
|
||||
|
||||
The following examples show a `browserlistrc` and `tsconfig.json` file for a newly created Angular application. In this configuration, legacy browsers such as IE 9-11 are ignored, and the compilation target is ES2015.
|
||||
The following examples show a `.browserslistrc` and `tsconfig.json` file for a newly created Angular application. In this configuration, legacy browsers such as IE 9-11 are ignored, and the compilation target is ES2015.
|
||||
|
||||
<code-example language="none" header="browserslistrc">
|
||||
<code-example language="none" header=".browserslistrc">
|
||||
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
@ -527,7 +527,7 @@ The following examples show a `browserlistrc` and `tsconfig.json` file for a new
|
||||
last 1 Chrome version
|
||||
last 1 Firefox version
|
||||
last 2 Edge major versions
|
||||
last 2 Safari major version
|
||||
last 2 Safari major versions
|
||||
last 2 iOS major versions
|
||||
Firefox ESR
|
||||
not IE 9-11 # For IE 9-11 support, remove 'not'.
|
||||
|
@ -38,7 +38,6 @@ v9 - v12
|
||||
| `@angular/bazel` | [`Bazel builder and schematics`](#bazelbuilder) | v10 |
|
||||
| `@angular/common` | [`ReflectiveInjector`](#reflectiveinjector) | <!--v8--> v11 |
|
||||
| `@angular/common` | [`CurrencyPipe` - `DEFAULT_CURRENCY_CODE`](api/common/CurrencyPipe#currency-code-deprecation) | <!--v9--> v11 |
|
||||
| `@angular/core` | [`CollectionChangeRecord`](#core) | <!--v7--> v11 |
|
||||
| `@angular/core` | [`DefaultIterableDiffer`](#core) | <!--v7--> v11 |
|
||||
| `@angular/core` | [`ReflectiveKey`](#core) | <!--v8--> v11 |
|
||||
| `@angular/core` | [`RenderComponentType`](#core) | <!--v7--> v11 |
|
||||
@ -89,7 +88,6 @@ Tip: In the [API reference section](api) of this doc site, deprecated APIs are i
|
||||
|
||||
| API | Replacement | Deprecation announced | Notes |
|
||||
| --- | ----------- | --------------------- | ----- |
|
||||
| [`CollectionChangeRecord`](api/core/CollectionChangeRecord) | [`IterableChangeRecord`](api/core/IterableChangeRecord) | v4 | none |
|
||||
| [`DefaultIterableDiffer`](api/core/DefaultIterableDiffer) | n/a | v4 | Not part of public API. |
|
||||
| [`ReflectiveInjector`](api/core/ReflectiveInjector) | [`Injector.create`](api/core/Injector#create) | v5 | See [`ReflectiveInjector`](#reflectiveinjector) |
|
||||
| [`ReflectiveKey`](api/core/ReflectiveKey) | none | v5 | none |
|
||||
|
@ -119,7 +119,14 @@ The recently-developed [custom elements](https://developer.mozilla.org/en-US/doc
|
||||
|
||||
In browsers that support Custom Elements natively, the specification requires developers use ES2015 classes to define Custom Elements - developers can opt-in to this by setting the `target: "es2015"` property in their project's [TypeScript configuration file](/guide/typescript-configuration). As Custom Element and ES2015 support may not be available in all browsers, developers can instead choose to use a polyfill to support older browsers and ES5 code.
|
||||
|
||||
Use the [Angular CLI](cli) to automatically set up your project with the correct polyfill: `ng add @angular/elements --project=*your_project_name*`.
|
||||
Use the [Angular CLI](cli) to automatically set up your project with the correct polyfill:
|
||||
|
||||
<code-example language="sh">
|
||||
|
||||
ng add @angular/elements --project=*your_project_name*
|
||||
|
||||
</code-example>
|
||||
|
||||
- For more information about polyfills, see [polyfill documentation](https://www.webcomponents.org/polyfills).
|
||||
|
||||
- For more information about Angular browser support, see [Browser Support](guide/browser-support).
|
||||
|
@ -76,6 +76,12 @@ All router components must be entry components. Because this would require you t
|
||||
|
||||
## The `entryComponents` array
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Since 9.0.0 with Ivy, the `entryComponents` property is no longer necessary. See [deprecations guide](guide/deprecations#entryComponents).
|
||||
|
||||
</div>
|
||||
|
||||
Though the `@NgModule` decorator has an `entryComponents` array, most of the time
|
||||
you won't have to explicitly set any entry components because Angular adds components listed in `@NgModule.bootstrap` and those in route definitions to entry components automatically. Though these two mechanisms account for most entry components, if your app happens to bootstrap or dynamically load a component by type imperatively,
|
||||
you must add it to `entryComponents` explicitly.
|
||||
|
@ -1,104 +0,0 @@
|
||||
# Feature modules
|
||||
|
||||
Feature modules are NgModules for the purpose of organizing code.
|
||||
|
||||
For the final sample app with a feature module that this page describes,
|
||||
see the <live-example></live-example>.
|
||||
|
||||
<hr>
|
||||
|
||||
As your app grows, you can organize code relevant for a specific feature.
|
||||
This helps apply clear boundaries for features. With feature modules,
|
||||
you can keep code related to a specific functionality or feature
|
||||
separate from other code. Delineating areas of your
|
||||
app helps with collaboration between developers and teams, separating
|
||||
directives, and managing the size of the root module.
|
||||
|
||||
## Feature modules vs. root modules
|
||||
|
||||
A feature module is an organizational best practice, as opposed to a concept of the core Angular API. A feature module delivers a cohesive set of functionality focused on a
|
||||
specific application need such as a user workflow, routing, or forms.
|
||||
While you can do everything within the root module, feature modules
|
||||
help you partition the app into focused areas. A feature module
|
||||
collaborates with the root module and with other modules through
|
||||
the services it provides and the components, directives, and
|
||||
pipes that it shares.
|
||||
|
||||
## How to make a feature module
|
||||
|
||||
Assuming you already have an app that you created with the [Angular CLI](cli), create a feature
|
||||
module using the CLI by entering the following command in the
|
||||
root project directory. Replace `CustomerDashboard` with the
|
||||
name of your module. You can omit the "Module" suffix from the name because the CLI appends it:
|
||||
|
||||
```sh
|
||||
ng generate module CustomerDashboard
|
||||
|
||||
```
|
||||
|
||||
This causes the CLI to create a folder called `customer-dashboard` with a file inside called `customer-dashboard.module.ts` with the following contents:
|
||||
|
||||
```typescript
|
||||
import { NgModule } from "@angular/core";
|
||||
import { CommonModule } from "@angular/common";
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule],
|
||||
declarations: [],
|
||||
})
|
||||
export class CustomerDashboardModule {}
|
||||
```
|
||||
|
||||
The structure of an NgModule is the same whether it is a root module or a feature module. In the CLI generated feature module, there are two JavaScript import statements at the top of the file: the first imports `NgModule`, which, like the root module, lets you use the `@NgModule` decorator; the second imports `CommonModule`, which contributes many common directives such as `ngIf` and `ngFor`. Feature modules import `CommonModule` instead of `BrowserModule`, which is only imported once in the root module. `CommonModule` only contains information for common directives such as `ngIf` and `ngFor` which are needed in most templates, whereas `BrowserModule` configures the Angular app for the browser which needs to be done only once.
|
||||
|
||||
The `declarations` array is available for you to add declarables, which
|
||||
are components, directives, and pipes that belong exclusively to this particular module. To add a component, enter the following command at the command line where `customer-dashboard` is the directory where the CLI generated the feature module and `CustomerDashboard` is the name of the component:
|
||||
|
||||
```sh
|
||||
ng generate component customer-dashboard/CustomerDashboard
|
||||
|
||||
```
|
||||
|
||||
This generates a folder for the new component within the customer-dashboard folder and updates the feature module with the `CustomerDashboardComponent` info:
|
||||
|
||||
<code-example path="feature-modules/src/app/customer-dashboard/customer-dashboard.module.ts" region="customer-dashboard-component" header="src/app/customer-dashboard/customer-dashboard.module.ts"></code-example>
|
||||
|
||||
The `CustomerDashboardComponent` is now in the JavaScript import list at the top and added to the `declarations` array, which lets Angular know to associate this new component with this feature module.
|
||||
|
||||
## Importing a feature module
|
||||
|
||||
To incorporate the feature module into your app, you have to let the root module, `app.module.ts`, know about it. Notice the `CustomerDashboardModule` export at the bottom of `customer-dashboard.module.ts`. This exposes it so that other modules can get to it. To import it into the `AppModule`, add it to the imports in `app.module.ts` and to the `imports` array:
|
||||
|
||||
<code-example path="feature-modules/src/app/app.module.ts" region="app-module" header="src/app/app.module.ts"></code-example>
|
||||
|
||||
Now the `AppModule` knows about the feature module. If you were to add any service providers to the feature module, `AppModule` would know about those too, as would any other feature modules. However, NgModules don’t expose their components.
|
||||
|
||||
## Rendering a feature module’s component template
|
||||
|
||||
When the CLI generated the `CustomerDashboardComponent` for the feature module, it included a template, `customer-dashboard.component.html`, with the following markup:
|
||||
|
||||
<code-example path="feature-modules/src/app/customer-dashboard/customer-dashboard/customer-dashboard.component.html" region="feature-template" header="src/app/customer-dashboard/customer-dashboard/customer-dashboard.component.html"></code-example>
|
||||
|
||||
To see this HTML in the `AppComponent`, you first have to export the `CustomerDashboardComponent` in the `CustomerDashboardModule`. In `customer-dashboard.module.ts`, just beneath the `declarations` array, add an `exports` array containing `CustomerDashboardComponent`:
|
||||
|
||||
<code-example path="feature-modules/src/app/customer-dashboard/customer-dashboard.module.ts" region="component-exports" header="src/app/customer-dashboard/customer-dashboard.module.ts"></code-example>
|
||||
|
||||
Next, in the `AppComponent`, `app.component.html`, add the tag `<app-customer-dashboard>`:
|
||||
|
||||
<code-example path="feature-modules/src/app/app.component.html" region="app-component-template" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Now, in addition to the title that renders by default, the `CustomerDashboardComponent` template renders too:
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/feature-modules/feature-module.png" alt="feature module component">
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
## More on NgModules
|
||||
|
||||
You may also be interested in the following:
|
||||
|
||||
- [Lazy Loading Modules with the Angular Router](guide/lazy-loading-ngmodules).
|
||||
- [Providers](guide/providers).
|
||||
- [Types of Feature Modules](guide/module-types).
|
@ -1,79 +1,106 @@
|
||||
# Módulos de funcionalidades
|
||||
# Feature modules
|
||||
|
||||
Los módulos de funcionalidades son NgModules con el propósito de organizar el código.
|
||||
Feature modules are NgModules for the purpose of organizing code.
|
||||
|
||||
Para la aplicación de muestra final con un módulo de funcionalidades que se describe en esta página,
|
||||
ver el <live-example> </live-example>.
|
||||
For the final sample app with a feature module that this page describes,
|
||||
see the <live-example></live-example>.
|
||||
|
||||
<hr>
|
||||
|
||||
A medida que tu aplicación crece, puedes organizar el código relevante para una funcionalidad específica. Esto ayuda a aplicar límites claros para las funcionalidades. Con módulos de funcionalidades,
|
||||
puedes mantener el código relacionado con una funcionalidad o característica específica
|
||||
separado de otro código. Delinear áreas de suaplicación ayuda con la colaboración entre desarrolladores y equipos, separando directivas y gestionar el tamaño del módulo raíz.
|
||||
As your app grows, you can organize code relevant for a specific feature.
|
||||
This helps apply clear boundaries for features. With feature modules,
|
||||
you can keep code related to a specific functionality or feature
|
||||
separate from other code. Delineating areas of your
|
||||
app helps with collaboration between developers and teams, separating
|
||||
directives, and managing the size of the root module.
|
||||
|
||||
## Módulos de funcionalidades frente a módulos raíz
|
||||
|
||||
Un módulo de funcionalidades es una mejor práctica organizativa, a diferencia de un concepto de la API angular principal. Un módulo de funcionalidades ofrece un conjunto coherente de funcionalidades centradas en una necesidad de aplicación específica, como un flujo de trabajo, enrutamiento o formularios de usuario. Si bien puede hacer todo dentro del módulo raíz, los módulos de funcionalidades lo ayudan a dividir la aplicación en áreas específicas. Un módulo de funcionalidades colabora con el módulo raíz y con otros módulos a través de los servicios que proporciona y los componentes, directivas y canalizaciones que comparte.
|
||||
## Feature modules vs. root modules
|
||||
|
||||
## Cómo hacer un módulo de funcionalidades
|
||||
A feature module is an organizational best practice, as opposed to a concept of the core Angular API. A feature module delivers a cohesive set of functionality focused on a
|
||||
specific application need such as a user workflow, routing, or forms.
|
||||
While you can do everything within the root module, feature modules
|
||||
help you partition the app into focused areas. A feature module
|
||||
collaborates with the root module and with other modules through
|
||||
the services it provides and the components, directives, and
|
||||
pipes that it shares.
|
||||
|
||||
Suponiendo que ya tienes una aplicación que creó con la [CLI Angular](cli), crea un módulo de funcionalidades usando la CLI ingresando el siguiente comando en el directorio raíz del proyecto. Reemplaza `CustomerDashboard` con el nombre de tu módulo. Puedes omitir el sufijo "Módulo" / "Module" del nombre porque la CLI lo agrega:
|
||||
## How to make a feature module
|
||||
|
||||
Assuming you already have an app that you created with the [Angular CLI](cli), create a feature
|
||||
module using the CLI by entering the following command in the
|
||||
root project directory. Replace `CustomerDashboard` with the
|
||||
name of your module. You can omit the "Module" suffix from the name because the CLI appends it:
|
||||
|
||||
```sh
|
||||
ng generate module CustomerDashboard
|
||||
|
||||
```
|
||||
|
||||
Esto hace que la CLI cree una carpeta llamada `customer-dashboard` con un archivo dentro llamado` customer-dashboard.module.ts` con el siguiente contenido:
|
||||
|
||||
This causes the CLI to create a folder called `customer-dashboard` with a file inside called `customer-dashboard.module.ts` with the following contents:
|
||||
|
||||
```typescript
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule],
|
||||
declarations: [],
|
||||
imports: [
|
||||
CommonModule
|
||||
],
|
||||
declarations: []
|
||||
})
|
||||
export class CustomerDashboardModule {}
|
||||
export class CustomerDashboardModule { }
|
||||
```
|
||||
|
||||
La estructura de un NgModule es la misma si es un módulo raíz o un módulo de funcionalidades. En el módulo de funcionalidades generado por CLI, hay dos declaraciones de importación de JavaScript en la parte superior del archivo: la primera importa `NgModule`, que, como el módulo raíz, le permite usar el decorador `@NgModule`; el segundo importa `CommonModule`, que aporta muchas directivas comunes como `ngIf` y `ngFor`. Los módulos de funcionalidades importan `CommonModule` en lugar de `BrowserModule`, que solo se importa una vez en el módulo raíz. `CommonModule` solo contiene información para directivas comunes como `ngIf` y `ngFor` que se necesitan en la mayoría de las plantillas, mientras que `BrowserModule` configura la aplicación Angular para el navegador, lo cual debe hacerse solo una vez.
|
||||
The structure of an NgModule is the same whether it is a root module or a feature module. In the CLI generated feature module, there are two JavaScript import statements at the top of the file: the first imports `NgModule`, which, like the root module, lets you use the `@NgModule` decorator; the second imports `CommonModule`, which contributes many common directives such as `ngIf` and `ngFor`. Feature modules import `CommonModule` instead of `BrowserModule`, which is only imported once in the root module. `CommonModule` only contains information for common directives such as `ngIf` and `ngFor` which are needed in most templates, whereas `BrowserModule` configures the Angular app for the browser which needs to be done only once.
|
||||
|
||||
La matriz `declaraciones` está disponible para que agregue declarables, que son componentes, directivas y canalizaciones que pertenecen exclusivamente a este módulo en particular. Para agregar un componente, ingresa el siguiente comando en la línea de comando donde `customer-dashboard` es el directorio donde la CLI generó el módulo de funciones y CustomerDashboard` es el nombre del componente:
|
||||
The `declarations` array is available for you to add declarables, which
|
||||
are components, directives, and pipes that belong exclusively to this particular module. To add a component, enter the following command at the command line where `customer-dashboard` is the directory where the CLI generated the feature module and `CustomerDashboard` is the name of the component:
|
||||
|
||||
```sh
|
||||
ng generate component customer-dashboard/CustomerDashboard
|
||||
|
||||
```
|
||||
|
||||
Esto genera una carpeta para el nuevo componente dentro de la carpeta del panel del cliente y actualiza el módulo de funcionalidades con la información de `CustomerDashboardComponent`:
|
||||
This generates a folder for the new component within the customer-dashboard folder and updates the feature module with the `CustomerDashboardComponent` info:
|
||||
|
||||
|
||||
<code-example path="feature-modules/src/app/customer-dashboard/customer-dashboard.module.ts" region="customer-dashboard-component" header="src/app/customer-dashboard/customer-dashboard.module.ts"></code-example>
|
||||
|
||||
El `CustomerDashboardComponent` ahora se encuentra en la lista de importación de JavaScript en la parte superior y se agregó a la matriz de `declaraciones`, lo que le permite a Angular asociar este nuevo componente con este módulo de funciones.
|
||||
|
||||
## Importación de un módulo de funcionalidades
|
||||
|
||||
Para incorporar el módulo de funcionalidades en tu aplicación, debes informar al módulo raíz, `app.module.ts`. Observa la exportación de "CustomerDashboardModule" en la parte inferior de `customer-dashboard.module.ts`. Esto lo expone para que otros módulos puedan acceder a él. Para importarlo en el `AppModule`, agrégalo a las importaciones en` app.module.ts` y al arreglo de `import`:
|
||||
The `CustomerDashboardComponent` is now in the JavaScript import list at the top and added to the `declarations` array, which lets Angular know to associate this new component with this feature module.
|
||||
|
||||
## Importing a feature module
|
||||
|
||||
To incorporate the feature module into your app, you have to let the root module, `app.module.ts`, know about it. Notice the `CustomerDashboardModule` export at the bottom of `customer-dashboard.module.ts`. This exposes it so that other modules can get to it. To import it into the `AppModule`, add it to the imports in `app.module.ts` and to the `imports` array:
|
||||
|
||||
<code-example path="feature-modules/src/app/app.module.ts" region="app-module" header="src/app/app.module.ts"></code-example>
|
||||
|
||||
Ahora el `AppModule` conoce el módulo de funcionalidades. Si tuviera que agregar cualquier proveedor de servicios al módulo de funcionalidades, `AppModule` también lo conocería, al igual que cualquier otro módulo de funcionalidades. Sin embargo, los NgModules no exponen sus componentes.
|
||||
|
||||
## Representación de la plantilla de componente de un módulo de funcionalidades
|
||||
Now the `AppModule` knows about the feature module. If you were to add any service providers to the feature module, `AppModule` would know about those too, as would any other feature modules. However, NgModules don’t expose their components by default.
|
||||
|
||||
Cuando la CLI generó el `CustomerDashboardComponent` para el módulo de funcionalidades, incluyó una plantilla, `customer-dashboard.component.html`, con el siguiente marcado:
|
||||
|
||||
## Rendering a feature module’s component template
|
||||
|
||||
When the CLI generated the `CustomerDashboardComponent` for the feature module, it included a template, `customer-dashboard.component.html`, with the following markup:
|
||||
|
||||
<code-example path="feature-modules/src/app/customer-dashboard/customer-dashboard/customer-dashboard.component.html" region="feature-template" header="src/app/customer-dashboard/customer-dashboard/customer-dashboard.component.html"></code-example>
|
||||
|
||||
Para ver este HTML en el `AppComponent`, primero tienes que exportar el `CustomerDashboardComponent` en el `CustomerDashboardModule`. En `customer-dashboard.module.ts`, justo debajo de la matriz de `declaraciones`, agrega una matriz de `exportaciones` que contenga `CustomerDashboardComponent`:
|
||||
|
||||
To see this HTML in the `AppComponent`, you first have to export the `CustomerDashboardComponent` in the `CustomerDashboardModule`. In `customer-dashboard.module.ts`, just beneath the `declarations` array, add an `exports` array containing `CustomerDashboardComponent`:
|
||||
|
||||
<code-example path="feature-modules/src/app/customer-dashboard/customer-dashboard.module.ts" region="component-exports" header="src/app/customer-dashboard/customer-dashboard.module.ts"></code-example>
|
||||
|
||||
Luego, en el `AppComponent`, `app.component.html`, agrega la etiqueta `<app-customer-dashboard>`:
|
||||
|
||||
|
||||
Next, in the `AppComponent`, `app.component.html`, add the tag `<app-customer-dashboard>`:
|
||||
|
||||
<code-example path="feature-modules/src/app/app.component.html" region="app-component-template" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Ahora, además del título que se representa de forma predeterminada, la plantilla `CustomerDashboardComponent` también se representa:
|
||||
|
||||
Now, in addition to the title that renders by default, the `CustomerDashboardComponent` template renders too:
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/feature-modules/feature-module.png" alt="feature module component">
|
||||
@ -81,10 +108,9 @@ Ahora, además del título que se representa de forma predeterminada, la plantil
|
||||
|
||||
<hr />
|
||||
|
||||
## Más sobre NgModules
|
||||
## More on NgModules
|
||||
|
||||
También te puede interesar lo siguiente:
|
||||
|
||||
- [Módulos de carga diferida con el enrutador angular](guide/lazy-loading-ngmodules).
|
||||
- [Proveedores](guide/providers).
|
||||
- [Tipos de módulos de funciones](guide/module-types).
|
||||
You may also be interested in the following:
|
||||
* [Lazy Loading Modules with the Angular Router](guide/lazy-loading-ngmodules).
|
||||
* [Providers](guide/providers).
|
||||
* [Types of Feature Modules](guide/module-types).
|
||||
|
@ -40,8 +40,7 @@ The top level of the workspace contains workspace-wide configuration files, conf
|
||||
| `package-lock.json` | Provides version information for all packages installed into `node_modules` by the npm client. See [npm documentation](https://docs.npmjs.com/files/package-lock.json) for details. If you use the yarn client, this file will be [yarn.lock](https://yarnpkg.com/lang/en/docs/yarn-lock/) instead. |
|
||||
| `src/` | Source files for the root-level application project. |
|
||||
| `node_modules/` | Provides [npm packages](guide/npm-packages) to the entire workspace. Workspace-wide `node_modules` dependencies are visible to all projects. |
|
||||
| `tsconfig.json` | The `tsconfig.json` file is a ["Solution Style"](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#support-for-solution-style-tsconfigjson-files) TypeScript configuration file. Code editors and TypeScript’s language server use this file to improve development experience. Compilers do not use this file. |
|
||||
| `tsconfig.base.json` | The base [TypeScript](https://www.typescriptlang.org/) configuration for projects in the workspace. All other configuration files inherit from this base file. For more information, see the [Configuration inheritance with extends](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#configuration-inheritance-with-extends) section of the TypeScript documentation.|
|
||||
| `tsconfig.json` | The base [TypeScript](https://www.typescriptlang.org/) configuration for projects in the workspace. All other configuration files inherit from this base file. For more information, see the [Configuration inheritance with extends](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#configuration-inheritance-with-extends) section of the TypeScript documentation.|
|
||||
| `tslint.json` | Default [TSLint](https://palantir.github.io/tslint/) configuration for projects in the workspace. |
|
||||
|
||||
|
||||
@ -91,7 +90,7 @@ Angular components, templates, and styles go here.
|
||||
|
||||
| `src/app/` FILES | PURPOSE |
|
||||
| :-------------------------- | :------------------------------------------|
|
||||
| `app/app.component.ts` | Defines the logic for the app's root component, named `AppComponent`. The view associated with this root component becomes the root of the [view hierarchy](guide/glossary#view-tree) as you add components and services to your application. |
|
||||
| `app/app.component.ts` | Defines the logic for the app's root component, named `AppComponent`. The view associated with this root component becomes the root of the [view hierarchy](guide/glossary#view-hierarchy) as you add components and services to your application. |
|
||||
| `app/app.component.html` | Defines the HTML template associated with the root `AppComponent`. |
|
||||
| `app/app.component.css` | Defines the base CSS stylesheet for the root `AppComponent`. |
|
||||
| `app/app.component.spec.ts` | Defines a unit test for the root `AppComponent`. |
|
||||
@ -103,7 +102,7 @@ Angular components, templates, and styles go here.
|
||||
The application-specific configuration files for the root application reside at the workspace root level.
|
||||
For a multi-project workspace, project-specific configuration files are in the project root, under `projects/project-name/`.
|
||||
|
||||
Project-specific [TypeScript](https://www.typescriptlang.org/) configuration files inherit from the workspace-wide `tsconfig.base.json`, and project-specific [TSLint](https://palantir.github.io/tslint/) configuration files inherit from the workspace-wide `tslint.json`.
|
||||
Project-specific [TypeScript](https://www.typescriptlang.org/) configuration files inherit from the workspace-wide `tsconfig.json`, and project-specific [TSLint](https://palantir.github.io/tslint/) configuration files inherit from the workspace-wide `tslint.json`.
|
||||
|
||||
| APPLICATION-SPECIFIC CONFIG FILES | PURPOSE |
|
||||
| :--------------------- | :------------------------------------------|
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user