Compare commits

..

58 Commits

Author SHA1 Message Date
2a6e6c02ed build(zone.js): update gulp task to gen changelog automatically (#31915)
PR Close #31915
2019-08-02 14:28:49 -07:00
fa4e17082c build(zone.js): update changelog of zone.js (#31915)
PR Close #31915
2019-08-02 14:28:49 -07:00
ebb27727e4 docs: add anyComponentStyle budget description (#31955)
In CLI 8.2 we introduced a new budget see: https://github.com/angular/angular-cli/pull/15127

PR Close #31955
2019-08-02 09:35:38 -07:00
046532b661 docs: add links to web.dev/angular guides (#31804)
This PR adds the following links to web.dev/angular:

1. Link to the guides in the resource section under "Online Training"
2. Links to code-splitting & preloading in the lazy-loading guide
3. Link to the accessibility guide on web.dev/angular

PR Close #31804
2019-08-01 17:45:43 -07:00
7b9891d7cd feat(language-service): Introduce 'angularOnly' flag (#31935)
This PR changes the language service to work in two different modes:

1. TS + Angular
   Plugin augments TS language service to provide additonal Angular
   information. This only works with inline template and is meant to be
   used as a local plugin (configured via tsconfig.json).
2. Angular only
   Plugin only provides information on Angular templates, no TS info at
   all. This effectively disables native TS features and is meant for
   internal use only.

Default mode is `angularOnly = false` so that we don't break any users
already using Angular LS as local plugin.

As part of the refactoring, `undefined` is removed from type aliases
because it is considered bad practice.

go/tsstyle#nullableundefined-type-aliases
```
Type aliases must not include |null or |undefined in a union type.
Nullable aliases typically indicate that null values are being passed
around through too many layers of an application, and this clouds the
source of the original issue that resulted in null. They also make it
unclear when specific values on a class or interface might be absent.
```

PR Close #31935
2019-08-01 17:43:21 -07:00
a2183ddb7a fix(ivy): directive matching not working in some cases when preceded by styling attributes (#31942)
Fixes Ivy's directive matching not capturing attribute selectors when there is one class binding, one style binding and a regular binding that precede  the attribute that would match the directive. The issue appears to come from the fact that we weren't skipping over style bindings correctly which was throwing the loop off not to go into `bindingsMode` and to skip some of the bindings when matching.

PR Close #31942
2019-08-01 17:42:42 -07:00
3122f3415a perf(ivy): remove global state acces from postProcessDirective (#31946)
PR Close #31946
2019-08-01 17:42:24 -07:00
aaf29c8099 perf(ivy): remove firstTemplatePass check from directive instantiation (#31946)
PR Close #31946
2019-08-01 17:42:24 -07:00
32e2f4daef refactor(ivy): remove code duplication around root component view creation (#31946)
PR Close #31946
2019-08-01 17:42:23 -07:00
a7c71d1a57 perf(ivy): remove firstTemplatePass check for component view creation (#31946)
PR Close #31946
2019-08-01 17:42:23 -07:00
f2d47c96c4 fix(ivy): ngcc emits static fields before extra statements (#31933)
This commit changes the emit order of ngcc when a class has multiple static
fields being assigned. Previously, ngcc would emit each static field
followed immediately by any extra statements specified for that field. This
causes issues with downstream tooling such as build optimizer, which expects
all of the static fields for a class to be grouped together. ngtsc already
groups static fields and additional statements. This commit changes ngcc's
ordering to match.

PR Close #31933
2019-08-01 10:45:36 -07:00
184d270725 fix(ivy): DebugElement.triggerEventHandler not picking up events registered via Renderer2 (#31845)
Fixes Ivy's `DebugElement.triggerEventHandler` to picking up events that have been registered through a `Renderer2`, unlike ViewEngine.

This PR resolves FW-1480.

PR Close #31845
2019-08-01 10:13:07 -07:00
a610d12266 docs(core): add missing closing brace in directive input example (#31901)
PR Close #31901
2019-08-01 10:11:50 -07:00
d0d875a3fe fix(ivy): pass schemas field to nested views (#31913)
Prior to this commit, the `schemas` configuration was applied to top-level view only. That leads to problems when using unknown props with elements inside nested views (for example generated as a result of *ngIf). This commit passes `schemas` information down to nested views to make sure that all the checks are consistent.

PR Close #31913
2019-08-01 10:11:01 -07:00
e8b8f6d09b fix(language-service): getSourceFile() should only be called on TS files (#31920)
PR Close #31920
2019-08-01 10:10:09 -07:00
9e9179e915 docs: update Zenika trainings URL in resources.json (#31910)
PR Close #31910
2019-08-01 10:09:49 -07:00
c1ae6124c8 fix(upgrade): compile downgraded components synchronously (if possible) (#31840)
AngularJS compilation is a synchronous operation (unless having to fetch
a template, which is not supported for downgraded components).
Previously, ngUpgrade tried to retain the synchronous nature of the
compilation for downgraded components (when possible), by using a
synchronous thenable implementation (`ParentInjectorPromise`). This was
accidentally broken in #27217 by replacing a call to
`ParentInjectorPromise#then()` (which can be synchronous) with a call to
`Promise.all()` (which is asynchronous).

This commit fixes this by introducing a `SyncPromise.all()` static
method; similar to `Promise.all()` but retaining the synchronous
capabilities of `SyncPromise` (which `ParentInjectorPromise` inherits
from).

Fixes #30330

PR Close #31840
2019-08-01 10:09:02 -07:00
b3b5c66414 refactor(upgrade): extract promise-related utilities to separate file and add tests (#31840)
PR Close #31840
2019-08-01 10:09:02 -07:00
82b97280f3 fix(ivy): speed up ngtsc if project has no templates to check (#31922)
If a project being built with ngtsc has no templates to check, then ngtsc
previously generated an empty typecheck file. This seems to trigger some
pathological behavior in TS where the entire user program is re-checked,
which is extremely expensive. This likely has to do with the fact that the
empty file is not considered an ES module, meaning the module structure of
the program has changed.

This commit causes an export to be produced in the typecheck file regardless
of its other contents, which guarantees that it will be an ES module. The
pathological behavior is avoided and template type-checking is fast once
again.

PR Close #31922
2019-07-31 16:20:38 -07:00
ecffbda664 test: fix outDir in TS integration tests (#29284)
PR Close #29284
2019-07-31 11:40:27 -07:00
adc39752f3 build(docs-infra): upgrade cli command docs sources to 403bcb01c (#31925)
Updating [angular#master](https://github.com/angular/angular/tree/master) from [cli-builds#master](https://github.com/angular/cli-builds/tree/master).

##
Relevant changes in [commit range](1e83a8ecb...403bcb01c):

**Added**
- help/deploy.json

##

PR Close #31925
2019-07-31 11:39:00 -07:00
584b42343f build: Do not generate *.umd.min.js for language service (#31917)
`language-service.umd.min.js` takes a long time to build (because of
running terser), but it is not used at all.
See https://unpkg.com/browse/@angular/language-service@8.1.3/package.json
where 'main' points to the unminified bundle.

PR Close #31917
2019-07-31 11:38:31 -07:00
8e7a0d4ff9 docs: add ReactiveConf 2019 to events (#31895)
PR Close #31895
2019-07-31 11:37:44 -07:00
4db959260b docs(ivy): Add README to indexer module (#31260)
Describe the indexer module for Angular compiler developers. Include
scope of analysis provided by the module and the indexers it targets as
first-party.

PR Close #31260
2019-07-31 11:37:11 -07:00
76503e65c8 release: cut the v9.0.0-next.0 release 2019-07-31 11:04:40 -07:00
eac993dfce docs: release notes for the v8.2.0 release 2019-07-31 10:46:14 -07:00
975917bafd Revert "fix(zone.js): don't wrap uncaught promise error. (#31443)" (#31918)
This reverts commit 2bb9a65351.

It breaks tests in google3 which rely on the error handling behavior.

PR Close #31918
2019-07-30 15:03:49 -07:00
185b3dd08e build(docs-infra): update main bundle size (#31839)
PR #31839 contains perf and code cleanup changes that add 48 bytes to the
main bundle size. Perf gains and code clarity justify this increase.

Unfortunately the size verification job is rejecting this PR as it reports
size gains from a fixed size and not relative increase of size from a particular PR.

It was decided during the internal team discussion to bump up size limits to
correctly reflect current state of the master and increase from this PR.

PR Close #31839
2019-07-30 13:01:33 -07:00
78659ec0b0 perf(ivy): avoid creating holey LView Arrays (#31839)
PR Close #31839
2019-07-30 13:01:33 -07:00
a9ec3db91a perf(ivy): limit creationMode checks (#31839)
PR Close #31839
2019-07-30 13:01:33 -07:00
561ec6a5be perf(ivy): stricter null checks (#31839)
PR Close #31839
2019-07-30 13:01:33 -07:00
c0317d40c9 perf(ivy): call refreshContentQueries only when there are content queries defined (#31839)
PR Close #31839
2019-07-30 13:01:32 -07:00
a4bc0db474 refactor(ivy): remove unnecessary call to setPreviousOrParentTNode (#31839)
setPreviousOrParentTNode is set in enterView so no need to reset it
just before entering a view.

PR Close #31839
2019-07-30 13:01:32 -07:00
430124a051 perf(ivy): only refresh child components if those are defined in a given view (#31839)
PR Close #31839
2019-07-30 13:01:32 -07:00
e08391b333 refactor(ivy): rewrite refreshDynamicEmbeddedViews for clarity (#31839)
PR Close #31839
2019-07-30 13:01:32 -07:00
a77d0e22bf perf(ivy): avoid repeated tView.firstTemplatePass writes (#31839)
PR Close #31839
2019-07-30 13:01:32 -07:00
4f42eb4e77 test(zone.js): add test codes to ensure not include sourcemap (#31892)
PR Close #31892
2019-07-30 13:00:26 -07:00
f216724c2c build(zone.js): remove sourceMappingUrl from bundle (#31892)
Close #31883

PR Close #31892
2019-07-30 13:00:26 -07:00
5c9a8961da fix(zone.js): don't rely on global node typings outside of node/ directory (#31783)
PR Close #31783
2019-07-30 12:59:40 -07:00
3479fddf68 docs: fix typo in Animation guide (#31888)
PR Close #31888
2019-07-30 12:58:52 -07:00
5bebac42f9 docs: change Angular Material Design to Material Design in animations guide (#31889)
PR Close #31889
2019-07-30 12:56:22 -07:00
cbcbe23fd1 build(docs-infra): upgrade cli command docs sources to 1e83a8ecb (#31906)
Updating [angular#master](https://github.com/angular/angular/tree/master) from [cli-builds#master](https://github.com/angular/cli-builds/tree/master).

##
Relevant changes in [commit range](a8fe15cb6...1e83a8ecb):

**Modified**
- help/generate.json

##

PR Close #31906
2019-07-30 12:55:44 -07:00
fc6f48185c fix(ivy): ngcc - render decorators in UMD and CommonJS bundles correctly (#31614)
In #31426 a fix was implemented to render namespaced decorator imports
correctly, however it turns out that the fix only worked when decorator
information was extracted from static properties, not when using
`__decorate` calls.

This commit fixes the issue by creating the decorator metadata with the
full decorator expression, instead of only its name.

Closes #31394

PR Close #31614
2019-07-29 16:10:58 -07:00
80f290e301 fix(ivy): ngcc - recognize suffixed tslib helpers (#31614)
An identifier may become repeated when bundling multiple source files
into a single bundle, so bundlers have a strategy of suffixing non-unique
identifiers with a suffix like $2. Since ngcc operates on such bundles,
it needs to process potentially suffixed identifiers in their canonical
form without the suffix. The "ngx-pagination" package was previously not
compiled fully, as most decorators were not recognized.

This commit ensures that identifiers are first canonicalized by removing
the suffix, such that they are properly recognized and processed by ngcc.

Fixes #31540

PR Close #31614
2019-07-29 16:10:58 -07:00
5e5be43acd refactor(ivy): ngcc - categorize the various decorate calls upfront (#31614)
Any decorator information present in TypeScript is emitted into the
generated JavaScript sources by means of `__decorate` call. This call
contains both the decorators as they existed in the original source
code, together with calls to `tslib` helpers that convey additional
information on e.g. type information and parameter decorators. These
different kinds of decorator calls were not previously distinguished on
their own, but instead all treated as `Decorator` by themselves. The
"decorators" that were actually `tslib` helper calls were conveniently
filtered out because they were not imported from `@angular/core`, a
characteristic that ngcc uses to drop certain decorators.

Note that this posed an inconsistency in ngcc when it processes
`@angular/core`'s UMD bundle, as the `tslib` helper functions have been
inlined in said bundle. Because of the inlining, the `tslib` helpers
appear to be from `@angular/core`, so ngcc would fail to drop those
apparent "decorators". This inconsistency does not currently cause any
issues, as ngtsc is specifically looking for decorators based on  their
name and any remaining decorators are simply ignored.

This commit rewrites the decorator analysis of a class to occur all in a
single phase, instead of all throughout the `ReflectionHost`. This
allows to categorize the various decorate calls in a single sweep,
instead of constantly needing to filter out undesired decorate calls on
the go. As an added benefit, the computed decorator information is now
cached per class, such that subsequent reflection queries that need
decorator information can reuse the cached info.

PR Close #31614
2019-07-29 16:10:57 -07:00
0386c964b5 build: secure yarn lock files (#31640)
See https://yarnpkg.com/blog/2019/07/12/recommended-security-update/

PR Close #31640
2019-07-29 16:10:23 -07:00
f5c605b608 fix(zone.js): should expose some other internal intefaces (#31866)
PR Close #31866
2019-07-29 16:08:55 -07:00
14dba72aee fix(core): DebugElement.listeners not cleared on destroy (#31820)
Currently the `DebugElement.listeners` array are retained after the node is destroyed. This means that they'll continue to fire through `triggerEventHandler` and can cause memory leaks. This has already been fixed in Ivy, but these changes fix it in ViewEngine for consistency.

PR Close #31820
2019-07-29 10:05:19 -07:00
5f0d5e9ccf build: update to nodejs rules 0.34.0 and bazel 0.28.1 (#31824)
nodejs rules 0.34.0 now includes protractor_web_test_suite rule (via new @bazel/protractor rule) so we switch to that location for that rule in this PR so that /packages/bazel/src/protractor can be removed in a future PR

this PR also brings in node toolchain support which was released in nodejs rules 0.33.0. this is a prerequisite for RBE for mac & windows users

bazel schematics also updated with the same. @bazel/bazel 0.28.1 npm package includes transitive dep on hide-bazel-files so we're able to remove an explicit dep on that as well.

PR Close #31824
2019-07-26 15:01:25 -07:00
5296c04f61 fix(ivy): set LOCALE_ID when using the injector (#31566)
In `BrowserModule` the value of `LOCALE_ID` is defined in the `APPLICATION_MODULE_PROVIDERS` after `APP_INITIALIZER` has run.
This PR ensures that `LOCALE_ID` is also set for ivy at the same moment which allows the application to fetch the locale from a backend (for example).

Fixes #31465

FW-1436 #resolve

PR Close #31566
2019-07-26 14:04:47 -07:00
40a0666651 fix(ivy): error when using forwardRef in Injectable's useClass (#30532)
Fixes Ivy throwing an error when something is passed in as a `forwardRef` into `@Injectable`'s `useClass` option. The error was being thrown, because we were trying to get the provider factory off of the wrapper function, rather than the value itself.

This PR resolves FW-1335.

PR Close #30532
2019-07-26 14:02:49 -07:00
4da805243a docs(core): clarify @ContentChild(ren) behavior (#31846)
Describe that @ContentChild(ren) doesn't search within other component templates (doesn't go across "component boundaries").
PR Close #31846
2019-07-26 14:02:10 -07:00
14ae50b4c3 docs: fix header mistake (#31811)
The code example refers to `src/app/heroes/heroes.component.html` but its header was `src/app/hero.service.ts` which was obviously a mistake.
PR Close #31811
2019-07-26 14:01:28 -07:00
397d0ba9a3 test(ivy): fix broken testcase in Windows (#31860)
In #30181, several testcases were added that were failing in Windows.
The reason was that a recent rebase missed a required change to interact
with the compiler's virtualized filesystems. This commit introduces the
required usage of the VFS layer to fix the testcase.

PR Close #31860
2019-07-26 12:22:12 -07:00
859ebdd836 fix(ivy): correctly bind targetToIdentifier to the TemplateVisitor (#31861)
`TemplateVisitor#visitBoundAttribute` currently has to invoke visiting
expressions manually (this is fixed in #31813). Previously, it did not
bind `targetToIdentifier` to the visitor before deferring to the
expression visitor, which breaks the `targetToIdentifier` code. This
fixes that and adds a test to ensure the closure processed correctly.

This change is urgent; without it, many indexing targets in g3 are
broken.

PR Close #31861
2019-07-26 12:03:16 -07:00
30673090ec build(zone.js): add changelog gulptask for zone.js (#31852)
PR Close #31852
2019-07-26 11:30:08 -07:00
6033446d2d docs: release notes for the v8.2.0-rc.0 release 2019-07-26 10:25:18 -07:00
174770e6f3 docs: release notes for the v release 2019-07-25 20:32:22 -07:00
232 changed files with 4421 additions and 5634 deletions

View File

@ -36,6 +36,22 @@ build --incompatible_strict_action_env
run --incompatible_strict_action_env
test --incompatible_strict_action_env
###############################
# Saucelabs support #
# Turn on these settings with #
# --config=saucelabs #
###############################
# Expose SauceLabs environment to actions
# These environment variables are needed by
# web_test_karma to run on Saucelabs
test:saucelabs --action_env=SAUCE_USERNAME
test:saucelabs --action_env=SAUCE_ACCESS_KEY
test:saucelabs --action_env=SAUCE_READY_FILE
test:saucelabs --action_env=SAUCE_PID_FILE
test:saucelabs --action_env=SAUCE_TUNNEL_IDENTIFIER
test:saucelabs --define=KARMA_WEB_TEST_MODE=SL_REQUIRED
###############################
# Release support #
# Turn on these settings with #

View File

@ -37,5 +37,5 @@ build --verbose_failures=true
# > Example job: https://circleci.com/gh/angular/angular/385517
# We expect that TypeScript compilations will parallelize wider than the number of local cores anyway
# so we should saturate remote workers with TS compilations
build --strategy=AngularTemplateCompile=local
build --strategy=TypeScriptCompile=local
build --strategy=TypeScriptCompile=standalone
build --strategy=AngularTemplateCompile=standalone

View File

@ -143,7 +143,7 @@ var_14: &notify_dev_infra_on_fail
# Cache key for the Material unit tests job. **Note** when updating the SHA in the cache keys,
# also update the SHA for the "MATERIAL_REPO_COMMIT" environment variable.
var_15: &material_unit_tests_cache_key v4-angular-material-18b9ef3f5529f0fa8f034944681486447af7b879
var_15: &material_unit_tests_cache_key v4-angular-material-701302dc482d7e4b77990b24e3b5ab330bbf1aa5
var_16: &material_unit_tests_cache_key_short v4-angular-material
version: 2
@ -198,6 +198,13 @@ jobs:
# Setup remote execution and run RBE-compatible tests.
- *setup_bazel_remote_execution
- run: yarn bazel test //... --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only
- run: mkdir ~/testlogs
- run: cp -Lr dist/testlogs/* ~/testlogs
- store_test_results:
# Bazel always writes test.xml files under this directory
path: ~/testlogs
- store_artifacts:
path: ~/testlogs
# Temporary job to test what will happen when we flip the Ivy flag to true
test_ivy_aot:
@ -249,19 +256,23 @@ jobs:
- *init_environment
- *setup_circleci_bazel_config
- run:
name: Run Bazel tests in saucelabs
# All web tests are contained within a single //:test_web_all target for Saucelabs
# as running each set of tests as a separate target will attempt to acquire too
# many browsers on Saucelabs (7 per target currently) and some tests will always
# fail to acquire browsers. For example:
# 14 02 2019 19:52:33.170:WARN [launcher]: chrome beta on SauceLabs have not captured in 180000 ms, killing.
# //packages/forms/test:web_test_sauce TIMEOUT in 315.0s
command: |
./scripts/saucelabs/run-bazel-via-tunnel.sh \
--tunnel-id angular-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_INDEX} \
--username $SAUCE_USERNAME \
--key $(echo $SAUCE_ACCESS_KEY | rev) \
yarn bazel test //:test_web_all
name: Preparing environment for running tests on Saucelabs.
command: setSecretVar SAUCE_ACCESS_KEY $(echo $SAUCE_ACCESS_KEY | rev)
- run:
name: Starting Saucelabs tunnel
command: ./scripts/saucelabs/start-tunnel.sh
background: true
# Waits for the Saucelabs tunnel to be ready. This ensures that we don't run tests
# too early without Saucelabs not being ready.
- run: ./scripts/saucelabs/wait-for-tunnel.sh
# All web tests are contained within a single //:test_web_all target for Saucelabs
# as running each set of tests as a separate target will attempt to acquire too
# many browsers on Saucelabs (7 per target currently) and some tests will always
# fail to acquire browsers. For example:
# 14 02 2019 19:52:33.170:WARN [launcher]: chrome beta on SauceLabs have not captured in 180000 ms, killing.
# //packages/forms/test:web_test_sauce TIMEOUT in 315.0s
- run: yarn bazel test --config=saucelabs //:test_web_all
- run: ./scripts/saucelabs/stop-tunnel.sh
- *notify_dev_infra_on_fail
test_aio:
@ -310,7 +321,7 @@ jobs:
- *attach_workspace
- *init_environment
# Build aio (with local Angular packages)
- run: yarn --cwd aio build-local-ci
- run: yarn --cwd aio build-local --progress=false
# Run unit tests
- run: yarn --cwd aio test --progress=false --watch=false
# Run e2e tests
@ -329,7 +340,7 @@ jobs:
- *attach_workspace
- *init_environment
# Build aio with Ivy (using local Angular packages)
- run: yarn --cwd aio build-with-ivy-ci
- run: yarn --cwd aio build-with-ivy --progress=false
# Run unit tests
- run: yarn --cwd aio test --progress=false --watch=false
# Run e2e tests
@ -662,10 +673,7 @@ workflows:
version: 2
default_workflow:
jobs:
- setup:
filters:
branches:
ignore: g3
- setup
- lint:
requires:
- setup
@ -776,3 +784,9 @@ workflows:
branches:
only:
- master
# TODO:
# - don't build the g3 branch
# - verify that we are bootstrapping with the right yarn version coming from the docker image
# - check local chrome version pulled from docker image
# - remove /tools/ngcontainer

View File

@ -61,7 +61,6 @@ else
setPublicVar SAUCE_USERNAME "angular-ci";
setSecretVar SAUCE_ACCESS_KEY "9b988f434ff8-fbca-8aa4-4ae3-35442987";
fi
# TODO(josephperrott): Remove environment variables once all saucelabs tests are via bazel method.
setPublicVar SAUCE_LOG_FILE /tmp/angular/sauce-connect.log
setPublicVar SAUCE_READY_FILE /tmp/angular/sauce-connect-ready-file.lock
setPublicVar SAUCE_PID_FILE /tmp/angular/sauce-connect-pid-file.lock
@ -80,7 +79,7 @@ setPublicVar MATERIAL_REPO_TMP_DIR "/tmp/material2"
setPublicVar MATERIAL_REPO_URL "https://github.com/angular/material2.git"
setPublicVar MATERIAL_REPO_BRANCH "master"
# **NOTE**: When updating the commit SHA, also update the cache key in the CircleCI "config.yml".
setPublicVar MATERIAL_REPO_COMMIT "18b9ef3f5529f0fa8f034944681486447af7b879"
setPublicVar MATERIAL_REPO_COMMIT "701302dc482d7e4b77990b24e3b5ab330bbf1aa5"
# Source `$BASH_ENV` to make the variables available immediately.
source $BASH_ENV;

View File

@ -0,0 +1,126 @@
# escape=`
ARG core=mcr.microsoft.com/windows/servercore:1809
ARG target=mcr.microsoft.com/powershell:windowsservercore-1809
FROM $core as download
ARG node_version=10.13.0
ARG yarn_version=1.13.0
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
ENV GPG_VERSION 2.3.4
RUN Invoke-WebRequest $('https://files.gpg4win.org/gpg4win-vanilla-{0}.exe' -f $env:GPG_VERSION) -OutFile 'gpg4win.exe' -UseBasicParsing ; `
Start-Process .\gpg4win.exe -ArgumentList '/S' -NoNewWindow -Wait
RUN @( `
'94AE36675C464D64BAFA68DD7434390BDBE9B9C5', `
'FD3A5288F042B6850C66B31F09FE44734EB7990E', `
'71DCFD284A79C3B38668286BC97EC7A07EDE3FC1', `
'DD8F2338BAE7501E3DD5AC78C273792F7D83545D', `
'C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8', `
'B9AE9905FFD7803F25714661B63B535A4C206CA9', `
'77984A986EBC2AA786BC0F66B01FBB92821C587A', `
'8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600', `
'4ED778F539E3634C779C87C6D7062848A1AB005C', `
'A48C2BEE680E841632CD4E44F07496B3EB3C1762', `
'B9E2F5981AA6E0CD28160D9FF13993A75599653C' `
) | foreach { `
gpg --keyserver ha.pool.sks-keyservers.net --recv-keys $_ ; `
}
ENV NODE_VERSION=$node_version
RUN Invoke-WebRequest $('https://nodejs.org/dist/v{0}/SHASUMS256.txt.asc' -f $env:NODE_VERSION) -OutFile 'SHASUMS256.txt.asc' -UseBasicParsing ; `
gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc
RUN Invoke-WebRequest $('https://nodejs.org/dist/v{0}/node-v{0}-win-x64.zip' -f $env:NODE_VERSION) -OutFile 'node.zip' -UseBasicParsing ; `
$sum = $(cat SHASUMS256.txt.asc | sls $(' node-v{0}-win-x64.zip' -f $env:NODE_VERSION)) -Split ' ' ; `
if ((Get-FileHash node.zip -Algorithm sha256).Hash -ne $sum[0]) { Write-Error 'SHA256 mismatch' } ; `
Expand-Archive node.zip -DestinationPath C:\ ; `
Rename-Item -Path $('C:\node-v{0}-win-x64' -f $env:NODE_VERSION) -NewName 'C:\nodejs'
ENV YARN_VERSION=$yarn_version
RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ; `
Invoke-WebRequest $('https://yarnpkg.com/downloads/{0}/yarn-{0}.msi' -f $env:YARN_VERSION) -OutFile yarn.msi -UseBasicParsing ; `
$sig = Get-AuthenticodeSignature yarn.msi ; `
if ($sig.Status -ne 'Valid') { Write-Error 'Authenticode signature is not valid' } ; `
Write-Output $sig.SignerCertificate.Thumbprint ; `
if (@( `
'7E253367F8A102A91D04829E37F3410F14B68A5F', `
'AF764E1EA56C762617BDC757C8B0F3780A0CF5F9' `
) -notcontains $sig.SignerCertificate.Thumbprint) { Write-Error 'Unknown signer certificate' } ; `
Start-Process msiexec.exe -ArgumentList '/i', 'yarn.msi', '/quiet', '/norestart' -NoNewWindow -Wait
ENV GIT_VERSION 2.20.1
ENV GIT_DOWNLOAD_URL https://github.com/git-for-windows/git/releases/download/v${GIT_VERSION}.windows.1/MinGit-${GIT_VERSION}-busybox-64-bit.zip
ENV GIT_SHA256 9817ab455d9cbd0b09d8664b4afbe4bbf78d18b556b3541d09238501a749486c
RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ; `
Invoke-WebRequest -UseBasicParsing $env:GIT_DOWNLOAD_URL -OutFile git.zip; `
if ((Get-FileHash git.zip -Algorithm sha256).Hash -ne $env:GIT_SHA256) {exit 1} ; `
Expand-Archive git.zip -DestinationPath C:\git; `
Remove-Item git.zip
FROM $target as baseimage
ENV NPM_CONFIG_LOGLEVEL info
COPY --from=download /nodejs /nodejs
COPY --from=download [ "/Program Files (x86)/yarn", "/yarn" ]
COPY --from=download /git /git
ARG SETX=/M
RUN setx %SETX% PATH "%PATH%;C:\nodejs;C:\yarn\bin;C:\git\cmd;C:\git\mingw64\bin;C:\git\usr\bin"
CMD [ "node.exe" ]
FROM baseimage
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
# Install Bazel prereqs on Windows (https://docs.bazel.build/versions/master/install-windows.html)
# Install MSYS2
RUN Invoke-WebRequest -UseBasicParsing 'https://www.7-zip.org/a/7z1805-x64.exe' -OutFile 7z.exe; `
Start-Process -FilePath 'C:\\7z.exe' -ArgumentList '/S', '/D=C:\\7zip0' -NoNewWindow -Wait; `
Invoke-WebRequest -UseBasicParsing 'http://repo.msys2.org/distrib/x86_64/msys2-base-x86_64-20180531.tar.xz' -OutFile msys2.tar.xz; `
Start-Process -FilePath 'C:\\7zip\\7z' -ArgumentList 'e', 'msys2.tar.xz' -Wait; `
Start-Process -FilePath 'C:\\7zip\\7z' -ArgumentList 'x', 'msys2.tar', '-oC:\\' -Wait; `
Remove-Item msys2.tar.xz; `
Remove-Item msys2.tar; `
Remove-Item 7z.exe; `
Remove-Item -Recurse 7zip; `
[Environment]::SetEnvironmentVariable('Path', $env:Path + ';C:\msys64\usr\bin', [System.EnvironmentVariableTarget]::Machine); `
[Environment]::SetEnvironmentVariable('BAZEL_SH', 'C:\msys64\usr\bin\bash.exe', [System.EnvironmentVariableTarget]::Machine)
# Install MSYS2 packages
RUN C:\msys64\usr\bin\bash.exe -l -c \"pacman --needed --noconfirm -S zip unzip patch diffutils git\"
# Install VS Build Tools (required to build C++ targets)
RUN Invoke-WebRequest -UseBasicParsing https://download.visualstudio.microsoft.com/download/pr/df649173-11e9-4af2-8eb7-0eb02ba8958a/cadb5bdac41e55bb8f6a6b7c45273370/vs_buildtools.exe -OutFile vs_BuildTools.exe; `
# Installer won't detect DOTNET_SKIP_FIRST_TIME_EXPERIENCE if ENV is used, must use setx /M
setx /M DOTNET_SKIP_FIRST_TIME_EXPERIENCE 1; `
Start-Process vs_BuildTools.exe `
-ArgumentList `
'--add', 'Microsoft.VisualStudio.Workload.VCTools', `
'--add', 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', `
'--add', 'Microsoft.Component.VC.Runtime.UCRTSDK', `
'--add', 'Microsoft.VisualStudio.Component.Windows10SDK.17763', `
'--quiet', '--norestart', '--nocache' `
-NoNewWindow -Wait; `
Remove-Item -Force vs_buildtools.exe; `
Remove-Item -Force -Recurse \"${Env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\"; `
Remove-Item -Force -Recurse ${Env:TEMP}\*; `
Remove-Item -Force -Recurse \"${Env:ProgramData}\Package Cache\"; `
[Environment]::SetEnvironmentVariable('BAZEL_VC', \"${Env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\BuildTools\VC\", [System.EnvironmentVariableTarget]::Machine)
# Install Python (required to build Python targets)
RUN Invoke-WebRequest -UseBasicParsing https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe -OutFile python-3.5.1.exe; `
Start-Process python-3.5.1.exe -ArgumentList '/quiet InstallAllUsers=1 PrependPath=1' -Wait; `
Remove-Item -Force python-3.5.1.exe
CMD ["cmd.exe"]

33
.codefresh/README.md Normal file
View File

@ -0,0 +1,33 @@
# CodeFresh configuration
[![Codefresh build status](https://g.codefresh.io/api/badges/pipeline/angular/angular%2Fangular%2Fangular?type=cf-1)](https://g.codefresh.io/public/accounts/angular/pipelines/angular/angular/angular)
This folder contains configuration for the [CodeFresh](<https://codefresh.io/>) based CI checks for this repository.
## The build pipeline
CodeFresh uses a several pipeline for each repository. The `codefresh.yml` file defines pipeline [build steps](https://codefresh.io/docs/docs/configure-ci-cd-pipeline/introduction-to-codefresh-pipelines/) for this repository.
Run results can be seen in the GitHub checks interface and in the [public pipeline](https://g.codefresh.io/public/accounts/angular/pipelines/angular/angular/angular)
Although most configuration is done via `pipeline.yml`, some options are only available in the online [pipeline settings](https://g.codefresh.io/pipelines/angular/services?repoOwner=angular&repoName=angular&project=angular%2Fangular&context=github&serviceName=angular%2Fangular), which needs a login to access.
## Caretaker
CodeFresh status can be found at <http://status.codefresh.io/>.
Issues related to the CodeFresh setup should be escalated to the Tools Team via the current caretaker, followed by Alex Eagle and Filipe Silva.
## Rollout strategy
Currently it is only used for tests on Windows platforms, on the master branch, and without pushing user-facing reports. It's only possible to see current builds in the [public pipeline dashboard](https://g.codefresh.io/public/accounts/angular/pipelines/angular/angular/angular).
After a week or two of running like this, we should reassess how stable and reliable it is.
Next steps include:
- building PRs
- showing build status publicly
- blocking PRs that break the build
- expanding the test suite

38
.codefresh/bazel.rc Normal file
View File

@ -0,0 +1,38 @@
# These options are enabled when running on CI
# We do this by copying this file to /etc/bazel.bazelrc at the start of the build.
# See documentation in /docs/BAZEL.md
# Save built files and downloaded repositories in a location that can be cached by CodeFresh and
# shared between builds. This helps speed up the analysis time significantly with Bazel managed node
# dependencies on the CI.
# https://codefresh.io/docs/docs/configure-ci-cd-pipeline/introduction-to-codefresh-pipelines/#caching-the-artifacts-of-your-build-system
build --repository_cache=C:/codefresh/volume/bazel_repository_cache
# Setting the output_base to a Docker volume is currently broken because of a Docker bug on Windows:
# https://github.com/moby/moby/issues/37024
# This affects Bazel because bazel_output_base\external\bazel_tools is an absolute path junction.
# When its fixed we can uncomment this line, and use a different output_base for Ivy tests (they
# use a separate compiler and destructively replace the cache).
# startup --output_base=C:/codefresh/volume/bazel_output_base
# Don't be spammy in the logs
# TODO(gmagolan): Hide progress again once build performance improves
# Presently, CircleCI can timeout during bazel test ... with the following
# error: Too long with no output (exceeded 10m0s)
build --noshow_progress
# Print all the options that apply to the build.
# This helps us diagnose which options override others
# (e.g. /etc/bazel.bazelrc vs. tools/bazel.rc)
build --announce_rc
# Workaround https://github.com/bazelbuild/bazel/issues/3645
# Bazel doesn't calculate the memory ceiling correctly when running under Docker.
# Limit Bazel to consuming resources that fit in CodeFresh VMs
# TODO(filipesilva): determine the correct memory limit
build --local_resources=10240,8.0,1.0
# Retry in the event of flakes, eg. https://circleci.com/gh/angular/angular/31309
test --flaky_test_attempts=2
# More details on failures
build --verbose_failures=true

28
.codefresh/codefresh.yml Normal file
View File

@ -0,0 +1,28 @@
version: '1.0'
steps:
BuildImage:
title: Build Docker image
type: build
image_name: node-bazel-windows
working_directory: ./.codefresh
no_cf_cache: true
build_arguments:
- node_version=10.13.0
- yarn_version=1.13.0
dockerfile: ./Dockerfile.win-1809
RunTests:
title: Run Bazel tests
image: ${{BuildImage}}
commands:
# Install dependencies
- yarn install --frozen-lockfile --non-interactive --network-timeout 100000 --no-progress
# Add Bazel CI config
- copy .codefresh\bazel.rc %ProgramData%\bazel.bazelrc
# Run tests
# At the moment 'browser:chromium-local' are broken in CI while locally they work
# VE
- yarn bazel test --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only,-browser:chromium-local //...
# Ivy
- yarn bazel test --define=compile=aot --build_tag_filters=-no-ivy-aot,-fixme-ivy-aot --test_tag_filters=-no-ivy-aot,-fixme-ivy-aot,-browser:chromium-local //...

10
.github/CODEOWNERS vendored
View File

@ -101,6 +101,7 @@
#
# - brandonroberts
# - gkalpak
# - jenniferfell
# - petebacondarwin
@ -883,6 +884,7 @@ testing/** @angular/fw-test
/* @angular/fw-dev-infra
/.buildkite/** @angular/fw-dev-infra
/.circleci/** @angular/fw-dev-infra
/.codefresh/** @angular/fw-dev-infra
/.devcontainer/** @angular/fw-dev-infra
/.github/** @angular/fw-dev-infra
/.vscode/** @angular/fw-dev-infra
@ -910,6 +912,14 @@ testing/** @angular/fw-test
# ================================================
# Material CI
# ================================================
/tools/material-ci/** @angular/fw-core @angular/framework-global-approvers
# ================================================
# Public API
# ================================================

View File

@ -1,69 +1,44 @@
<a name="8.2.4"></a>
## [8.2.4](https://github.com/angular/angular/compare/8.2.3...8.2.4) (2019-08-28)
<a name="8.2.3"></a>
## [8.2.3](https://github.com/angular/angular/compare/8.2.2...8.2.3) (2019-08-21)
### Bug Fixes
* **bazel:** pin `[@microsoft](https://github.com/microsoft)/api-extractor` ([#32187](https://github.com/angular/angular/issues/32187)) ([a7b9478](https://github.com/angular/angular/commit/a7b9478))
<a name="8.2.2"></a>
## [8.2.2](https://github.com/angular/angular/compare/8.2.1...8.2.2) (2019-08-12)
### Bug Fixes
* **bazel:** disable treeshaking when generating FESM and UMD bundles ([#32069](https://github.com/angular/angular/issues/32069)) ([3420d29](https://github.com/angular/angular/commit/3420d29))
<a name="8.2.1"></a>
## [8.2.1](https://github.com/angular/angular/compare/8.2.0...8.2.1) (2019-08-08)
### Bug Fixes
* **upgrade:** compile downgraded components synchronously (if possible) ([#31840](https://github.com/angular/angular/issues/31840)) ([04ebd59](https://github.com/angular/angular/commit/04ebd59)), closes [#27217](https://github.com/angular/angular/issues/27217) [#30330](https://github.com/angular/angular/issues/30330)
<a name="9.0.0-next.0"></a>
# [9.0.0-next.0](https://github.com/angular/angular/compare/8.2.0-next.2...9.0.0-next.0) (2019-07-31)
* Ivy related improvements and fixes
<a name="8.2.0"></a>
# [8.2.0](https://github.com/angular/angular/compare/8.2.0-rc.0...8.2.0) (2019-07-31)
### Bug Fixes
* **core:** DebugElement.listeners not cleared on destroy ([#31820](https://github.com/angular/angular/issues/31820)) ([46b160e](https://github.com/angular/angular/commit/46b160e))
<a name="8.2.0-rc.0"></a>
# [8.2.0-rc.0](https://github.com/angular/angular/compare/8.2.0-next.2...8.2.0-rc.0) (2019-07-26)
### Bug Fixes
* **bazel:** increase memory limit of ngc under bazel from 2 to 4 GB ([#31784](https://github.com/angular/angular/issues/31784)) ([5a8eb92](https://github.com/angular/angular/commit/5a8eb92))
* **core:** allow Z variations of CSS transforms in sanitizer ([#29264](https://github.com/angular/angular/issues/29264)) ([78e7fdd](https://github.com/angular/angular/commit/78e7fdd))
* **elements:** handle falsy initial value ([#31604](https://github.com/angular/angular/issues/31604)) ([7151eae](https://github.com/angular/angular/commit/7151eae)), closes [angular/angular#30834](https://github.com/angular/angular/issues/30834)
* **platform-browser:** debug element query predicates not compatible with strictFunctionTypes ([#30993](https://github.com/angular/angular/issues/30993)) ([10a1e19](https://github.com/angular/angular/commit/10a1e19))
### Features
* **core:** TypeScript 3.5 support ([#31615](https://github.com/angular/angular/issues/31615)) ([6ece7db]
* **core:** add automatic migration from Renderer to Renderer2 ([#30936](https://github.com/angular/angular/issues/30936)) ([c095597](https://github.com/angular/angular/commit/c095597))
* **bazel:** compile targets used for indexing by Kythe with Ivy ([#31786](https://github.com/angular/angular/issues/31786)) ([82055b2](https://github.com/angular/angular/commit/82055b2))
* **upgrade:** support $element in upgraded component template/templateUrl functions ([#31637](https://github.com/angular/angular/issues/31637)) ([29e1c53](https://github.com/angular/angular/commit/29e1c53))
* **bazel:** allow passing a custom bazel compiler host to ngc compile ([#31341](https://github.com/angular/angular/issues/31341)) ([a29dc96](https://github.com/angular/angular/commit/a29dc96))
* **bazel:** allow passing and rewriting an old bazel host ([#31381](https://github.com/angular/angular/issues/31381)) ([11a208f](https://github.com/angular/angular/commit/11a208f)), closes [#31341](https://github.com/angular/angular/issues/31341)
### Performance Improvements
* **compiler:** avoid copying from prototype while cloning an object ([#31638](https://github.com/angular/angular/issues/31638)) ([24ca582](https://github.com/angular/angular/commit/24ca582)), closes [#31627](https://github.com/angular/angular/issues/31627)
### Bug Fixes
* **core:** DebugElement.listeners not cleared on destroy ([#31820](https://github.com/angular/angular/issues/31820)) ([46b160e](https://github.com/angular/angular/commit/46b160e))
* **bazel:** increase memory limit of ngc under bazel from 2 to 4 GB ([#31784](https://github.com/angular/angular/issues/31784)) ([5a8eb92](https://github.com/angular/angular/commit/5a8eb92))
* **core:** allow Z variations of CSS transforms in sanitizer ([#29264](https://github.com/angular/angular/issues/29264)) ([78e7fdd](https://github.com/angular/angular/commit/78e7fdd))
* **elements:** handle falsy initial value ([#31604](https://github.com/angular/angular/issues/31604)) ([7151eae](https://github.com/angular/angular/commit/7151eae)), closes [angular/angular#30834](https://github.com/angular/angular/issues/30834)
* **platform-browser:** debug element query predicates not compatible with strictFunctionTypes ([#30993](https://github.com/angular/angular/issues/30993)) ([10a1e19](https://github.com/angular/angular/commit/10a1e19))
* use the correct WTF array to iterate over ([#31208](https://github.com/angular/angular/issues/31208)) ([9204de9](https://github.com/angular/angular/commit/9204de9))
* **bazel:** pass custom bazel compiler host rather than rewriting one ([#31496](https://github.com/angular/angular/issues/31496)) ([0c61a35](https://github.com/angular/angular/commit/0c61a35))
* **compiler-cli:** Return original sourceFile instead of redirected sourceFile from getSourceFile ([#26036](https://github.com/angular/angular/issues/26036)) ([3166cff](https://github.com/angular/angular/commit/3166cff)), closes [#22524](https://github.com/angular/angular/issues/22524)
* **language-service:** Eagarly initialize data members ([#31577](https://github.com/angular/angular/issues/31577)) ([0110de2](https://github.com/angular/angular/commit/0110de2))
* **bazel:** revert location of xi18n outputs to bazel-genfiles ([#31410](https://github.com/angular/angular/issues/31410)) ([1d3e227](https://github.com/angular/angular/commit/1d3e227))
* **compiler:** give ASTWithSource its own visit method ([#31347](https://github.com/angular/angular/issues/31347)) ([6aaca21](https://github.com/angular/angular/commit/6aaca21))
* **core:** handle `undefined` meta in `injectArgs` ([#31333](https://github.com/angular/angular/issues/31333)) ([80ccd6c](https://github.com/angular/angular/commit/80ccd6c)), closes [CLI #14888](https://github.com/angular/angular-cli/issues/14888)
* **service-worker:** cache opaque responses in data groups with `freshness` strategy ([#30977](https://github.com/angular/angular/issues/30977)) ([d7be38f](https://github.com/angular/angular/commit/d7be38f)), closes [#30968](https://github.com/angular/angular/issues/30968)
* **service-worker:** cache opaque responses when requests exceeds timeout threshold ([#30977](https://github.com/angular/angular/issues/30977)) ([93abc35](https://github.com/angular/angular/commit/93abc35))
<a name="8.1.3"></a>
@ -80,17 +55,6 @@
* **compiler:** avoid copying from prototype while cloning an object ([#31638](https://github.com/angular/angular/issues/31638)) ([1f3daa0](https://github.com/angular/angular/commit/1f3daa0)), closes [#31627](https://github.com/angular/angular/issues/31627)
<a name="8.2.0-next.2"></a>
# [8.2.0-next.2](https://github.com/angular/angular/compare/8.2.0-next.1...8.2.0-next.2) (2019-07-17)
### Bug Fixes
* use the correct WTF array to iterate over ([#31208](https://github.com/angular/angular/issues/31208)) ([9204de9](https://github.com/angular/angular/commit/9204de9))
* **bazel:** pass custom bazel compiler host rather than rewriting one ([#31496](https://github.com/angular/angular/issues/31496)) ([0c61a35](https://github.com/angular/angular/commit/0c61a35))
* **compiler-cli:** Return original sourceFile instead of redirected sourceFile from getSourceFile ([#26036](https://github.com/angular/angular/issues/26036)) ([3166cff](https://github.com/angular/angular/commit/3166cff)), closes [#22524](https://github.com/angular/angular/issues/22524)
* **language-service:** Eagarly initialize data members ([#31577](https://github.com/angular/angular/issues/31577)) ([0110de2](https://github.com/angular/angular/commit/0110de2))
<a name="8.1.2"></a>
@ -104,23 +68,6 @@
* **core:** export provider interfaces that are part of the public API types ([#31377](https://github.com/angular/angular/issues/31377)) ([bebf089](https://github.com/angular/angular/commit/bebf089)), closes [/github.com/angular/angular/pull/31377#discussion_r299254408](https://github.com//github.com/angular/angular/pull/31377/issues/discussion_r299254408) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L365-L366](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L365-L366) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L283-L284](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L283-L284) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts#L23](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts/issues/L23)
<a name="8.2.0-next.1"></a>
# [8.2.0-next.1](https://github.com/angular/angular/compare/8.2.0-next.0...8.2.0-next.1) (2019-07-10)
### Bug Fixes
* **bazel:** revert location of xi18n outputs to bazel-genfiles ([#31410](https://github.com/angular/angular/issues/31410)) ([1d3e227](https://github.com/angular/angular/commit/1d3e227))
* **compiler:** give ASTWithSource its own visit method ([#31347](https://github.com/angular/angular/issues/31347)) ([6aaca21](https://github.com/angular/angular/commit/6aaca21))
### Features
* **core:** add automatic migration from Renderer to Renderer2 ([#30936](https://github.com/angular/angular/issues/30936)) ([c095597](https://github.com/angular/angular/commit/c095597))
<a name="8.1.1"></a>
## [8.1.1](https://github.com/angular/angular/compare/8.1.0...8.1.1) (2019-07-10)
@ -130,23 +77,6 @@
* **core:** export provider interfaces that are part of the public API types ([#31377](https://github.com/angular/angular/issues/31377)) ([bebf089](https://github.com/angular/angular/commit/bebf089)), closes [/github.com/angular/angular/pull/31377#discussion_r299254408](https://github.com//github.com/angular/angular/pull/31377/issues/discussion_r299254408) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L365-L366](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L365-L366) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L283-L284](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L283-L284) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts#L23](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts/issues/L23)
<a name="8.2.0-next.0"></a>
# [8.2.0-next.0](https://github.com/angular/angular/compare/8.1.0-rc.0...8.2.0-next.0) (2019-07-02)
### Bug Fixes
* **core:** handle `undefined` meta in `injectArgs` ([#31333](https://github.com/angular/angular/issues/31333)) ([80ccd6c](https://github.com/angular/angular/commit/80ccd6c)), closes [CLI #14888](https://github.com/angular/angular-cli/issues/14888)
* **service-worker:** cache opaque responses in data groups with `freshness` strategy ([#30977](https://github.com/angular/angular/issues/30977)) ([d7be38f](https://github.com/angular/angular/commit/d7be38f)), closes [#30968](https://github.com/angular/angular/issues/30968)
* **service-worker:** cache opaque responses when requests exceeds timeout threshold ([#30977](https://github.com/angular/angular/issues/30977)) ([93abc35](https://github.com/angular/angular/commit/93abc35))
### Features
* **bazel:** allow passing a custom bazel compiler host to ngc compile ([#31341](https://github.com/angular/angular/issues/31341)) ([a29dc96](https://github.com/angular/angular/commit/a29dc96))
* **bazel:** allow passing and rewriting an old bazel host ([#31381](https://github.com/angular/angular/issues/31381)) ([11a208f](https://github.com/angular/angular/commit/11a208f)), closes [#31341](https://github.com/angular/angular/issues/31341)
<a name="8.1.0"></a>
# [8.1.0](https://github.com/angular/angular/compare/8.1.0-rc.0...8.1.0) (2019-07-02)

View File

@ -233,7 +233,6 @@ There are currently a few exceptions to the "use package name" rule:
* **docs-infra**: used for docs-app (angular.io) related changes within the /aio directory of the
repo
* **ivy**: used for changes to the [Ivy renderer](https://github.com/angular/angular/issues/21706).
* **ngcc**: used for changes to the [Angular Compatibility Compiler](./packages/compiler-cli/ngcc/README.md)
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all
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`).

View File

@ -6,7 +6,7 @@
# Angular
Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages.
Angular is a development platform for building mobile and desktop web applications using Typescript/JavaScript and other languages.
## Quickstart
@ -14,7 +14,7 @@ Angular is a development platform for building mobile and desktop web applicatio
## Changelog
[Learn about the latest improvements][changelog].
[Learn about the latest improvements][changelog].
## Want to help?

View File

@ -14,12 +14,10 @@ Here are the most important tasks you might need to use:
* `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 setup-local` - same as `setup`, but use the locally built Angular packages for aio and docs examples boilerplate.
* `yarn build` - create a production build of the application (after installing dependencies, boilerplate, etc).
* `yarn build-local` - same as `build`, but use `setup-local` instead of `setup`.
* `yarn build-with-ivy` - same as `build-local`, but in addition also turns on `ivy` mode in aio.
(Note: To turn on `ivy` mode in examples, see `yarn boilerplate:add` below.)
* `yarn start` - run a development web server that watches the files; then builds the doc-viewer and reloads the page, as necessary.
* `yarn serve-and-sync` - run both the `docs-watch` and `start` in the same console.
@ -33,10 +31,7 @@ Here are the most important tasks you might need to use:
* `yarn docs-lint` - check that the doc gen code follows our style rules.
* `yarn docs-test` - run the unit tests for the doc generation code.
* `yarn boilerplate:add` - generate all the boilerplate code for the examples, so that they can be run locally.
- Add the option `--local` to use your local version of Angular contained in the "dist" folder.
- Add the option `--ivy` to turn on `ivy` mode.
* `yarn boilerplate:add` - generate all the boilerplate code for the examples, so that they can be run locally. Add the option `--local` to use your local version of Angular contained in the "dist" folder.
* `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.
@ -46,15 +41,6 @@ Here are the most important tasks you might need to use:
- `yarn example-e2e --filter=foo` - limit e2e tests to those containing the word "foo"
- `yarn example-e2e --setup --local` - run e2e tests with the local version of Angular contained in the "dist" folder
> **Note for Windows users**
>
> Setting up the examples involves creating some [symbolic links](https://en.wikipedia.org/wiki/Symbolic_link) (see [here](./tools/examples/README.md#symlinked-node_modules) for details). On Windows, this requires to either have [Developer Mode enabled](https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10) (supported on Windows 10 or newer) or run the setup commands as administrator.
>
> The affected commands are:
> - `yarn setup` / `yarn setup-*`
> - `yarn build` / `yarn build-*`
> - `yarn boilerplate:add`
> - `yarn example-e2e --setup`
## Using ServiceWorker locally

View File

@ -1,6 +1,6 @@
// #docplaster
// #docregion imports
import { Component, OnInit } from '@angular/core';
import { Component } from '@angular/core';
import { CartService } from '../cart.service';
// #enddocregion imports
@ -10,14 +10,12 @@ import { CartService } from '../cart.service';
styleUrls: ['./cart.component.css']
})
// #docregion props-services, submit
export class CartComponent implements OnInit {
export class CartComponent {
items;
constructor(
private cartService: CartService
) { }
ngOnInit() {
) {
this.items = this.cartService.getItems();
}
}

View File

@ -1,6 +1,6 @@
// #docplaster
// #docregion imports
import { Component, OnInit } from '@angular/core';
import { Component } from '@angular/core';
import { CartService } from '../cart.service';
// #enddocregion
@ -11,7 +11,7 @@ import { CartService } from '../cart.service';
styleUrls: ['./shipping.component.css']
})
// #docregion props, ctor
export class ShippingComponent implements OnInit {
export class ShippingComponent {
shippingCosts;
// #enddocregion props
@ -19,12 +19,10 @@ export class ShippingComponent implements OnInit {
constructor(
private cartService: CartService
) {
// #enddocregion inject-cart-service
this.shippingCosts = this.cartService.getShippingPrices();
// #docregion inject-cart-service
}
// #enddocregion inject-cart-service
ngOnInit() {
this.shippingCosts = this.cartService.getShippingPrices();
}
// #docregion props
}

View File

@ -1,6 +1,6 @@
<h1>HTTP Sample</h1>
<div>
<input type="checkbox" id="heroes" [checked]="showHeroes" (click)="toggleHeroes()">
<input type="checkbox" id="heroes" [checked]="toggleHeroes" (click)="toggleHeroes()">
<label for="heroes">Heroes</label>
<input type="checkbox" id="config" [checked]="showConfig" (click)="toggleConfig()">

View File

@ -12,7 +12,7 @@ if (environment.production) {
// use the require method provided by webpack
declare const require;
// we use the webpack raw-loader to return the content as a string
const translations = require('raw-loader!./locale/messages.fr.xlf').default;
const translations = require(`raw-loader!./locale/messages.fr.xlf`);
platformBrowserDynamic().bootstrapModule(AppModule, {
providers: [

View File

@ -1,24 +0,0 @@
import { browser, element, by } from 'protractor';
import { logging } from 'selenium-webdriver';
describe('Providers and ViewProviders', function () {
beforeEach(() => {
browser.get('');
});
it('shows basic flower emoji', function() {
expect(element.all(by.css('p')).get(0).getText()).toContain('🌺');
});
it('shows whale emoji', function() {
expect(element.all(by.css('p')).get(1).getText()).toContain('🐳');
});
it('shows sunflower from FlowerService', function() {
expect(element.all(by.css('p')).get(8).getText()).toContain('🌻');
});
});

View File

@ -1,10 +0,0 @@
// #docregion animal-service
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class AnimalService {
emoji = '🐳';
}
// #enddocregion animal-service

View File

@ -1,15 +0,0 @@
import { Component } from '@angular/core';
import { FlowerService } from './flower.service';
import { AnimalService } from './animal.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
// #docregion injection
export class AppComponent {
constructor(public flower: FlowerService) {}
}
// #enddocregion injection

View File

@ -1,15 +0,0 @@
<h2>From AppComponent:</h2>
<!-- #docregion binding-flower -->
<p>Emoji from FlowerService: {{flower.emoji}}</p>
<!-- #enddocregion binding-flower -->
<!-- #docregion binding-animal -->
<p>Emoji from AnimalService: {{animal.emoji}}</p>
<!-- #enddocregion binding-animal -->
<hr />
<h2>From ChildComponent:</h2>
<!-- #docregion content-projection -->
<app-child><app-inspector></app-inspector></app-child>
<!-- #enddocregion content-projection -->

View File

@ -1,15 +0,0 @@
import { Component } from '@angular/core';
import { FlowerService } from './flower.service';
import { AnimalService } from './animal.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
// #docregion inject-animal-service
export class AppComponent {
constructor(public flower: FlowerService, public animal: AnimalService) {}
}
// #enddocregion inject-animal-service

View File

@ -1,17 +0,0 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { ChildComponent } from './child/child.component';
import { InspectorComponent } from './inspector/inspector.component';
// #docregion appmodule
@NgModule({
imports: [ BrowserModule, FormsModule ],
declarations: [ AppComponent, ChildComponent, InspectorComponent ],
bootstrap: [ AppComponent ],
providers: []
})
export class AppModule { }
// #enddocregion appmodule

View File

@ -1,19 +0,0 @@
import { Component, OnInit, Host, SkipSelf, Optional } from '@angular/core';
import { FlowerService } from '../flower.service';
// #docregion flowerservice
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css'],
// use the providers array to provide a service
providers: [{ provide: FlowerService, useValue: { emoji: '🌻' } }]
})
export class ChildComponent {
// inject the service
constructor( public flower: FlowerService) { }
}
// #enddocregion flowerservice

View File

@ -1,4 +0,0 @@
.container {
border: 1px solid darkblue;
padding: 1rem;
}

View File

@ -1,24 +0,0 @@
<!-- #docplaster -->
<!-- #docregion child-component -->
<!-- #docregion flower-binding -->
<p>Emoji from FlowerService: {{flower.emoji}}</p>
<!-- #enddocregion flower-binding -->
<!-- #docregion animal-binding -->
<p>Emoji from AnimalService: {{animal.emoji}}</p>
<!-- #enddocregion animal-binding -->
<div class="container">
<h3>Content projection</h3>
<!-- #enddocregion child-component -->
<p>The following is coming from content. It doesn't get to see the puppy because the puppy is declared inside the view only.</p>
<!-- #docregion child-component -->
<ng-content></ng-content>
</div>
<h3>Inside the view</h3>
<!-- #enddocregion child-component -->
<p>The following is inside the view so it does see the puppy.</p>
<!-- #docregion child-component -->
<app-inspector></app-inspector>
<!-- #enddocregion child-component -->

View File

@ -1,44 +0,0 @@
// #docplaster
import { Component, OnInit, Host, SkipSelf, Optional } from '@angular/core';
import { FlowerService } from '../flower.service';
import { AnimalService } from '../animal.service';
// #docregion provide-animal-service
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css'],
// provide services
providers: [{ provide: FlowerService, useValue: { emoji: '🌻' } }],
viewProviders: [{ provide: AnimalService, useValue: { emoji: '🐶' } }]
})
export class ChildComponent {
// inject service
constructor( public flower: FlowerService, public animal: AnimalService) { }
// #enddocregion provide-animal-service
// viewProviders ensures that only the view gets to see this.
// With the AnimalService in the viewProviders, the
// InspectorComponent doesn't get to see it because the
// inspector is in the content.
// constructor( public flower: FlowerService, @Optional() @Host() public animal: AnimalService) { }
// Comment out the above constructor and alternately
// uncomment the two following constructors to see the
// effects of @Host() and @Host() + @SkipSelf().
// constructor(
// @Host() public animal : AnimalService,
// @Host() @Optional() public flower : FlowerService) { }
// constructor(
// @SkipSelf() @Host() public animal : AnimalService,
// @SkipSelf() @Host() @Optional() public flower : FlowerService) { }
// #docregion provide-animal-service
}
// #enddocregion provide-animal-service

View File

@ -1,11 +0,0 @@
import { Injectable } from '@angular/core';
// #docregion flowerservice
@Injectable({
providedIn: 'root'
})
export class FlowerService {
emoji = '🌺';
}
// #enddocregion flowerservice

View File

@ -1,4 +0,0 @@
<!-- #docregion binding -->
<p>Emoji from FlowerService: {{flower.emoji}}</p>
<p>Emoji from AnimalService: {{animal.emoji}}</p>
<!-- #enddocregion binding -->

View File

@ -1,14 +0,0 @@
import { Component } from '@angular/core';
import { FlowerService } from '../flower.service';
import { AnimalService } from '../animal.service';
@Component({
selector: 'app-inspector',
templateUrl: './inspector.component.html',
styleUrls: ['./inspector.component.css']
})
// #docregion injection
export class InspectorComponent {
constructor(public flower: FlowerService, public animal: AnimalService) { }
}
// #enddocregion injection

View File

@ -1,14 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>providers vs. viewProviders</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
</html>

View File

@ -1,12 +0,0 @@
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.log(err));

View File

@ -1,10 +0,0 @@
{
"description": "Inputs and Outputs",
"files": [
"!**/*.d.ts",
"!**/*.js",
"!**/*.[1,2].*"
],
"file": "src/app/app.component.ts",
"tags": ["Inputs and Outputs"]
}

View File

@ -1,21 +0,0 @@
import { browser, element, by } from 'protractor';
describe('Resolution-modifiers-example', function () {
beforeAll(function () {
browser.get('');
});
it('shows basic flower emoji', function() {
expect(element.all(by.css('p')).get(0).getText()).toContain('🌸');
});
it('shows basic leaf emoji', function() {
expect(element.all(by.css('p')).get(1).getText()).toContain('🌿');
});
it('shows yellow flower in host child', function() {
expect(element.all(by.css('p')).get(9).getText()).toContain('🌼');
});
});

View File

@ -1,14 +0,0 @@
<h1>DI resolution modifiers</h1>
<p>Basic flower service: {{flower.emoji}}</p>
<p>Basic leaf service: {{leaf.emoji}}</p>
<app-optional></app-optional>
<app-self></app-self>
<app-self-no-data></app-self-no-data>
<app-skipself></app-skipself>
<app-host-parent></app-host-parent>

View File

@ -1,13 +0,0 @@
import { Component } from '@angular/core';
import { LeafService } from './leaf.service';
import { FlowerService } from './flower.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular';
constructor(public flower: FlowerService, public leaf: LeafService) {}
}

View File

@ -1,33 +0,0 @@
;
import { OptionalComponent } from './optional/optional.component';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { SelfNoDataComponent } from './self-no-data/self-no-data.component';
import { HostComponent } from './host/host.component';
import { SelfComponent } from './self/self.component';
import { SkipselfComponent } from './skipself/skipself.component';
import { HostParentComponent } from './host-parent/host-parent.component';
import { HostChildComponent } from './host-child/host-child.component';
@NgModule({
imports: [
BrowserModule,
FormsModule
],
declarations: [
AppComponent,
OptionalComponent,
SelfComponent,
SelfNoDataComponent,
HostComponent,
SkipselfComponent,
HostParentComponent,
HostChildComponent
],
bootstrap: [AppComponent],
providers: []
})
export class AppModule { }

View File

@ -1,9 +0,0 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root' // provide this service in the root ModuleInjector
})
export class FlowerService {
emoji = '🌸';
}

View File

@ -1,5 +0,0 @@
.section {
border: 2px solid #369;
padding: 1rem;
margin: 1rem 0;
}

View File

@ -1,4 +0,0 @@
<div class="section">
<h2>Child of @Host() Component</h2>
<p>Flower emoji: {{flower.emoji}}</p>
</div>

View File

@ -1,11 +0,0 @@
import { Component } from '@angular/core';
import { FlowerService } from '../flower.service';
@Component({
selector: 'app-host-child',
templateUrl: './host-child.component.html',
styleUrls: ['./host-child.component.css']
})
export class HostChildComponent {
constructor(public flower: FlowerService) { }
}

View File

@ -1,5 +0,0 @@
.section {
border: 2px solid #369;
padding: 1rem;
margin: 1rem 0;
}

View File

@ -1,5 +0,0 @@
<div class="section">
<h2>Parent of @Host() Component</h2>
<p>Flower emoji: {{flower.emoji}}</p>
<app-host></app-host>
</div>

View File

@ -1,16 +0,0 @@
import { Component } from '@angular/core';
import { FlowerService } from '../flower.service';
@Component({
selector: 'app-host-parent',
templateUrl: './host-parent.component.html',
styleUrls: ['./host-parent.component.css'],
providers: [{ provide: FlowerService, useValue: { emoji: '🌺' } }]
})
export class HostParentComponent {
constructor(public flower: FlowerService) { }
}

View File

@ -1,5 +0,0 @@
.section {
border: 2px solid #369;
padding: 1rem;
margin: 1rem 0;
}

View File

@ -1,6 +0,0 @@
<div class="section">
<h2>@Host() Component</h2>
<p>Flower emoji: {{flower.emoji}}</p>
<p><i>(@Host() stops it here)</i></p>
<app-host-child></app-host-child>
</div>

View File

@ -1,21 +0,0 @@
import { Component, Host, Optional } from '@angular/core';
import { FlowerService } from '../flower.service';
// #docregion host-component
@Component({
selector: 'app-host',
templateUrl: './host.component.html',
styleUrls: ['./host.component.css'],
// provide the service
providers: [{ provide: FlowerService, useValue: { emoji: '🌼' } }]
})
export class HostComponent {
// use @Host() in the constructor when injecting the service
constructor(@Host() @Optional() public flower: FlowerService) { }
}
// #enddocregion host-component
// if you take out @Host() and the providers array, flower will be red hibiscus

View File

@ -1,11 +0,0 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
// #docregion leafservice
export class LeafService {
emoji = '🌿';
}
// #enddocregion leafservice

View File

@ -1,7 +0,0 @@
import { Injectable } from '@angular/core';
@Injectable()
export class OptionalService {
}
// This service isn't provided anywhere.

View File

@ -1,5 +0,0 @@
.section {
border: 2px solid #369;
padding: 1rem;
margin: 1rem 0;
}

View File

@ -1,4 +0,0 @@
<div class="section">
<h2>@Optional() Component</h2>
<p>This component still works even though the OptionalService (notice @Optional() in the consturctor isn't provided or configured anywhere. Angular goes through tree and visibilty rules, and if it doesn't find the requested service, returns null.</p>
</div>

View File

@ -1,21 +0,0 @@
import { Component, Optional } from '@angular/core';
import { OptionalService } from '../optional.service';
@Component({
selector: 'app-optional',
templateUrl: './optional.component.html',
styleUrls: ['./optional.component.css']
})
// #docregion optional-component
export class OptionalComponent {
constructor(@Optional() public optional: OptionalService) {}
}
// #enddocregion optional-component
// The OptionalService isn't provided here, in the @Injectable()
// providers array, or in the NgModule. If you remove @Optional()
// from the constructor, you'll get an error.

View File

@ -1,5 +0,0 @@
.section {
border: 2px solid #369;
padding: 1rem;
margin: 1rem 0;
}

View File

@ -1,4 +0,0 @@
<div class="section">
<h2>@Self() Component (without a provider)</h2>
<p>Leaf emoji: {{leaf?.emoji}}</p>
</div>

View File

@ -1,18 +0,0 @@
import { Component, Self, Optional } from '@angular/core';
import { LeafService } from '../leaf.service';
// #docregion self-no-data-component
@Component({
selector: 'app-self-no-data',
templateUrl: './self-no-data.component.html',
styleUrls: ['./self-no-data.component.css']
})
export class SelfNoDataComponent {
constructor(@Self() @Optional() public leaf: LeafService) { }
}
// #enddocregion self-no-data-component
// The app doesn't break because the value being available at self is optional.
// If you remove @Optional(), the app breaks.

View File

@ -1,5 +0,0 @@
.section {
border: 2px solid #369;
padding: 1rem;
margin: 1rem 0;
}

View File

@ -1,4 +0,0 @@
<div class="section">
<h2>@Self() Component</h2>
<p>Flower emoji: {{flower?.emoji}}</p>
</div>

View File

@ -1,19 +0,0 @@
import { Component, Self } from '@angular/core';
import { FlowerService } from '../flower.service';
// #docregion self-component
@Component({
selector: 'app-self',
templateUrl: './self.component.html',
styleUrls: ['./self.component.css'],
providers: [{ provide: FlowerService, useValue: { emoji: '🌼' } }]
})
export class SelfComponent {
constructor(@Self() public flower: FlowerService) {}
}
// #enddocregion self-component
// This component provides the FlowerService so the injector
// doesn't have to look further up the injector tree

View File

@ -1,5 +0,0 @@
.section {
border: 2px solid #369;
padding: 1rem;
margin: 1rem 0;
}

View File

@ -1,4 +0,0 @@
<div class="section">
<h2>@SkipSelf() Component</h2>
<p>Leaf emoji: {{leaf.emoji}}</p>
</div>

View File

@ -1,18 +0,0 @@
import { Component, SkipSelf } from '@angular/core';
import { LeafService } from '../leaf.service';
// #docregion skipself-component
@Component({
selector: 'app-skipself',
templateUrl: './skipself.component.html',
styleUrls: ['./skipself.component.css'],
// Angular would ignore this LeafService instance
providers: [{ provide: LeafService, useValue: { emoji: '🍁' } }]
})
export class SkipselfComponent {
// Use @SkipSelf() in the constructor
constructor(@SkipSelf() public leaf: LeafService) { }
}
// #enddocregion skipself-component
// @SkipSelf(): Specifies that the dependency resolution should start from the parent injector, not here.

View File

@ -1,14 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>DI Resolution Modifiers Example</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root>Loading...</app-root>
</body>
</html>

View File

@ -1,11 +0,0 @@
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule);

View File

@ -1,10 +0,0 @@
{
"description": "NgModules",
"files": [
"!**/*.d.ts",
"!**/*.js",
"!**/*.[1,2].*"
],
"file": "src/app/app.component.ts",
"tags": ["NgModules"]
}

View File

@ -0,0 +1,12 @@
{
"description": "Quickstart AppComponent Testing",
"files":[
"src/browser-test-shim.js",
"src/app/app.component.ts",
"src/app/app.component.spec.ts",
"src/quickstart-specs.html"
],
"main": "src/quickstart-specs.html",
"file": "src/app/app.component.spec.ts",
"tags": ["quickstart", "setup", "testing"]
}

View File

@ -0,0 +1,36 @@
<!-- Run application specs in a browser -->
<!-- #docregion -->
<!DOCTYPE html>
<html>
<head>
<base href="/">
<title>1st Specs</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="node_modules/jasmine-core/lib/jasmine-core/jasmine.css">
</head>
<body>
<!-- Polyfills -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/jasmine-core/lib/jasmine-core/jasmine.js"></script>
<script src="node_modules/jasmine-core/lib/jasmine-core/jasmine-html.js"></script>
<script src="node_modules/jasmine-core/lib/jasmine-core/boot.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/zone.js/dist/zone-testing.js"></script>
<!-- #docregion files -->
<script>
var __spec_files__ = [
'app/app.component.spec'
];
</script>
<!-- #enddocregion files-->
<script src="browser-test-shim.js"></script>
</body>
</html>

View File

@ -0,0 +1,12 @@
{
"description": "QuickStart Setup",
"files": [
"src/app/app.component.ts",
"src/app/app.module.ts",
"src/index.html",
"src/main.ts",
"src/styles.css"
],
"file": "src/app/app.component.ts",
"tags": ["quickstart", "setup", "seed"]
}

View File

@ -1,22 +1,24 @@
{
"description": "Testing - specs",
"files":[
"src/expected.ts",
"src/index-specs.html",
"src/main-specs.ts",
"src/styles.css",
"src/test.css",
"src/tests.sb.ts",
"e2e/src/**/*.ts",
"src/app/**/*.css",
"src/app/**/*.html",
"src/app/**/*.ts",
"src/app/**/*.spec.ts",
"src/testing/**/*",
"src/testing/*.ts",
"src/**/*.spec.ts"
"!src/main.ts",
"!src/app/bag/*.*",
"!src/app/1st.spec.ts",
"src/expected.ts",
"src/test.css",
"src/tests.sb.ts",
"src/main-specs.ts",
"src/index-specs.html"
],
"main": "src/index-specs.html",
"tags": ["testing"]

View File

@ -1,3 +1,3 @@
import jasmineRequire from 'jasmine-core/lib/jasmine-core/jasmine.js';
const jasmineRequire = require('jasmine-core/lib/jasmine-core/jasmine.js');
window['jasmineRequire'] = jasmineRequire;

View File

@ -1,18 +1,19 @@
{
"description": "Heroes Test App",
"files":[
"src/index.html",
"src/main.ts",
"src/styles.css",
"src/test.css",
"e2e/src/**/*.ts",
"src/app/**/*.css",
"src/app/**/*.html",
"src/app/**/*.ts",
"!src/**/*.spec.ts"
"!src/app/bag/*.*",
"!src/test.ts",
"src/test.css",
"src/main.ts",
"src/index.html"
],
"tags": ["testing"]
}

View File

@ -99,7 +99,7 @@ The following example shows how to make a simple progress bar accessible by usin
// Sets the minimum and maximum values for the progressbar role.
'aria-valuemin': '0',
'aria-valuemax': '100',
'aria-valuemax': '0',
// Binding that updates the current value of the progressbar.
'[attr.aria-valuenow]': 'value',

View File

@ -1,179 +0,0 @@
# Angular compiler options
When you use [AoT compilation](guide/aot-compiler), you can control how your application is compiled by specifying *template* compiler options in the `tsconfig.json` [TypeScript configuration file](guide/typescript-configuration).
The template options object, `angularCompilerOptions`, is a sibling to the `compilerOptions` object that supplies standard options to the TypeScript compiler.
```json
{
"compilerOptions": {
"experimentalDecorators": true,
...
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"preserveWhitespaces": true,
...
}
}
```
{@a tsconfig-extends}
## Configuration inheritance with extends
Like the TypeScript compiler, The Angular AoT compiler also supports `extends` in the `angularCompilerOptions` section of the TypeScript configuration file, `tsconfig.json`.
The `extends` property is at the top level, parallel to `compilerOptions` and `angularCompilerOptions`.
A TypeScript configuration can inherit settings from another file using the `extends` property.
The configuration options from the base file are loaded first, then overridden by those in the inheriting `tsconfig` file.
For example:
```json
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"experimentalDecorators": true,
...
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"preserveWhitespaces": true,
...
}
}
```
For more informaton, see the [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html).
## Template options
The following options are available for configuring the AoT template compiler.
### `allowEmptyCodegenFiles`
When true, generate all possible files even if they are empty. Default is false. Used by the Bazel build rules to simplify how Bazel rules track file dependencies. Do not use this option outside of the Bazel rules.
### `annotationsAs`
Modifies how Angular-specific annotations are emitted to improve tree-shaking. Non-Angular annotations are not affected. One of `static fields` (the default) or `decorators`.
* By default, the compiler replaces decorators with a static field in the class, which allows advanced tree-shakers like [Closure compiler](https://github.com/google/closure-compiler) to remove unused classes.
* The `decorators` value leaves the decorators in place, which makes compilation faster. TypeScript emits calls to the` __decorate` helper. Use `--emitDecoratorMetadata` for runtime reflection (but note that the resulting code will not properly tree-shake.
### `annotateForClosureCompiler`
When true, use [Tsickle](https://github.com/angular/tsickle) to annotate the emitted JavaScript with [JSDoc](http://usejsdoc.org/) comments needed by the
[Closure Compiler](https://github.com/google/closure-compiler). Default is false.
### `disableExpressionLowering`
When true (the default), transforms code that is or could be used in an annotation, to allow it to be imported from template factory modules. See [metadata rewriting](guide/aot-compiler#metadata-rewriting) for more information.
When `false`, disables this rewriting, requiring the rewriting to be done manually.
### `disableTypeScriptVersionCheck`
When `true`, the compiler does not check the TypeScript version and does not report an error when an unsupported version of TypeScript is used. Not recommended, as unsupported versions of TypeScript might have undefined behavior. Default is false.
### `enableResourceInlining`
When true, replaces the `templateUrl` and `styleUrls` property in all `@Component` decorators with inlined contents in `template` and `styles` properties.
When enabled, the `.js` output of `ngc` does not include any lazy-loaded template or style URLs.
{@a enablelegacytemplate}
### `enableLegacyTemplate`
When true, enables use of the `<template>` element, which was deprecated in Angular 4.0, in favor of `<ng-template>` (to avoid colliding with the DOM's element of the same name). Default is false. Might be required by some third-party Angular libraries. |
### `flatModuleId`
The module ID to use for importing a flat module (when `flatModuleOutFile` is true). References generated by the template compiler use this module name when importing symbols
from the flat module. Ignored if `flatModuleOutFile` is false.
### `flatModuleOutFile`
When true, generates a flat module index of the given file name and the corresponding flat module metadata. Use to create flat modules that are packaged similarly to `@angular/core` and `@angular/common`. When this option is used, the `package.json` for the library should refer
to the generated flat module index instead of the library index file.
Produces only one `.metadata.json` file, which contains all the metadata necessary
for symbols exported from the library index. In the generated `.ngfactory.js` files, the flat
module index is used to import symbols that includes both the public API from the library index
as well as shrowded internal symbols.
By default the `.ts` file supplied in the `files` field is assumed to be the library index.
If more than one `.ts` file is specified, `libraryIndex` is used to select the file to use.
If more than one `.ts` file is supplied without a `libraryIndex`, an error is produced.
A flat module index `.d.ts` and `.js` is created with the given `flatModuleOutFile` name in the same location as the library index `.d.ts` file.
For example, if a library uses the `public_api.ts` file as the library index of the module, the `tsconfig.json` `files` field would be `["public_api.ts"]`.
The `flatModuleOutFile` options could then be set to (for example) `"index.js"`, which produces `index.d.ts` and `index.metadata.json` files.
The `module` field of the library's `package.json` would be `"index.js"` and the `typings` field
would be `"index.d.ts"`.
### `fullTemplateTypeCheck`
When true (recommended), enables the [binding expression validation](guide/aot-compiler#binding-expression-validation) phase of the template compiler, which uses TypeScript to validate binding expressions.
Default is currently false.
### `generateCodeForLibraries`
When true (the default), generates factory files (`.ngfactory.js` and `.ngstyle.js`)
for `.d.ts` files with a corresponding `.metadata.json` file.
When false, factory files are generated only for `.ts` files. Do this when using factory summaries.
### `preserveWhitespaces`
When false (the default), removes blank text nodes from compiled templates, which results in smaller emitted template factory modules. Set to true to preserve blank text nodes.
### `skipMetadataEmit`
When true, does not to produce `.metadata.json` files. Default is `false`.
The `.metadata.json` files contain information needed by the template compiler from a `.ts`
file that is not included in the `.d.ts` file produced by the TypeScript compiler.
This information includes, for example, the content of annotations (such as a component's template), which TypeScript emits to the `.js` file but not to the `.d.ts` file.
You can set to `true` when using factory summaries, because the factory summaries
include a copy of the information that is in the `.metadata.json` file.
Set to `true` if you are using TypeScript's `--outFile` option, because the metadata files
are not valid for this style of TypeScript output. However, we do not recommend using `--outFile` with Angular. Use a bundler, such as [webpack](https://webpack.js.org/), instead.
### `skipTemplateCodegen`
When true, does not emit `.ngfactory.js` and `.ngstyle.js` files. This turns off most of the template compiler and disables the reporting of template diagnostics.
Can be used to instruct the template compiler to produce `.metadata.json` files for distribution with an `npm` package while avoiding the production of `.ngfactory.js` and `.ngstyle.js` files that cannot be distributed to `npm`.
### `strictMetadataEmit`
When true, reports an error to the `.metadata.json` file if `"skipMetadataEmit"` is `false`.
Default is false. Use only when `"skipMetadataEmit"` is false and `"skipTemplateCodeGen"` is true.
This option is intended to validate the `.metadata.json` files emitted for bundling with an `npm` package. The validation is strict and can emit errors for metadata that would never produce an error when used by the template compiler. You can choose to suppress the error emitted by this option for an exported symbol by including `@dynamic` in the comment documenting the symbol.
It is valid for `.metadata.json` files to contain errors.
The template compiler reports these errors if the metadata is used to determine the contents of an annotation.
The metadata collector cannot predict the symbols that are designed for use in an annotation, so it preemptively includes error nodes in the metadata for the exported symbols.
The template compiler can then use the error nodes to report an error if these symbols are used.
If the client of a library intends to use a symbol in an annotation, the template compiler does not normally report this until the client uses the symbol.
This option allows detection of these errors during the build phase of
the library and is used, for example, in producing Angular libraries themselves.
### `strictInjectionParameters`
When true (recommended), reports an error for a supplied parameter whose injection type cannot be determined. When false (currently the default), constructor parameters of classes marked with `@Injectable` whose type cannot be resolved produce a warning.
### `trace`
When true, prints extra information while compiling templates. Default is false.

View File

@ -260,7 +260,7 @@ What it does
</tr>
<tr>
<td><code><a href="api/animations/state" class="code-anchor">state()</a></code></td>
<td><code>state()</code></td>
<td>Creates a named set of CSS styles that should be applied on successful transition to a given state. The state can then be referenced by name within other animation functions.</td>
</tr>
@ -280,7 +280,7 @@ What it does
</tr>
<tr>
<td><code><a href="api/animations/group" class="code-anchor">group()</a></code></td>
<td><code>group()</code></td>
<td>Specifies a group of animation steps (<em>inner animations</em>) to be run in parallel. Animation continues only after all inner animation steps have completed. Used within <code>sequence()</code> or <code>transition().</code></td>
</tr>

File diff suppressed because it is too large Load Diff

View File

@ -1,540 +0,0 @@
# AoT metadata errors
The following are metadata errors you may encounter, with explanations and suggested corrections.
[Expression form not supported](#expression-form-not-supported)<br>
[Reference to a local (non-exported) symbol](#reference-to-a-local-symbol)<br>
[Only initialized variables and constants](#only-initialized-variables)<br>
[Reference to a non-exported class](#reference-to-a-non-exported-class)<br>
[Reference to a non-exported function](#reference-to-a-non-exported-function)<br>
[Function calls are not supported](#function-calls-not-supported)<br>
[Destructured variable or constant not supported](#destructured-variable-not-supported)<br>
[Could not resolve type](#could-not-resolve-type)<br>
[Name expected](#name-expected)<br>
[Unsupported enum member name](#unsupported-enum-member-name)<br>
[Tagged template expressions are not supported](#tagged-template-expressions-not-supported)<br>
[Symbol reference expected](#symbol-reference-expected)<br>
<hr>
{@a expression-form-not-supported}
## Expression form not supported
<div class="alert is-helpful">
*The compiler encountered an expression it didn't understand while evaluating Angular metadata.*
</div>
Language features outside of the compiler's [restricted expression syntax](guide/aot-compiler#expression-syntax)
can produce this error, as seen in the following example:
```ts
// ERROR
export class Fooish { ... }
...
const prop = typeof Fooish; // typeof is not valid in metadata
...
// bracket notation is not valid in metadata
{ provide: 'token', useValue: { [prop]: 'value' } };
...
```
You can use `typeof` and bracket notation in normal application code.
You just can't use those features within expressions that define Angular metadata.
Avoid this error by sticking to the compiler's [restricted expression syntax](guide/aot-compiler#expression-syntax)
when writing Angular metadata
and be wary of new or unusual TypeScript features.
<hr>
{@a reference-to-a-local-symbol}
## Reference to a local (non-exported) symbol
<div class="alert is-helpful">
_Reference to a local (non-exported) symbol 'symbol name'. Consider exporting the symbol._
</div>
The compiler encountered a referenced to a locally defined symbol that either wasn't exported or wasn't initialized.
Here's a `provider` example of the problem.
```ts
// ERROR
let foo: number; // neither exported nor initialized
@Component({
selector: 'my-component',
template: ... ,
providers: [
{ provide: Foo, useValue: foo }
]
})
export class MyComponent {}
```
The compiler generates the component factory, which includes the `useValue` provider code, in a separate module. _That_ factory module can't reach back to _this_ source module to access the local (non-exported) `foo` variable.
You could fix the problem by initializing `foo`.
```ts
let foo = 42; // initialized
```
The compiler will [fold](guide/aot-compiler#code-folding) the expression into the provider as if you had written this.
```ts
providers: [
{ provide: Foo, useValue: 42 }
]
```
Alternatively, you can fix it by exporting `foo` with the expectation that `foo` will be assigned at runtime when you actually know its value.
```ts
// CORRECTED
export let foo: number; // exported
@Component({
selector: 'my-component',
template: ... ,
providers: [
{ provide: Foo, useValue: foo }
]
})
export class MyComponent {}
```
Adding `export` often works for variables referenced in metadata such as `providers` and `animations` because the compiler can generate _references_ to the exported variables in these expressions. It doesn't need the _values_ of those variables.
Adding `export` doesn't work when the compiler needs the _actual value_
in order to generate code.
For example, it doesn't work for the `template` property.
```ts
// ERROR
export let someTemplate: string; // exported but not initialized
@Component({
selector: 'my-component',
template: someTemplate
})
export class MyComponent {}
```
The compiler needs the value of the `template` property _right now_ to generate the component factory.
The variable reference alone is insufficient.
Prefixing the declaration with `export` merely produces a new error, "[`Only initialized variables and constants can be referenced`](#only-initialized-variables)".
<hr>
{@a only-initialized-variables}
## Only initialized variables and constants
<div class="alert is-helpful">
_Only initialized variables and constants can be referenced because the value of this variable is needed by the template compiler._
</div>
The compiler found a reference to an exported variable or static field that wasn't initialized.
It needs the value of that variable to generate code.
The following example tries to set the component's `template` property to the value of
the exported `someTemplate` variable which is declared but _unassigned_.
```ts
// ERROR
export let someTemplate: string;
@Component({
selector: 'my-component',
template: someTemplate
})
export class MyComponent {}
```
You'd also get this error if you imported `someTemplate` from some other module and neglected to initialize it there.
```ts
// ERROR - not initialized there either
import { someTemplate } from './config';
@Component({
selector: 'my-component',
template: someTemplate
})
export class MyComponent {}
```
The compiler cannot wait until runtime to get the template information.
It must statically derive the value of the `someTemplate` variable from the source code
so that it can generate the component factory, which includes
instructions for building the element based on the template.
To correct this error, provide the initial value of the variable in an initializer clause _on the same line_.
```ts
// CORRECTED
export let someTemplate = '<h1>Greetings from Angular</h1>';
@Component({
selector: 'my-component',
template: someTemplate
})
export class MyComponent {}
```
<hr>
{@a reference-to-a-non-exported-class}
## Reference to a non-exported class
<div class="alert is-helpful">
_Reference to a non-exported class <class name>. Consider exporting the class._
</div>
Metadata referenced a class that wasn't exported.
For example, you may have defined a class and used it as an injection token in a providers array
but neglected to export that class.
```ts
// ERROR
abstract class MyStrategy { }
...
providers: [
{ provide: MyStrategy, useValue: ... }
]
...
```
Angular generates a class factory in a separate module and that
factory [can only access exported classes](guide/aot-compiler#exported-symbols).
To correct this error, export the referenced class.
```ts
// CORRECTED
export abstract class MyStrategy { }
...
providers: [
{ provide: MyStrategy, useValue: ... }
]
...
```
<hr>
{@a reference-to-a-non-exported-function}
## Reference to a non-exported function
<div class="alert is-helpful">
*Metadata referenced a function that wasn't exported.*
</div>
For example, you may have set a providers `useFactory` property to a locally defined function that you neglected to export.
```ts
// ERROR
function myStrategy() { ... }
...
providers: [
{ provide: MyStrategy, useFactory: myStrategy }
]
...
```
Angular generates a class factory in a separate module and that
factory [can only access exported functions](guide/aot-compiler#exported-symbols).
To correct this error, export the function.
```ts
// CORRECTED
export function myStrategy() { ... }
...
providers: [
{ provide: MyStrategy, useFactory: myStrategy }
]
...
```
<hr>
{@a function-calls-not-supported}
## Function calls are not supported
<div class="alert is-helpful">
_Function calls are not supported. Consider replacing the function or lambda with a reference to an exported function._
</div>
The compiler does not currently support [function expressions or lambda functions](guide/aot-compiler#function-expression).
For example, you cannot set a provider's `useFactory` to an anonymous function or arrow function like this.
```ts
// ERROR
...
providers: [
{ provide: MyStrategy, useFactory: function() { ... } },
{ provide: OtherStrategy, useFactory: () => { ... } }
]
...
```
You also get this error if you call a function or method in a provider's `useValue`.
```ts
// ERROR
import { calculateValue } from './utilities';
...
providers: [
{ provide: SomeValue, useValue: calculateValue() }
]
...
```
To correct this error, export a function from the module and refer to the function in a `useFactory` provider instead.
```ts
// CORRECTED
import { calculateValue } from './utilities';
export function myStrategy() { ... }
export function otherStrategy() { ... }
export function someValueFactory() {
return calculateValue();
}
...
providers: [
{ provide: MyStrategy, useFactory: myStrategy },
{ provide: OtherStrategy, useFactory: otherStrategy },
{ provide: SomeValue, useFactory: someValueFactory }
]
...
```
<hr>
{@a destructured-variable-not-supported}
## Destructured variable or constant not supported
<div class="alert is-helpful">
_Referencing an exported destructured variable or constant is not supported by the template compiler. Consider simplifying this to avoid destructuring._
</div>
The compiler does not support references to variables assigned by [destructuring](https://www.typescriptlang.org/docs/handbook/variable-declarations.html#destructuring).
For example, you cannot write something like this:
```ts
// ERROR
import { configuration } from './configuration';
// destructured assignment to foo and bar
const {foo, bar} = configuration;
...
providers: [
{provide: Foo, useValue: foo},
{provide: Bar, useValue: bar},
]
...
```
To correct this error, refer to non-destructured values.
```ts
// CORRECTED
import { configuration } from './configuration';
...
providers: [
{provide: Foo, useValue: configuration.foo},
{provide: Bar, useValue: configuration.bar},
]
...
```
<hr>
{@a could-not-resolve-type}
## Could not resolve type
<div class="alert is-helpful">
*The compiler encountered a type and can't determine which module exports that type.*
</div>
This can happen if you refer to an ambient type.
For example, the `Window` type is an ambient type declared in the global `.d.ts` file.
You'll get an error if you reference it in the component constructor,
which the compiler must statically analyze.
```ts
// ERROR
@Component({ })
export class MyComponent {
constructor (private win: Window) { ... }
}
```
TypeScript understands ambient types so you don't import them.
The Angular compiler does not understand a type that you neglect to export or import.
In this case, the compiler doesn't understand how to inject something with the `Window` token.
Do not refer to ambient types in metadata expressions.
If you must inject an instance of an ambient type,
you can finesse the problem in four steps:
1. Create an injection token for an instance of the ambient type.
1. Create a factory function that returns that instance.
1. Add a `useFactory` provider with that factory function.
1. Use `@Inject` to inject the instance.
Here's an illustrative example.
```ts
// CORRECTED
import { Inject } from '@angular/core';
export const WINDOW = new InjectionToken('Window');
export function _window() { return window; }
@Component({
...
providers: [
{ provide: WINDOW, useFactory: _window }
]
})
export class MyComponent {
constructor (@Inject(WINDOW) private win: Window) { ... }
}
```
The `Window` type in the constructor is no longer a problem for the compiler because it
uses the `@Inject(WINDOW)` to generate the injection code.
Angular does something similar with the `DOCUMENT` token so you can inject the browser's `document` object (or an abstraction of it, depending upon the platform in which the application runs).
```ts
import { Inject } from '@angular/core';
import { DOCUMENT } from '@angular/platform-browser';
@Component({ ... })
export class MyComponent {
constructor (@Inject(DOCUMENT) private doc: Document) { ... }
}
```
<hr>
{@a name-expected}
## Name expected
<div class="alert is-helpful">
*The compiler expected a name in an expression it was evaluating.*
</div>
This can happen if you use a number as a property name as in the following example.
```ts
// ERROR
provider: [{ provide: Foo, useValue: { 0: 'test' } }]
```
Change the name of the property to something non-numeric.
```ts
// CORRECTED
provider: [{ provide: Foo, useValue: { '0': 'test' } }]
```
<hr>
{@a unsupported-enum-member-name}
## Unsupported enum member name
<div class="alert is-helpful">
*Angular couldn't determine the value of the [enum member](https://www.typescriptlang.org/docs/handbook/enums.html) that you referenced in metadata.*
</div>
The compiler can understand simple enum values but not complex values such as those derived from computed properties.
```ts
// ERROR
enum Colors {
Red = 1,
White,
Blue = "Blue".length // computed
}
...
providers: [
{ provide: BaseColor, useValue: Colors.White } // ok
{ provide: DangerColor, useValue: Colors.Red } // ok
{ provide: StrongColor, useValue: Colors.Blue } // bad
]
...
```
Avoid referring to enums with complicated initializers or computed properties.
<hr>
{@a tagged-template-expressions-not-supported}
## Tagged template expressions are not supported
<div class="alert is-helpful">
_Tagged template expressions are not supported in metadata._
</div>
The compiler encountered a JavaScript ES2015 [tagged template expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_template_literals) such as the following.
```ts
// ERROR
const expression = 'funky';
const raw = String.raw`A tagged template ${expression} string`;
...
template: '<div>' + raw + '</div>'
...
```
[`String.raw()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/raw)
is a _tag function_ native to JavaScript ES2015.
The AoT compiler does not support tagged template expressions; avoid them in metadata expressions.
<hr>
{@a symbol-reference-expected}
## Symbol reference expected
<div class="alert is-helpful">
*The compiler expected a reference to a symbol at the location specified in the error message.*
</div>
This error can occur if you use an expression in the `extends` clause of a class.
<!--
Chuck: After reviewing your PR comment I'm still at a loss. See [comment there](https://github.com/angular/angular/pull/17712#discussion_r132025495).
-->

View File

@ -53,7 +53,7 @@ Angular supports most recent browsers. This includes the following specific vers
IE
</td>
<td>
11, 10, 9 ("compatibility view" mode not supported)
11, 10, 9
</td>
</tr>
<tr>
@ -183,7 +183,7 @@ These are the polyfills required to run an Angular application on each supported
<td>
Chrome, Firefox, Edge, <br>
Safari, Android, IE 10+
Safari, Android, IE10+
</td>
<td>
@ -197,7 +197,7 @@ These are the polyfills required to run an Angular application on each supported
<tr style="vertical-align: top">
<td>
IE 9
IE9
</td>
<td>
@ -275,7 +275,7 @@ Some features of Angular may require additional polyfills.
</td>
<td>
All but Chrome, Firefox, Edge, IE 11 and Safari 10
All but Chrome, Firefox, Edge, IE11 and Safari 10
</td>
</tr>
@ -294,7 +294,7 @@ Some features of Angular may require additional polyfills.
</td>
<td>
IE 10, IE 11
IE10, IE11
</td>
</tr>

View File

@ -253,7 +253,7 @@ In the `package.json` file, add a `builders` key that tells the Architect tool w
</code-example>
The official name of our builder is now ` @example/command-runner:command`.
The first part of this is the package name (resolved using node resolution), and the second part is the builder name (resolved using the `builders.json` file).
The first part of this is the package name (resolved using node resolution), and the second part is the builder name (resolved using the `builder.json` file).
Using one of our `options` is very straightforward, we did this in the previous section when we accessed `options.command`.
@ -279,28 +279,28 @@ By default, for example, the `build` command runs the builder `@angular-devkit/
"myApp": {
...
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/myApp",
"index": "src/index.html",
...
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
...
}
}
},
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/myApp",
"index": "src/index.html",
...
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
...
}
}
},
...
</code-example>
@ -419,13 +419,15 @@ We need to update the `angular.json` file to add a target for this builder to th
"projects": {
"builder-test": {
"architect": {
"touch": {
"builder": "@example/command-runner:command",
"options": {
"command": "touch",
"args": [
"src/main.ts"
]
"builder-test": {
"touch": {
"builder": "@example/command-runner:command",
"options": {
"command": "touch",
"args": [
"src/main.ts"
]
}
}
},
"build": {
@ -495,14 +497,14 @@ The test uses the builder to run the `ls` command, then validates that it ran su
<code-example language="typescript">
import { Architect } from '@angular-devkit/architect';
import { Architect, ArchitectHost } from '@angular-devkit/architect';
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
// Our builder forwards the STDOUT of the command to the logger.
import { logging, schema } from '@angular-devkit/core';
describe('Command Runner Builder', () => {
let architect: Architect;
let architectHost: TestingArchitectHost;
let architectHost: ArchitectHost;
beforeEach(async () => {
const registry = new schema.CoreSchemaRegistry();

View File

@ -30,7 +30,7 @@ The Filter/Stagger tab in the live example shows a list of heroes with an introd
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.
* Use `query()` to look for any element entering or leaving the page. The query specifies elements meeting certain CSS class 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.

View File

@ -134,7 +134,7 @@ The `@NgModule()` and `@Component()` decorators have the `providers` metadata op
Components are directives, and the `providers` option is inherited from `@Directive()`. You can also configure providers for directives and pipes at the same level as the component.
Learn more about [where to configure providers](guide/hierarchical-dependency-injection).
Learn more about [where to configure providers](guide/hierarchical-dependency-injection#where-to-register).
</div>

View File

@ -8,7 +8,7 @@ When you are ready to deploy your Angular application to a remote server, you ha
## Simple deployment options
Before fully deploying your application, you can test the process, build configuration, and deployed behavior by using one of these interim techniques.
Before fully deploying your application, you can test the process, build configuration, and deployed behavior by using one of these interim techniques
### Building and serving from disk
@ -41,7 +41,7 @@ You will need two terminals to get the live-reload experience.
<code-example language="none" class="code-shell">
lite-server --baseDir="dist/project-name"
lite-server --baseDir="dist"
</code-example>
@ -53,35 +53,6 @@ This method is for development and testing only, and is not a supported or secur
</div>
### Automatic deployment with the CLI
The Angular CLI command `ng deploy` (introduced in version 8.3.0) executes the `deploy` [CLI builder](https://angular.io/guide/cli-builder) associated with your project. A number of third-party builders implement deployment capabilities to different platforms. You can add any of them to your project by running `ng add [package name]`.
When you add a package with deployment capability, it'll automatically update your workspace configuration (`angular.json` file) with a `deploy` section for the selected project. You can then use the `ng deploy` command to deploy that project.
For example, the following command automatically deploys a project to Firebase.
<code-example language="none" class="code-shell">
ng add @angular/fire
ng deploy
</code-example>
The command is interactive. In this case, you must have or create a Firebase account, and authenticate using that account. The command prompts you to select a Firebase project for deployment
After the command produces an optimal build of your application (equivalent to `ng deploy --prod`), it'll upload the production assets to Firebase.
In the table below, you can find a list of packages which implement deployment functionality to different platforms. The `deploy` command for each package may require different command line options. You can read more by following the links associated with the package names below:
| Deployment to | Package |
|---------------------------------------------------------------|--------------------------------------------------------------------------------|
| [Firebase hosting](https://firebase.google.com/docs/hosting) | [`@angular/fire`](https://npmjs.org/package/@angular/fire) |
| [Azure](https://azure.microsoft.com/en-us/) | [`@azure/ng-deploy`](https://npmjs.org/package/@azure/ng-deploy) |
| [Now](https://zeit.co/now) | [`@zeit/ng-deploy`](https://npmjs.org/package/@zeit/ng-deploy) |
| [Netlify](https://www.netlify.com/) | [`@netlify-builder/deploy`](https://npmjs.org/package/@netlify-builder/deploy) |
| [GitHub pages](https://pages.github.com/) | [`angular-cli-ghpages`](https://npmjs.org/package/angular-cli-ghpages) |
If you're deploying to a self-managed server or there's no builder for your favorite cloud platform, you can either create a builder that allows you to use the `ng deploy` command, or read through this guide to learn how to manually deploy your app.
### Basic deployment to a remote server
For the simplest deployment, create a production build and copy the output directory to a web server.

View File

@ -178,7 +178,7 @@ For more information, see [/deep/, >>>, and ::ng-deep](guide/component-styles#de
{@a template-tag}
### &lt;template&gt; tag
The `<template>` tag was deprecated in v4 to avoid colliding with the DOM's element of the same name (such as when using web components). Use `<ng-template>` instead. For more information, see the [Ahead-of-Time Compilation](guide/angular-compiler-options#enablelegacytemplate) guide.
The `<template>` tag was deprecated in v4 to avoid colliding with the DOM's element of the same name (such as when using web components). Use `<ng-template>` instead. For more information, see the [Ahead-of-Time Compilation](guide/aot-compiler#enablelegacytemplate) guide.

File diff suppressed because it is too large Load Diff

View File

@ -40,7 +40,7 @@ into an application class as shown in the following `ConfigService` example.
header="app/config/config.service.ts (excerpt)">
</code-example>
## Requesting data from server
## Getting JSON data
Applications often request JSON data from the server.
For example, the app might need a configuration file on the server, `config.json`,
@ -73,37 +73,45 @@ the component **subscribes** to the method's return value.
The subscription callback copies the data fields into the component's `config` object,
which is data-bound in the component template for display.
<div class="callout is-helpful">
<header>Why write a service?</header>
### Why write a service
This example is so simple that it is tempting to write the `Http.get()` inside the
component itself and skip the service.
In practice, however, data access rarely stays this simple.
You typically need to post-process the data, add error handling, and maybe some retry logic to
However, data access rarely stays this simple.
You typically post-process the data, add error handling, and maybe some retry logic to
cope with intermittent connectivity.
The component quickly becomes cluttered with data access minutia.
The component becomes harder to understand, harder to test, and the data access logic can't be re-used or standardized.
That's why it's a best practice to separate presentation of data from data access by
That's why it is a best practice to separate presentation of data from data access by
encapsulating data access in a separate service and delegating to that service in
the component, even in simple cases like this one.
</div>
### Requesting a typed response
### Type-checking the response
You can structure your `HttpClient` request to declare the type of the response object, to make consuming the output easier and more obvious.
Specifying the response type acts as a type assertion during the compile time.
The subscribe callback above requires bracket notation to extract the data values.
To specify the response object type, first define an interface with the required properties.
(Use an interface rather than a class; a response cannot be automatically converted to an instance of a class.)
<code-example
path="http/src/app/config/config.component.ts"
region="v1_callback">
</code-example>
You can't write `data.heroesUrl` because TypeScript correctly complains that the `data` object from the service does not have a `heroesUrl` property.
The `HttpClient.get()` method parsed the JSON server response into the anonymous `Object` type. It doesn't know what the shape of that object is.
You can tell `HttpClient` the type of the response to make consuming the output easier and more obvious.
First, define an interface with the correct shape:
<code-example
path="http/src/app/config/config.service.ts"
region="config-interface">
</code-example>
Next, specify that interface as the `HttpClient.get()` call's type parameter in the service.
Then, specify that interface as the `HttpClient.get()` call's type parameter in the service:
<code-example
path="http/src/app/config/config.service.ts"
@ -111,12 +119,6 @@ Next, specify that interface as the `HttpClient.get()` call's type parameter in
header="app/config/config.service.ts (getConfig v.2)">
</code-example>
<div class="alert is-helpful">
When you pass an interface as a type parameter to the `HttpClient.get()` method, use the RxJS `map` operator to transform the response data as needed by the UI. You can then pass the transformed data to the [async pipe](api/common/AsyncPipe).
</div>
The callback in the updated component method receives a typed data object, which is
easier and safer to consume:
@ -126,24 +128,6 @@ easier and safer to consume:
header="app/config/config.component.ts (showConfig v.2)">
</code-example>
<div class="alert is-important">
Specifying the response type is a declaration to TypeScript that it should expect your response to be of the given type.
This is a build-time check and doesn't guarantee that the server will actually respond with an object of this type. It is up to the server to ensure that the type specified by the server API is returned.
</div>
To access properties that are defined in an interface, you must explicitly convert the Object you get from the JSON to the required response type.
For example, the following `subscribe` callback receives `data` as an Object, and then type-casts it in order to access the properties.
<code-example>
.subscribe(data => this.config = {
heroesUrl: (data as any).heroesUrl,
textfile: (data as any).textfile,
});
</code-example>
### Reading the full response
The response body doesn't return all the data you may need. Sometimes servers return special headers or status codes to indicate certain conditions that are important to the application workflow.
@ -155,7 +139,7 @@ Tell `HttpClient` that you want the full response with the `observe` option:
region="getConfigResponse">
</code-example>
Now `HttpClient.get()` returns an `Observable` of type `HttpResponse` rather than just the JSON data.
Now `HttpClient.get()` returns an `Observable` of typed `HttpResponse` rather than just the JSON data.
The component's `showConfigResponse()` method displays the response headers as well as the configuration:
@ -168,54 +152,6 @@ The component's `showConfigResponse()` method displays the response headers as w
As you can see, the response object has a `body` property of the correct type.
### Making a JSONP request
Apps can use the the `HttpClient` to make [JSONP](https://en.wikipedia.org/wiki/JSONP) requests across domains when the server doesn't support [CORS protocol](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS).
Angular JSONP requests return an `Observable`.
Follow the pattern for subscribing to observables and use the RxJS `map` operator to transform the response before using the [async pipe](api/common/AsyncPipe) to manage the results.
In Angular, use JSONP by including `HttpClientJsonpModule` in the `NgModule` imports.
In the following example, the `searchHeroes()` method uses a JSONP request to query for heroes whose names contain the search term.
```ts
/* GET heroes whose name contains search term */
searchHeroes(term: string): Observable {
term = term.trim();
let heroesURL = `${this.heroesURL}?${term}`;
return this.http.jsonp(heroesUrl, 'callback').pipe(
catchError(this.handleError('searchHeroes', []) // then handle the error
);
};
```
This request passes the `heroesURL` as the first parameter and the callback function name as the second parameter.
The response is wrapped in the callback function, which takes the observables returned by the JSONP method and pipes them through to the error handler.
### Requesting non-JSON data
Not all APIs return JSON data.
In this next example, a `DownloaderService` method reads a text file from the server and logs the file contents, before returning those contents to the caller as an `Observable<string>`.
<code-example
path="http/src/app/downloader/downloader.service.ts"
region="getTextFile"
header="app/downloader/downloader.service.ts (getTextFile)" linenums="false">
</code-example>
`HttpClient.get()` returns a string rather than the default JSON because of the `responseType` option.
The RxJS `tap` operator (as in "wiretap") lets the code inspect both success and error values passing through the observable without disturbing them.
A `download()` method in the `DownloaderComponent` initiates the request by subscribing to the service method.
<code-example
path="http/src/app/downloader/downloader.component.ts"
region="download"
header="app/downloader/downloader.component.ts (download)" linenums="false">
</code-example>
## Error handling
What happens if the request fails on the server, or if a poor network connection prevents it from even reaching the server? `HttpClient` will return an _error_ object instead of a successful response.
@ -268,7 +204,7 @@ and _pipe them through_ to the error handler.
header="app/config/config.service.ts (getConfig v.3 with error handler)">
</code-example>
### Retrying
### `retry()`
Sometimes the error is transient and will go away automatically if you try again.
For example, network interruptions are common in mobile scenarios, and trying again
@ -306,34 +242,29 @@ If you're following along with these code snippets, note that you must import th
header="app/config/config.service.ts (RxJS imports)">
</code-example>
## HTTP headers
## Requesting non-JSON data
Many servers require extra headers for save operations.
For example, they may require a "Content-Type" header to explicitly declare the MIME type of the request body; or the server may require an authorization token.
### Adding headers
The `HeroesService` defines such headers in an `httpOptions` object that will be passed
to every `HttpClient` save method.
Not all APIs return JSON data. In this next example,
a `DownloaderService` method reads a text file from the server
and logs the file contents, before returning those contents to the caller
as an `Observable<string>`.
<code-example
path="http/src/app/heroes/heroes.service.ts"
region="http-options"
header="app/heroes/heroes.service.ts (httpOptions)">
path="http/src/app/downloader/downloader.service.ts"
region="getTextFile"
header="app/downloader/downloader.service.ts (getTextFile)">
</code-example>
### Updating headers
`HttpClient.get()` returns a string rather than the default JSON because of the `responseType` option.
You can't directly modify the existing headers within the previous options
object because instances of the `HttpHeaders` class are immutable.
The RxJS `tap` operator (as in "wiretap") lets the code inspect good and error values passing through the observable without disturbing them.
Use the `set()` method instead, to return a clone of the current instance with the new changes applied.
Here's how you might update the authorization header (after the old token expired) before making the next request.
A `download()` method in the `DownloaderComponent` initiates the request by subscribing to the service method.
<code-example
path="http/src/app/heroes/heroes.service.ts"
region="update-headers" linenums="false">
path="http/src/app/downloader/downloader.component.ts"
region="download"
header="app/downloader/downloader.component.ts (download)">
</code-example>
## Sending data to the server
@ -345,6 +276,22 @@ that fetches heroes and enables users to add, delete, and update them.
The following sections excerpt methods of the sample's `HeroesService`.
### Adding headers
Many servers require extra headers for save operations.
For example, they may require a "Content-Type" header to explicitly declare
the MIME type of the request body.
Or perhaps the server requires an authorization token.
The `HeroesService` defines such headers in an `httpOptions` object that will be passed
to every `HttpClient` save method.
<code-example
path="http/src/app/heroes/heroes.service.ts"
region="http-options"
header="app/heroes/heroes.service.ts (httpOptions)">
</code-example>
### Making a POST request
Apps often POST data to a server. They POST when submitting a form.
@ -466,8 +413,118 @@ in order to initiate the request.
We have discussed the basic HTTP functionality in `@angular/common/http`, but sometimes you need to do more than make simple requests and get data back.
{@a intercepting-requests-and-responses }
### HTTP interceptors
### Configuring the request
Other aspects of an outgoing request can be configured via the options object
passed as the last argument to the `HttpClient` method.
You [saw earlier](#adding-headers) that the `HeroesService` sets the default headers by
passing an options object (`httpOptions`) to its save methods.
You can do more.
#### Update headers
You can't directly modify the existing headers within the previous options
object because instances of the `HttpHeaders` class are immutable.
Use the `set()` method instead.
It returns a clone of the current instance with the new changes applied.
Here's how you might update the authorization header (after the old token expired)
before making the next request.
<code-example
path="http/src/app/heroes/heroes.service.ts"
region="update-headers">
</code-example>
#### URL Parameters
Adding URL search parameters works a similar way.
Here is a `searchHeroes` method that queries for heroes whose names contain the search term.
<code-example
path="http/src/app/heroes/heroes.service.ts"
region="searchHeroes">
</code-example>
If there is a search term, the code constructs an options object with an HTML URL-encoded search parameter. If the term were "foo", the GET request URL would be `api/heroes/?name=foo`.
The `HttpParams` are immutable so you'll have to use the `set()` method to update the options.
### Debouncing requests
The sample includes an _npm package search_ feature.
When the user enters a name in a search-box, the `PackageSearchComponent` sends
a search request for a package with that name to the NPM web API.
Here's a pertinent excerpt from the template:
<code-example
path="http/src/app/package-search/package-search.component.html"
region="search"
header="app/package-search/package-search.component.html (search)">
</code-example>
The `(keyup)` event binding sends every keystroke to the component's `search()` method.
Sending a request for every keystroke could be expensive.
It's better to wait until the user stops typing and then send a request.
That's easy to implement with RxJS operators, as shown in this excerpt.
<code-example
path="http/src/app/package-search/package-search.component.ts"
region="debounce"
header="app/package-search/package-search.component.ts (excerpt)">
</code-example>
The `searchText$` is the sequence of search-box values coming from the user.
It's defined as an RxJS `Subject`, which means it is a multicasting `Observable`
that can also produce values for itself by calling `next(value)`,
as happens in the `search()` method.
Rather than forward every `searchText` value directly to the injected `PackageSearchService`,
the code in `ngOnInit()` _pipes_ search values through three operators:
1. `debounceTime(500)` - wait for the user to stop typing (1/2 second in this case).
1. `distinctUntilChanged()` - wait until the search text changes.
1. `switchMap()` - send the search request to the service.
The code sets `packages$` to this re-composed `Observable` of search results.
The template subscribes to `packages$` with the [AsyncPipe](api/common/AsyncPipe)
and displays search results as they arrive.
A search value reaches the service only if it's a new value and the user has stopped typing.
<div class="alert is-helpful">
The `withRefresh` option is explained [below](#cache-refresh).
</div>
#### _switchMap()_
The `switchMap()` operator has three important characteristics.
1. It takes a function argument that returns an `Observable`.
`PackageSearchService.search` returns an `Observable`, as other data service methods do.
2. If a previous search request is still _in-flight_ (as when the connection is poor),
it cancels that request and sends a new one.
3. It returns service responses in their original request order, even if the
server returns them out of order.
<div class="alert is-helpful">
If you think you'll reuse this debouncing logic,
consider moving it to a utility function or into the `PackageSearchService` itself.
</div>
### Intercepting requests and responses
_HTTP Interception_ is a major feature of `@angular/common/http`.
With interception, you declare _interceptors_ that inspect and transform HTTP requests from your application to the server.
@ -585,7 +642,7 @@ You may have expected the `intercept()` and `handle()` methods to return observa
Instead they return observables of `HttpEvent<any>`.
That's because interceptors work at a lower level than those `HttpClient` methods. A single HTTP request can generate multiple _events_, including upload and download progress events. The `HttpResponse` class itself is actually an event, whose type is `HttpEventType.Response`.
That's because interceptors work at a lower level than those `HttpClient` methods. A single HTTP request can generate multiple _events_, including upload and download progress events. The `HttpResponse` class itself is actually an event, whose type is `HttpEventType.HttpResponseEvent`.
Many interceptors are only concerned with the outgoing request and simply return the event stream from `next.handle()` without modifying it.
@ -788,117 +845,6 @@ the cached response first (and immediately), followed later
by the response from the server.
Subscribers see a sequence of _two_ responses.
### Configuring the request
Other aspects of an outgoing request can be configured via the options object
passed as the last argument to the `HttpClient` method.
In [Adding headers](#adding-headers), the `HeroesService` set the default headers by
passing an options object (`httpOptions`) to its save methods.
You can do more.
#### URL query strings
In this section, you will see how to use the `HttpParams` class to add URL query strings in your `HttpRequest`.
The following `searchHeroes` method queries for heroes whose names contain the search term.
Start by importing `HttpParams` class.
<code-example hideCopy language="typescript">
import {HttpParams} from "@angular/common/http";
</code-example>
<code-example
path="http/src/app/heroes/heroes.service.ts"
region="searchHeroes" linenums="false">
</code-example>
If there is a search term, the code constructs an options object with an HTML URL-encoded search parameter.
If the term were "foo", the GET request URL would be `api/heroes?name=foo`.
The `HttpParams` are immutable so you'll have to save the returned value of the `.set()` method in order to update the options.
#### Use `fromString` to create HttpParams
You can also create HTTP parameters directly from a query string by using the `fromString` variable:
<code-example hideCopy language="typescript">
const params = new HttpParams({fromString: 'name=foo'});
</code-example>
### Debouncing requests
The sample includes an _npm package search_ feature.
When the user enters a name in a search-box, the `PackageSearchComponent` sends
a search request for a package with that name to the NPM web API.
Here's a pertinent excerpt from the template:
<code-example
path="http/src/app/package-search/package-search.component.html"
region="search"
header="app/package-search/package-search.component.html (search)">
</code-example>
The `keyup` event binding sends every keystroke to the component's `search()` method.
Sending a request for every keystroke could be expensive.
It's better to wait until the user stops typing and then send a request.
That's easy to implement with RxJS operators, as shown in this excerpt.
<code-example
path="http/src/app/package-search/package-search.component.ts"
region="debounce"
header="app/package-search/package-search.component.ts (excerpt)">
</code-example>
The `searchText$` is the sequence of search-box values coming from the user.
It's defined as an RxJS `Subject`, which means it is a multicasting `Observable`
that can also emit values for itself by calling `next(value)`,
as happens in the `search()` method.
Rather than forward every `searchText` value directly to the injected `PackageSearchService`,
the code in `ngOnInit()` _pipes_ search values through three operators:
1. `debounceTime(500)` - wait for the user to stop typing (1/2 second in this case).
2. `distinctUntilChanged()` - wait until the search text changes.
3. `switchMap()` - send the search request to the service.
The code sets `packages$` to this re-composed `Observable` of search results.
The template subscribes to `packages$` with the [AsyncPipe](api/common/AsyncPipe)
and displays search results as they arrive.
A search value reaches the service only if it's a new value and the user has stopped typing.
<div class="alert is-helpful">
The `withRefresh` option is explained [below](#cache-refresh).
</div>
#### _switchMap()_
The `switchMap()` operator has three important characteristics.
1. It takes a function argument that returns an `Observable`.
`PackageSearchService.search` returns an `Observable`, as other data service methods do.
2. If a previous search request is still _in-flight_ (as when the network connection is poor),
it cancels that request and sends a new one.
3. It returns service responses in their original request order, even if the
server returns them out of order.
<div class="alert is-helpful">
If you think you'll reuse this debouncing logic,
consider moving it to a utility function or into the `PackageSearchService` itself.
</div>
### Listening to progress events
Sometimes applications transfer large amounts of data and those transfers can take a long time.
@ -949,26 +895,22 @@ by returning an observable of simulated events.
</div>
## Security: XSRF protection
## Security: XSRF Protection
[Cross-Site Request Forgery (XSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery) is an attack technique by which the attacker can trick an authenticated user into unknowingly executing actions on your website.
`HttpClient` supports a [common mechanism](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Cookie-to-Header_Token) used to prevent XSRF attacks.
When performing HTTP requests, an interceptor reads a token from a cookie, by default `XSRF-TOKEN`, and sets it as an HTTP header, `X-XSRF-TOKEN`.
Since only code that runs on your domain could read the cookie, the backend can be certain that the HTTP request came from your client application and not an attacker.
[Cross-Site Request Forgery (XSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery) is an attack technique by which the attacker can trick an authenticated user into unknowingly executing actions on your website. `HttpClient` supports a [common mechanism](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Cookie-to-Header_Token) used to prevent XSRF attacks. When performing HTTP requests, an interceptor reads a token from a cookie, by default `XSRF-TOKEN`, and sets it as an HTTP header, `X-XSRF-TOKEN`. Since only code that runs on your domain could read the cookie, the backend can be certain that the HTTP request came from your client application and not an attacker.
By default, an interceptor sends this header on all mutating requests (such as POST)
to relative URLs, but not on GET/HEAD requests or on requests with an absolute URL.
By default, an interceptor sends this header on all mutating requests (POST, etc.)
to relative URLs but not on GET/HEAD requests or
on requests with an absolute URL.
To take advantage of this, your server needs to set a token in a JavaScript readable session cookie called `XSRF-TOKEN` on either the page load or the first GET request.
On subsequent requests the server can verify that the cookie matches the `X-XSRF-TOKEN` HTTP header, and therefore be sure that only code running on your domain could have sent the request.
The token must be unique for each user and must be verifiable by the server; this prevents the client from making up its own tokens.
Set the token to a digest of your site's authentication cookie with a salt for added security.
To take advantage of this, your server needs to set a token in a JavaScript readable session cookie called `XSRF-TOKEN` on either the page load or the first GET request. On subsequent requests the server can verify that the cookie matches the `X-XSRF-TOKEN` HTTP header, and therefore be sure that only code running on your domain could have sent the request. The token must be unique for each user and must be verifiable by the server; this prevents the client from making up its own tokens. Set the token to a digest of your site's authentication
cookie with a salt for added security.
In order to prevent collisions in environments where multiple Angular apps share the same domain or subdomain, give each application a unique cookie name.
<div class="alert is-important">
*`HttpClient` supports only the client half of the XSRF protection scheme.*
*Note that `HttpClient` supports only the client half of the XSRF protection scheme.*
Your backend service must be configured to set the cookie for your page, and to verify that
the header is present on all eligible requests.
If not, Angular's default protection will be ineffective.
@ -987,13 +929,19 @@ use `HttpClientXsrfModule.withOptions()` to override the defaults.
## Testing HTTP requests
As for any external dependency, you must mock the HTTP backend so your tests can simulate interaction with a remote server.
The `@angular/common/http/testing` library makes it straightforward to set up such mocking .
Like any external dependency, the HTTP backend needs to be mocked
so your tests can simulate interaction with a remote server.
The `@angular/common/http/testing` library makes
setting up such mocking straightforward.
Angular's HTTP testing library is designed for a pattern of testing in which the app executes code and makes requests first.
The test then expects that certain requests have or have not been made,
### Mocking philosophy
Angular's HTTP testing library is designed for a pattern of testing wherein
the app executes code and makes requests first.
Then a test expects that certain requests have or have not been made,
performs assertions against those requests,
and finally provides responses by "flushing" each expected request.
and finally provide responses by "flushing" each expected request.
At the end, tests may verify that the app has made no unexpected requests.

View File

@ -707,24 +707,22 @@ the CLI configuration file, `angular.json`.
"i18nLocale": "fr",
"i18nMissingTranslation": "error",
}
}
// ...
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "my-project:build"
},
...
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "my-project:build"
"configurations": {
"production": {
"browserTarget": "my-project:build:production"
},
"configurations": {
"production": {
"browserTarget": "my-project:build:production"
},
"fr": {
"browserTarget": "my-project:build:fr"
}
"fr": {
"browserTarget": "my-project:build:fr"
}
}
}
},
```
The same configuration options can also be provided through the CLI with your existing `production` configuration.

View File

@ -2,17 +2,15 @@
Angular makes use of observables as an interface to handle a variety of common asynchronous operations. For example:
* You can define [custom events](guide/template-syntax#custom-events-with-eventemitter) that send observable output data from a child to a parent component.
* The `EventEmitter` class extends `Observable`.
* The HTTP module uses observables to handle AJAX requests and responses.
* The Router and Forms modules use observables to listen for and respond to user-input events.
## Transmitting data between components
## Event emitter
Angular provides an `EventEmitter` class that is used when publishing values from a component through the [`@Output()` decorator](guide/template-syntax#how-to-use-output).
`EventEmitter` extends [RxJS `Subject`](https://rxjs.dev/api/index/class/Subject), adding an `emit()` method so it can send arbitrary values.
When you call `emit()`, it passes the emitted value to the `next()` method of any subscribed observer.
Angular provides an `EventEmitter` class that is used when publishing values from a component through the `@Output()` decorator. `EventEmitter` extends `Observable`, adding an `emit()` method so it can send arbitrary values. When you call `emit()`, it passes the emitted value to the `next()` method of any subscribed observer.
A good example of usage can be found in the [EventEmitter](https://angular.io/api/core/EventEmitter) documentation. Here is the example component that listens for open and close events:
A good example of usage can be found on the [EventEmitter](https://angular.io/api/core/EventEmitter) documentation. Here is the example component that listens for open and close events:
`<zippy (open)="onOpen($event)" (close)="onClose($event)"></zippy>`

View File

@ -519,8 +519,7 @@ During each navigation, the `Router` emits navigation events through the `Router
<td>
An [event](api/router/NavigationCancel) triggered when navigation is canceled.
This can happen when a [Route Guard](#guards) returns false during navigation,
or redirects by returning a `UrlTree`.
This is due to a [Route Guard](#guards) returning false during navigation.
</td>
</tr>

View File

@ -1,6 +1,6 @@
# The RxJS library
Reactive programming is an asynchronous programming paradigm concerned with data streams and the propagation of change ([Wikipedia](https://en.wikipedia.org/wiki/Reactive_programming)). RxJS (Reactive Extensions for JavaScript) is a library for reactive programming using observables that makes it easier to compose asynchronous or callback-based code. See ([RxJS Docs](https://rxjs.dev/guide/overview)).
Reactive programming is an asynchronous programming paradigm concerned with data streams and the propagation of change ([Wikipedia](https://en.wikipedia.org/wiki/Reactive_programming)). RxJS (Reactive Extensions for JavaScript) is a library for reactive programming using observables that makes it easier to compose asynchronous or callback-based code ([RxJS Docs](http://reactivex.io/rxjs/)).
RxJS provides an implementation of the `Observable` type, which is needed until the type becomes part of the language and until browsers support it. The library also provides utility functions for creating and working with observables. These utility functions can be used for:
@ -45,7 +45,7 @@ The `pipe()` function is also a method on the RxJS `Observable`, so you use this
### Common operators
RxJS provides many operators, but only a handful are used frequently. For a list of operators and usage samples, visit the [RxJS API Documentation](https://rxjs.dev/api).
RxJS provides many operators, but only a handful are used frequently. For a list of operators and usage samples, visit the [RxJS API Documentation](https://rxjs-dev.firebaseapp.com/api).
<div class="alert is-helpful">
Note that, for Angular apps, we prefer combining operators with pipes, rather than chaining. Chaining is used in many RxJS examples.

View File

@ -137,9 +137,8 @@ export interface DataGroup {
Similar to `assetGroups`, every data group has a `name` which uniquely identifies it.
### `urls`
A list of URL patterns. URLs that match these patterns are cached according to this data group's policy. Only non-mutating requests (GET and HEAD) are cached.
* Negative glob patterns are not supported.
* `?` is matched literally; that is, it matches *only* the character `?`.
A list of URL patterns. URLs that match these patterns will be cached according to this data group's policy.<br>
_(Negative glob patterns are not supported and `?` will be matched literally; i.e. it will not match any character other than `?`.)_
### `version`
Occasionally APIs change formats in a way that is not backward-compatible. A new version of the app may not be compatible with the old API format and thus may not be compatible with existing cached resources from that API.

View File

@ -31,54 +31,22 @@ Installing the Angular service worker is as simple as including an `NgModule`. I
## Prerequisites
To make use of all the features of Angular service worker, use the latest versions of Angular and the Angular CLI.
Your application must run in a web browser that supports service workers. Currently, service workers are supported in the latest versions of Chrome, Firefox, Edge, Safari, Opera, UC Browser (Android version) and Samsung Internet. Browsers like IE and Opera Mini do not provide the support. To learn more about other browsers that are service worker ready, see the [Can I Use](https://caniuse.com/#feat=serviceworkers) page and [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API).
In order for service workers to be registered, the app must be accessed over HTTPS, not HTTP.
Browsers ignore service workers on pages that are served over an insecure connection.
The reason is that service workers are quite powerful, so extra care needs to be taken to ensure the service worker script has not been tampered with.
There is one exception to this rule: to make local development easier, browsers do _not_ require a secure connection when accessing an app on `localhost`.
### Browser support
To benefit from the Angular service worker, your app must run in a web browser that supports service workers in general.
Currently, service workers are supported in the latest versions of Chrome, Firefox, Edge, Safari, Opera, UC Browser (Android version) and Samsung Internet.
Browsers like IE and Opera Mini do not support service workers.
If the user is accessing your app via a browser that does not support service workers, the service worker is not registered and related behavior such as offline cache management and push notifications does not happen.
More specifically:
* The browser does not download the service worker script and `ngsw.json` manifest file.
* Active attempts to interact with the service worker, such as calling `SwUpdate.checkForUpdate()`, return rejected promises.
* The observable events of related services, such as `SwUpdate.available`, are not triggered.
It is highly recommended that you ensure that your app works even without service worker support in the browser.
Although an unsupported browser ignores service worker caching, it will still report errors if the app attempts to interact with the service worker.
For example, calling `SwUpdate.checkForUpdate()` will return rejected promises.
To avoid such an error, you can check whether the Angular service worker is enabled using `SwUpdate.isEnabled()`.
To learn more about other browsers that are service worker ready, see the [Can I Use](https://caniuse.com/#feat=serviceworkers) page and [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API).
In addition, in order for service workers to be registered, the app must be accessed over HTTPS, not HTTP. Browsers will ignore service workers on pages that are served over an insecure connection. The reason is that service workers are quite powerful, so extra care needs to be taken to ensure the service worker script has not been tampered with.
There is one exception to this rule: To make local development easier, browsers do _not_ require a secure connection when accessing an app on `localhost`.
## Related resources
The rest of the articles in this section specifically address the Angular implementation of service workers.
* [App Shell](guide/app-shell)
* [Service Worker Communication](guide/service-worker-communications)
* [Service Worker in Production](guide/service-worker-devops)
* [Service Worker Configuration](guide/service-worker-config)
For more information about service workers in general, see [Service Workers: an Introduction](https://developers.google.com/web/fundamentals/primers/service-workers/).
For more information about browser support, see the [browser support](https://developers.google.com/web/fundamentals/primers/service-workers/#browser_support) section of [Service Workers: an Introduction](https://developers.google.com/web/fundamentals/primers/service-workers/), Jake Archibald's [Is Serviceworker ready?](https://jakearchibald.github.io/isserviceworkerready/), and
[Can I Use](http://caniuse.com/#feat=serviceworkers).
For additional recommendations and examples, see:
The remainder of this Angular documentation specifically addresses the Angular implementation of service workers.
* [Precaching with Angular Service Worker](https://web.dev/precaching-with-the-angular-service-worker/)
* [Creating a PWA with Angular CLI](https://web.dev/creating-pwa-with-angular-cli/)
## More on Angular service workers
## Next steps
To begin using Angular service workers, see [Getting Started with service workers](guide/service-worker-getting-started).
You may also be interested in the following:
* [Getting Started with service workers](guide/service-worker-getting-started).

View File

@ -1,15 +1,15 @@
# Setup for Upgrading from AngularJS
<!--
<!--
Question: Can we remove this file and instead direct readers to https://github.com/angular/quickstart/blob/master/README.md
-->
<div class="alert is-critical">
**Audience:** Use this guide **only** in the context of [Upgrading from AngularJS](guide/upgrade "Upgrading from AngularJS to Angular") or [Upgrading for Performance](guide/upgrade-performance "Upgrading for Performance").
Those Upgrade guides refer to this Setup guide for information about using the [deprecated QuickStart GitHub repository](https://github.com/angular/quickstart "Deprecated Angular QuickStart GitHub repository"), which was created prior to the current Angular [CLI](cli "CLI Overview").
**Audience:** Use this guide **only** in the context of [Upgrading from AngularJS](guide/upgrade "Upgrading from AngularJS to Angular") or [Upgrading for Performance](guide/upgrade-performance "Upgrading for Performance").
Those Upgrade guides refer to this Setup guide for information about using the [deprecated QuickStart GitHub repository](https://github.com/angular/quickstart "Deprecated Angular QuickStart GitHub repository"), which was created prior to the current Angular [CLI](cli "CLI Overview").
**For all other scenarios,** see the current instructions in [Setting up the Local Environment and Workspace](guide/setup-local "Setting up for Local Development").
**For all other scenarios,** see the current instructions in [Local Environment Setup](guide/setup-local "Setting up for Local Development").
</div>
@ -139,11 +139,6 @@ Consequently, there are many files in the project folder on your machine,
most of which you can [learn about later](guide/file-structure).
<div class="alert is-helpful">
**Reminder:** The "QuickStart seed" example was created prior to the Angular CLI, so there are some differences between what is described here and an Angular CLI application.
</div>
{@a app-files}
@ -270,8 +265,8 @@ The following are all in `src/`
Defines `AppModule`, the [root module](guide/bootstrapping "AppModule: the root module") that tells Angular how to assemble the application.
When initially created, it declares only the `AppComponent`.
Over time, you add more components to declare.
Right now it declares only the `AppComponent`.
Soon there will be more components to declare.
</td>
</tr>
@ -289,8 +284,8 @@ The following are all in `src/`
[bootstraps](guide/bootstrapping)
the application's main module (`AppModule`) to run in the browser.
The JIT compiler is a reasonable choice during the development of most projects and
it's the only viable choice for a sample running in a _live-coding_ environment such as Stackblitz.
Alternative [compilation](guide/aot-compiler), [build](guide/build), and [deployment](guide/deployment) options are available.
it's the only viable choice for a sample running in a _live-coding_ environment like Stackblitz.
You'll learn about alternative compiling and [deployment](guide/deployment) options later in the documentation.
</td>
@ -299,6 +294,43 @@ The following are all in `src/`
</table>
<div class="alert is-helpful">
### Next Step
If you're new to Angular, we recommend you follow the [tutorial](tutorial "Tour of Heroes tutorial").
</div>
<br></br><br></br>
{@a install-prerequisites}
## Appendix: Node.js and npm
[Node.js](https://nodejs.org/en/) and the [npm](https://www.npmjs.com/) package manager are essential to modern web development with Angular and other platforms.
Node.js powers client development and build tools.
The _npm_ package manager, which is itself a _Node.js_ application, installs JavaScript libraries.
<a href="https://docs.npmjs.com/getting-started/installing-node" target="_blank" title="Installing Node.js and updating npm">
Get them now</a> if they're not already installed on your machine.
**Verify that you are running Node.js `v8.x` or higher and npm `5.x` or higher**
by running the commands `node -v` and `npm -v` in a terminal/console window.
Older versions produce errors.
We recommend [nvm](https://github.com/creationix/nvm) for managing multiple versions of Node.js and npm.
You may need [nvm](https://github.com/creationix/nvm) if you already have projects running on your machine that use other versions of Node.js and npm.
## Appendix: Develop locally with IE
If you develop angular locally with `ng serve`, a `websocket` connection is set up automatically between browser and local dev server, so when your code changes, the browser can automatically refresh.

View File

@ -1,6 +1,6 @@
# Singleton services
A singleton service is a service for which only one instance exists in an app.
A singleton service is a service for which only once instance exists in an app.
For a sample app using the app-wide singleton service that this page describes, see the
<live-example name="ngmodules"></live-example> showcasing all the documented features of NgModules.

View File

@ -927,7 +927,7 @@ As always, strive for consistency.
<div class="s-rule do">
**Do** use a custom prefix for a component selector.
For example, the prefix `toh` represents **T**our **o**f **H**eroes and the prefix `admin` represents an admin feature area.
For example, the prefix `toh` represents from **T**our **o**f **H**eroes and the prefix `admin` represents an admin feature area.
</div>
@ -1080,10 +1080,6 @@ For example, the prefix `toh` represents **T**our **o**f **H**eroes and the pref
**Do** use consistent names for all pipes, named after their feature.
The pipe class name should use [UpperCamelCase](guide/glossary#case-types)
(the general convention for class names),
and the corresponding `name` string should use *lowerCamelCase*.
The `name` string cannot use hyphens ("dash-case" or "kebab-case").
</div>
@ -1674,7 +1670,7 @@ keep the **F**lattest structure you can, and
**Why?** LIFT provides a consistent structure that scales well, is modular, and makes it easier to increase developer efficiency by finding code quickly.
**Why?** LIFT Provides a consistent structure that scales well, is modular, and makes it easier to increase developer efficiency by finding code quickly.
To confirm your intuition about a particular structure, ask:
_can I quickly open and start work in all of the related files for this feature_?
@ -1694,7 +1690,7 @@ _can I quickly open and start work in all of the related files for this feature_
**Do** make locating code intuitive, simple, and fast.
**Do** make locating code intuitive, simple and fast.
</div>

View File

@ -6,7 +6,8 @@
h4 .syntax { font-size: 100%; }
</style>
The Angular application manages what the user sees and can do, achieving this through the interaction of a component class instance (the *component*) and its user-facing template.
The Angular application manages what the user sees and can do, achieving this through the interaction of a
component class instance (the *component*) and its user-facing template.
You may be familiar with the component/template duality from your experience with model-view-controller (MVC) or model-view-viewmodel (MVVM).
In Angular, the component plays the part of the controller/viewmodel, and the template represents the view.
@ -84,10 +85,12 @@ converts the expression results to strings, and links them with neighboring lite
it assigns this composite interpolated result to an **element or directive property**.
You appear to be inserting the result between element tags and assigning it to attributes.
However, interpolation is a special syntax that Angular converts into a *property binding*.
<div class="alert is-helpful">
However, interpolation is a special syntax that Angular converts into a
property binding.
If you'd like to use something other than `{{` and `}}`, you can
configure the interpolation delimiter via the
[interpolation](api/core/Component#interpolation)
@ -121,8 +124,8 @@ including:
Other notable differences from JavaScript syntax include:
* No support for the bitwise operators such as `|` and `&`
* New [template expression operators](guide/template-syntax#expression-operators), such as `|`, `?.` and `!`
* New template expression operators, such as `|`, `?.` and `!`
<!-- link to: guide/template-syntax#expression-operators -->
### Expression context
@ -168,29 +171,12 @@ members of the expression context.
When using template expressions follow these guidelines:
* [Simplicity](guide/template-syntax#simplicity)
* [Quick execution](guide/template-syntax#quick-execution)
* [No visible side effects](guide/template-syntax#no-visible-side-effects)
* [Quick execution](guide/template-syntax#quick-execution)
* [Simplicity](guide/template-syntax#simplicity)
#### Simplicity
Although it's possible to write complex template expressions, it's a better
practice to avoid them.
A property name or method call should be the norm, but an occasional Boolean negation, `!`, is OK.
Otherwise, confine application and business logic to the component,
where it is easier to develop and test.
#### Quick execution
Angular executes template expressions after every change detection cycle.
Change detection cycles are triggered by many asynchronous activities such as
promise resolutions, HTTP results, timer events, key presses and mouse moves.
Expressions should finish quickly or the user experience may drag, especially on slower devices.
Consider caching values when their computation is expensive.
#### No visible side effects
### No visible side effects
A template expression should not change any application state other than the value of the
target property.
@ -201,18 +187,40 @@ The view should be stable throughout a single rendering pass.
An [idempotent](https://en.wikipedia.org/wiki/Idempotence) expression is ideal because
it is free of side effects and improves Angular's change detection performance.
In Angular terms, an idempotent expression always returns
*exactly the same thing* until one of its dependent values changes.
*exactly the same thing* until
one of its dependent values changes.
Dependent values should not change during a single turn of the event loop.
If an idempotent expression returns a string or a number, it returns the same string or number when called twice in a row. If the expression returns an object, including an `array`, it returns the same object *reference* when called twice in a row.
<div class="alert is-helpful">
There is one exception to this behavior that applies to `*ngFor`. `*ngFor` has `trackBy` functionality that can deal with referential inequality of objects when iterating over them. See [*ngFor with `trackBy`](guide/template-syntax#ngfor-with-trackby) for details.
There is one exception to this behavior that applies to `*ngFor`. `*ngFor` has `trackBy` functionality that can deal with referential inequality of objects that when iterating over them.
For more information, see the [*ngFor with `trackBy`](guide/template-syntax#ngfor-with-trackby) section of this guide.
</div>
### Quick execution
Angular executes template expressions after every change detection cycle.
Change detection cycles are triggered by many asynchronous activities such as
promise resolutions, HTTP results, timer events, key presses and mouse moves.
Expressions should finish quickly or the user experience may drag, especially on slower devices.
Consider caching values when their computation is expensive.
### Simplicity
Although it's possible to write complex template expressions, it's a better
practice to avoid them.
A property name or method call should be the norm, but an occasional Boolean negation, `!`, is OK.
Otherwise, confine application and business logic to the component,
where it is easier to develop and test.
<!-- end of Interpolation doc -->
<hr/>
@ -270,15 +278,19 @@ Template context names take precedence over component context names.
In `deleteHero(hero)` above, the `hero` is the template input variable,
not the component's `hero` property.
### Statement guidelines
Template statements cannot refer to anything in the global namespace. They
can't refer to `window` or `document`.
They can't call `console.log` or `Math.max`.
### Statement guidelines
As with expressions, avoid writing complex template statements.
A method call or simple property assignment should be the norm.
Now that you have a feel for template expressions and statements,
you're ready to learn about the varieties of data binding syntax beyond interpolation.
<hr/>
{@a binding-syntax}
@ -384,7 +396,7 @@ Every public member of a **source** directive is automatically available for bin
You don't have to do anything special to access a directive member in a template expression or statement.
### Data-binding and HTML
## 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.
@ -403,10 +415,10 @@ Notice that the binding is to the `disabled` property of the button's DOM elemen
**not** the attribute. This applies to data-binding in general. Data-binding works with *properties* of DOM elements, components, and directives, not HTML *attributes*.
### 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.**
how Angular binding works. **Attributes are defined by HTML. Properties are accessed from DOM, or the Document Object Model, nodes.**
* A few HTML attributes have 1:1 mapping to properties; for example, `id`.
@ -414,30 +426,31 @@ how Angular binding works. **Attributes are defined by HTML. Properties are acce
* 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.
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.**
<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.
There is, of course, an exception to this rule because attributes can be changed by `setAttribute()`, which will re-initialize corresponding DOM properties again.
</div>
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`.
**The HTML attribute and the DOM property are not the same thing, even when they have the same name.**
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>`
### 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".
@ -453,7 +466,7 @@ The HTML attribute `value` specifies the *initial* value; the DOM `value` proper
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
### 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.
@ -466,7 +479,8 @@ so the button is disabled.
<button disabled>Test Button</button>
```
Adding and removing the `disabled` *attribute* disables and enables the 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>`.
@ -474,7 +488,7 @@ 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:
**Note:** 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">
@ -485,15 +499,26 @@ Generally, use property binding over attribute binding as it is more intuitive (
</div>
**The HTML attribute and the DOM property are different things, even when they have the same name.**
**Template binding works with *properties* and *events*, not *attributes*.**
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
### Angular and attributes
In Angular, the only role of attributes is to initialize element and directive state.
When you write a data-binding, you're dealing exclusively with properties and events of the target object.
## Binding 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.
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:
<style>
td, th {vertical-align: top}
@ -653,9 +678,10 @@ for parent and child components to communicate:
<code-example path="property-binding/src/app/app.component.html" region="model-property-binding" header="src/app/app.component.html"></code-example>
### Binding targets
### Binding target
An element property between enclosing square brackets identifies the target property.
An element property between enclosing square brackets identifies
the target property.
The target property in the following code is the image element's `src` property.
<code-example path="property-binding/src/app/app.component.html" region="property-binding" header="src/app/app.component.html"></code-example>
@ -821,10 +847,10 @@ property binding but both approaches render the
content harmlessly. The following is the browser output
of the `evilTitle` examples.
<code-example language="bash">
```
"Template <script>alert("evil never sleeps")</script> Syntax" is the interpolated evil title.
"Template alert("evil never sleeps")Syntax" is the property bound evil title.
</code-example>
```
<hr/>
{@a other-bindings}
@ -872,7 +898,7 @@ If you wrote something like this:
You'd get this error:
<code-example language="bash">
<code-example format="nocode">
Template parse errors:
Can't bind to 'colspan' since it isn't a known native property
</code-example>
@ -942,8 +968,8 @@ The following example conditionally sets the font size in “em” and “%”
<code-example path="attribute-binding/src/app/app.component.html" region="style-binding-condition" header="src/app/app.component.html"></code-example>
This technique is suitable for setting a single style, but consider
the [`NgStyle`](guide/template-syntax#ngStyle) directive when setting several inline styles at the same time.
**This technique is suitable for setting a single style, but consider
the [`NgStyle`](guide/template-syntax#ngStyle) directive when setting several inline styles at the same time.**
<div class="alert is-helpful">
@ -1130,7 +1156,7 @@ Angular desugars the `SizerComponent` binding into this:
The `$event` variable contains the payload of the `SizerComponent.sizeChange` event.
Angular assigns the `$event` value to the `AppComponent.fontSizePx` when the user clicks the buttons.
### Two-way binding in forms
## Two-way binding in forms
The two-way binding syntax is a great convenience compared to
separate property and event bindings. It would be convenient to
@ -1391,7 +1417,7 @@ efficient alternative to showing/hiding.
<div class="alert is-helpful">
For more information on `NgIf` and `ngIfElse`, see the [API documentation about NgIf](api/common/NgIf).
**Note:** For more information on `NgIf` and `ngIfElse`, see the [API documentation about NgIf](api/common/NgIf).
</div>
@ -1422,20 +1448,26 @@ See also the
`NgFor` is a repeater directive&mdash;a way to present a list of items.
You define a block of HTML that defines how a single item should be displayed
and then you tell Angular to use that block as a template for rendering each item in the list.
The text assigned to `*ngFor` is the instruction that guides the repeater process.
The following example shows `NgFor` applied to a simple `<div>`. (Don't forget the asterisk (`*`) in front of `ngFor`.)
Here is an example of `NgFor` applied to a simple `<div>`:
<code-example path="built-in-directives/src/app/app.component.html" region="NgFor-1" header="src/app/app.component.html"></code-example>
You can also apply an `NgFor` to a component element, as in the following example.
You can also apply an `NgFor` to a component element, as in this example:
<code-example path="built-in-directives/src/app/app.component.html" region="NgFor-2" header="src/app/app.component.html"></code-example>
<div class="alert is-critical">
Don't forget the asterisk (`*`) in front of `ngFor`.
</div>
The text assigned to `*ngFor` is the instruction that guides the repeater process.
{@a microsyntax}
<div class="callout is-critical">
<header>*ngFor microsyntax</header>
#### `*ngFor` microsyntax
The string assigned to `*ngFor` is not a [template expression](guide/template-syntax#template-expressions). Rather,
it's a *microsyntax*&mdash;a little language of its own that Angular interprets.
@ -1447,15 +1479,15 @@ make it available to the templated HTML for each iteration.*
Angular translates this instruction into an `<ng-template>` around the host element,
then uses this template repeatedly to create a new set of elements and bindings for each `item`
in the list.
For more information about microsyntax, see the [Structural Directives](guide/structural-directives#microsyntax) guide.
</div>
For more information about microsyntax, see the [Structural Directives](guide/structural-directives#microsyntax) guide.
{@a template-input-variable}
{@a template-input-variables}
#### Template input variables
The `let` keyword before `item` creates a template input variable called `item`.
@ -1898,7 +1930,7 @@ in the child template UI.
Now, in order to see the `@Output()` working, add the following to the parent's template:
```html
```
<ul>
<li *ngFor="let item of items">{{item}}</li>
</ul>
@ -1957,7 +1989,7 @@ properties do indeed exist, double check
that your properties are annotated with `@Input()` / `@Output()` or that you've declared
them in an `inputs`/`outputs` array:
<code-example language="bash">
<code-example language="sh" class="code-shell">
Uncaught Error: Template parse errors:
Can't bind to 'item' since it isn't a known property of 'app-item-detail'
</code-example>
@ -2035,7 +2067,7 @@ The generated output would look something like this:
<div class="alert is-helpful">
The pipe operator has a higher precedence than the ternary operator (`?:`),
**Note**: The pipe operator has a higher precedence than the ternary operator (`?:`),
which means `a ? b : c | x` is parsed as `a ? b : (c | x)`.
Nevertheless, for a number of reasons,
the pipe operator cannot be used without parentheses in the first and second operands of `?:`.
@ -2065,7 +2097,7 @@ Consider the next example, with a `nullItem`.
Since there is no safe navigation operator and `nullItem` is `null`, JavaScript and Angular would throw a `null` reference error and break the rendering process of Angular:
<code-example language="bash">
<code-example format="nocode">
TypeError: Cannot read property 'name' of null.
</code-example>
@ -2119,9 +2151,9 @@ The non-null assertion operator, `!`, is optional with the exception that you mu
### The `$any()` type cast function
Sometimes a binding expression triggers a type error during [AOT compilation](guide/aot-compiler) and it is not possible or difficult to fully specify the type.
To silence the error, you can use the `$any()` cast function to cast
the expression to the [`any` type](http://www.typescriptlang.org/docs/handbook/basic-types.html#any) as in the following example:
Sometimes a binding expression triggers a type error during [AOT compilation](guide/aot-compiler) and it is not possible or difficult
to fully specify the type. To silence the error, you can use the `$any()` cast function to cast
the expression to [the `any` type](http://www.typescriptlang.org/docs/handbook/basic-types.html#any) as in the following example:
<code-example path="built-in-template-functions/src/app/app.component.html" region="any-type-cast-function-1" header="src/app/app.component.html"></code-example>
@ -2151,7 +2183,7 @@ Refer to the sample code snippet below for a syntax example:
<code-example path="template-syntax/src/app/svg.component.ts" header="src/app/svg.component.ts"></code-example>
Add the following code to your `svg.component.svg` file:
Add the below code to your `svg.component.svg` file:
<code-example path="template-syntax/src/app/svg.component.svg" header="src/app/svg.component.svg"></code-example>

View File

@ -6,14 +6,14 @@ This guide offers tips and techniques for unit and integration testing Angular a
The guide presents tests of a sample application created with the [Angular CLI](cli). This sample application is much like the one created in the [_Tour of Heroes_ tutorial](tutorial).
The sample application and all tests in this guide are available for inspection and experimentation:
- <live-example embedded-style noDownload>Sample app</live-example>
- <live-example stackblitz="specs" noDownload>Tests</live-example>
- <live-example embedded-style>Sample app</live-example>
- <live-example stackblitz="specs">Tests</live-example>
<hr>
## Setup
The Angular CLI downloads and installs everything you need to test an Angular application with the [Jasmine test framework](https://jasmine.github.io/).
The Angular CLI downloads and install everything you need to test an Angular application with the [Jasmine test framework](https://jasmine.github.io/).
The project you create with the CLI is immediately ready to test.
Just run the [`ng test`](cli/test) CLI command:
@ -116,7 +116,7 @@ jobs:
build:
working_directory: ~/my-project
docker:
- image: circleci/node:10-browsers
- image: circleci/node:8-browsers
steps:
- checkout
- restore_cache:
@ -1212,8 +1212,7 @@ value becomes available. The test must become _asynchronous_.
#### Async test with _fakeAsync()_
To use `fakeAsync()` functionality, you must import `zone.js/dist/zone-testing` in your test setup file.
If you created your project with the Angular CLI, `zone-testing` is already imported in `src/test.ts`.
To use `fakeAsync()` functionality, you need to import `zone-testing`, for details, please read [setup guide](guide/setup#appendix-test-using-fakeasyncasync).
The following test confirms the expected behavior when the service returns an `ErrorObservable`.
@ -1232,13 +1231,6 @@ The `fakeAsync()` function enables a linear coding style by running the test bod
The test body appears to be synchronous.
There is no nested syntax (like a `Promise.then()`) to disrupt the flow of control.
<div class="alert is-helpful">
Limitation: The `fakeAsync()` function won't work if the test body makes an `XMLHttpRequest` (XHR) call.
XHR calls within a test are rare, but if you need to call XHR, see [`async()`](#async), below.
</div>
{@a tick}
#### The _tick()_ function
@ -1414,13 +1406,13 @@ Then you can assert that the quote element displays the expected text.
#### Async test with _async()_
To use `async()` functionality, you must import `zone.js/dist/zone-testing` in your test setup file.
If you created your project with the Angular CLI, `zone-testing` is already imported in `src/test.ts`.
To use `async()` functionality, you need to import `zone-testing`, for details, please read [setup guide](guide/setup#appendix-test-using-fakeasyncasync).
The `fakeAsync()` utility function has a few limitations.
In particular, it won't work if the test body makes an `XMLHttpRequest` (XHR) call.
XHR calls within a test are rare so you can generally stick with [`fakeAsync()`](#fake-async).
But if you ever do need to call `XMLHttpRequest`, you'll want to know about `async()`.
In particular, it won't work if the test body makes an `XHR` call.
`XHR` calls within a test are rare so you can generally stick with `fakeAsync()`.
But if you ever do need to call `XHR`, you'll want to know about `async()`.
<div class="alert is-helpful">

View File

@ -28,34 +28,9 @@ For details about `tsconfig.json`, see the official
</div>
The initial `tsconfig.json` for an Angular app typically looks like this example:
<code-example lang="json" header="tsconfig.json" linenums="false">
{
"compileOnSave": false,
"compilerOptions": {
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"module": "es2015",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
]
}
</code-example>
The [Setup](guide/setup-local) guide uses the following `tsconfig.json`:
<code-example path="getting-started/tsconfig.0.json" header="tsconfig.json"></code-example>
This file contains options and flags that are essential for Angular applications.

Some files were not shown because too many files have changed in this diff Show More