Compare commits

..

200 Commits

Author SHA1 Message Date
13d176302b release: cut the v10.0.4 release 2020-07-15 10:56:55 -07:00
e3b801053a fix(ngcc): report a warning if ngcc tries to use a solution-style tsconfig (#38003)
In CLI v10 there was a move to use the new solution-style tsconfig
which became available in TS 3.9.

The result of this is that the standard tsconfig.json no longer contains
important information such as "paths" mappings, which ngcc might need to
correctly compute dependencies.

ngcc (and ngc and tsc) infer the path to tsconfig.json if not given an
explicit tsconfig file-path. But now that means it infers the solution
tsconfig rather than one that contains the useful information it used to
get.

This commit logs a warning in this case to inform the developer
that they might not have meant to load this tsconfig and offer
alternative options.

Fixes #36386

PR Close #38003
2020-07-14 13:21:32 -07:00
6626739798 docs(core): fixes minor typo in initNgDevMode function docs (#38042)
PR Close #38042
2020-07-14 13:17:33 -07:00
396033da80 refactor(forms): remove unnecessary ! operators from validators (#36805)
When we added the strict null checks, the lexer had some `!` operators added to prevent the compilation from failing.

See #24571

PR Close #36805
2020-07-14 11:01:54 -07:00
02ee9d2938 docs(forms): Fix typos in template-driven forms tutorial (#37933)
Fix two typos in the 'Building a template-driven form` that caused the guide to not be displayed correctly.

PR Close #37933
2020-07-14 11:01:30 -07:00
a4c7f183d7 docs(forms): Minor fix in forms overview guide (#37933)
Remove an article from the `Data flow in forms` section of the forms overview guide. The use of `the` and `a` together
is not syntactically correct.

PR Close #37933
2020-07-14 11:01:30 -07:00
d690eec88f docs(router): fix typo in "spotlight on pathmatch" (#38039)
https://angular.io/guide/router-tutorial-toh#pathmatch

PR Close #38039
2020-07-14 09:20:19 -07:00
10e4dfae27 docs(router): fix typo in https://angular.io/guide/router#activated-route (#38034)
In angular.io, it linked to the wrong part of the page. https://angular.io/guide/router#activated-route

PR Close #38034
2020-07-14 09:10:26 -07:00
f8d948b46b docs: fix live examples in testing guides (#38038)
In #37957, parts of the testing guide were broken out into separate
guides. As part of that work, the `<live-example>` tags were also copied
to the new guides. These `<live-example>` tags did not specify the
targeted example project via the `name` attribute, thus they were
implicitly targeting the example with the same name as the guide they
were in. See the [Docs style guide][1] for more info.

However, there is only one example project (`testing/`) and all
`<live-example>` tags were supposed to target that. This worked fine on
the `testing.md` guide, but it broke on other guides (which tried to
target non-existing example projects based on their names).

This commit fixes it by explicitly specifying which example is targeted
by the `<live-example>` tags. It also removes the `embedded-style`
attribute that has no effect.

[1]: https://angular.io/guide/docs-style-guide#live-examples

Fixes #38036

PR Close #38038
2020-07-14 09:10:01 -07:00
9cf78d5701 docs(core): Fixed typo in Type JSdoc (#37930)
Updated comment doc in packages/core/src/interface/type.ts

PR Close #37930
2020-07-13 14:30:56 -07:00
45471dbbd6 refactor(dev-infra): allow for consumption with rules_nodejs v2.0.0 (#37968)
With `rules_nodejs` v2.0.0 being in RC phase currently, we should
make sure that the package is compatible so that we can use it
in the components repo in combination with rules_nodejs v2.0.0.

In v2.0.0 of the NodeJS rules, Bazel workspaces are recommended
to no longer be symlinked under a separate repository. Instead,
bazel rules and targets should be accessed directly from the
user-selected NPM repository. Usually `@npm`, so that the import
changes to `@npm//@angular/dev-infra-private/<..>`.

PR Close #37968
2020-07-13 14:18:23 -07:00
387e8386d1 fix(language-service): remove completion for string (#37983)
If the user inputs a string(e.g. `<div [ngClass]="'str~{cursor}'"></div>`), the completion is useless.

PR Close #37983
2020-07-13 14:16:56 -07:00
eec6e4be7a docs: fixed typo in https://angular.io/guide/glossary (#36220)
PR Close #36220
2020-07-13 14:10:07 -07:00
b711f25892 docs(router): fix typo 'containa' to 'contains' (#36764)
Closes #36763

PR Close #36764
2020-07-13 14:09:33 -07:00
788f0453f7 docs: Add Scully to resources.json (#37678)
Add Scully to the resource page by adding it to the "Tooling" subcategory in resources.json file

PR Close #37678
2020-07-13 14:08:41 -07:00
45b1775a53 docs: remove Markus Padourek from angular collaborators (#37962)
This person was never onboarded

PR Close #37962
2020-07-13 14:08:14 -07:00
53e4ff72d2 docs: fix typo in router.md (#37227)
This commit fixes a typo in the router documentation. "Benfits of a routing module" => "Benefits of a routing module"

PR Close #37227
2020-07-13 09:27:29 -07:00
7813a7d129 docs(http): Remove extra semicolons in the http guide (#37228)
An extra semicolon in searchHeroes function was removed in the http guide
found in aio/content/guide/http.md

docs(http): Remove extra semicolon in a code example found in the http guide

Removed extra semicolon in handleError function in the file located at
aio/content/examples/http/src/app/config/config.service.ts, which serves
as a source of code examples for the http guide.

Replace a comma for a dot in the comment at line 79 to ensure consistency
with the rest of the document.

Capitalized and added a dot at the end of the comment at line 84 to
ensure consistency with the other comments.

PR Close #37228
2020-07-13 09:25:20 -07:00
c0ced6dc2d build(docs-infra): ensure the correct files are in the i18n example (#37947)
The Stackblitz and zip-file include `doc-files` unnecssarily and are missing
the locale files. This commit updates the `stackblitz.json` to fix this.

PR Close #37947
2020-07-13 09:24:34 -07:00
8157ee87b0 build(docs-infra): remove unnecessary zipper.json file (#37947)
The `zipper.json` file is only needed if the example does not
have a `stackblitz.json` file, which this (i18n) example does.

Moreover, it appears that having both can cause the generated
zip file to be corrupted and not unzippable.

Fixes #37849

PR Close #37947
2020-07-13 09:24:34 -07:00
ab051aba27 docs: reformat and update CONTRIBUTING.md (#37951)
This doc is very old and rusty. I'm reformatting it to follow the one-setence-per-line rule.
I also updated a few sections, since they were either poorly written or obsolete.

PR Close #37951
2020-07-13 09:23:04 -07:00
5a61ef0c49 build: add .gitmessage file with commit message template (#37951)
Git provides a way to create a commit message template via the `.gitmessage` file.

Introduce an Angular-specific .gitmessage template based on the original Commit Message Guidelines.
https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-commit-message-guidelines

If this template workflow is proven in practice, we can move the commit message guidelines into the
.gitmessage file to prevent duplication of the content.

This change is a follow up on #37949 and is inspired by info found in the following blog post:
https://thoughtbot.com/blog/better-commit-messages-with-a-gitmessage-template

PR Close #37951
2020-07-13 09:23:04 -07:00
c451dbda9f build: adding shared .ng-dev/gitconfig file for convenience and consistent git config (#37951)
This file is inert unless it's explicitly included into the local git config via:

```
git config --add include.path '../.ng-dev/gitconfig'
```

Calling that command will append the following into `.git/config` of the current git workspace
(i.e. $GIT_DIR, typically `angular/.git/config`):

```
[include]
	path = ../.ng-dev/gitconfig
```

I'm intentionally keeping the config inert for now until we prove that this is a good idea.

Eventually we could roll this change out to all the contributors via an npm post-install script.

PR Close #37951
2020-07-13 09:23:04 -07:00
0d38288078 docs: Move router tutorial (toh) from router.md to new file (#37979)
In an effort to make angular documentation easier for users to read,
we are moving the router tutorial currently in router.md to a new file.
To support this change, we have done the following:

* Update files to fix any broken links caused by moving the file
* Updated the new file to follow tutorial guidelines
* Add the new file to the table of  contents under, Tutorials.

PR Close #37979
2020-07-10 15:04:56 -07:00
2e9b953e9d docs(router): fix routerLink docs (#37997)
The current content for the routerLink commands input does not make it to aio.
fixes #35414

PR Close #37997
2020-07-10 11:24:29 -07:00
a94383f168 fix(compiler): check more cases for pipe usage inside host bindings (#37883)
Builds on top of #34655 to support more cases that could be using a pipe inside host bindings (e.g. ternary expressions or function calls).

Fixes #37610.

PR Close #37883
2020-07-10 11:00:21 -07:00
75c40ddd61 feat(dev-infra): commit message validation should skip lines consisting of URLs (#37890)
The dev-infra commit message validation optionally can check for lines
to not exceed a given amount of characters. This is desired for most
commit messages, but sometimes not actionable if a long URL is inserted
into the commit message. With this commit, we skip the max line length
check for lines that start with an URL.

PR Close #37890
2020-07-10 10:59:29 -07:00
86a75a0670 build: split dev-infra configuration into individual files (#37890)
Splits the dev-infra configurations into individual files inside the
`.ng-dev/` folder. This helps with clarity as there is no single
configuration file that becomes extremely large and difficult to
maintain.

Additionally, more explicit configuration types are now used. This
fixed the max-line length setting for commit message validation.
This option is currently named incorrectly and a noop.

PR Close #37890
2020-07-10 10:59:29 -07:00
c776825fdd fix(dev-infra): include bazel utility files in npm package (#37891)
We recently added a new folder for common bazel utilities
to `dev-infra`. The `ng_rollup_bundle` rule relies on an
utility that is provided by this `bazel/` folder.

Unfortunately though it looks like this folder is currently
not included in the NPM package, so that the `ng_rollup_bundle`
rule does not work as expected. This commit fixes that by
including the bazel utilities in the NPM package.

PR Close #37891
2020-07-10 10:06:12 -07:00
1cc9383d91 build: set up caretaker note label in merge tooling (#37778)
Leverage the caretaker note label configuration in ng-dev's merge
tooling to prompt the caretaker for confirmation  when a PR has
the `PR action: merge-assistance` label. This should help to
surface for the caretaker, PRs which may need additional steps
taken, announcement messaging, etc.

PR Close #37778
2020-07-10 16:58:36 +00:00
8ed1e53e99 test: update symbol goldens to reflect optimized application (#37778)
Interestingly enough, our rollup bundle optimization pipeline
did not work properly before 1b827b058e5060963590628d4735e6ac83c6dfdd.

Unused declarations were not elided because build optimizer did not
consider the Angular packages as side-effect free. Build optimizer has
a hard-coded list of Angular packages that are considered side-effect
free. Though this one did not match in the old version of the rollup
bundle rule, as internal sources were resolved through their resolved
bazel-out paths. Hence build optimizer could not detect the known
Angular framework packages. Now though, since we leverage the
Bazel-idiomatic `@bazel/rollup` implementation, sources are resolved
through linked `node_modules`, and build optimizer is able to properly
detect files as side-effect free.

PR Close #37778
2020-07-10 16:58:35 +00:00
7833c88ac4 ci: update components-repo-unit-tests job commit (#37778)
Updates to the latest commit of the `angular/components` repository. We
need to do this because we removed the `esm5.bzl` output flavour aspect,
but an old version of the components repo relied on this file to exist.

This is no longer the case, and we can simply update the version of the
components repo we can test against.

PR Close #37778
2020-07-10 16:58:35 +00:00
12f177399f fix(language-service): non-existent module format in package output (#37778)
The language-service package currently sets the `module` `package.json`
property and refers to a folder called `fesm5`. The language-service
though does not build with `ng_package` so this folder never existed.
Now with APF v10, ng package would not generate this folder either.

We should just remove the property as the primary entry-point is
the UMD bundle resolved through `main`. There is no module flavour
exposed to the NPM package as `pkg_npm` uses the named AMD module
devmode output that doesn't work for `module`.

PR Close #37778
2020-07-10 16:58:35 +00:00
5be32366be test: remove unused stale ng_package test golden file (#37778)
It looks like there is a leftover golden in the `ng_package`
tests that is no longer used anywhere and does not reflect
the latest Angular Package Format v10 changes. We should be
able to remove it to keep our codebase healthy.

PR Close #37778
2020-07-10 16:58:35 +00:00
5b7d2eeabf refactor(dev-infra): ng_rollup_bundle rule should leverage @bazel/rollup (#37778)
Refactors the `ng_rollup_bundle` rule to a macro that relies on
the `@bazel/rollup` package. This means that the rule no longer
deals with custom ESM5 flavour output, but rather only builds
prodmode ES2015 output. This matches the common build output
in Angular projects, and optimizations done in CLI where
ES2015 is the default optimization input.

The motiviation for this change is:

* Not duplicating rollup Bazel rules. Instead leveraging the official
rollup rule.
* Not dealing with a third TS output flavor in Bazel.The ESM5 flavour has the
potential of slowing down local development (as it requires compilation replaying)
* Updating the rule to be aligned with current CLI optimizations.

This also _fixes_ a bug that surfaced in the old rollup bundle rule.
Code that is unused, is not removed properly. The new rule fixes this by
setting the `toplevel` flag. This instructs terser to remove unused
definitions at top-level. This matches the optimization applied in CLI
projects. Notably the CLI doesn't need this flag, as code is always
wrapped by Webpack. Hence, the unused code eliding runs by default.

PR Close #37778
2020-07-10 16:58:35 +00:00
6cd10a1b10 feat(bazel): provide LinkablePackageInfo from ng_module (#37778)
Adds the `LinkablePackageInfo` to the `ng_module` rule. This allows
the linker to properly link `ng_module` targets in Node runtime
actions. Currently this does not work properly and packages like
`@angular/core` are not linked, so we cannot rely on the linker.

9a5de3728b/internal/linker/link_node_modules.bzl (L144-L146).

PR Close #37778
2020-07-10 16:58:35 +00:00
822652aa0d refactor(bazel): cleanup ng_package rule to not build fesm5 and esm5 output (#37778)
As of Angular Package Format v10, we no longer ship a `fesm5` and
`fesm5` output in packages. We made this change to the `ng_package`
rule but intentionally did not clean up related build actions.

This follow-up commit cleans this up by:

* No longer building fesm5 bundles, or providing esm2015 output.
* No longer requesting and building a third flavor for ESM5. We can
use TSC to downlevel ES2015 sources/prodmode output similarly to how it
is done in `ng-packagr`.

The third output flavor (ESM5) resulted in a build slow-down as we
required a full recompilation of sources. Now, we only have a single
compilation for prodmode output, and then downlevel it on-demand
to ES5 for the UMD bundles. Here is timing for building the release
packages in `angular/angular` before this change, and afterwards:

* Before: 462.157s = ~7.7min
* After: 339.703s =  ~5.6min

This signifies a time reduction by 27% when running
`./scripts/build/build-packages-dist.sh`.

PR Close #37778
2020-07-10 16:58:35 +00:00
cf47ace493 refactor(dev-infra): migrate github api in GitClient to rely on GithubClient (#37778)
GitClient now uses GithubClient for github API interactions.  GithubClient is
a class which extends Octokit and provides a member which allows for GraphQL
requests against the Github GraphQL api, as well as providing convenience methods
for common/repeated Github API requests.

PR Close #37778
2020-07-10 16:58:35 +00:00
0595f11950 refactor(dev-infra): cleanup shared package dependencies (#37778)
Cleans up the dependencies used in the shared dev-infra package
configuration. With the recent benchmarking utilities that have
been added, a lot of peer dependencies have been added.

We decided that we don't want to list every used dependencies as
peer dependency as that could result in unnecessary churn/noise
for consumers of the dev-infra package. Additionally, not all parts
of the dev-infra package are necessarily used.

Due to this, we want to apply the following rules for the package
dependencies:

1. If a dependency is only used in a shipped Bazel macro/rule that can be
optionally consumed, omit it from `package.json`. Bazel reports the
missing dependency on its own, so we want to avoid adding it to the
package json file.

2. Otherwise, if the dependency is large and commonly used (like
buildifier), add it to the `peerDependencies`. If not, add it
to the dependencies that are always brought in. We consider it
as acceptable to bring in a few small dependencies that might not
be used or not. Making all of those option would complicate the
use of the dev-infra package.

ds

PR Close #37778
2020-07-10 16:58:35 +00:00
35df312ea4 refactor(dev-infra): use shelljs instead of fs-extra for benchmark utils (#37778)
We added a new dependency on `fs-extra` to the dev-infra package. We can
remove this dependency and replace it with `shelljs` that is extensively
used in other places already.

The motiviation is that we can reduce dependencies needed for
for consumption of the shared dev-infra package.

PR Close #37778
2020-07-10 16:58:34 +00:00
489eb8519e feat(dev-infra): support for caretaker note label in merge script (#37595) (#37778)
Adds support for a caretaker note label to the merge script.
Whenever a configured label is applied, the merge script will
not merge automatically, but instead prompt first in order
to ensure that the caretaker paid attention to the manual
caretaker note on the PR. This helps if a PR needs special
attention.

PR Close #37595

PR Close #37778
2020-07-10 16:58:34 +00:00
b76a2dc2cb fix(bazel): ng_module rule does not expose flat module information in Ivy (#36971)
The `ng_module` rule supports the generation of flat module bundles. In
View Engine, information about this flat module bundle is exposed
as a Bazel provider. This is helpful as other rules like `ng_package`
could rely on this information to determine entry-points for the APF.

With Ivy this currently does not work because the flat module
information is not exposed in the provider. The reason for this is
unclear. We should also provide this information in Ivy so that rules
like `ng_package` can also determine the correct entry-points when a
package is built specifically with `--config=ivy`.

PR Close #36971
2020-07-09 22:11:17 +00:00
f2f5f7fc6e docs(animations): Added consistency in code examples (#37081)
PR Close #37081
2020-07-09 22:08:01 +00:00
8ee23ba67b docs: add explanation for providedIn any (#35283)
Angular 9 introduces a new value for providedIn called `any` which lets us use unique instance
for servicec in each lazy loaded module, this PR is to document the same

fixes #35179

PR Close #35283
2020-07-09 10:12:00 -07:00
ecb422b360 ci: fix payload size (#37993)
Payload size test is failing on the 10.0.x branch at the moment.

PR Close #37993
2020-07-09 10:09:10 -07:00
60389d5441 refactor(service-worker): use nominal type for normalized URLs (#37922)
Some ServiceWorker operations and methods require normalized URLs.
Previously, the generic `string` type was used.

This commit introduces a new `NormalizedUrl` type, a special kind of
`string`, to make this requirement explicit and use the type system to
enforce it.

PR Close #37922
2020-07-09 09:44:58 -07:00
b186db70db fix(service-worker): correctly handle relative base href (#37922)
In some cases, it is useful to use a relative base href in the app (e.g.
when an app has to be accessible on different URLs, such as on an
intranet and the internet - see #25055 for a related discussion).

Previously, the Angular ServiceWorker was not able to handle relative
base hrefs (for example when building the with `--base-href=./`).

This commit fixes this by normalizing all URLs from the ServiceWorker
configuration wrt the ServiceWorker's scope.

Fixes #25055

PR Close #37922
2020-07-09 09:44:58 -07:00
324b6f1b1a test(service-worker): make mock implementations more similar to actual ones (#37922)
This commit makes the mock implementations used is ServiceWorker tests
behave more similar to the actual ones.

PR Close #37922
2020-07-09 09:44:58 -07:00
cdba1d37a4 refactor(service-worker): move asset URL normalization to Adapter (#37922)
This is in preparation of enabling the ServiceWorker to handle
relative paths in `ngsw.json` (as discussed in #25055), which will
require normalizing URLs in other parts of the ServiceWorker.

PR Close #37922
2020-07-09 09:44:58 -07:00
dc42c97ee4 fix(service-worker): correctly serve ngsw/state with a non-root SW scope (#37922)
The Angular ServiceWorker can serve requests to a special virtual path,
`ngsw/state`, showing [information about its internal state][1], which
can be useful for debugging.

Previously, this would only work if the ServiceWorker's [scope][2] was
the root directory (`/`). Otherwise, (e.g. when building the app with
`--baseHref=/some/path/`), the ServiceWorker would fail to detect a
request to `/some/path/ngsw/state` as matching `ngsw/state` and would
not serve it with the debugging information.

This commit fixes it by ensuring that the ServiceWorker's scope is taken
into account when detecting a request to `ngsw/state`.

[1]: https://angular.io/guide/service-worker-devops#locating-and-analyzing-debugging-information
[2]: https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/scope

Fixes #30505

PR Close #37922
2020-07-09 09:44:57 -07:00
bc00e8d312 docs: add Formly library to the list of resources (#37257)
This commit adds the Formly library to the Angular list of resources at aio/content/marketing/resources.json.

PR Close #37257
2020-07-09 09:19:49 -07:00
720b71d01f docs(router): get rid of unnecessary line in wildcard route example and fixing wildcard docregions (#37127)
The wildcard example leads to display a 404 page with the PageNotFoundComponent. But before, there is a wildcard to redirect to the FirstComponent and because of the routes order the FirstComponent will be displayed; which it is not the target of the wildcard route example code. Also, fixing some wildcard docregions
PR Close #37127
2020-07-08 16:04:51 -07:00
1132b07c53 test: fix test failure in saucelabs ivy ie10 (#37892)
One of the ivy acceptance tests currently fails in IE10. This
is because we recently added a new test that asserts that injecting
`ViewRef` results in a `NullInjectorError`.

Due to limitations in TypeScript and in polyfills for `setPrototypeOf`,
the error cannot be thrown as `ViewRef` is always considered injectable.
In reality, `ViewRef` should not be injectable, as explicitly noted
in c00f4ab2ae.

There seems no way to simulate the proper prototype chain in such
browsers that do not natively support `__proto__`, so TypeScript
and `core-js` polyfills simply break the prototype chain and
assign inherited properties directly on `ViewRef`. i.e. so that
`ViewRef.__NG_ELEMENT_ID__` exists and DI picks it up.

There is a way for TypeScript to theoretically generate proper
prototype chain in ES5 output, but they intend to only bother
about the proper prototype chain in ES6 where `setPrototypeOf`
etc. are offically standarized. See the response:

https://github.com/microsoft/TypeScript/issues/1601#issuecomment-94892833.

PR Close #37892
2020-07-08 16:03:34 -07:00
9230194794 build(docs-infra): update @angular/cli to 10.0.1 (#37898)
This commit updates the version of Angular CLI used in angular.io to
version 10.0.1. It also reverts some changes (namely commits 38dfbc775f
and eee2fd22e0) which were made due to an older bug that is fixed in
the latest version. See #37688 for more details.

Fixes #37699

PR Close #37898
2020-07-08 16:02:47 -07:00
d724896f04 refactor(docs-infra): avoid Material style duplication warning (#37898)
This commit removes some duplicate imports of Material themes and
theming-related utilities. While this change does not have any impact on
the size of the generated `styles.css` file, it silences a build warning
pointing to [Avoiding duplicated theming styles][1].

[1]: db4b0cd1bf/guides/duplicate-theming-styles.md

PR Close #37898
2020-07-08 16:02:47 -07:00
29866dfb91 build(docs-infra): update @angular/material to 10.0.1 (#37898)
This commit updates the version of Angular Components used in angular.io
to version 10.0.1. It also updates the angular.io app to adapt to
breaking changes.

PR Close #37898
2020-07-08 16:02:47 -07:00
a249622159 build(docs-infra): update @angular/core to 10.0.2 (#37898)
This commit updates the version of Angular framework used in angular.io
to version 10.0.2. It also features a commit message with a 100+ chars
long body.

PR Close #37898
2020-07-08 16:02:47 -07:00
9f2393fb80 refactor(core): remove duplicated WrappedValue class (#37940)
Before this refactoring we had the WrappedValue class in
2 separate places:
- packages/core/src/change_detection/change_detection_util.ts
- packages/core/src/util/WrappedValue.ts

This commit removes the duplicate, leaving the class that has
the deprecation notice.

PR Close #37940
2020-07-08 16:02:17 -07:00
d5f8040d0a docs: break testing doc into multiple docs (#37957)
This commit breaks up the testing document into nine total documents, with each document focusing on an existing section of the current testing documentation. There are no content changes.

PR Close #37957
2020-07-08 16:01:50 -07:00
e0b8ea136b docs(elements): fix typo (you custom element --> your custom element) (#37966)
PR Close #37966
2020-07-08 16:01:22 -07:00
879b2273c1 ci: decrease the minBodyLength commit message limit to 20 chars (#37949)
The motivation behind this change is to improve the productivity in the angular/angular repo
without sacrificing the original goal of having better understanding of changes within
the repo.

When the minBodyLength limit was originally introduced the goal was simple: force
committers to provide more contextual information for each change coming into the
repo. Too often we found ourselves in a situation where nobody understood what
motivated some of the changes and we needed more contextual info to know if the
change was correct, desirable, and still relevant (at a later point in time).

When the limit was introduced, we needed to pick a minimum body length - given no
data, and frustration with even big changes being committed with just a words in
the subject (along the lines of "fix(core): fixing a bug"), we overcompensated
and started off with a really high bar of minBodyLength set to 100 chars.

This turned out to be impractical and created a big friction point in making valid
changes in the angular/angular repo, and in fact caused some of the refactorings
and smaller changes to be either skipped or combined into other commits which
increased the burden for code reviewers.

The evidence in the friction points can be seen in the number of PRs that fail to pass
the current lint check on the first try, but more importantly also in the "creative"
writing that some of the committers are forced to resort to in order to satisfy the
current checks. Examples:

- 286fbf42c6
- b2816a1536

Given that we primarily care to document the motivation behind each change
(the answer to the ultimate question: WHY?), I've collected several *common* &
*valid* commit messages that are minimalistic and capture the WHY sufficiently:

```
Refactoring for readability.  => 28 chars
Improving variable naming.    => 26 chars
Additional test coverage.     => 25 chars
Cleaning up the code.         => 21 chars
Simplified the code.          => 20 chars
```

These commit message bodies in addition to the commit message subject should
sufficiently satisfy the need to capture the context and motivation behind each
change without creating an undue burden on committers.

Example minimalistic commit message:

------

refactor(core): cleanup the expression parser

Simplifying the code.

----

Given this research, I'm decreasing the minBodyLenth in angular/angular to 20 chars.

The commit message quality can be additionally improved by implementing a commit message
template via `.gitmessage` that will guide the committers in following our commit message
guidelines via instructions provided in the form of in-the-flow help rather than as an after
the fact lint check.

More info: https://thoughtbot.com/blog/better-commit-messages-with-a-gitmessage-template

I'm intentionally deferring such change for a separate PR as not to complicate or delay the
minBodyLength limit decrease.

PR Close #37949
2020-07-08 15:43:03 -07:00
f24972b1b1 release: cut the v10.0.3 release 2020-07-08 13:44:29 -07:00
d2886b3bb4 build: filter out duplicate cherry-picked commits in changelog (#37956)
Often changelogs are generated from the patch branch and then
cherry-picked into the `CHANGELOG.md` file in `master` for
better access and readability. This is problematic though as
`conventional-changelog` (the tool we use for generating the
changelog), will duplicate commits when a future changelog
is generated from `master` then (i.e. for a new minor release).

This happens because conventional-changelog always generates the
changelog from the latest tag in a given branch to `HEAD`. The
tag in the patch branch does not correspond to any SHA in `master`
so the intersection of commits is not automatically omitted.

We work around this naively (until we have a better tool provided
by dev-infra), by deduping commits that are already part of the
changelog. This has proven to work as expected in the components
repo.

PR Close #37956
2020-07-08 12:04:47 -07:00
f296fea112 docs: minor fixes to docs related to updating to v10 (#37897)
This commit includes a couple of minor fixes to docs related to updating
to v10:
- Fix markdown link in "Updating to Angular version 10" guide.
- Correctly display numbered list in
  "Solution-style `tsconfig.json` migration" guide.

PR Close #37897
2020-07-07 12:17:05 -07:00
2605fc46e7 feat(dev-infra): merge script should link to original commit when cherry-picking with API strategy (#37889)
The merge script uses `git cherry-pick` for both the API merge strategy
and the autosquash strategy. It uses cherry-pick to push commits to
different target branches (e.g. into the `10.0.x` branch).

Those commits never point to the commits that landed in the primary
Github branch though. For the autosquash strategy the pull request number
is always included, so there is a way to go back to the source. On the other
hand though, for commits cherry-picked in the API merge strategy, the
pull request number might not always be included (due to Github's
implementation of the rebase merge method).

e.g.
27f52711c0

For those cases we'd want to link the cherry-picked commits to the
original commits so that the corresponding PR is easier to track
down. This is not needed for the autosquash strategy (as outlined
before), but it would have been good for consistency. Unfortunately
though this would rather complicate the strategy as the autosquash
strategy cherry-picks directly from the PR head, so the SHAs that
are used in the primary branch are not known.

PR Close #37889
2020-07-07 12:16:22 -07:00
9d54b3a14b fix(docs-infra): prevent search-bar from overlapping nav-items (#37938)
As part of angular.io's responsive layout, the menu shown in the top-bar
is collapsed into the sidenav on narrow screens at the point where the
search-bar (on the right side of the top-bar) would overlap with the
menu's nav-items.

Previously, the value used as break-point would work on marketing pages,
where the hamburger button is not shown on wide screens. However, on
docs pages (where the hamburger button is always shown, pushing the menu
further to the right), the search-bar would still overlap the menu
nav-items on some resolutions.

This commit fixes it by raising the screen width threshold at a value
that ensures there is no overlap even on pages where the hamburger
button is visible alongside the top-bar menu.

Fixes #37937

PR Close #37938
2020-07-06 13:57:38 -07:00
d09a6283ed refactor(docs-infra): decouple showing the top-menu in top-bar from showing the sidenav (#37938)
As part of angular.io's responsive layout, the following rules are
applied:
- On wide screens, a menu is shown in the top-bar and the sidenav is
  shown side-by-side with the docs content.
- On narrow screens, the top-menu is moved from the top-bar to the
  sidenav and the sidenav is closed by default and floats over the
  content when manually opened.

Previously, the break-points at which the top-menu was shown in the
top-bar and the sidenav was shown side-by-side with the content were the
same (using a single variable).

This commit decouples the two break-points to make it possible to use
different values in the future.

PR Close #37938
2020-07-06 13:57:38 -07:00
1c168c3a44 refactor(docs-infra): use Sass variable for top-bar hamburger button show/hide threshold (#37938)
Use a Sass variable for the screen width break-point at which the
top-bar hamburger button is hidden/shown. This allows more easily
updating the break-point.

PR Close #37938
2020-07-06 13:57:38 -07:00
0f74479c47 build(docs-infra): improve applying post-install patches (#37896)
In `aio/`, we have a mechanism to apply patches in a `postinstall` hook.
See `aio/tools/cli-patches/README.md` for more info.

Previously, we had to update `aio/tools/cli-patches/patch.js` to list
each `.patch` file separately. While working on #37688, I found it
helpful for the script to automatically pick up `.patch` files.

This commit updates the script to automatically pick up and apply
`.patch` files from the `aio/tools/cli-patches/` directory. If one wants
to keep a `.patch` file but not apply it, they can change the file's
extension or move it to a sub-directory (without having to update the
script).

PR Close #37896
2020-07-06 13:56:15 -07:00
790bb949f6 fix(core): handle spaces after select and plural ICU keywords (#37866)
Currently when the `plural` or `select` keywords in an ICU contain trailing spaces (e.g. `{count, select , ...}`), these spaces are also included into the key names in ICU vars (e.g. "VAR_SELECT "). These trailing spaces are not desirable, since they will later be converted into `_` symbols while normalizing placeholder names, thus causing mismatches at runtime (i.e. placeholder will not be replaced with the correct value). This commit updates the code to trim these spaces while generating an object with placeholders, to make sure the runtime logic can replace these placeholders with the right values.

PR Close #37866
2020-07-06 13:55:48 -07:00
2adcad6dd2 fix(dev-infra): fix typo in ng-dev config (#37862)
The logic to exclude certain types of commits (specifically 'docs' ones) was implemented in c5b125b7db. The ng-dev config was updated in the followup commit acf3cff9ee, but there was a typo that prevented the new logic from being activated. This commit updates the name of the config option in the ng-dev config to the right one (minBodyLengthTypeExcludes).

PR Close #37862
2020-07-06 13:55:19 -07:00
242ef1ace1 docs: mention for depreciation for Testbed.get() (#37815)
As mention in https://angular.io/guide/deprecations for this API, it may be important mention for this to make developers migrate or avoid using it

PR Close #37815
2020-07-06 13:42:28 -07:00
842b6a1247 docs: clean up api doc in core (#37053)
Add introductions to usage examples and edit descriptions to be more complete and consistent with current API reference styles

PR Close #37053
2020-06-30 12:11:16 -07:00
98335529eb docs: add missing single quote (#37854)
The current code is missing a single quote at the end of the import.

(cherry picked from commit e13171ea2960dd0fa0666cb964b53799d2883e3a)

PR Close #37854
2020-06-30 12:10:14 -07:00
ca7ee794bf release: cut the v10.0.2 release 2020-06-30 11:40:40 -07:00
f9f2ba6faf docs: add Sonu Kapoor to the collaborator list (#37777)
After 6 months of continuous contributions, Sonu Kapoor did finally make
it into the collaborator list.

PR Close #37777
2020-06-30 10:47:55 -07:00
aea1d211d4 docs: update /config/app-package-json redirect (#37774)
With this change we change the redirect for `/config/app-package-json` from `https://webpack.js.org/configuration/optimization/#optimizationsideeffects` to `https://angular.io/guide/strict-mode#non-local-side-effects-in-applications`

The latter page has more details.

PR Close #37774
2020-06-30 10:45:53 -07:00
57a518a36d perf(compiler-cli): fix memory leak in retained incremental state (#37835)
Incremental compilation allows for the output state of one compilation to be
reused as input to the next compilation. This involves retaining references
to instances from prior compilations, which must be done carefully to avoid
memory leaks.

This commit fixes such a leak with a complicated retention chain:

* `TrackedIncrementalBuildStrategy` unnecessarily hangs on to the previous
  `IncrementalDriver` (state of the previous compilation) once the current
  compilation completes.

  In general this is unnecessary, but should be safe as long as the chain
  only goes back one level - if the `IncrementalDriver` doesn't retain any
  previous `TrackedIncrementalBuildStrategy` instances. However, this does
  happen:

* `NgCompiler` indirectly causes retention of previous `NgCompiler`
  instances (and thus previous `TrackedIncrementalBuildStrategy` instances)
  through accidental capture of the `this` context in a closure created in
  its constructor. This closure is wrapped in a `ts.ModuleResolutionCache`
  used to create a `ModuleResolver` class, which is passed to the program's
  `TraitCompiler` on construction.

* The `IncrementalDriver` retains a reference to the `TraitCompiler` of the
  previous compilation, completing the reference chain.

The final retention chain thus looks like:

* `TrackedIncrementalBuildStrategy` of current program
* `.previous`: `IncrementalDriver` of previous program
* `.lastGood.traitCompiler`: `TraitCompiler`
* `.handlers[..].moduleResolver.moduleResolutionCache`: cache
* (via `getCanonicalFileName` closure): `NgCompiler`
* `.incrementalStrategy`: `TrackedIncrementalBuildStrategy` of previous
  program.

The closure link is the "real" leak here. `NgCompiler` is creating a closure
for `getCanonicalFileName`, delegating to its
`this.adapter.getCanonicalFileName`, for the purposes of creating a
`ts.ModuleResolutionCache`. The fact that the closure references
`NgCompiler` thus eventually causes previous `NgCompiler` iterations to be
retained. This is also potentially problematic due to the shared nature of
`ts.ModuleResolutionCache`, which is potentially retained across multiple
compilations intentionally.

This commit fixes the first two links in the retention chain: the build
strategy is patched to not retain a `previous` pointer, and the `NgCompiler`
is patched to not create a closure in the first place, but instead pass a
bound function. This ensures that the `NgCompiler` does not retain previous
instances of itself in the first place, even if the build strategy does
end up retaining the previous incremental state unnecessarily.

The third link (`IncrementalDriver` unnecessarily retaining the whole
`TraitCompiler`) is not addressed in this commit as it's a more
architectural problem that will require some refactoring. However, the leak
potential of this retention is eliminated thanks to fixing the first two
issues.

PR Close #37835
2020-06-29 16:34:52 -07:00
29b83189b0 build(docs-infra): update to latest dgeni-packages (#37793)
This update of dgeni-packages to 0.28.4 fixes the
rendering of type initializers for classes and interfaces.

Closes #37694

PR Close #37793
2020-06-29 15:01:16 -07:00
1d3df7885d docs: correct the spelling mistake in observables error handling code (#36437)
This commit fixes a spelling error in the word error in the
observables.md guide. It is currently
spelled errror  and the mistake is not intentional.

PR Close #36437
2020-06-29 15:00:39 -07:00
fd06ffa2af docs: change definition of providedIn any (#35292)
change in the definition of providedIn:any any instance creates a singleton instance
for each lazy loaded module and one instance for eager loaded module

PR Close #35292
2020-06-29 15:00:01 -07:00
36a1622dd1 docs: correct left nav to remove duplicated page links (#37833)
The major sections Angular Libraries, Schematics, and CLI Builders appear twice, in their old location under Techniques, and in the new correct location under Extending Angular.

PR Close #37833
2020-06-29 14:57:37 -07:00
7a91b23cb5 fix(core): fake_async_fallback should have the same logic with fake-async (#37680)
PR https://github.com/angular/angular/pull/37523 failed when trying to use `rxjs delay` operator
inside `fakeAsync`, and the reasons are:

1. we need to import `rxjs-fake-async` patch to make the integration work.
2. since in `angular` repo, the bazel target `/tools/testing:node` not using `zone-testing` bundle,
instead it load `zone-spec` packages seperately, so it causes one issue which is the `zone.js/testing/fake-async`
package is not loaded, we do have a fallback logic under `packages/core/testing` calles `fake_async_fallback`,
but the logic is out of date with `fake-async` under `zone.js` package.

So this PR, I updated the content of `fake_async_fallback` to make it consistent with
`fake-async`. And I will make another PR to try to remove the `fallback` logic.

PR Close #37680
2020-06-29 12:22:52 -07:00
4b90b6a226 fix(ngcc): prevent including JavaScript sources outside of the package (#37596)
When ngcc creates an entry-point program, the `allowJs` option is enabled
in order to operate on the JavaScript source files of the entry-point.
A side-effect of this approach is that external modules that don't ship
declaration files will also have their JavaScript source files loaded
into the program, as the `allowJs` flag allows for them to be imported.
This may pose an issue in certain edge cases, where ngcc would inadvertently
operate on these external modules. This can introduce all sorts of undesirable
behavior and incompatibilities, e.g. the reflection host that is selected for
the entry-point's format could be incompatible with that of the external
module's JavaScript bundles.

To avoid these kinds of issues, module resolution that would resolve to
a JavaScript file located outside of the package will instead be rejected,
as if the file would not exist. This would have been the behavior when
`allowJs` is set to false, which is the case in typical Angular compilations.

Fixes #37508

PR Close #37596
2020-06-29 12:21:23 -07:00
b13daa4cdf refactor(ngcc): let isWithinPackage operate on paths instead of source files (#37596)
Changes `isWithinPackage` to take an `AbsoluteFsPath` instead of `ts.SourceFile`,
to allow for an upcoming change to use it when no `ts.SourceFile` is available,
but just a path.

PR Close #37596
2020-06-29 12:21:23 -07:00
0c6f026828 docs: Changing typo Stacblitz into Stackblitz in the Tour of Hereos tutorial docs page (#37794)
Changing the typo of Stacblitz into Stackblitz in the tour of hereos tutorial docs page since that is the actual name of the service

PR Close #37794
2020-06-29 12:17:41 -07:00
a2520bd267 docs: remove first person from 2 sentences (#37768)
This commit removes two instances of the first person in the
Dependency injection providers documentation.

PR Close #37768
2020-06-29 12:17:04 -07:00
b928a209a4 docs: add Amadou Sall to GDE page (#36509)
This commit adds Amadou Sall to the Angular GDE page along with a
biography, his role at Air France, and a photograph.

PR Close #36509
2020-06-29 12:16:23 -07:00
89e16ed6a5 fix(elements): fire custom element output events during component initialization (#37570)
Previously, event listeners for component output events attached on an
Angular custom element before inserting it into the DOM (i.e. before
instantiating the underlying component) didn't fire for events emitted
during initialization lifecycle hooks, such as `ngAfterContentInit`,
`ngAfterViewInit`, `ngOnChanges` (initial call) and `ngOnInit`.
The reason was that `NgElementImpl` [subscribed to events][1] _after_
calling [ngElementStrategy#connect()][2], which is where the
[initial change detection][3] takes place (running the initialization
lifecycle hooks).

This commit fixes this by:
1. Ensuring `ComponentNgElementStrategy#events` is defined and available
   for subscribing to, even before instantiating the component.
2. Changing `NgElementImpl` to subscribe to `NgElementStrategy#events`
   (if available) before calling `NgElementStrategy#connect()` (which
   initializes the component instance) if available.
3. Falling back to the old behavior (subscribing to `events` after
   calling `connect()` for strategies that do not initialize `events`
   before their `connect()` is run).

NOTE:
By falling back to the old behavior when `NgElementStrategy#events` is
not initialized before calling `NgElementStrategy#connect()`, we avoid
breaking existing custom `NgElementStrategy` implementations (with
@remackgeek's [ElementZoneStrategy][4] being a commonly used example).

Jira issue: [FW-2010](https://angular-team.atlassian.net/browse/FW-2010)

[1]: c0143cb2ab/packages/elements/src/create-custom-element.ts (L167-L170)
[2]: c0143cb2ab/packages/elements/src/create-custom-element.ts (L164)
[3]: c0143cb2ab/packages/elements/src/component-factory-strategy.ts (L158)
[4]: f1b6699495/projects/elements-zone-strategy/src/lib/element-zone-strategy.ts

Fixes #36141

PR Close #37570
2020-06-29 10:33:40 -07:00
1a1f99af37 fix(ngcc): ensure lockfile is removed when analyzeFn fails (#37739)
Previously an error thrown in the `analyzeFn` would cause
the ngcc process to exit immediately without removing the
lockfile, and potentially before the unlocker process had been
successfully spawned resulting in the lockfile being orphaned
and left behind.

Now we catch these errors and remove the lockfile as needed.

PR Close #37739
2020-06-29 10:29:12 -07:00
df2cd37ed2 fix(core): error when invoking callbacks registered via ViewRef.onDestroy (#37543) (#37783)
Invoking a callback registered through `ViewRef.onDestroy` throws an error, because we weren't registering it correctly in the internal data structure. These changes also remove the `storeCleanupFn` function, because it was mostly identical to `storeCleanupWithContext` and was only used in one place.

Fixes #36213.

PR Close #37543

PR Close #37783
2020-06-29 10:27:39 -07:00
12a71bc6bc fix(core): determine required DOMParser feature availability (#36578) (#37783)
Verify that HTML parsing is supported in addition to DOMParser existence.
This maybe wasn't as important before when DOMParser was used just as a
fallback on Firefox, but now that DOMParser is the default choice, we need
to be more accurate.

PR Close #37783
2020-06-29 10:27:39 -07:00
7d270c235a refactor(core): split inert strategies to separate classes (#36578) (#37783)
The `inertDocument` member is only needed when using the InertDocument
strategy. By separating the DOMParser and InertDocument strategies into
separate classes, we can easily avoid creating the inert document
unnecessarily when using DOMParser.

PR Close #37783
2020-06-29 10:27:39 -07:00
b0b7248504 fix(core): do not trigger CSP alert/report in Firefox and Chrome (#36578) (#37783)
If [innerHTML] is used in a component and a Content-Security-Policy is set
that does not allow inline styles then Firefox and Chrome show the following
message:

> Content Security Policy: The page’s settings observed the loading of a
resource at self (“default-src”). A CSP report is being sent.

This message is caused because Angular is creating an inline style tag to
test for a browser bug that we use to decide what sanitization strategy to
use, which causes CSP violation errors if inline CSS is prohibited.

This test is no longer necessary, since the `DOMParser` is now safe to use
and the `style` based check is redundant.

In this fix, we default to using `DOMParser` if it is available and fall back
to `createHTMLDocument()` if needed. This is the approach used by DOMPurify
too.

The related unit tests in `html_sanitizer_spec.ts`, "should not allow
JavaScript execution when creating inert document" and "should not allow
JavaScript hidden in badly formed HTML to get through sanitization (Firefox
bug)", are left untouched to assert that the behavior hasn't changed in
those scenarios.

Fixes #25214.

PR Close #37783
2020-06-29 10:27:38 -07:00
78460c1848 test(core): update symbols used in the test app (#37785)
This commit updates the golden file that contains the set of symbols used in the test TODO app. The `storeCleanupFn` function was replaced by `storeCleanupWithContext` in 75b119eafc and this commit updates the golden file to reflect that.

PR Close #37785
2020-06-26 16:44:00 -07:00
75b119eafc fix(core): error when invoking callbacks registered via ViewRef.onDestroy (#37543)
Invoking a callback registered through `ViewRef.onDestroy` throws an error, because we weren't registering it correctly in the internal data structure. These changes also remove the `storeCleanupFn` function, because it was mostly identical to `storeCleanupWithContext` and was only used in one place.

Fixes #36213.

PR Close #37543
2020-06-26 15:02:43 -07:00
64b0ae93f7 fix(core): don't consider inherited NG_ELEMENT_ID during DI (#37574)
Special DI tokens like `ChangeDetectorRef` and `ElementRef` can provide a factory via `NG_ELEMENT_ID`. The problem is that we were reading it off the token as `token[NG_ELEMENT_ID]` which will go up the prototype chain if it couldn't be found on the current token, resulting in the private `ViewRef` API being exposed, because it extends `ChangeDetectorRef`.

These changes fix the issue by guarding the property access with `hasOwnProperty`.

Fixes #36235.

PR Close #37574
2020-06-26 15:01:21 -07:00
7c0b25f5a6 fix(language-service): incorrect autocomplete results on unknown symbol (#37518)
This commit fixes a bug whereby the language service would incorrectly
return HTML elements if autocomplete is requested for an unknown symbol.
This is because we walk through every possible scenario, and fallback to
element autocomplete if none of the scenarios match.

The fix here is to return results from interpolation if we know for sure
we are in a bound text. This means we will now return an empty results if
there is no suggestions.

This commit also refactors the code a little to make it easier to
understand.

PR Close #37518
2020-06-26 14:51:33 -07:00
07b5df3a19 release: cut the v10.0.1 release 2020-06-26 13:17:36 -07:00
e7023726f4 ci: exclude "docs" commit type from minBodyLength commit message validation (#37764)
docs commits are sometimes trivial (e.g. an obvious typo fix) and in such cases its very
akward to to write up 100 chars worth of text about why this typo fix is the best thing in the
world and why it is so important and crucial that we must know why we are fixing the typo
at all. After all most typos are not just typos. Or are they? We'll shall see...

PR Close #37764
2020-06-26 11:13:10 -07:00
a9ccd9254c feat(dev-infra): add support for minBodyLengthTypeExcludes to commit-message validation (#37764)
This feature will allow us to exclude certain commits from the 100 chars minBodyLength requirement for commit
messages which is hard to satisfy for commits that make trivial changes (e.g. fixing typos in docs or comments).

PR Close #37764
2020-06-26 11:13:10 -07:00
335f3271d2 refactor(core): throw more descriptive error message in case of invalid host element (#35916)
This commit replaces an assert with more descriptive error message that is thrown in case `<ng-template>` or `<ng-container>` is used as host element for a Component.

Resolves #35240.

PR Close #35916
2020-06-26 11:10:15 -07:00
7f93f7ef47 build: move shims_for_IE to third_party directory (#37624)
The shims_for_IE.js file contains vendor code that predates the third_party
directory. This file is currently used for internal karma testing setup. This
change corrects this by moving the shims_for_IE file to //third_part/

PR Close #37624
2020-06-26 11:09:02 -07:00
cf46a87fcd refactor(compiler-cli): Remove any cast for CompilerHost (#37079)
This commit removes the FIXME for casting CompilerHost to any since
google3 is now already on TS 3.8.

PR Close #37079
2020-06-26 11:08:18 -07:00
ad6680f602 fix(language-service): reinstate getExternalFiles() (#37750)
`getExternalFiles()` is an API that could optionally be provided by a tsserver plugin
to notify the server of any additional files that should belong to a particular project.

This API was removed in https://github.com/angular/angular/pull/34260 mainly
due to performance reasons.

However, with the introduction of "solution-style" tsconfig in typescript 3.9,
the Angular extension could no longer reliably detect the owning Project solely
based on the ancestor tsconfig.json. In order to support this use case, we have
to reinstate `getExternalFiles()`.

Fixes https://github.com/angular/vscode-ng-language-service/issues/824

PR Close #37750
2020-06-26 09:57:08 -07:00
5e287f67af docs: correct outdated dev instructions for public api golds (#37026)
This change updates the dev instructions to reflect the location and generation of public API golds, which changed in #35768.

PR Close #37026
2020-06-26 09:56:33 -07:00
ecfe6e0609 docs: add note about the month being zero-based in the Date constructor (#37770)
Because the month is zero based, it may confuse some users that '3'
is in fact 'April'. This comment should clear that up.

PR Close #37770
2020-06-26 09:55:19 -07:00
df9790dd11 fix(dev-infra): support running scripts from within a detached head (#37737)
Scripts provided in the `ng-dev` command might use local `git`
commands. For such scripts, we keep track of the branch that
has been checked out before the command has been invoked.

We do this so that we can later (upon command completion)
restore back to the original branch. We do not want to
leave the Git repository in a dirty state.

It looks like this logic currently only deals with branches
but does not work properly when a command is invoked from
a detached head. We can make it work by just checking out
the previous revision (if no branch is checked out).

PR Close #37737
2020-06-26 09:51:10 -07:00
67cfc4c9bc build: add wombot proxy for publish config for @angular/benchpress (#37752)
Adds the publishConfig registry value to the package.json of the
@angular/benchpress package to publish it via wombat rather than
through npm directly.

PR Close #37752
2020-06-25 17:08:19 -07:00
a68e623c80 docs(elements): fixed command that adds the package @angular/elements (#37681)
I was using schematics with the `--name` parameter instead of the `--project`, I did both ways before sending and my suspicion about outdated documentation was confirmed

PR Close #37681
2020-06-25 17:07:30 -07:00
9e3915ba48 docs: typo fixes for schematics-for-libraries.md (#37753)
Addresses small typos such as extra whitespaces.

This change was extracted from #29505.
This change was extracted from #29505.
This change was extracted from #29505.

PR Close #37753
2020-06-25 17:06:38 -07:00
ba2de61748 fix(docs-infra): fix deploy-to-firebase.sh for master and v10.0.x branches (#37762)
The deployment to aio is currently failing because #37721 introduced
"project" entry into the firebase.json which means that we now need to
select the deployment target before deploying to firebase.

This change fixes the issue and refactors the file to be easier to read.

I also added extra echo statements so that the CI logs are easier to
read in case we need to troubleshoot future issues.

PR Close #37762
2020-06-25 17:03:25 -07:00
a9a4edebe2 fix(docs-infra): fix typo in the deploy-to-firebase.sh script (#37754)
This typo caused the script to fail on Linux (interestingly it works fine on Mac).

This is a painful reminder that we should not write any more Bash scripts EVER. shelljs FTW! :-)

PR Close #37754
2020-06-25 15:21:25 -07:00
64f2ffa166 fix(core): cleanup DOM elements when root view is removed (#37600)
Currently when bootstrapped component is being removed using `ComponentRef.destroy` or `NgModuleRef.destroy` methods, DOM nodes may be retained in the DOM tree. This commit fixes that problem by always attaching host element of the internal root view to the component's host view node, so the cleanup can happen correctly.

Resolves #36449.

PR Close #37600
2020-06-25 14:34:36 -07:00
13020b9cc2 fix(migrations): do not incorrectly add todo for @Injectable or @Pipe (#37732)
As of v10, the `undecorated-classes-with-decorated-fields` migration
generally deals with undecorated classes using Angular features. We
intended to run this migation as part of v10 again as undecorated
classes with Angular features are no longer supported in planned v11.

The migration currently behaves incorrectly in some cases where an
`@Injectable` or `@Pipe` decorated classes uses the `ngOnDestroy`
lifecycle hook. We incorrectly add a TODO for those classes. This
commit fixes that.

Additionally, this change makes the migration more robust to
not migrate a class if it inherits from a component, pipe
injectable or non-abstract directive. We previously did not
need this as the undecorated-classes-with-di migration ran
before, but this is no longer the case.

Last, this commit fixes an issue where multiple TODO's could be
added. This happens when multiple Angular CLI build targets have
an overlap in source files. Multiple programs then capture the
same source file, causing the migration to detect an undecorated
class multiple times (i.e. adding a TODO twice).

Fixes #37726.

PR Close #37732
2020-06-25 14:22:09 -07:00
96b96fba0f perf(compiler-cli): fix regressions in incremental program reuse (#37690)
Commit 4213e8d5 introduced shim reference tagging into the compiler, and
changed how the `TypeCheckProgramHost` worked under the hood during the
creation of a template type-checking program. This work enabled a more
incremental flow for template type-checking, but unintentionally introduced
several regressions in performance, caused by poor incrementality during
`ts.Program` creation.

1. The `TypeCheckProgramHost` was made to rely on the `ts.CompilerHost` to
   retrieve instances of `ts.SourceFile`s from the original program. If the
   host does not return the original instance of such files, but instead
   creates new instances, this has two negative effects: it incurs
   additional parsing time, and it interferes with TypeScript's ability to
   reuse information about such files.

2. During the incremental creation of a `ts.Program`, TypeScript compares
   the `referencedFiles` of `ts.SourceFile` instances from the old program
   with those in the new program. If these arrays differ, TypeScript cannot
   fully reuse the old program. The implementation of reference tagging
   introduced in 4213e8d5 restores the original `referencedFiles` array
   after a `ts.Program` is created, which means that future incremental
   operations involving that program will always fail this comparison,
   effectively limiting the incrementality TypeScript can achieve.

Problem 1 exacerbates problem 2: if a new `ts.SourceFile` is created by the
host after shim generation has been disabled, it will have an untagged
`referencedFiles` array even if the original file's `referencedFiles` was
not restored, triggering problem 2 when creating the template type-checking
program.

To fix these issues, `referencedFiles` arrays are now restored on the old
`ts.Program` prior to the creation of a new incremental program. This allows
TypeScript to get the most out of reusing the old program's data.

Additionally, the `TypeCheckProgramHost` now uses the original `ts.Program`
to retrieve original instances of `ts.SourceFile`s where possible,
preventing issues when a host would otherwise return fresh instances.

Together, these fixes ensure that program reuse is as incremental as
possible, and tests have been added to verify this for certain scenarios.

An optimization was further added to prevent the creation of a type-checking
`ts.Program` in the first place if no type-checking is necessary.

PR Close #37690
2020-06-25 14:13:34 -07:00
2cbe53a9ba docs: Uses correct component in the MessageService (#37666)
This commit uses the correct component (`HeroesComponent`) in the.
`MessageService`. Previously, the `MessageService` was using
`HeroeService`.

Closes #37654

PR Close #37666
2020-06-25 13:49:00 -07:00
48755114e5 feat(docs-infra): update deploy-to-firebase.sh script to support v9 multisite setup (#37721)
v9.angular.io was used to pilot the firebase hosting multisites setup for angular.io.

The deployments so far have been done manually to control the deployment process.

This change, automates the deployment for v9.angular.io so that future deployments can be made from
the CI.

See https://angular-team.atlassian.net/browse/DEV-125 for more info.

In the process of updating the scripts I rediscovered a bug in the deploy-to-firebase.sh script that
incorrect compared two numbers as strings. This previously worked correctly because we were comparing
single digit numbers. With the release of v10, we now compare 9 > 10 which behaves differently for
strings and numbers. The bug was fixed by switching to an arithmetic comparison of the two variables.

This bug has been fixed on the master branch but not on the 9.1.x branch. I realized this during the
rebase, but found my version to be a bit cleaner, so I kept it.

PR Close #37721
2020-06-25 13:44:53 -07:00
a5d5f67be7 fix(http): avoid abort a request when fetch operation is completed (#37367)
`abort` method is calling, even if fetch operation is completed

Fixes https://github.com/angular/angular/issues/36537

PR Close #37367
2020-06-25 12:09:40 -07:00
dfb58c44a2 fix(forms): correct usage of selectedOptions (#37620)
Previously, `registerOnChange` used `hasOwnProperty` to identify if the
property is supported. However, this does not work as the `selectedOptions`
property is an inherited property. This commit fixes this by verifying
the property on the prototype instead.

Closes #37433

PR Close #37620
2020-06-25 12:08:01 -07:00
69948ce919 fix(router): add null support for RouterLink directive (#32616)
Value of "undefined" passed as segment in routerLink is stringified to string "undefined".
This change introduces the same behavior for value of "null".

PR Close #32616
2020-06-25 11:58:01 -07:00
3190ccf3b2 fix(router): fix error when calling ParamMap.get function (#31599)
fix this.params.hasOwnProperty is not a function in case of creating an object using Object.create()

PR Close #31599
2020-06-25 11:57:25 -07:00
a8ea8173aa fix(router): RouterLinkActive should run CD when setting isActive (#21411)
When using the routerLinkActive directive inside a component that is using ChangeDetectionStrategy.OnPush and lazy loaded module routes the routerLinkActive directive does not update after clicking a link to a lazy loaded route that has not already been loaded.

Also the OnPush nav component does not set routerLinkActive correctly when the default route loads, the non-OnPush nav component works fine.

regression caused by #15943
closes #19934

PR Close #21411
2020-06-25 11:56:26 -07:00
e13a49d1f0 feat(dev-infra): add a way to pass assets down to a benchmark application (#37695)
* add a param called ng_assets to the component_benchmark macro to allow static assets to be provided to the base angular app, not just through the ts_devserver

PR Close #37695
2020-06-25 11:51:52 -07:00
2f0b8f675a docs: Add support schedule for v10 (#37745)
This commit adds the support schedule for v10.
v10.0.0 was released on June 24, 2020.
Active support ends six months later, on Dec 24, 2020.
Long term support ends a year after that, on Dec 24, 2021.

PR Close #37745
2020-06-25 11:49:18 -07:00
c2aed033ba ci(compiler-cli): exempt compiler-cli .bazel files from dev-infra approval (#37558)
Previously, dev-infra approval (via PullApprove) was required for all
.bazel files in the monorepo, including those in packages/compiler-cli.

The compiler-cli package is a little special in this sense:
 * it's not shipped to NPM in the APF
 * it uses lots of internal subpackages to organize and test its code

As a result:
 * changes to compiler-cli BUILD.bazel files are not user visible and
   don't have larger implications for the packages published to NPM,
   unlike changes to other BUILD.bazel files in the repo
 * the requirement for dev-infra approval for BUILD.bazel changes is
   overly burdensome, because compiler-cli build files change more
   rapidly than those of other packages.

This commit exempts the compiler-cli's build files from the requirement
for dev-infra approval. It will be sufficient for such files to be
approved by the normal compiler reviewers.

PR Close #37558
2020-06-25 11:47:51 -07:00
0f8a780b0d docs: Replace $emdash; with an actual em dash (#37723)
fix documentation in the lifecycle hooks guide where $emdash; was not being replaced by an actual em dash (-)

PR Close #37723
2020-06-25 11:41:54 -07:00
c5bc2e77c8 fix(forms): change error message (#37643)
Error message mention that ngModel and ngModelChange will be removed in Angular v7 but right not now sure when it will be removed so changed it to a future version

PR Close #37643
2020-06-25 11:37:00 -07:00
079310dc7c test(docs-infra): add end to end tests for api reference (#37612)
Api search functionality only had unit tests @gkalpak suggested we should have some e2e tests too. Added some end to end tests.

Fixes #35170

PR Close #37612
2020-06-25 11:36:03 -07:00
0d2cdf6165 docs: add v9.angular.io to the angular.io version picker (#37719)
Now that v10 is out, it's time to add the v9.angular.io link to the version picker, so here we go...

PR Close #37719
2020-06-24 19:53:25 -07:00
436dde271f docs(changelog): fix v10 announcement url (#37722)
PR Close #37722
2020-06-24 19:50:45 -07:00
96891a076f release: sort the v10.0.0 release in CHANGELOG.md 2020-06-24 15:58:06 -07:00
9ce0067bdf release: consolidate the v10.0.0 release CHANGELOG.md 2020-06-24 13:55:21 -07:00
345940bbc1 release: cut the v10.0.0 release 2020-06-24 11:46:57 -07:00
c49507b289 docs: updating guides and docs related to the v10 release (#37705)
Mostly just adding links to the migrations that were missing, adding the migrations into the navbar,
as well as correcting the @angular/bazel removal in the update guide.

I also added a commented out preamble for the release notes.

PR Close #37705
2020-06-24 09:37:35 -07:00
c730142508 Revert "docs: add lightweight token page to library section of docs (#36144)"
This reverts commit 27aa00b15f.
2020-06-24 09:29:01 -07:00
27aa00b15f docs: add lightweight token page to library section of docs (#36144)
adds new DI technique recommendation for libraries to ensure tree-shaking for unused services
includes reasons for packaging schematics with libraries, clarify schematic usage recommendation

PR Close #36144
2020-06-23 16:34:51 -07:00
36a00a255b ci(docs-infra): disable flaky tests (#37673)
I could not figure out the root cause of the flakes, so disabling the
flaky tests for now. See
https://github.com/angular/angular/pull/37637#issuecomment-647608149 for
more info.

Fixes #37629

PR Close #37673
2020-06-23 13:13:53 -07:00
0e3249c89b docs: add tslib update migration docs (#37402)
This adds documentation for the v10.0 tooling migration `update-libraries-tslib` contained within the `@schematics/angular` package.

PR Close #37402
2020-06-23 13:07:40 -07:00
920019ab70 docs: add module/target compiler option migration docs (#37429)
This adds documentation for the v10.0 tooling migration `update-module-and-target-compiler-options` contained within the `@schematics/angular` package.

PR Close #37429
2020-06-23 12:46:23 -07:00
82c8b44db7 docs: Initial commit of update guide for v10 release. (#37152)
This update includes modifications to the navigation.json file to
remove unneeded migration guides.

TODO: Redirects from v9 topics to v10; links to removed migration
guides need to point to v9.angular.io.

PR Close #37152
2020-06-23 11:56:50 -07:00
bb3a307d5a docs: add solution-style tsconfig migration docs (#37512)
This adds documentation for the v10.0 tooling migration `solution-style-tsconfig` contained within the `@schematics/angular` package.

PR Close #37512
2020-06-23 11:55:02 -07:00
dcb0ddaf5e docs: add strict-mode.md file to pullapprove (#37679)
When I created the strict-mode.md file, I didn't add it to the
pullapprove list. Now it's there.

The issue was introduced in #37486.

PR Close #37679
2020-06-23 10:05:51 -07:00
4c1edd52c5 docs: Add content for new strict mode for Angular CLI (#37486)
In v10, the Angular CLI supports a strict mode, which turns
on additional flags for the TypeScript and Angular compilers.

PR Close #37486
2020-06-22 16:29:16 -07:00
d512e27979 docs: fix invalid anchor for CLI flags in deprecation guide (#37662)
7521834296 added content for CLI
deprecations to the `angular.io` deprecations guide. It looks
like the anchor for the CLI deprecations is incorrect and
ends up showing up as code in the guide.

This commit fixes the anchor so that it doesn't show
up as code in the guide.

PR Close #37662
2020-06-22 10:57:16 -07:00
0619d82e0b docs: Refactor-i18n (#36924)
Rewrite headings to focus on tasks and separate reference info and best practices from tasks. Add missing steps or procedures, and links to important information. Make the example open in StackBlitz. See i18n Documentation Plan at https://docs.google.com/document/d/1aV2TKsIqry7JnNiHEfhmheu5rNAbNl1IRYVhYErc7Ks/edit?usp=sharing

PR Close #36924
2020-06-22 10:53:00 -07:00
a4038d5b94 Revert "fix(router): fix navigation ignoring logic to compare to the browser url (#37408)" (#37650)
This reverts commit d3a817549b.

The reason for the revert is the problem reported in g3 which requires additional investigation.

PR Close #37650
2020-06-22 10:47:47 -07:00
e3d5e1fab7 docs: fix grammatical errors in developer docs (#37633)
The CONTRIBUTOR and DEVELOPER markdown docs contained a few typos
and grammatical errors, which are fixed in this commit.

PR Close #37633
2020-06-18 16:04:59 -07:00
035036308a docs(core): correct type for opts.read (#37626)
The ContentChildren decorator has a metadata property named "read" which
can be used to read a different token from the queried elements. The
documentation incorrectly says "True to read..." when it should say
"Used to read...".

PR Close #37626
2020-06-18 16:04:10 -07:00
0d29259d9b docs: move ng-vikings 2020 to the already presented section (#37466)
This commit moves the ng-vikings 2020 event from the currently presenting
section into the already presented section.

PR Close #37466
2020-06-17 11:18:48 -07:00
26b0f3dc96 docs: add side effect package.json in app structure (#37521)
With this change we add the special `package.json` which is used to mark the application free of non-local side-effects in the application source files section

PR Close #37521
2020-06-16 11:57:40 -07:00
5c9306b0fe docs: @angular/language‑service is no longer a dev-dependencies (#37521)
`@angular/
language‑service` is no longer needed as a dev-dependencies, infact we no longer generate project with this dependency as it can conflict with the https://marketplace.visualstudio.com/items?itemName=Angular.ng-template

PR Close #37521
2020-06-16 11:57:40 -07:00
3befb0e4b9 docs: add new section for CLI deprecations (#37332)
Current documentation does not list CLI flag deprecations. This
change adds it for v10.

PR Close #37332
2020-06-16 11:57:05 -07:00
97bb88f10b docs: wrong example in routerLink (#37590)
In routerLink if a fragment is added than fragment example shows that it is added before the params '/user/bob#education?debug=true' but actually they are added after that '/user/bob?debug=true#education' changed documentation to show correct example

Fixes #18630

PR Close #37590
2020-06-16 09:45:23 -07:00
6c7467a58b perf(forms): optimize internal method _anyControls in FormGroup (#32534)
The method was previously looping through all controls, even after finding at least one that
satisfies the provided condition. This can be a bottleneck with large forms. The new version
of the method returns as soon as a single control which conforms to the condition is found.

PR Close #32534
2020-06-15 14:31:48 -07:00
c579a85c12 ci: include PR author as an approver of all PRs (#36915)
This change adds an implicit approval for any change by the
PR author.  This allows for a PR author to provide the required
owner approval for an area of the code base.

This change helps to align the review methodology with how Google's
internal system works. Where anyone is able to provide the LGTM
for a change if thats all that is needed.

PR Close #36915
2020-06-15 14:29:33 -07:00
400fdd08fd fix(dev-infra): allow for deep merging of pullapprove config aliases (#36915)
Set the yaml parser to support deep merges of yaml aliases,
to support having a default value for all rules to build upon.

PR Close #36915
2020-06-15 14:29:33 -07:00
c1fe6c9c81 release: cut the v10.0.0-rc.6 release 2020-06-15 14:01:15 -07:00
c58a0bea91 build: Update size to make tests pass again
`//integration:cli-hello-world-ivy-i18n_test` was failing because the size has decreased from expected 37640 to actual 37246.
2020-06-15 13:51:02 -07:00
88a934b93c refactor(compiler-cli): skip class decorators in tooling constructor parameters transform (#37545)
We recently added a transformer to NGC that is responsible for downleveling Angular
decorators and constructor parameter types. The primary goal was to mitigate a
TypeScript limitation/issue that surfaces in Angular projects due to the heavy
reliance on type metadata being captured for DI. Additionally this is a pre-requisite
of making `tsickle` optional in the Angular bazel toolchain.

See: 401ef71ae5 for more context on this.

Another (less important) goal was to make sure that the CLI can re-use
this transformer for its JIT mode compilation. The CLI (as outlined in
the commit mentioned above), already has a transformer for downleveling
constructor parameters. We want to avoid this duplication and exported
the transform through the tooling-private compiler entry-point.

Early experiments in using this transformer over the current one, highlighted
that in JIT, class decorators cannot be downleveled. Angular relies on those
to be invoked immediately for JIT (so that factories etc. are generated upon loading)

The transformer we exposed, always downlevels such class decorators
though, so that would break CLI's JIT mode. We can address the CLI's
needs by adding another flag to skip class decorators. This will allow
us to continue with the goal of de-duplication.

PR Close #37545
2020-06-15 12:47:57 -07:00
cde5cced69 refactor(compiler-cli): make IncrementalBuild strategy configurable (#37339)
Commit 24b2f1da2b introduced an `NgCompiler` which operates on a
`ts.Program` independently of the `NgtscProgram`. The NgCompiler got its
`IncrementalDriver` (for incremental reuse of Angular compilation results)
by looking at a monkey-patched property on the `ts.Program`.

This monkey-patching operation causes problems with the Angular indexer
(specifically, it seems to cause the indexer to retain too much of prior
programs, resulting in OOM issues). To work around this, `IncrementalDriver`
reuse is now handled by a dedicated `IncrementalBuildStrategy`. One
implementation of this interface is used by the `NgtscProgram` to perform
the old-style reuse, relying on the previous instance of `NgtscProgram`
instead of monkey-patching. Only for `NgTscPlugin` is the monkey-patching
strategy used, as the plugin sits behind an interface which only provides
access to the `ts.Program`, not a prior instance of the plugin.

PR Close #37339
2020-06-15 09:50:09 -07:00
472bedd3ea docs(service-worker): minor fixes/improvements in the SW Communication guide (#37555)
This commit includes various fixes/improvements for the
"Service worker communication" guide.

This partially addresses #37527.

PR Close #37555
2020-06-15 09:48:56 -07:00
d8a06d03bd docs(service-worker): update default value of SwRegistrationOptions#registrationStrategy (#37555)
The default value was changed from `registerWhenStable` to
`registerWhenStable:30000` in 29e8a64cf0,
but the decumentation was not updated to reflect that.

This commit updates the documentation to mention the correct default
value.

PR Close #37555
2020-06-15 09:48:56 -07:00
32020f9fb3 fix(language-service): wrong completions in conditional operator (#37505)
In `a ? b.~{cursor}`, the LS will provide the symbols in the scope of the current template, because the `path.tail` is `falseExp` whose value is `EmptyExpr`, and the span of `falseExp` is wider than the `trueExp`, so the value of `path` should be narrowed.

PR Close #37505
2020-06-15 09:41:26 -07:00
d574b14934 docs: describe how to configure CommonJS modules (#37331)
In version 10, we have a new option for the `angular.json` file,
`allowedCommonJsDependencies`, so users can opt in to support
CommonJS modules.

PR Close #37331
2020-06-15 09:40:45 -07:00
00c5d89e7d refactor: move hover into a proper @media hover (#37320)
This commit moves the contributor hover into the `@media(hover:hover)`
query. This will help to identify if the user's primary input mechanism
can hover over elements.

PR Close #37320
2020-06-15 09:39:17 -07:00
d2c8aefe64 docs: Update documentation to reflect addition of tsconfig.base.json. (#37222)
In version 10, there is a new `tsconfig.json` file, which contains
the paths to all other `tsconfig` files used in a workspace. The
previous `tsconfig.json` file still exists, but has been renamed to
`tsconfig.base.json`.

In addition to documenting this change, I have updated files that
refer to TypeScript configuration files generically to remove specific
references to `tsconfig.json.` This should help avoid confusing users.

PR Close #37222
2020-06-15 09:37:01 -07:00
ba796bbdd3 feat(bazel): expose explicit mapping from closure to devmode files (#36262)
This feature is aimed at development tooling that has to translate
production build inputs into their devmode equivalent. The current
process involves guessing the devmode filename based on string
replace patterns. This allows consuming build actions to read the
known mappings instead.

This is a change in anticipation of an update to the general
Typescript build rules to consume this data.

PR Close #36262
2020-06-15 09:35:35 -07:00
a0bb2ba7b7 docs: Change 'function' to 'method' for clarity that getHereos() is (#35998)
intended as a class method

Change 'function' to 'method' for clarity that getHereos() is
intended as a class method in Tour of Heroes part 4.

PR Close #35998
2020-06-15 09:07:52 -07:00
f9fa3b5b6c docs: update CONTRIBUTING.md with info about major docs changes (#35238)
The goal of this change is to clarify definition of major feature submissions to include writing new topics for the docs.

PR Close #35238
2020-06-15 09:05:16 -07:00
f89d438116 docs: fix typo in control_value_accessor.ts (#37057)
This commit updates the `ControlValueAccessor` class description in the `@angular/forms` package to fix a typo.

PR Close #37057
2020-06-12 15:11:11 -07:00
1abe791d46 Revert "feat(platform-server): use absolute URLs from Location for HTTP (#37071)" (#37547)
This reverts commit 9edea0bb75.

PR Close #37547
2020-06-12 15:09:58 -07:00
1502ae78b6 Revert "fix(platform-server): correctly handle absolute relative URLs (#37341)" (#37547)
This reverts commit 420d1c35f5.

PR Close #37547
2020-06-12 15:09:58 -07:00
bad6e719de feat(dev-infra): add # to outputed list of PRs for discover-new-conflicts (#37556)
Adding in a `#` prepended to each PR number in the list of conflicting PRs
found by the discover-new-conflicts script will allow for users to copy
paste the output from the script into a github comment and have the PRs
automatically link.

PR Close #37556
2020-06-12 15:08:53 -07:00
8c7129f3d2 ci: upload build results to ResultStore for CI linux bazel executions (#37560)
Bazel invocations will upload to ResultStore to allow for us to have better viewing
of execution/build logs.  This is only done on CI as the BES API requires credentials
from service accounts, rather than end user accounts.

PR Close #37560
2020-06-12 15:08:04 -07:00
dbff6f71e1 style(common): enforce format on newly included files (#36940)
Historically files to be formatted were added to a listing (via matchers)
to be included in formatting.  Instead, this change begins efforts to
instead include all files in format enforcement, relying instead on an
opt out methodology.

PR Close #36940
2020-06-12 15:06:43 -07:00
fcd934ccf6 style(dev-infra): enforce format on newly included files (#36940)
Historically files to be formatted were added to a listing (via matchers)
to be included in formatting.  Instead, this change begins efforts to
instead include all files in format enforcement, relying instead on an
opt out methodology.

PR Close #36940
2020-06-12 15:06:43 -07:00
45a8f340d9 build: increase scope of files with enforced formatting (#36940)
Historically files to be formatted were added to a listing (via matchers)
to be included in formatting.  Instead, this change begins efforts to
instead include all files in format enforcement, relying instead on an
opt out methodology.

PR Close #36940
2020-06-12 15:06:42 -07:00
5856513405 docs: add redirects for cli generated config files (#37533)
With this change we add redirects for config files generated by the Angular CLI. These links form part of a comment in the generated files, thus it is important that they valid for the many years to come.

PR Close #37533
2020-06-12 08:51:24 -07:00
01fa3ee5c3 docs: fix contributor website links with no protocol (#37528)
Two contributor website links do not have a protocol so they are treated as a relative URL and do not work as expected.

PR Close #37528
2020-06-12 08:50:52 -07:00
b8d69ffdf3 docs: document how external link icons work (#37025)
After PR #36601 which added icons to all external links. Documented how this is happening via comments in scss file. For details visit PR #36601

PR Close #37025
2020-06-12 08:50:18 -07:00
7ef60ec2a9 docs: small change in the Introduction (#35528)
The word "both" is automatically connected with the previous two bullet points and not the following two (because documents are usually read from top to bottom), which made the original sentence confusing for first time readers.

PR Close #35528
2020-06-11 19:11:57 -07:00
83f905c0e1 docs: fix result of sanitization example (#36059)
This commit fixes sanitization example
in https://angular.io/guide/template-syntax#content-security.

* Escape < and > of interpolation result.
* Fix result of property binding result.

PR Close #36059
2020-06-11 19:11:23 -07:00
72ba3a3918 docs: make correction in Tutorial toh-pt6 (#37516)
Fixes issue [29535](https://github.com/angular/angular/issues/29535) for the tutorial (toh-pt6) to remove the phrase that directed the reader to delete mock-heroes.ts when it is still needed for further tutorial steps.

PR Close #37516
2020-06-11 19:10:49 -07:00
df10597da4 fix(compiler): unable to resolve destructuring variable declarations (#37497)
Currently the partial evaluator isn't able to resolve a variable declaration that uses destructuring in the form of `const {value} = {value: 0}; const foo = value;`. These changes add some logic to allow for us to resolve the variable's value.

Fixes #36917.

PR Close #37497
2020-06-11 19:10:04 -07:00
5db2e794a9 fix(router): fix navigation ignoring logic to compare to the browser url (#37408)
This PR changes the logic for determining when to skip route processing from
using the URL of the last attempted navigation to the actual resulting URL after
that transition.

Because guards may prevent navigation and reset the browser URL, the raw
URL of the previous transition may not match the actual URL of the
browser at the end of the navigation process. For that reason, we need to use
`urlAfterRedirects` instead.

Other notes:
These checks in scheduleNavigation were added in eb2ceff4ba
The test still passes and, more surprisingly, passes if the checks are removed
completely. There have likely been changes to the navigation handling that
handle the test in a different way. That said, it still appears to be important
to keep the checks there in some capacity because it does affect how many
navigation events occur. This addresses an issue that came up in #16710: https://github.com/angular/angular/issues/16710#issuecomment-634869739
This also partially addresses #13586 in fixing history for imperative
navigations that are cancelled by guards.

PR Close #37408
2020-06-11 19:03:41 -07:00
486aa06747 docs: add tslib change to v10 CHANGELOG (#37303)
Previously the tslib 2.0 change was not listed in the CHANGELOG because
it was marked as a refactoring. This change is important enough to be
listed in the changelog even tough it doesn't affect most of the users.

For users that do get unexpectedly affected by this change, it might be
useful to find the change listed in the CHANGELOG.

PR Close #37303
2020-06-11 19:01:26 -07:00
01ce1b32df refactor(compiler): remove extra imports (#37246)
There are some extra imports in the compiler package. These imports are not used anywhere in the file. So, removed those extra imports

PR Close #37246
2020-06-11 19:00:34 -07:00
c78b0b2c51 docs: update api ref doc for platform browser (#37186)
Edit descriptions, usage examples, and add links to be complete and consistent with API reference doc style

PR Close #37186
2020-06-11 18:59:12 -07:00
9ade1c3ea3 fix(ngcc): correctly get config for packages in nested node_modules/ (#37040)
Previously, ngcc would only be able to match an ngcc configuration to
packages that were located inside the project's top-level
`node_modules/`. However, if there are multiple versions of a package in
a project (e.g. as a transitive dependency of other packages), multiple
copies of a package (at different versions) may exist in nested
`node_modules/` directories. For example, one at
`<project-root>/node_modules/some-package/` and one at
`<project-root>/node_modules/other-package/node_modules/some-package/`.
In such cases, ngcc was only able to detect the config for the first
copy but not for the second.

This commit fixes this by returning a new instance of
`ProcessedNgccPackageConfig` for each different package path (even if
they refer to the same package name). In these
`ProcessedNgccPackageConfig`, the `entryPoints` paths have been
processed to take the package path into account.

PR Close #37040
2020-06-11 18:58:38 -07:00
315a4cfcd4 refactor(ngcc): add packageName property to EntryPoint interface (#37040)
This commit adds a `packageName` property to the `EntryPoint` interface.
In a subsequent commit this will be used to retrieve the correct ngcc
configuration for each package, regardless of its path.

PR Close #37040
2020-06-11 18:58:38 -07:00
11c04027ab fix(ngcc): correctly retrieve a package's version from its package.json (#37040)
In order to retrieve the ngcc configuration (if any) for an entry-point,
ngcc has to detect the containing package's version.

Previously, ngcc would try to read the version from the entry-point's
`package.json` file, which was different than the package's top-level
`package.json` for secondary entry-points. For example, it would try to
read it from `node_modules/@angular/common/http/package.json` for
entry-point `@angular/common/http`. However, the `package.json` files
for secondary entry-points are not guaranteed to include a `version`
property.

This commit fixes this by first trying to read the version from the
_package's_ `package.json` (falling back to the entry-point's
`package.json`). For example, it will first try to read it from
`@angular/common/package.json` for entry-point `@angular/common/http`.

PR Close #37040
2020-06-11 18:58:38 -07:00
eabe3b4c39 refactor(ngcc): refactor how info is retrieved from entry-point package.json (#37040)
This commit refactors the way info is retrieved from entry-point
`package.json` files to make it easier to extract more info (such as the
package's name) in the future. It also avoids reading and parsing the
`package.json` file multiple times (as was happening before).

PR Close #37040
2020-06-11 18:58:37 -07:00
d471454675 refactor(ngcc): rename EntryPoint#package to EntryPoint#packagePath (#37040)
Rename the `package` property to `packagePath` on the `EntryPoint`
interface. This makes it more clear that the `packagePath` property
holds the absolute path to the containing package (similar to how `path`
holds the path to the entry-point). This will also align with the
`packageName` property that will be added in a subsequent commit.

This commit also re-orders the `EntryPoint` properties to group related
properties together and to match the order of properties on instances
with that on the interface.

PR Close #37040
2020-06-11 18:58:37 -07:00
bf57776b59 fix(ngcc): correctly get config for sub-entry-points when primary entry-point is ignored (#37040)
Previously, when an entry-point was ignored via an ngcc config, ngcc
would scan sub-directories for sub-entry-points, but would not use the
correct `packagePath`. For example, if `@angular/common` was ignored, it
would look at `@angular/common/http` but incorrectly use
`.../@angular/common/http` as the `packagePath` (instead of
`.../@angular/common`). As a result, it would not retrieve the correct
ngcc config for the actual package.

This commit fixes it by ensuring the correct `packagePath` is used, even
if the primary entry-point corresponding to that path is ignored. In
order to do this, a new return value for `getEntryPointInfo()` is added:
`IGNORED_ENTRY_POINT`. This is used to differentiate between directories
that correspond to no or an incompatible entry-point and those that
correspond to an entry-point that could otherwise be valid but is
explicitly ignored. Consumers of `getEntryPointInfo()` can then use this
info to discard ignored entry-points, but still use the correct
`packagePath` when scanning their sub-directories for secondary
entry-points.

PR Close #37040
2020-06-11 18:58:37 -07:00
a32579ae5b refactor(ngcc): clean up unused imports, unused regex parenthesis, typos (#37040)
This is a follow-up to #37075, because I didn't manage to finish my
review before the PR got merged.

PR Close #37040
2020-06-11 18:58:37 -07:00
780601d27a refactor(ngcc): fix typos in comments (#37040)
This is a follow-up to #36944, because I didn't manage to finish my
review before the PR got merged.

PR Close #37040
2020-06-11 18:58:37 -07:00
c909e731d7 fix(zone.js): remove unused Promise overwritten setter logic (#36851)
In the early Zone.js versions (< 0.10.3), `ZoneAwarePromise` did not support `Symbol.species`,
so when user used a 3rd party `Promise` such as `es6-promise`, and try to load the promise library after import of `zone.js`, the loading promise library will overwrite the patched `Promise` from `zone.js` and will break `Promise` semantics with respect to `zone.js`.

Starting with `zone.js` 0.10.3, `Symbol.species` is supported therefore this will not longer be an issue. (https://github.com//pull/34533)

Before 0.10.3, the logic in zone.js tried to handle the case in the wrong way. It did so by overriding the descriptor of `global.Promise`, to allow the 3rd party libraries to override native `Promise` instead of `ZoneAwarePromise`. This is not the correct solution, and since the `Promise.species` is now supported, the 3rd party solution of overriding `global.Promise` is no longer needed.

PR removes the wrong work around logic. (This will improve the bundle size.)

PR Close #36851
2020-06-11 18:56:19 -07:00
9b8eb42354 fix(core): should fake a top event task when coalescing events to prevent draining microTaskQueue too early. (#36841)
Close #36839.

This is a known issue of zone.js,

```
(window as any)[(Zone as any).__symbol__('setTimeout')](() => {
  let log = '';
  button.addEventListener('click', () => {
    Zone.current.scheduleMicroTask('test', () => log += 'microtask;');
    log += 'click;';
  });
  button.click();
  expect(log).toEqual('click;microtask;');
  done();
});
```

Since in this case, we use native `setTimeout` which is not a ZoneTask,
so zone.js consider the button click handler as the top Task then drain the
microTaskQueue after the click at once, which is not correct(too early).

This case was an edge case and not reported by the users, until we have the
new option ngZoneEventCoalescing, since the event coalescing will happen
in native requestAnimationFrame, so it will not be a ZoneTask, and zone.js will
consider any Task happen in the change detection stage as the top task, and if
there are any microTasks(such as Promise.then) happen in the process, it may be
drained earlier than it should be, so to prevent this situation, we need to schedule
a fake event task and run the change detection check in this fake event task,
so the Task happen in the change detection stage will not be
considered as top ZoneTask.

PR Close #36841
2020-06-11 18:54:22 -07:00
0757174e8e docs: Refactor-pipes (#36820)
Language tightened, and headings rewritten to focus on user tasks. Tasks now separated from concepts, and clarified as examples. Content is up-to-date and complete. Links to important information and relevant topics added.

PR Close #36820
2020-06-11 18:45:15 -07:00
1434 changed files with 50729 additions and 52498 deletions

View File

@ -19,4 +19,12 @@ build --local_ram_resources=14336
# All build executed remotely should be done using our RBE configuration.
build:remote --google_default_credentials
# Upload to GCP's Build Status viewer to allow for us to have better viewing of execution/build
# logs. This is only done on CI as the BES (GCP's Build Status viewer) API requires credentials
# from service accounts, rather than end user accounts.
build:remote --bes_backend=buildeventservice.googleapis.com
build:remote --bes_timeout=30s
build:remote --bes_results_url="https://source.cloud.google.com/results/invocations/"
build --config=remote

View File

@ -32,7 +32,7 @@ var_4_win: &cache_key_win_fallback v7-angular-win-node-12-{{ checksum ".bazelver
# Cache key for the `components-repo-unit-tests` job. **Note** when updating the SHA in the
# cache keys also update the SHA for the "COMPONENTS_REPO_COMMIT" environment variable.
var_5: &components_repo_unit_tests_cache_key v7-angular-components-189d98e8b01b33974328255f085de04251d61567
var_5: &components_repo_unit_tests_cache_key v7-angular-components-f428c00465dfcf8a020237f22532480eedbd2cb6
var_6: &components_repo_unit_tests_cache_key_fallback v7-angular-components-
# Workspace initially persisted by the `setup` job, and then enhanced by `build-npm-packages` and

View File

@ -74,7 +74,7 @@ setPublicVar COMPONENTS_REPO_TMP_DIR "/tmp/angular-components-repo"
setPublicVar COMPONENTS_REPO_URL "https://github.com/angular/components.git"
setPublicVar COMPONENTS_REPO_BRANCH "master"
# **NOTE**: When updating the commit SHA, also update the cache key in the CircleCI `config.yml`.
setPublicVar COMPONENTS_REPO_COMMIT "189d98e8b01b33974328255f085de04251d61567"
setPublicVar COMPONENTS_REPO_COMMIT "f428c00465dfcf8a020237f22532480eedbd2cb6"
####################################################################################################

View File

@ -60,14 +60,15 @@ if (require.resolve === module) {
// Helpers
function _main(args) {
triggerWebhook(...args).
then(({statusCode, responseText}) => (200 <= statusCode && statusCode < 400) ?
console.log(`Status: ${statusCode}\n${responseText}`) :
Promise.reject(new Error(`Request failed (status: ${statusCode}): ${responseText}`))).
catch(err => {
console.error(err);
process.exit(1);
});
triggerWebhook(...args)
.then(
({statusCode, responseText}) => (200 <= statusCode && statusCode < 400) ?
console.log(`Status: ${statusCode}\n${responseText}`) :
Promise.reject(new Error(`Request failed (status: ${statusCode}): ${responseText}`)))
.catch(err => {
console.error(err);
process.exit(1);
});
}
function postJson(url, data) {
@ -77,15 +78,12 @@ function postJson(url, data) {
const statusCode = res.statusCode || -1;
let responseText = '';
res.
on('error', reject).
on('data', d => responseText += d).
on('end', () => resolve({statusCode, responseText}));
res.on('error', reject)
.on('data', d => responseText += d)
.on('end', () => resolve({statusCode, responseText}));
};
request(url, opts, onResponse).
on('error', reject).
end(JSON.stringify(data));
request(url, opts, onResponse).on('error', reject).end(JSON.stringify(data));
});
}

145
.gitmessage Normal file
View File

@ -0,0 +1,145 @@
<type>(<scope>): <summary>
<Describe the motivation behind this change - explain WHY you are making this change. Wrap all lines
at 100 characters.>
Fixes #<issue number>
# ────────────────────────────────────────── 100 chars ────────────────────────────────────────────┤
# Example Commit Messages
# =======================
# ─── Example: Simple refactor ────────────────────────────────────────────────────────────────────┤
# refactor(core): rename refreshDynamicEmbeddedViews to refreshEmbeddedViews
#
# Improve code readability. The original name no longer matches how the function is used.
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
# ─── Example: Simple docs change ─────────────────────────────────────────────────────────────────┤
# docs: clarify the service limitation in providers.md guide
#
# Fixes #36332
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
# ─── Example: A bug fix ──────────────────────────────────────────────────────────────────────────┤
# fix(ngcc): ensure lockfile is removed when `analyzeFn` fails
#
# Previously an error thrown in the `analyzeFn` would cause the ngcc process to exit immediately
# without removing the lockfile, and potentially before the unlocker process had been successfully
# spawned resulting in the lockfile being orphaned and left behind.
#
# Now we catch these errors and remove the lockfile as needed.
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
# ─── Example: Breaking change ────────────────────────────────────────────────────────────────────┤
# feat(bazel): simplify ng_package by dropping esm5 and fesm5
#
# esm5 and fesm5 distributions are no longer needed and have been deprecated in the past.
#
# https://v9.angular.io/guide/deprecations#esm5-and-fesm5-code-formats-in-angular-npm-packages
#
# This commit modifies ng_package to no longer distribute these two formats in npm packages built by
# ng_package (e.g. @angular/core).
#
# This commit intentionally doesn't fully clean up the ng_package rule to remove all traces of esm5
# and fems5 build artifacts as that is a bigger cleanup and currently we are narrowing down the
# scope of this change to the MVP needed for v10, which in this case is 'do not put esm5 and fesm5'
# into the npm packages.
#
# More cleanup to follow: https://angular-team.atlassian.net/browse/FW-2143
#
# BREAKING CHANGE: esm5 and fesm5 format is no longer distributed in Angular's npm packages e.g.
# @angular/core
#
# Angular CLI will automatically downlevel the code to es5 if differential loading is enabled in the
# Angular project, so no action is required from Angular CLI users.
#
# If you are not using Angular CLI to build your application or library, and you need to be able to
# build es5 artifacts, then you will need to downlevel the distributed Angular code to es5 on your
# own.
#
#
# Fixes #1234
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
# Angular Commit Message Format
# =============================
#
# The full specification of the Angular Commit Message Format can be found at
# https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
#
# The following is an excerpt of the specification with the most commonly needed info.
#
# Each commit message consists of a *header*, a *body*, and a *footer*.
#
# <header>
# <BLANK LINE>
# <body>
# <BLANK LINE>
# <footer>
#
# The header is mandatory.
#
# The body is mandatory for all commits except for those of scope "docs". When the body is required
# it must be at least 20 characters long.
#
# The footer is optional.
#
# Any line of the commit message cannot be longer than 100 characters.
#
#
# Commit Message Header
# ---------------------
#
# <type>(<scope>): <short summary>
# │ │ │
# │ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
# │ │
# │ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
# │ elements|forms|http|language-service|localize|platform-browser|
# │ platform-browser-dynamic|platform-server|platform-webworker|
# │ platform-webworker-dynamic|router|service-worker|upgrade|zone.js|
# │ packaging|changelog|dev-infra|docs-infra|migrations|ngcc|ve
# │ https://github.com/angular/angular/blob/master/CONTRIBUTING.md#scope
# │
# └─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
# https://github.com/angular/angular/blob/master/CONTRIBUTING.md#type
#
#
# Commit Message Body
# ---------------------
#
# Just as in the summary, use the imperative, present tense: "fix" not "fixed" nor "fixes".
#
# Explain the motivation for the change in the commit message body. This commit message should
# explain WHY you are making the change. You can include a comparison of the previous behavior with
# the new behavior in order to illustrate the impact of the change.
#
#
# Commit Message Footer
# ---------------------
#
# The footer can contain information about breaking changes and is also the place to reference
# GitHub issues, Jira tickets, and other PRs that this commit closes or is related to.
#
# ```
# BREAKING CHANGE: <breaking change summary>
# <BLANK LINE>
# <breaking change description + migration instructions>
# <BLANK LINE>
# <BLANK LINE>
# Fixes #<issue number>
# ```
#
# Breaking Change section should start with the phrase "BREAKING CHANGE: " followed by a summary of
# the breaking change, a blank line, and a detailed description of the breaking change that also
# includes migration instructions.
#

52
.ng-dev/commit-message.ts Normal file
View File

@ -0,0 +1,52 @@
import {CommitMessageConfig} from '../dev-infra/commit-message/config';
/**
* The configuration for `ng-dev commit-message` commands.
*/
export const commitMessage: CommitMessageConfig = {
maxLineLength: 120,
minBodyLength: 20,
minBodyLengthTypeExcludes: ['docs'],
types: [
'build',
'ci',
'docs',
'feat',
'fix',
'perf',
'refactor',
'release',
'style',
'test',
],
scopes: [
'animations',
'bazel',
'benchpress',
'changelog',
'common',
'compiler',
'compiler-cli',
'core',
'dev-infra',
'docs-infra',
'elements',
'forms',
'http',
'language-service',
'localize',
'migrations',
'ngcc',
'packaging',
'platform-browser',
'platform-browser-dynamic',
'platform-server',
'platform-webworker',
'platform-webworker-dynamic',
'router',
'service-worker',
'upgrade',
've',
'zone.js',
]
};

View File

@ -1,122 +1,8 @@
import {MergeConfig} from '../dev-infra/pr/merge/config';
import {commitMessage} from './commit-message';
import {format} from './format';
import {github} from './github';
import {merge} from './merge';
// The configuration for `ng-dev commit-message` commands.
const commitMessage = {
'maxLength': 120,
'minBodyLength': 100,
'types': [
'build',
'ci',
'docs',
'feat',
'fix',
'perf',
'refactor',
'release',
'style',
'test',
],
'scopes': [
'animations',
'bazel',
'benchpress',
'changelog',
'common',
'compiler',
'compiler-cli',
'core',
'dev-infra',
'docs-infra',
'elements',
'forms',
'http',
'language-service',
'localize',
'migrations',
'ngcc',
'packaging',
'platform-browser',
'platform-browser-dynamic',
'platform-server',
'platform-webworker',
'platform-webworker-dynamic',
'router',
'service-worker',
'upgrade',
've',
'zone.js',
]
};
// The configuration for `ng-dev format` commands.
const format = {
'clang-format': {
'matchers': [
'dev-infra/**/*.{js,ts}',
'packages/**/*.{js,ts}',
'!packages/zone.js',
'!packages/common/locales/**/*.{js,ts}',
'!packages/common/src/i18n/available_locales.ts',
'!packages/common/src/i18n/currencies.ts',
'!packages/common/src/i18n/locale_en.ts',
'modules/benchmarks/**/*.{js,ts}',
'modules/playground/**/*.{js,ts}',
'tools/**/*.{js,ts}',
'!tools/gulp-tasks/cldr/extract.js',
'!tools/public_api_guard/**/*.d.ts',
'!tools/ts-api-guardian/test/fixtures/**',
'*.{js,ts}',
'!**/node_modules/**',
'!**/dist/**',
'!**/built/**',
'!shims_for_IE.js',
]
},
'buildifier': true
};
/** Github metadata information for `ng-dev` commands. */
const github = {
owner: 'angular',
name: 'angular',
};
// Configuration for the `ng-dev pr merge` command. The command can be used
// for merging upstream pull requests into branches based on a PR target label.
const merge = () => {
// TODO: resume dynamically determining patch branch
const patch = '10.0.x';
const config: MergeConfig = {
githubApiMerge: false,
claSignedLabel: 'cla: yes',
mergeReadyLabel: /^PR action: merge(-assistance)?/,
commitMessageFixupLabel: 'commit message fixup',
labels: [
{
pattern: 'PR target: master-only',
branches: ['master'],
},
{
pattern: 'PR target: patch-only',
branches: [patch],
},
{
pattern: 'PR target: master & patch',
branches: ['master', patch],
},
],
requiredBaseCommits: {
// PRs that target either `master` or the patch branch, need to be rebased
// on top of the latest commit message validation fix.
// These SHAs are the commits that update the required license text in the header.
'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a',
[patch]: '27b95ba64a5d99757f4042073fd1860e20e3ed24'
},
};
return config;
};
// Export function to build ng-dev configuration object.
module.exports = {
commitMessage,
format,

22
.ng-dev/format.ts Normal file
View File

@ -0,0 +1,22 @@
import {FormatConfig} from '../dev-infra/format/config';
/**
* Configuration for the `ng-dev format` command.
*/
export const format: FormatConfig = {
'clang-format': {
'matchers': [
'**/*.{js,ts}',
// TODO: burn down format failures and remove aio and integration exceptions.
'!aio/**',
'!integration/**',
// Both third_party and .yarn are directories containing copied code which should
// not be modified.
'!third_party/**',
'!.yarn/**',
// Do not format d.ts files as they are generated
'!**/*.d.ts',
]
},
'buildifier': true
};

15
.ng-dev/gitconfig Normal file
View File

@ -0,0 +1,15 @@
# The file is inert unless it's explicitly included into the local git config via:
#
# ```
# git config --add include.path '../.ng-dev/gitconfig'
# ```
#
# Calling that command will append the following into `.git/config` of the current git workspace
# (i.e. $GIT_DIR, typically `angular/.git/config`):
#
# ```
# [include]
# path = ../.ng-dev/gitconfig
# ```
[commit]
template = .gitmessage

11
.ng-dev/github.ts Normal file
View File

@ -0,0 +1,11 @@
import {GithubConfig} from '../dev-infra/utils/config';
/**
* Github configuration for the `ng-dev` command. This repository is used as
* remote for the merge script and other utilities like `ng-dev pr rebase`.
*/
export const github: GithubConfig = {
owner: 'angular',
name: 'angular'
};

38
.ng-dev/merge.ts Normal file
View File

@ -0,0 +1,38 @@
import {MergeConfig} from '../dev-infra/pr/merge/config';
/**
* Configuration for the merge tool in `ng-dev`. This sets up the labels which
* are respected by the merge script (e.g. the target labels).
*/
export const merge = (): MergeConfig => {
// TODO: resume dynamically determining patch branch
const patch = '10.0.x';
return {
githubApiMerge: false,
claSignedLabel: 'cla: yes',
mergeReadyLabel: /^PR action: merge(-assistance)?/,
caretakerNoteLabel: 'PR action: merge-assistance',
commitMessageFixupLabel: 'commit message fixup',
labels: [
{
pattern: 'PR target: master-only',
branches: ['master'],
},
{
pattern: 'PR target: patch-only',
branches: [patch],
},
{
pattern: 'PR target: master & patch',
branches: ['master', patch],
},
],
requiredBaseCommits: {
// PRs that target either `master` or the patch branch, need to be rebased
// on top of the latest commit message validation fix.
// These SHAs are the commits that update the required license text in the header.
'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a',
[patch]: '27b95ba64a5d99757f4042073fd1860e20e3ed24'
},
};
};

View File

@ -34,41 +34,8 @@
####################################################################################
# GitHub usernames
####################################################################################
# aikidave - Dave Shevitz
# alan-agius4 - Alan Agius
# alxhub - Alex Rickabaugh
# AndrewKushnir - Andrew Kushnir
# andrewseguin - Andrew Seguin
# atscott - Andrew Scott
# ayazhafiz - Ayaz Hafiz
# clydin - Charles Lyding
# crisbeto - Kristiyan Kostadinov
# dennispbrown - Denny Brown
# devversion - Paul Gschwendtner
# dgp1130 - Doug Parker
# filipesilva - Filipe Silva
# gkalpak - Georgios Kalpakas
# gregmagolan - Greg Magolan
# IgorMinar - Igor Minar
# jbogarthyde - Judy Bogart
# jelbourn - Jeremy Elbourn
# JiaLiPassion - Jia Li
# JoostK - Joost Koehoorn
# josephperrott - Joey Perrott
# juleskremer - Jules Kremer
# kapunahelewong - Kapunahele Wong
# kara - Kara Erickson
# kyliau - Keen Yee Liau
# manughub - Manu Murthy
# matsko - Matias Niemela
# mgechev - Minko Gechev
# mhevery - Miško Hevery
# michaelprentice - Michael Prentice
# mmalerba - Miles Malerba
# petebacondarwin - Pete Bacon Darwin
# pkozlowski-opensource - Pawel Kozlowski
# robwormald - Rob Wormald
# StephenFluin - Stephen Fluin
# See reviewer list under `required-minimum-review` group. Team member names and
# usernames are managed there.
####################################################################################
@ -100,8 +67,16 @@ version: 3
# Meta field that goes unused by PullApprove to allow for defining aliases to be
# used throughout the config.
meta:
1: &can-be-global-approved "\"global-approvers\" not in groups.approved"
2: &can-be-global-docs-approved "\"global-docs-approvers\" not in groups.approved"
can-be-global-approved: &can-be-global-approved "\"global-approvers\" not in groups.approved"
can-be-global-docs-approved: &can-be-global-docs-approved "\"global-docs-approvers\" not in groups.approved"
defaults: &defaults
reviews:
# Authors provide their approval implicitly, this approval allows for a reviewer
# from a group not to need a review specifically for an area of the repository
# they own. This is coupled with the `required-minimum-review` group which requires
# that all PRs are reviewed by at least one team member who is not the author of
# the PR.
author_value: 1
# turn on 'draft' support
# https://docs.pullapprove.com/config/github-api-version/
@ -121,6 +96,55 @@ pullapprove_conditions:
groups:
# =========================================================
# Require review on all PRs
#
# All PRs require at least one review. This rule will not
# request any reviewers, however will require that at least
# one review is provided before the group is satisfied.
# =========================================================
required-minimum-review:
reviews:
request: 0 # Do not request any reviews from the reviewer group
required: 1 # Require that all PRs have approval from at least one of the users in the group
author_value: 0 # The author of the PR cannot provide an approval for themself
reviewers:
users:
- aikidave # Dave Shevitz
- alan-agius4 # Alan Agius
- alxhub # Alex Rickabaugh
- AndrewKushnir # Andrew Kushnir
- andrewseguin # Andrew Seguin
- atscott # Andrew Scott
- ayazhafiz # Ayaz Hafiz
- clydin # Charles Lyding
- crisbeto # Kristiyan Kostadinov
- dennispbrown # Denny Brown
- devversion # Paul Gschwendtner
- dgp1130 # Doug Parker
- filipesilva # Filipe Silva
- gkalpak # Georgios Kalpakas
- gregmagolan # Greg Magolan
- IgorMinar # Igor Minar
- jbogarthyde # Judy Bogart
- jelbourn # Jeremy Elbourn
- JiaLiPassion # Jia Li
- JoostK # Joost Koehoorn
- josephperrott # Joey Perrott
- juleskremer # Jules Kremer
- kapunahelewong # Kapunahele Wong
- kara # Kara Erickson
- kyliau # Keen Yee Liau
- manughub # Manu Murthy
- matsko # Matias Niemela
- mgechev # Minko Gechev
- mhevery # Miško Hevery
- michaelprentice # Michael Prentice
- mmalerba # Miles Malerba
- petebacondarwin # Pete Bacon Darwin
- pkozlowski-opensource # Pawel Kozlowski
- StephenFluin # Stephen Fluin
# =========================================================
# Global Approvers
#
@ -161,6 +185,7 @@ groups:
# Framework: Animations
# =========================================================
fw-animations:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -185,6 +210,7 @@ groups:
# Framework: Compiler
# =========================================================
fw-compiler:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -209,6 +235,7 @@ groups:
# Framework: Compiler / ngcc
# =========================================================
fw-ngcc:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -225,6 +252,7 @@ groups:
# Framework: Migrations
# =========================================================
fw-migrations:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -240,6 +268,7 @@ groups:
# Framework: Core
# =========================================================
fw-core:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -333,6 +362,7 @@ groups:
'aio/content/images/guide/pipes/**',
'aio/content/guide/providers.md',
'aio/content/examples/providers/**',
'aio/content/images/guide/providers/**',
'aio/content/guide/singleton-services.md',
'aio/content/guide/set-document-title.md',
'aio/content/examples/set-document-title/**',
@ -359,6 +389,7 @@ groups:
# Framework: Http
# =========================================================
fw-http:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -380,6 +411,7 @@ groups:
# Framework: Elements
# =========================================================
fw-elements:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -400,6 +432,7 @@ groups:
# Framework: Forms
# =========================================================
fw-forms:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -432,6 +465,7 @@ groups:
# Framework: i18n
# =========================================================
fw-i18n:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -465,6 +499,7 @@ groups:
# Framework: Platform Server
# =========================================================
fw-platform-server:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -484,6 +519,7 @@ groups:
# Framework: Router
# =========================================================
fw-router:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -493,6 +529,7 @@ groups:
'packages/examples/router/**',
'aio/content/guide/router.md',
'aio/content/guide/router-tutorial.md',
'aio/content/guide/router-tutorial-toh.md',
'aio/content/examples/router-tutorial/**',
'aio/content/examples/router/**',
'aio/content/images/guide/router/**'
@ -506,6 +543,7 @@ groups:
# Framework: Service Worker
# =========================================================
fw-service-worker:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -533,6 +571,7 @@ groups:
# Framework: Upgrade
# =========================================================
fw-upgrade:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -563,6 +602,7 @@ groups:
# Framework: Testing
# =========================================================
fw-testing:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -570,6 +610,14 @@ groups:
contains_any_globs(files.exclude('packages/compiler-cli/**'), [
'**/testing/**',
'aio/content/guide/testing.md',
'aio/content/guide/test-debugging.md',
'aio/content/guide/testing-attribute-directives.md',
'aio/content/guide/testing-code-coverage.md',
'aio/content/guide/testing-components-basics.md',
'aio/content/guide/testing-components-scenarios.md',
'aio/content/guide/testing-pipes.md',
'aio/content/guide/testing-services.md',
'aio/content/guide/testing-utility-apis.md',
'aio/content/examples/testing/**',
'aio/content/images/guide/testing/**'
])
@ -584,6 +632,7 @@ groups:
# Framework: Benchmarks
# =========================================================
fw-benchmarks:
<<: *defaults
conditions:
- *can-be-global-approved
- >
@ -600,6 +649,7 @@ groups:
# Framework: Playground
# =========================================================
fw-playground:
<<: *defaults
conditions:
- *can-be-global-approved
- >
@ -617,6 +667,7 @@ groups:
# Framework: Security
# =========================================================
fw-security:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -646,6 +697,7 @@ groups:
# Bazel
# =========================================================
bazel:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -664,6 +716,7 @@ groups:
# Language Service
# =========================================================
language-service:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -683,6 +736,7 @@ groups:
# zone.js
# =========================================================
zone-js:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -701,6 +755,7 @@ groups:
# Benchpress
# =========================================================
benchpress:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -718,6 +773,7 @@ groups:
# Integration Tests
# =========================================================
integration-tests:
<<: *defaults
conditions:
- *can-be-global-approved
- >
@ -735,6 +791,7 @@ groups:
# Docs: Gettings Started & Tutorial
# =========================================================
docs-getting-started-and-tutorial:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -767,6 +824,7 @@ groups:
# Docs: Marketing
# =========================================================
docs-marketing:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -789,6 +847,7 @@ groups:
# Docs: Observables
# =========================================================
docs-observables:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -814,6 +873,7 @@ groups:
# Docs: Packaging, Tooling, Releasing
# =========================================================
docs-packaging-and-releasing:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -833,7 +893,7 @@ groups:
'aio/content/guide/migration-localize.md',
'aio/content/guide/migration-module-with-providers.md',
'aio/content/guide/static-query-migration.md',
'aio/content/guide/updating-to-version-9.md',
'aio/content/guide/updating-to-version-10.md',
'aio/content/guide/ivy-compatibility.md',
'aio/content/guide/ivy-compatibility-examples.md'
])
@ -873,6 +933,7 @@ groups:
# Docs: CLI
# =========================================================
docs-cli:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -889,8 +950,12 @@ groups:
'aio/content/images/guide/deployment/**',
'aio/content/guide/file-structure.md',
'aio/content/guide/ivy.md',
'aio/content/guide/strict-mode.md',
'aio/content/guide/web-worker.md',
'aio/content/guide/workspace-config.md',
'aio/content/guide/migration-solution-style-tsconfig.md',
'aio/content/guide/migration-update-module-and-target-compiler-options.md',
'aio/content/guide/migration-update-libraries-tslib.md',
])
reviewers:
users:
@ -903,6 +968,7 @@ groups:
# Docs: CLI Libraries
# =========================================================
docs-libraries:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -923,6 +989,7 @@ groups:
# Docs: Schematics
# =========================================================
docs-schematics:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -945,6 +1012,7 @@ groups:
# Docs-infra
# =========================================================
docs-infra:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -974,10 +1042,11 @@ groups:
# Dev-infra
# =========================================================
dev-infra:
<<: *defaults
conditions:
- *can-be-global-approved
- >
contains_any_globs(files.exclude("CHANGELOG.md"), [
contains_any_globs(files.exclude("CHANGELOG.md").exclude("packages/compiler-cli/**/BUILD.bazel"), [
'*',
'.circleci/**',
'.devcontainer/**',
@ -1038,6 +1107,7 @@ groups:
# Public API
# =========================================================
public-api:
<<: *defaults
conditions:
- *can-be-global-approved
- >
@ -1066,6 +1136,7 @@ groups:
# Size tracking
# ================================================
size-tracking:
<<: *defaults
conditions:
- *can-be-global-approved
- >
@ -1088,6 +1159,7 @@ groups:
# Circular dependencies
# ================================================
circular-dependencies:
<<: *defaults
conditions:
- *can-be-global-approved
- >
@ -1110,6 +1182,7 @@ groups:
# Code Ownership
# =========================================================
code-ownership:
<<: *defaults
conditions:
- *can-be-global-approved
- >
@ -1125,6 +1198,7 @@ groups:
# Catch all for if no groups match the code change
# ====================================================
fallback:
<<: *defaults
# A group is considered to be `active` for a PR if at least one of group's
# conditions matches the PR.
#

View File

@ -24,7 +24,7 @@ filegroup(
"//packages/zone.js/dist:zone-testing.js",
"//packages/zone.js/dist:task-tracking.js",
"//:test-events.js",
"//:shims_for_IE.js",
"//:third_party/shims_for_IE.js",
# Including systemjs because it defines `__eval`, which produces correct stack traces.
"@npm//:node_modules/systemjs/dist/system.src.js",
"@npm//:node_modules/reflect-metadata/Reflect.js",

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
# Contributing to Angular
We would love for you to contribute to Angular and help make it even better than it is
today! As a contributor, here are the guidelines we would like you to follow:
We would love for you to contribute to Angular and help make it even better than it is today!
As a contributor, here are the guidelines we would like you to follow:
- [Code of Conduct](#coc)
- [Question or Problem?](#question)
@ -12,50 +12,63 @@ today! As a contributor, here are the guidelines we would like you to follow:
- [Commit Message Guidelines](#commit)
- [Signing the CLA](#cla)
## <a name="coc"></a> Code of Conduct
Help us keep Angular open and inclusive. Please read and follow our [Code of Conduct][coc].
Help us keep Angular open and inclusive.
Please read and follow our [Code of Conduct][coc].
## <a name="question"></a> Got a Question or Problem?
Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests. You've got much better chances of getting your question answered on [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) where the questions should be tagged with tag `angular`.
Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests.
Instead, we recommend using [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) to ask support-related questions. When creating a new question on Stack Overflow, make sure to add the `angular` tag.
Stack Overflow is a much better place to ask questions since:
- there are thousands of people willing to help on Stack Overflow
- questions and answers stay available for public viewing so your question / answer might help someone else
- questions and answers stay available for public viewing so your question/answer might help someone else
- Stack Overflow's voting system assures that the best answers are prominently visible.
To save your and our time, we will systematically close all issues that are requests for general support and redirect people to Stack Overflow.
If you would like to chat about the question in real-time, you can reach out via [our gitter channel][gitter].
## <a name="issue"></a> Found a Bug?
If you find a bug in the source code, you can help us by
[submitting an issue](#submit-issue) to our [GitHub Repository][github]. Even better, you can
[submit a Pull Request](#submit-pr) with a fix.
If you find a bug in the source code, you can help us by [submitting an issue](#submit-issue) to our [GitHub Repository][github].
Even better, you can [submit a Pull Request](#submit-pr) with a fix.
## <a name="feature"></a> Missing a Feature?
You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub
Repository. If you would like to *implement* a new feature, please submit an issue with
a proposal for your work first, to be sure that we can use it.
Please consider what kind of change it is:
You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub Repository.
If you would like to *implement* a new feature, please consider the size of the change in order to determine the right steps to proceed:
* For a **Major Feature**, first open an issue and outline your proposal so that it can be discussed.
This process allows us to better coordinate our efforts, prevent duplication of work, and help you to craft the change so that it is successfully accepted into the project.
**Note**: Adding a new topic to the documentation, or significantly re-writing a topic, counts as a major feature.
* For a **Major Feature**, first open an issue and outline your proposal so that it can be
discussed. This will also allow us to better coordinate our efforts, prevent duplication of work,
and help you to craft the change so that it is successfully accepted into the project.
* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
## <a name="submit"></a> Submission Guidelines
### <a name="submit-issue"></a> Submitting an Issue
Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available.
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs, we will systematically ask you to provide a minimal reproduction. Having a minimal reproducible scenario gives us a wealth of important information without going back & forth to you with additional questions.
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it.
In order to reproduce bugs, we require that you provide a minimal reproduction.
Having a minimal reproducible scenario gives us a wealth of important information without going back and forth to you with additional questions.
A minimal reproduction allows us to quickly confirm a bug (or point out a coding problem) as well as confirm that we are fixing the right problem.
We will be insisting on a minimal reproduction scenario in order to save maintainers time and ultimately be able to fix more bugs. Interestingly, from our experience, users often find coding problems themselves while preparing a minimal reproduction. We understand that sometimes it might be hard to extract essential bits of code from a larger codebase but we really need to isolate the problem before we can fix it.
We require a minimal reproduction to save maintainers' time and ultimately be able to fix more bugs.
Often, developers find coding problems themselves while preparing a minimal reproduction.
We understand that sometimes it might be hard to extract essential bits of code from a larger codebase but we really need to isolate the problem before we can fix it.
Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you, we are going to close an issue that doesn't have enough info to be reproduced.
@ -63,57 +76,66 @@ You can file new issues by selecting from our [new issue templates](https://gith
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
Before you submit your Pull Request (PR) consider the following guidelines:
1. Search [GitHub](https://github.com/angular/angular/pulls) for an open or closed PR
that relates to your submission. You don't want to duplicate effort.
1. Be sure that an issue describes the problem you're fixing, or documents the design for the feature you'd like to add.
Discussing the design up front helps to ensure that we're ready to accept your work.
1. Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
We cannot accept code without this. Make sure you sign with the primary email address of the Git identity that has been granted access to the Angular repository.
1. Fork the angular/angular repo.
1. Make your changes in a new git branch:
1. Search [GitHub](https://github.com/angular/angular/pulls) for an open or closed PR that relates to your submission.
You don't want to duplicate existing efforts.
2. Be sure that an issue describes the problem you're fixing, or documents the design for the feature you'd like to add.
Discussing the design upfront helps to ensure that we're ready to accept your work.
3. Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
We cannot accept code without a signed CLA.
Make sure you author all contributed Git commits with email address associated with your CLA signature.
4. Fork the angular/angular repo.
5. Make your changes in a new git branch:
```shell
git checkout -b my-fix-branch master
```
1. Create your patch, **including appropriate test cases**.
1. Follow our [Coding Rules](#rules).
1. Run the full Angular test suite, as described in the [developer documentation][dev-doc],
and ensure that all tests pass.
1. Commit your changes using a descriptive commit message that follows our
[commit message conventions](#commit). Adherence to these conventions
is necessary because release notes are automatically generated from these messages.
6. Create your patch, **including appropriate test cases**.
7. Follow our [Coding Rules](#rules).
8. Run the full Angular test suite, as described in the [developer documentation][dev-doc], and ensure that all tests pass.
9. Commit your changes using a descriptive commit message that follows our [commit message conventions](#commit).
Adherence to these conventions is necessary because release notes are automatically generated from these messages.
```shell
git commit -a
```
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
1. Push your branch to GitHub:
10. Push your branch to GitHub:
```shell
git push origin my-fix-branch
```
1. In GitHub, send a pull request to `angular:master`.
* If we suggest changes then:
* Make the required updates.
* Re-run the Angular test suites to ensure tests are still passing.
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
11. In GitHub, send a pull request to `angular:master`.
```shell
git rebase master -i
git push -f
```
If we ask for changes via code reviews then:
* Make the required updates.
* Re-run the Angular test suites to ensure tests are still passing.
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
```shell
git rebase master -i
git push -f
```
That's it! Thank you for your contribution!
#### After your pull request is merged
After your pull request is merged, you can safely delete your branch and pull the changes
from the main (upstream) repository:
After your pull request is merged, you can safely delete your branch and pull the changes from the main (upstream) repository:
* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
@ -139,55 +161,66 @@ from the main (upstream) repository:
git pull --ff upstream master
```
## <a name="rules"></a> Coding Rules
To ensure consistency throughout the source code, keep these rules in mind as you are working:
* All features or bug fixes **must be tested** by one or more specs (unit-tests).
* All public API methods **must be documented**. (Details TBC).
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at
**100 characters**. An automated formatter is available, see
[DEVELOPER.md](docs/DEVELOPER.md#clang-format).
* All public API methods **must be documented**.
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at **100 characters**.
## <a name="commit"></a> Commit Message Guidelines
An automated formatter is available, see [DEVELOPER.md](docs/DEVELOPER.md#clang-format).
We have very precise rules over how our git commit messages can be formatted. This leads to **more
readable messages** that are easy to follow when looking through the **project history**. But also,
we use the git commit messages to **generate the Angular change log**.
### Commit Message Format
Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
format that includes a **type**, a **scope** and a **subject**:
## <a name="commit"></a> Commit Message Format
*This specification is inspired and supersedes the [AngularJS commit message format][commit-message-format].*
We have very precise rules over how our Git commit messages must be formatted.
This format leads to **easier to read commit history**.
Each commit message consists of a **header**, a **body**, and a **footer**.
```
<type>(<scope>): <subject>
<header>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
```
The **header** is mandatory and the **scope** of the header is optional.
The `header` is mandatory and must conform to the [Commit Message Header](#commit-header) format.
Any line of the commit message cannot be longer than 100 characters! This allows the message to be easier
to read on GitHub as well as in various git tools.
The `body` is mandatory for all commits except for those of scope "docs".
When the body is required it must be at least 20 characters long.
The footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.
The `footer` is optional.
Samples: (even more [samples](https://github.com/angular/angular/commits/master))
Any line of the commit message cannot be longer than 100 characters.
#### <a href="commit-header"></a>Commit Message Header
```
docs(changelog): update changelog to beta.5
```
```
fix(release): need to depend on latest rxjs and zone.js
The version in our package.json gets copied to the one we publish, and users need the latest of these.
<type>(<scope>): <short summary>
│ │ │
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
│ │
│ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
│ elements|forms|http|language-service|localize|platform-browser|
│ platform-browser-dynamic|platform-server|platform-webworker|
│ platform-webworker-dynamic|router|service-worker|upgrade|zone.js|
│ packaging|changelog|dev-infra|docs-infra|migrations|ngcc|ve
└─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
```
### Revert
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.
The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is optional.
##### Type
### Type
Must be one of the following:
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
@ -200,67 +233,95 @@ Must be one of the following:
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
* **test**: Adding missing tests or correcting existing tests
### Scope
##### Scope
The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages).
The following is the list of supported scopes:
* **animations**
* **bazel**
* **benchpress**
* **common**
* **compiler**
* **compiler-cli**
* **core**
* **elements**
* **forms**
* **http**
* **language-service**
* **localize**
* **platform-browser**
* **platform-browser-dynamic**
* **platform-server**
* **platform-webworker**
* **platform-webworker-dynamic**
* **router**
* **service-worker**
* **upgrade**
* **zone.js**
* `animations`
* `bazel`
* `benchpress`
* `common`
* `compiler`
* `compiler-cli`
* `core`
* `elements`
* `forms`
* `http`
* `language-service`
* `localize`
* `platform-browser`
* `platform-browser-dynamic`
* `platform-server`
* `platform-webworker`
* `platform-webworker-dynamic`
* `router`
* `service-worker`
* `upgrade`
* `zone.js`
There are currently a few exceptions to the "use package name" rule:
* **packaging**: used for changes that change the npm package layout in all of our packages, e.g.
public path changes, package.json changes done to all packages, d.ts file/format changes, changes
to bundles, etc.
* **changelog**: used for updating the release notes in CHANGELOG.md
* **docs-infra**: used for docs-app (angular.io) related changes within the /aio directory of the
repo
* **dev-infra**: used for dev-infra related changes within the directories /scripts, /tools and /dev-infra
* **migrations**: used for changes to the `ng update` migrations.
* **ngcc**: used for changes to the [Angular Compatibility Compiler](./packages/compiler-cli/ngcc/README.md)
* **ve**: used for changes specific to ViewEngine (legacy compiler/renderer).
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all
packages (e.g. `style: add missing semicolons`) and for docs changes that are not related to a
specific package (e.g. `docs: fix typo in tutorial`).
* `packaging`: used for changes that change the npm package layout in all of our packages, e.g. public path changes, package.json changes done to all packages, d.ts file/format changes, changes to bundles, etc.
### Subject
The subject contains a succinct description of the change:
* `changelog`: used for updating the release notes in CHANGELOG.md
* `dev-infra`: used for dev-infra related changes within the directories /scripts, /tools and /dev-infra
* `docs-infra`: used for docs-app (angular.io) related changes within the /aio directory of the repo
* `migrations`: used for changes to the `ng update` migrations.
* `ngcc`: used for changes to the [Angular Compatibility Compiler](./packages/compiler-cli/ngcc/README.md)
* `ve`: used for changes specific to ViewEngine (legacy compiler/renderer).
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all packages (e.g. `style: add missing semicolons`) and for docs changes that are not related to a specific package (e.g. `docs: fix typo in tutorial`).
##### Summary
Use the summary field to provide a succinct description of the change:
* use the imperative, present tense: "change" not "changed" nor "changes"
* don't capitalize the first letter
* no dot (.) at the end
### Body
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
The body should include the motivation for the change and contrast this with previous behavior.
### Footer
The footer should contain any information about **Breaking Changes** and is also the place to
reference GitHub issues that this commit **Closes**.
#### Commit Message Body
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.
Just as in the summary, use the imperative, present tense: "fix" not "fixed" nor "fixes".
Explain the motivation for the change in the commit message body. This commit message should explain _why_ you are making the change.
You can include a comparison of the previous behavior with the new behavior in order to illustrate the impact of the change.
#### Commit Message Footer
The footer can contain information about breaking changes and is also the place to reference GitHub issues, Jira tickets, and other PRs that this commit closes or is related to.
```
BREAKING CHANGE: <breaking change summary>
<BLANK LINE>
<breaking change description + migration instructions>
<BLANK LINE>
<BLANK LINE>
Fixes #<issue number>
```
Breaking Change section should start with the phrase "BREAKING CHANGE: " followed by a summary of the breaking change, a blank line, and a detailed description of the breaking change that also includes migration instructions.
### Revert commits
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit.
The content of the commit message body should contain:
- information about the SHA of the commit being reverted in the following format: `This reverts commit <SHA>`,
- a clear description of the reason for reverting the commit message.
A detailed explanation can be found in this [document][commit-message-format].
## <a name="cla"></a> Signing the CLA
@ -271,18 +332,17 @@ changes to be accepted, the CLA must be signed. It's a quick process, we promise
* For corporations, we'll need you to
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
<hr>
If you have more than one GitHub accounts, or multiple email addresses associated with a single GitHub account, you must sign the CLA using the primary email address of the GitHub account used to author Git commits and send pull requests.
If you have more than one Git identity, you must make sure that you sign the CLA using the primary email address associated with the ID that has been granted access to the Angular repository. Git identities can be associated with more than one email address, and only one is primary. Here are some links to help you sort out multiple Git identities and email addresses:
The following documents can help you sort out issues with GitHub accounts and multiple email addresses:
* https://help.github.com/articles/setting-your-commit-email-address-in-git/
* https://stackoverflow.com/questions/37245303/what-does-usera-committed-with-userb-13-days-ago-on-github-mean
* https://help.github.com/articles/about-commit-email-addresses/
* https://help.github.com/articles/blocking-command-line-pushes-that-expose-your-personal-email-address/
Note that if you have more than one Git identity, it is important to verify that you are logged in with the same ID with which you signed the CLA, before you commit changes. If not, your PR will fail the CLA check.
<hr>
[angular-group]: https://groups.google.com/forum/#!forum/angular
[coc]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md

View File

@ -58,7 +58,7 @@
}
],
"styles": [
"src/styles.scss"
"src/styles/main.scss"
],
"scripts": [],
"budgets": [
@ -158,7 +158,7 @@
}
],
"styles": [
"src/styles.scss"
"src/styles/main.scss"
],
"scripts": []
}

View File

@ -32,15 +32,15 @@ export const slideInAnimation =
// #enddocregion style-view
// #docregion query
query(':enter', [
style({ left: '-100%'})
style({ left: '-100%' })
]),
query(':leave', animateChild()),
group([
query(':leave', [
animate('300ms ease-out', style({ left: '100%'}))
animate('300ms ease-out', style({ left: '100%' }))
]),
query(':enter', [
animate('300ms ease-out', style({ left: '0%'}))
animate('300ms ease-out', style({ left: '0%' }))
])
]),
query(':enter', animateChild()),
@ -56,15 +56,15 @@ export const slideInAnimation =
})
]),
query(':enter', [
style({ left: '-100%'})
style({ left: '-100%' })
]),
query(':leave', animateChild()),
group([
query(':leave', [
animate('200ms ease-out', style({ left: '100%'}))
animate('200ms ease-out', style({ left: '100%' }))
]),
query(':enter', [
animate('300ms ease-out', style({ left: '0%'}))
animate('300ms ease-out', style({ left: '0%' }))
])
]),
query(':enter', animateChild()),

View File

@ -17,7 +17,7 @@ Toggle All Animations <input type="checkbox" [checked]="!animationsDisabled" (cl
</nav>
<!-- #docregion route-animations-outlet -->
<div [@routeAnimations]="prepareRoute(outlet)" >
<div [@routeAnimations]="prepareRoute(outlet)">
<router-outlet #outlet="outlet"></router-outlet>
</div>
<!-- #enddocregion route-animations-outlet -->

View File

@ -76,15 +76,15 @@ export class ConfigService {
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
// The response body may contain clues as to what went wrong.
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
// return an observable with a user-facing error message
// Return an observable with a user-facing error message.
return throwError(
'Something bad happened; please try again later.');
};
}
// #enddocregion handleError
makeIntentionalError() {

View File

@ -0,0 +1,12 @@
{
"description": "i18n",
"files":[
"!**/*.d.ts",
"!**/*.js",
"!**/*.[0-9].*",
"!doc-files/**/*",
"**/*.xlf"
],
"file": "src/app/app.component.ts",
"tags": ["Angular", "i18n", "internationalization"]
}

View File

@ -1,9 +0,0 @@
{
"files": [
"!dist/",
"!**/*.d.ts",
"!src/**/*.js",
"!doc-files/**/*",
"**/*.xlf"
]
}

View File

@ -6,5 +6,5 @@ import { Component } from '@angular/core';
templateUrl: './app.component.html'
})
export class AppComponent {
birthday = new Date(1988, 3, 15); // April 15, 1988
birthday = new Date(1988, 3, 15); // April 15, 1988 -- since month parameter is zero-based
}

View File

@ -8,5 +8,5 @@ import { Component } from '@angular/core';
// #enddocregion hero-birthday-template
})
export class HeroBirthdayComponent {
birthday = new Date(1988, 3, 15); // April 15, 1988
birthday = new Date(1988, 3, 15); // April 15, 1988 -- since month parameter is zero-based
}

View File

@ -12,7 +12,7 @@ import { Component } from '@angular/core';
})
// #docregion class
export class HeroBirthday2Component {
birthday = new Date(1988, 3, 15); // April 15, 1988
birthday = new Date(1988, 3, 15); // April 15, 1988 -- since month parameter is zero-based
toggle = true; // start with true == shortDate
get format() { return this.toggle ? 'shortDate' : 'fullDate'; }

View File

@ -0,0 +1,7 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'any',
})
export class UserService {
}

View File

@ -6,13 +6,11 @@ import { Routes, RouterModule } from '@angular/router'; // CLI imports router
const routes: Routes = [
{ path: 'first-component', component: FirstComponent },
{ path: 'second-component', component: SecondComponent },
// #enddocregion routes
// #enddocregion routes, routes-with-wildcard
{ path: '', redirectTo: '/first-component', pathMatch: 'full' }, // redirect to `first-component`
{ path: '**', component: FirstComponent },
// #enddocregion redirect
// #docregion routes-with-wildcard
{ path: '**', component: PageNotFoundComponent }, // Wildcard route for a 404 page
// #docregion routes
// #docregion redirect
];
// #enddocregion routes, routes-with-wildcard, redirect

View File

@ -33,7 +33,7 @@ export class HeroesComponent implements OnInit {
onSelect(hero: Hero): void {
this.selectedHero = hero;
this.messageService.add(`HeroService: Selected hero id=${hero.id}`);
this.messageService.add(`HeroesComponent: Selected hero id=${hero.id}`);
}
// #docregion getHeroes

View File

@ -1,6 +1,6 @@
# 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).
When you use [AOT compilation](guide/aot-compiler), you can control how your application is compiled by specifying *template* compiler options in the [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.
@ -21,11 +21,11 @@ The template options object, `angularCompilerOptions`, is a sibling to the `comp
{@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`.
Like the TypeScript compiler, The Angular AOT compiler also supports `extends` in the `angularCompilerOptions` section of the TypeScript configuration file.
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.
The configuration options from the base file are loaded first, then overridden by those in the inheriting configuration file.
For example:

View File

@ -105,7 +105,7 @@ For help in understanding and resolving these problems, see [AOT Metadata Errors
### Configuring AOT compilation
You can provide options in the `tsconfig.json` [TypeScript configuration file](guide/typescript-configuration) that control the compilation process. See [Angular compiler options](guide/angular-compiler-options) for a complete list of available options.
You can provide options in the [TypeScript configuration file](guide/typescript-configuration) that controls the compilation process. See [Angular compiler options](guide/angular-compiler-options) for a complete list of available options.
## Phase 1: Code analysis
@ -211,7 +211,7 @@ The compiler later reports the error if it needs that piece of metadata to gener
<div class="alert is-helpful">
If you want `ngc` to report syntax errors immediately rather than produce a `.metadata.json` file with errors, set the `strictMetadataEmit` option in the TypeScript configuration file, `tsconfig.json`.
If you want `ngc` to report syntax errors immediately rather than produce a `.metadata.json` file with errors, set the `strictMetadataEmit` option in the TypeScript configuration file.
```
"angularCompilerOptions": {
@ -548,7 +548,7 @@ It does not, however, rewrite the `.d.ts` file, so TypeScript doesn't recognize
One of the Angular compiler's most helpful features is the ability to type-check expressions within templates, and catch any errors before they cause crashes at runtime.
In the template type-checking phase, the Angular template compiler uses the TypeScript compiler to validate the binding expressions in templates.
Enable this phase explicitly by adding the compiler option `"fullTemplateTypeCheck"` in the `"angularCompilerOptions"` of the project's `tsconfig.json`
Enable this phase explicitly by adding the compiler option `"fullTemplateTypeCheck"` in the `"angularCompilerOptions"` of the project's TypeScript configuration file
(see [Angular Compiler Options](guide/angular-compiler-options)).
<div class="alert is-helpful">

View File

@ -11,7 +11,7 @@ The basic building blocks are *NgModules*, which provide a compilation context f
* Components use *services*, which provide specific functionality not directly related to views. Service providers can be *injected* into components as *dependencies*, making your code modular, reusable, and efficient.
Both components and services are simply classes, with *decorators* that mark their type and provide metadata that tells Angular how to use them.
Modules, components and services are classes that use *decorators*. These decorators mark their type and provide metadata that tells Angular how to use them.
* The metadata for a component class associates it with a *template* that defines a view. A template combines ordinary HTML with Angular *directives* and *binding markup* that allow Angular to modify the HTML before rendering it for display.

View File

@ -262,6 +262,33 @@ Each budget entry is a JSON object with the following properties:
</table>
{@a commonjs }
## Configuring CommonJS dependencies
<div class="alert is-important">
It is recommended that you avoid depending on CommonJS modules in your Angular applications.
Depending on CommonJS modules can prevent bundlers and minifiers from optimizing your application, which results in larger bundle sizes.
Instead, it is recommended that you use [ECMAScript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) in your entire application.
For more information, see [How CommonJS is making your bundles larger](https://web.dev/commonjs-larger-bundles/).
</div>
The Angular CLI outputs warnings if it detects that your browser application depends on CommonJS modules.
To disable these warnings, you can add the CommonJS module name to `allowedCommonJsDependencies` option in the `build` options located in `angular.json` file.
<code-example lang="json">
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"allowedCommonJsDependencies": [
"lodash"
]
...
}
...
},
</code-example>
{@a browser-compat}

View File

@ -197,11 +197,11 @@ Like `EvenBetterLogger`, `HeroService` needs to know if the user is authorized
That authorization can change during the course of a single application session,
as when you log in a different user.
Let's say you don't want to inject `UserService` directly into `HeroService`, because you don't want to complicate that service with security-sensitive information.
Imagine that you don't want to inject `UserService` directly into `HeroService`, because you don't want to complicate that service with security-sensitive information.
`HeroService` won't have direct access to the user information to decide
who is authorized and who isn't.
To resolve this, we give the `HeroService` constructor a boolean flag to control display of secret heroes.
To resolve this, give the `HeroService` constructor a boolean flag to control display of secret heroes.
<code-example path="dependency-injection/src/app/heroes/hero.service.ts" region="internals" header="src/app/heroes/hero.service.ts (excerpt)"></code-example>

View File

@ -320,7 +320,7 @@ You can dramatically reduce launch time by only loading the application modules
absolutely must be present when the app starts.
Configure the Angular Router to defer loading of all other modules (and their associated code), either by
[waiting until the app has launched](guide/router#preloading "Preloading")
[waiting until the app has launched](guide/router-tutorial-toh#preloading "Preloading")
or by [_lazy loading_](guide/router#lazy-loading "Lazy loading")
them on demand.
@ -469,7 +469,7 @@ The following configurations determine your requirements.
* TypeScript configuration
In the TypeScript configuration file, `tsconfig.json`, the "target" option in the `compilerOptions` section determines the ECMAScript target version that the code is compiled to.
In the TypeScript configuration file, the "target" option in the `compilerOptions` section determines the ECMAScript target version that the code is compiled to.
Modern browsers support ES2015 natively, while ES5 is more commonly used to support legacy browsers.
<div class="alert is-helpful">

View File

@ -490,6 +490,56 @@ If you rely on the behavior that the same object instance should cause change de
- Clone the resulting value so that it has a new identity.
- Explicitly call [`ChangeDetectorRef.detectChanges()`](api/core/ChangeDetectorRef#detectchanges) to force the update.
{@a deprecated-cli-flags}
## Deprecated CLI APIs and Options
This section contains a complete list all of the currently deprecated CLI flags.
### @angular-devkit/build-angular
| API/Option | May be removed in | Notes |
| ------------------------------- | ----------------- |-------------------------------------------------------------------------------- |
| `i18nFile` | <!--v9--> v11 | Specified in the project locale configuration in version 9 and later. |
| `i18nFormat` | <!--v9--> v11 | Format is now automatically detected. |
| `i18nLocale` | <!--v9--> v11 | New [localization option](/guide/i18n#localize-config) in version 9 and later. |
| `lazyModules` | <!--v9--> v11 | Used with deprecated SystemJsNgModuleLoader. |
| `rebaseRootRelativeCssUrls` | <!--v8--> v11 | Intended only to assist with specific migration issues. |
| `scripts[].lazy` | <!--v8--> v11 | Renamed to `scripts[].inject`. |
| `styles[].lazy` | <!--v8--> v11 | Renamed to `styles[].inject`. |
| `i18nFormat` | <!--v9--> v11 | Renamed to `format` to simplify the user experience. |
| `i18nLocale` | <!--v9--> v11 | Redundant with projects source locale. |
| `scripts[].lazy` | <!--v8--> v11 | Renamed to `scripts[].inject`. |
| `styles[].lazy` | <!--v8--> v11 | Renamed to `styles[].inject`. |
| `i18nFile` | <!--v9--> v11 | Specified in the project locale configuration in version 9 and later. |
| `i18nFormat` | <!--v9--> v11 | Format is now automatically detected. |
| `i18nLocale` | <!--v9--> v11 | New [localization option](/guide/i18n#localize-config) in version 9 and later. |
| `lazyModules` | <!--v9--> v11 | Used with deprecated SystemJsNgModuleLoader. |
### @angular-devkit/core
| API/Option | May be removed in | Notes |
| ------------------------------- | ----------------- |-------------------------------------------------------------------------------- |
| `ModuleNotFoundException` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Not Yarn PnP compatible and not used in the Angular CLI. Use Node.js [require.resolve](https://nodejs.org/api/modules.html#modules_require_resolve_request_options).|
| `resolve` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Not Yarn PnP compatible and not used in the Angular CLI. Use Node.js [require.resolve](https://nodejs.org/api/modules.html#modules_require_resolve_request_options).|
| `setResolveHook` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Not Yarn PnP compatible and not used in the Angular CLI. Use Node.js [require.resolve](https://nodejs.org/api/modules.html#modules_require_resolve_request_options).|
| `ResolveOptions` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Not Yarn PnP compatible and not used in the Angular CLI. Use Node.js [require.resolve](https://nodejs.org/api/modules.html#modules_require_resolve_request_options).|
| `terminal` | <!--v8--> v10 | Unused implementation of terminal codes (color). |
| `isObservable` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Use `isObservable` function from the `rxjs` package.|
### @ngtools/webpack
| API/Option | May be removed in | Notes |
| ------------------------------- | ----------------- |-------------------------------------------------------------------------------- |
| `discoverLazyRoutes` | <!--v9--> TBD | Used with deprecated SystemJsNgModuleLoader. |
| `additionalLazyModules` | <!--v9--> TBD | Used with deprecated SystemJsNgModuleLoader. |
| `additionalLazyModuleResources` | <!--v9--> TBD | Used with deprecated SystemJsNgModuleLoader. |
### @schematics/angular
| API/Option | May be removed in | Notes |
| ------------------------------- | ----------------- |-------------------------------------------------------------------------------- |
| `entryComponent` | <!--v9--> TBD | No longer needed with Ivy. |
{@a removed}
## Removed APIs

View File

@ -117,9 +117,9 @@ The recently-developed [custom elements](https://developer.mozilla.org/en-US/doc
</tr>
</table>
In browsers that support Custom Elements natively, the specification requires developers use ES2015 classes to define Custom Elements - developers can opt-in to this by setting the `target: "es2015"` property in their project's `tsconfig.json`. As Custom Element and ES2015 support may not be available in all browsers, developers can instead choose to use a polyfill to support older browsers and ES5 code.
In browsers that support Custom Elements natively, the specification requires developers use ES2015 classes to define Custom Elements - developers can opt-in to this by setting the `target: "es2015"` property in their project's [TypeScript configuration file](/guide/typescript-configuration). As Custom Element and ES2015 support may not be available in all browsers, developers can instead choose to use a polyfill to support older browsers and ES5 code.
Use the [Angular CLI](cli) to automatically set up your project with the correct polyfill: `ng add @angular/elements --name=*your_project_name*`.
Use the [Angular CLI](cli) to automatically set up your project with the correct polyfill: `ng add @angular/elements --project=*your_project_name*`.
- For more information about polyfills, see [polyfill documentation](https://www.webcomponents.org/polyfills).
- For more information about Angular browser support, see [Browser Support](guide/browser-support).
@ -186,7 +186,7 @@ aDialog.content = 123; // <-- ERROR: TypeScript knows this should be a string.
aDialog.body = 'News'; // <-- ERROR: TypeScript knows there is no `body` property on `aDialog`.
```
This is a good way to quickly get TypeScript features, such as type checking and autocomplete support, for you custom element. But it can get cumbersome if you need it in several places, because you have to cast the return type on every occurrence.
This is a good way to quickly get TypeScript features, such as type checking and autocomplete support, for your custom element. But it can get cumbersome if you need it in several places, because you have to cast the return type on every occurrence.
An alternative way, that only requires defining each custom element's type once, is augmenting the `HTMLElementTagNameMap`, which TypeScript uses to infer the type of a returned element based on its tag name (for DOM methods such as `document.createElement()`, `document.querySelector()`, etc.):

View File

@ -40,7 +40,8 @@ The top level of the workspace contains workspace-wide configuration files, conf
| `package-lock.json` | Provides version information for all packages installed into `node_modules` by the npm client. See [npm documentation](https://docs.npmjs.com/files/package-lock.json) for details. If you use the yarn client, this file will be [yarn.lock](https://yarnpkg.com/lang/en/docs/yarn-lock/) instead. |
| `src/` | Source files for the root-level application project. |
| `node_modules/` | Provides [npm packages](guide/npm-packages) to the entire workspace. Workspace-wide `node_modules` dependencies are visible to all projects. |
| `tsconfig.json` | Default [TypeScript](https://www.typescriptlang.org/) configuration for projects in the workspace. |
| `tsconfig.json` | The `tsconfig.json` file is a ["Solution Style"](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#support-for-solution-style-tsconfigjson-files) TypeScript configuration file. Code editors and TypeScripts language server use this file to improve development experience. Compilers do not use this file. |
| `tsconfig.base.json` | The base [TypeScript](https://www.typescriptlang.org/) configuration for projects in the workspace. All other configuration files inherit from this base file. For more information, see the [Configuration inheritance with extends](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#configuration-inheritance-with-extends) section of the TypeScript documentation.|
| `tslint.json` | Default [TSLint](https://palantir.github.io/tslint/) configuration for projects in the workspace. |
@ -77,6 +78,12 @@ Files at the top level of `src/` support testing and running your application. S
| `styles.sass` | Lists CSS files that supply styles for a project. The extension reflects the style preprocessor you have configured for the project. |
| `test.ts` | The main entry point for your unit tests, with some Angular-specific configuration. You don't typically need to edit this file. |
<div class="alert is-helpful">
If you create an application using Angular's strict mode, you will also have an additional `package.json` file in the `src/app` directory. For more information, see [Strict mode](/guide/strict-mode).
</div>
{@a app-src}
Inside the `src/` folder, the `app/` folder contains your project's logic and data.
@ -89,13 +96,14 @@ Angular components, templates, and styles go here.
| `app/app.component.css` | Defines the base CSS stylesheet for the root `AppComponent`. |
| `app/app.component.spec.ts` | Defines a unit test for the root `AppComponent`. |
| `app/app.module.ts` | Defines the root module, named `AppModule`, that tells Angular how to assemble the application. Initially declares only the `AppComponent`. As you add more components to the app, they must be declared here. |
| `app/package.json` | This file is generated only in applications created using `--strict` mode. This file is not used by package managers. It is used to tell the tools and bundlers whether the code under this directory is free of non-local [side-effects](guide/strict-mode#side-effect). |
### Application configuration files
The application-specific configuration files for the root application reside at the workspace root level.
For a multi-project workspace, project-specific configuration files are in the project root, under `projects/project-name/`.
Project-specific [TypeScript](https://www.typescriptlang.org/) configuration files inherit from the workspace-wide `tsconfig.json`, and project-specific [TSLint](https://palantir.github.io/tslint/) configuration files inherit from the workspace-wide `tslint.json`.
Project-specific [TypeScript](https://www.typescriptlang.org/) configuration files inherit from the workspace-wide `tsconfig.base.json`, and project-specific [TSLint](https://palantir.github.io/tslint/) configuration files inherit from the workspace-wide `tslint.json`.
| APPLICATION-SPECIFIC CONFIG FILES | PURPOSE |
| :--------------------- | :------------------------------------------|

View File

@ -117,7 +117,7 @@ As users change values and make selections through the view, the new values must
Similarly, when the program logic changes values in the data model, those values must be reflected in the view.
Reactive and template-driven forms differ in how they handle data flowing from the user or from programmatic changes.
The following diagrams illustrate both kinds of data flow for each type of form, using the a favorite-color input field defined above.
The following diagrams illustrate both kinds of data flow for each type of form, using the favorite-color input field defined above.
### Data flow in reactive forms

View File

@ -93,7 +93,7 @@ In the course of this tutorial, you bind a sample form to data and handle user i
* Add custom CSS to provide visual feedback on the status.
* Show and hide validation-error messages.
4. Respond to a native HTML button-click event by adding to the model data.
5. Handle form submission using the [`ngSubmit`(api/forms/NgForm#properties)] output property of the form.
5. Handle form submission using the [`ngSubmit`](api/forms/NgForm#properties) output property of the form.
* Disable the **Submit** button until the form is valid.
* After submit, swap out the finished form for different content on the page.
@ -467,7 +467,7 @@ You will bind the form property that indicates its overall validity to the **Sub
3. Run the application now. Notice that the button is enabled&mdash;although
it doesn't do anything useful yet.
4. Delete the **Name** value. This violates the "required" rule, so it displays the error message&emdash;and notice that it also disables the **Submit** button.
4. Delete the **Name** value. This violates the "required" rule, so it displays the error message&mdash;and notice that it also disables the **Submit** button.
You didn't have to explicitly wire the button's enabled state to the form's validity.

View File

@ -732,7 +732,7 @@ The alternative is a [template-driven form](#template-driven-forms).
When using reactive forms:
* The "source of truth", the form model, is defined in the component class.
* Validation is set up through validation functions rather than valdation directives.
* Validation is set up through validation functions rather than validation directives.
* Each control is explicitly created in the component class by creating a `FormControl` instance manually or with `FormBuilder`.
* The template input elements do *not* use `ngModel`.
* The associated Angular directives are prefixed with `form`, such as `formControl`, `formGroup`, and `formControlName`.
@ -950,6 +950,10 @@ Many code editors and IDEs support TypeScript either natively or with plug-ins.
TypeScript is the preferred language for Angular development.
Read more about TypeScript at [typescriptlang.org](http://www.typescriptlang.org/).
## TypeScript configuration file
A file specifies the root files and the compiler options required to compile a TypeScript project. For more information, see [TypeScript configuration](/guide/typescript-configuration).
{@a U}

View File

@ -277,7 +277,7 @@ searchHeroes(term: string): Observable {
return this.http.jsonp(heroesUrl, 'callback').pipe(
catchError(this.handleError('searchHeroes', [])) // then handle the error
);
};
}
```
This request passes the `heroesURL` as the first parameter and the callback function name as the second parameter.

File diff suppressed because it is too large Load Diff

View File

@ -2,20 +2,20 @@
The Angular team has worked hard to ensure Ivy is as backwards-compatible with the previous rendering engine ("View Engine") as possible.
However, in rare cases, minor changes were necessary to ensure that the Angular's behavior was predictable and consistent, correcting issues in the View Engine implementation.
In order to smooth the transition, we have provided [automated migrations](guide/updating-to-version-9#migrations) wherever possible so your application and library code is migrated automatically by the CLI.
In order to smooth the transition, we have provided [automated migrations](guide/updating-to-version-10#migrations) wherever possible so your application and library code is migrated automatically by the CLI.
That said, some applications will likely need to apply some manual updates.
{@a debugging}
## How to debug errors with Ivy
In version 9, [a few deprecated APIs have been removed](guide/updating-to-version-9#removals) and there are a [few breaking changes](guide/updating-to-version-9#breaking-changes) unrelated to Ivy.
In version 10, [a few deprecated APIs have been removed](guide/updating-to-version-10#removals) and there are a [few breaking changes](guide/updating-to-version-10#breaking-changes) unrelated to Ivy.
If you're seeing errors after updating to version 9, you'll first want to rule those changes out.
To do so, temporarily [turn off Ivy](guide/ivy#opting-out-of-angular-ivy) in your `tsconfig.json` and re-start your app.
To do so, temporarily [turn off Ivy](guide/ivy#opting-out-of-angular-ivy) in your `tsconfig.base.json` and re-start your app.
If you're still seeing the errors, they are not specific to Ivy. In this case, you may want to consult the [general version 9 guide](guide/updating-to-version-9). If you've opted into any of the stricter type-checking settings that are new with v9, you may also want to check out the [template type-checking guide](guide/template-typecheck).
If you're still seeing the errors, they are not specific to Ivy. In this case, you may want to consult the [general version 10 guide](guide/updating-to-version-10). If you've opted into any of the new, stricter type-checking settings, you may also want to check out the [template type-checking guide](guide/template-typecheck).
If the errors are gone, switch back to Ivy by removing the changes to the `tsconfig.json` and review the list of expected changes below.
If the errors are gone, switch back to Ivy by removing the changes to the `tsconfig.base.json` and review the list of expected changes below.
{@a payload-size-debugging}
### Payload size debugging

View File

@ -311,7 +311,7 @@ ngOnInit() {
}
</code-example>
For more information with a working example, see the [routing tutorial section on preloading](guide/router#preloading-background-loading-of-feature-areas).
For more information with a working example, see the [routing tutorial section on preloading](guide/router-tutorial-toh#preloading-background-loading-of-feature-areas).
<hr>

View File

@ -495,7 +495,7 @@ for one turn of the browser's JavaScript cycle, which triggers a new change-dete
#### Write lean hook methods to avoid performance problems
When you run the *AfterView* sample, notice how frequently Angular calls `AfterViewChecked()`$emdash;often when there are no changes of interest.
When you run the *AfterView* sample, notice how frequently Angular calls `AfterViewChecked()`-often when there are no changes of interest.
Be very careful about how much logic or computation you put into one of these methods.
<div class="lightbox">

View File

@ -0,0 +1,55 @@
# Solution-style `tsconfig.json` migration
## What does this migration do?
This migration adds support to existing projects for TypeScript's new ["solution-style" tsconfig feature](https://devblogs.microsoft.com/typescript/announcing-typescript-3-9/#solution-style-tsconfig).
Support is added by making two changes:
1. Renaming the workspace-level `tsconfig.json` to `tsconfig.base.json`.
All project [TypeScript configuration files](guide/typescript-configuration) will extend from this base which contains the common options used throughout the workspace.
2. Adding the solution `tsconfig.json` file at the root of the workspace.
This `tsconfig.json` file will only contain references to project-level TypeScript configuration files and is only used by editors/IDEs.
As an example, the solution `tsconfig.json` for a new project is as follows:
```json
// This is a "Solution Style" tsconfig.json file, and is used by editors and TypeScripts language server to improve development experience.
// It is not intended to be used to perform a compilation.
{
"files": [],
"references": [
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.spec.json"
},
{
"path": "./e2e/tsconfig.json"
}
]
}
```
## Why is this migration necessary?
Solution-style `tsconfig.json` files provide an improved editing experience and fix several long-standing defects when editing files in an IDE.
IDEs that leverage the TypeScript language service (for example, [Visual Studio Code](https://code.visualstudio.com)), will only use TypeScript configuration files that are named `tsconfig.json`.
In complex projects, there may be more than one compilation unit and each of these units may have different settings and options.
With the Angular CLI, a project will have application code that will target a browser.
It will also have unit tests that should not be included within the built application and that also need additional type information present (`jasmine` in this case).
Both parts of the project also share some but not all of the code within the project.
As a result, two separate TypeScript configuration files (`tsconfig.app.json` and `tsconfig.spec.json`) are needed to ensure that each part of the application is configured properly and that the right types are used for each part.
Also if web workers are used within a project, an additional tsconfig (`tsconfig.worker.json`) is needed.
Web workers use similar but incompatible types to the main browser application.
This requires the additional configuration file to ensure that the web worker files use the appropriate types and will build successfully.
While the Angular build system knows about all of these TypeScript configuration files, an IDE using TypeScript's language service does not.
Because of this, an IDE will not be able to properly analyze the code from each part of the project and may generate false errors or make suggestions that are incorrect for certain files.
By leveraging the new solution-style tsconfig, the IDE can now be aware of the configuration of each part of a project.
This allows each file to be treated appropriately based on its tsconfig.
IDE features such as error/warning reporting and auto-suggestion will operate more effectively as well.
The TypeScript 3.9 release [blog post](https://devblogs.microsoft.com/typescript/announcing-typescript-3-9/#solution-style-tsconfig) also contains some additional information regarding this new feature.

View File

@ -0,0 +1,52 @@
# `tslib` direct dependency migration
## What does this migration do?
If you have any libraries within your workspace, this migration will convert `tslib` peer dependencies to direct dependencies for the libraries.
TypeScript uses the `tslib` package to provide common helper functions used in compiled TypeScript code.
The `tslib` version is also updated to `2.0.0` to support TypeScript 3.9.
Before:
```json
{
"name": "my-lib",
"version": "0.0.1",
"peerDependencies": {
"@angular/common": "^9.0.0",
"@angular/core": "^9.0.0",
"tslib": "^1.12.0"
}
}
```
After:
```json
{
"name": "my-lib",
"version": "0.0.1",
"peerDependencies": {
"@angular/common": "^9.0.0",
"@angular/core": "^9.0.0"
},
"dependencies": {
"tslib": "^2.0.0"
}
}
```
## Why is this migration necessary?
The [`tslib`](https://github.com/Microsoft/tslib) is a runtime library for Typescript.
The version of this library is bound to the version of the TypeScript compiler used to compile a library.
Peer dependencies do not accurately represent this relationship between the runtime and the compiler.
If `tslib` remained declared as a library peer dependency, it would be possible for some Angular workspaces to get into a state where the workspace could not satisfy `tslib` peer dependency requirements for multiple libraries, resulting in build-time or run-time errors.
As of TypeScript 3.9 (used by Angular v10), `tslib` version of 2.x is required to build new applications.
However, older libraries built with previous version of TypeScript and already published to npm might need `tslib` 1.x.
This migration makes it possible for code depending on incompatible versions of the `tslib` runtime library to remain interoperable.
## Do I still need `tslib` as a dependency in my workspace `package.json`?
Yes.
The `tslib` dependency declared in the `package.json` file of the workspace is used to build applications within this workspace, as well as run unit tests for workspace libraries, and is required.

View File

@ -0,0 +1,33 @@
# Update `module` and `target` compiler options migration
## What does this migration do?
This migration adjusts the [`target`](https://www.typescriptlang.org/v2/en/tsconfig#target) and [`module`](https://www.typescriptlang.org/v2/en/tsconfig#module) settings within the [TypeScript configuration files](guide/typescript-configuration) for the workspace.
The changes to each option vary based on the builder or command that uses the TypeScript configuration file.
Unless otherwise noted, changes are only made if the existing value was not changed since the project was created.
This process helps ensure that intentional changes to the options are kept in place.
TypeScript Configuration File(s) | Changed Property | Existing Value | New Value
------------- | ------------- | ------------- | ------------- | -------------
`<workspace base>/tsconfig.base.json` | `"module"` | `"esnext"` | `"es2020"`
Used in `browser` builder options (`ng build` for applications) | `"module"` | `"esnext"` | `"es2020"`
Used in `ng-packgr` builder options (`ng build` for libraries) | `"module"` | `"esnext"` | `"es2020"`
Used in `karma` builder options (`ng test` for applications) | `"module"` | `"esnext"` | `"es2020"`
Used in `server` builder options (universal) | `"module"` | `"commonjs"` | _removed_
Used in `server` builder options (universal) | `"target"` | _any_ | `"es2016"`
Used in `protractor` builder options (`ng e2e` for applications) | `"target"` | `"es5"` | `"es2018"`
## Why is this migration necessary?
This migration provides improvements to the long-term supportability of projects by updating the projects to use recommended best practice compilation options.
For the functionality that executes on Node.js, such as Universal and Protractor, the new settings provide performance and troubleshooting benefits as well.
The minimum Node.js version for the Angular CLI (v10.13) supports features in ES2018 and earlier.
By targeting later ES versions, the compiler transforms less code and can use newer features directly.
Since zone.js does not support native `async` and `await`, the universal builds still target ES2016.
## Why `"es2020"` instead of `"esnext"`?
In TypeScript 3.9, the behavior of the TypeScript compiler controlled by `module` is the same with both `"esnext"` and `"es2020"` values.
This behavior can change in the future, because the `"esnext"` option could evolve in a backwards incompatible ways, resulting in build-time or run-time errors during a TypeScript update.
As a result, code can become unstable. Using the `"es2020"` option mitigates this risk.

View File

@ -118,7 +118,6 @@ Package name | Description
[**@angular&#8209;devkit/<br />build&#8209;angular**](https://github.com/angular/angular-cli/) | The Angular build tools.
[**@angular/cli**](https://github.com/angular/angular-cli/) | The Angular CLI tools.
**@angular/<br />compiler&#8209;cli** | The Angular compiler, which is invoked by the Angular CLI's `ng build` and `ng serve` commands.
**@angular/<br />language&#8209;service** | The [Angular language service](guide/language-service) analyzes component templates and provides type and error information that TypeScript-aware editors can use to improve the developer's experience. For example, see the [Angular language service extension for VS Code](https://marketplace.visualstudio.com/items?itemName=Angular.ng-template).
**@types/... ** | TypeScript definition files for 3rd party libraries such as Jasmine and Node.js.
[**codelyzer**](https://www.npmjs.com/package/codelyzer) | A linter for Angular apps whose rules conform to the Angular [style guide](guide/styleguide).
**jasmine/... ** | Packages to support the [Jasmine](https://jasmine.github.io/) test library.
@ -135,3 +134,4 @@ Package name | Description
* [Building and serving](guide/build) describes how packages come together to create a development build.
* [Deployment](guide/deployment) describes how packages come together to create a production build.

View File

@ -112,7 +112,7 @@ Because observables produce values asynchronously, try/catch will not effectivel
<code-example>
myObservable.subscribe({
next(num) { console.log('Next num: ' + num)},
error(err) { console.log('Received an errror: ' + err)}
error(err) { console.log('Received an error: ' + err)}
});
</code-example>

View File

@ -1,607 +1,440 @@
# Pipes
# Transforming Data Using Pipes
Every application starts out with what seems like a simple task: get data, transform them, and show them to users.
Getting data could be as simple as creating a local variable or as complex as streaming data over a WebSocket.
Use [pipes](guide/glossary#pipe "Definition of a pipe") to transform and format strings, currency amounts, dates, and other display data.
Pipes are simple functions you can use in [template expressions](/guide/glossary#template-expression "Definition of template expression") to accept an input value and return a transformed value.
For example, you would use a pipe to show a date as **April 15, 1988** rather than the raw string format.
<div class="alert is-helpful">
For the sample app that this page describes, see the <live-example></live-example>.
For the sample app used in this topic, see the <live-example></live-example>.
</div>
Once data arrives, you could push their raw `toString` values directly to the view,
but that rarely makes for a good user experience.
For example, in most use cases, users prefer to see a date in a simple format like
<samp>April 15, 1988</samp> rather than the raw string format
<samp>Fri Apr 15 1988 00:00:00 GMT-0700 (Pacific Daylight Time)</samp>.
Clearly, some values benefit from a bit of editing. You may notice that you
desire many of the same transformations repeatedly, both within and across many applications.
You can almost think of them as styles.
In fact, you might like to apply them in your HTML templates as you do styles.
Introducing Angular pipes, a way to write display-value transformations that you can declare in your HTML.
## Using pipes
A pipe takes in data as input and transforms it to a desired output.
In this page, you'll use pipes to transform a component's birthday property into
a human-friendly date.
<code-example path="pipes/src/app/hero-birthday1.component.ts" header="src/app/hero-birthday1.component.ts"></code-example>
Focus on the component's template.
<code-example path="pipes/src/app/app.component.html" region="hero-birthday-template" header="src/app/app.component.html"></code-example>
Inside the interpolation expression, you flow the component's `birthday` value through the
[pipe operator](guide/template-syntax#pipe) ( | ) to the [Date pipe](api/common/DatePipe)
function on the right. All pipes work this way.
## Built-in pipes
Angular comes with a stock of pipes such as
`DatePipe`, `UpperCasePipe`, `LowerCasePipe`, `CurrencyPipe`, and `PercentPipe`.
They are all available for use in any template.
Angular provides built-in pipes for typical data transformations, including transformations for internationalization (i18n), which use locale information to format data.
The following are commonly used built-in pipes for data formatting:
* [`DatePipe`](api/common/DatePipe): Formats a date value according to locale rules.
* [`UpperCasePipe`](api/common/UpperCasePipe): Transforms text to all upper case.
* [`LowerCasePipe`](api/common/LowerCasePipe): Transforms text to all lower case.
* [`CurrencyPipe`](api/common/CurrencyPipe): Transforms a number to a currency string, formatted according to locale rules.
* [`DecimalPipe`](/api/common/DecimalPipe): Transforms a number into a string with a decimal point, formatted according to locale rules.
* [`PercentPipe`](api/common/PercentPipe): Transforms a number to a percentage string, formatted according to locale rules.
<div class="alert is-helpful">
Read more about these and many other built-in pipes in the [pipes topics](api?type=pipe) of the
[API Reference](api); filter for entries that include the word "pipe".
Angular doesn't have a `FilterPipe` or an `OrderByPipe` for reasons explained in the [Appendix](guide/pipes#no-filter-pipe) of this page.
* For a complete list of built-in pipes, see the [pipes API documentation](/api/common#pipes "Pipes API reference summary").
* To learn more about using pipes for internationalization (i18n) efforts, see [formatting data based on locale](/guide/i18n#i18n-pipes "Formatting data based on locale").
</div>
You can also create pipes to encapsulate custom transformations and use your custom pipes in template expressions.
## Prerequisites
To use pipes you should have a basic understanding of the following:
## Parameterizing a pipe
* [Typescript](guide/glossary#typescript "Definition of Typescript") and HTML5 programming
* [Templates](guide/glossary#template "Definition of a template") in HTML with CSS styles
* [Components](guide/glossary#component "Definition of a component")
A pipe can accept any number of optional parameters to fine-tune its output.
To add parameters to a pipe, follow the pipe name with a colon ( : ) and then the parameter value
(such as `currency:'EUR'`). If the pipe accepts multiple parameters, separate the values with colons (such as `slice:1:5`)
## Using a pipe in a template
Modify the birthday template to give the date pipe a format parameter.
After formatting the hero's April 15th birthday, it renders as **<samp>04/15/88</samp>**:
To apply a pipe, use the pipe operator (`|`) within a template expression as shown in the following code example, along with the *name* of the pipe, which is `date` for the built-in [`DatePipe`](api/common/DatePipe).
The tabs in the example show the following:
* `app.component.html` uses `date` in a separate template to display a birthday.
* `hero-birthday1.component.ts` uses the same pipe as part of an in-line template in a component that also sets the birthday value.
<code-example path="pipes/src/app/app.component.html" region="format-birthday" header="src/app/app.component.html"></code-example>
<code-tabs>
<code-pane
header="src/app/app.component.html"
region="hero-birthday-template"
path="pipes/src/app/app.component.html">
</code-pane>
<code-pane
header="src/app/hero-birthday1.component.ts"
path="pipes/src/app/hero-birthday1.component.ts">
</code-pane>
</code-tabs>
The component's `birthday` value flows through the
[pipe operator](guide/template-syntax#pipe) ( | ) to the [`date`](api/common/DatePipe)
function.
{@a parameterizing-a-pipe}
The parameter value can be any valid template expression,
(see the [Template expressions](guide/template-syntax#template-expressions) section of the
[Template Syntax](guide/template-syntax) page)
such as a string literal or a component property.
In other words, you can control the format through a binding the same way you control the birthday value through a binding.
## Formatting data with parameters and chained pipes
Write a second component that *binds* the pipe's format parameter
to the component's `format` property. Here's the template for that component:
Use optional parameters to fine-tune a pipe's output.
For example, you can use the [`CurrencyPipe`](api/common/CurrencyPipe "API reference") with a country code such as EUR as a parameter.
The template expression `{{ amount | currency:'EUR' }}` transforms the `amount` to currency in euros.
Follow the pipe name (`currency`) with a colon (`:`) and the parameter value (`'EUR'`).
If the pipe accepts multiple parameters, separate the values with colons.
For example, `{{ amount | currency:'EUR':'Euros '}}` adds the second parameter, the string literal `'Euros '`, to the output string. You can use any valid template expression as a parameter, such as a string literal or a component property.
<code-example path="pipes/src/app/hero-birthday2.component.ts" region="template" header="src/app/hero-birthday2.component.ts (template)"></code-example>
Some pipes require at least one parameter and allow more optional parameters, such as [`SlicePipe`](/api/common/SlicePipe "API reference for SlicePipe"). For example, `{{ slice:1:5 }}` creates a new array or string containing a subset of the elements starting with element `1` and ending with element `5`.
### Example: Formatting a date
The tabs in the following example demonstrates toggling between two different formats (`'shortDate'` and `'fullDate'`):
You also added a button to the template and bound its click event to the component's `toggleFormat()` method.
That method toggles the component's `format` property between a short form
* The `app.component.html` template uses a format parameter for the [`DatePipe`](api/common/DatePipe) (named `date`) to show the date as **04/15/88**.
* The `hero-birthday2.component.ts` component binds the pipe's format parameter to the component's `format` property in the `template` section, and adds a button for a click event bound to the component's `toggleFormat()` method.
* The `hero-birthday2.component.ts` component's `toggleFormat()` method toggles the component's `format` property between a short form
(`'shortDate'`) and a longer form (`'fullDate'`).
<code-tabs>
<code-pane
header="src/app/app.component.html"
region="format-birthday"
path="pipes/src/app/app.component.html">
</code-pane>
<code-pane
header="src/app/hero-birthday2.component.ts (template)"
region="template"
path="pipes/src/app/hero-birthday2.component.ts">
</code-pane>
<code-pane
header="src/app/hero-birthday2.component.ts (class)"
region="class"
path="pipes/src/app/hero-birthday2.component.ts">
</code-pane>
</code-tabs>
<code-example path="pipes/src/app/hero-birthday2.component.ts" region="class" header="src/app/hero-birthday2.component.ts (class)"></code-example>
As you click the button, the displayed date alternates between
"**<samp>04/15/1988</samp>**" and
"**<samp>Friday, April 15, 1988</samp>**".
Clicking the **Toggle Format** button alternates the date format between **04/15/1988** and **Friday, April 15, 1988** as shown in Figure 1.
<div class="lightbox">
<img src='generated/images/guide/pipes/date-format-toggle-anim.gif' alt="Date Format Toggle">
</div>
**Figure 1.** Clicking the button toggles the date format
<div class="alert is-helpful">
Read more about the `DatePipe` format options in the [Date Pipe](api/common/DatePipe)
API Reference page.
For `date` pipe format options, see [DatePipe](api/common/DatePipe "DatePipe API Reference page").
</div>
### Example: Applying two formats by chaining pipes
You can chain pipes so that the output of one pipe becomes the input to the next.
## Chaining pipes
In the following example, chained pipes first apply a format to a date value, then convert the formatted date to uppercase characters.
The first tab for the `src/app/app.component.html` template chains `DatePipe` and `UpperCasePipe` to display the birthday as **APR 15, 1988**.
The second tab for the `src/app/app.component.html` template passes the `fullDate` parameter to `date` before chaining to `uppercase`, which produces **FRIDAY, APRIL 15, 1988**.
You can chain pipes together in potentially useful combinations.
In the following example, to display the birthday in uppercase,
the birthday is chained to the `DatePipe` and on to the `UpperCasePipe`.
The birthday displays as **<samp>APR 15, 1988</samp>**.
<code-tabs>
<code-pane
header="src/app/app.component.html (1)"
region="chained-birthday"
path="pipes/src/app/app.component.html">
</code-pane>
<code-pane
header="src/app/app.component.html (2)"
region="chained-parameter-birthday"
path="pipes/src/app/app.component.html">
</code-pane>
</code-tabs>
{@a Custom-pipes}
<code-example path="pipes/src/app/app.component.html" region="chained-birthday" header="src/app/app.component.html"></code-example>
## Creating pipes for custom data transformations
Create custom pipes to encapsulate transformations that are not provided with the built-in pipes.
You can then use your custom pipe in template expressions, the same way you use built-in pipes—to transform input values to output values for display.
### Marking a class as a pipe
This example&mdash;which displays **<samp>FRIDAY, APRIL 15, 1988</samp>**&mdash;chains
the same pipes as above, but passes in a parameter to `date` as well.
To mark a class as a pipe and supply configuration metadata, apply the [`@Pipe`](/api/core/Pipe "API reference for Pipe") [decorator](/guide/glossary#decorator--decoration "Definition for decorator") to the class.
Use [UpperCamelCase](guide/glossary#case-types "Definition of case types") (the general convention for class names) for the pipe class name, and [camelCase](guide/glossary#case-types "Definition of case types") for the corresponding `name` string.
Do not use hyphens in the `name`.
For details and more examples, see [Pipe names](guide/styleguide#pipe-names "Pipe names in the Angular coding style guide").
Use `name` in template expressions as you would for a built-in pipe.
<code-example path="pipes/src/app/app.component.html" region="chained-parameter-birthday" header="src/app/app.component.html"></code-example>
<div class="alert is-important">
## Custom pipes
You can write your own custom pipes.
Here's a custom pipe named `ExponentialStrengthPipe` that can boost a hero's powers:
<code-example path="pipes/src/app/exponential-strength.pipe.ts" header="src/app/exponential-strength.pipe.ts"></code-example>
This pipe definition reveals the following key points:
* A pipe is a class decorated with pipe metadata.
* The pipe class implements the `PipeTransform` interface's `transform` method that
accepts an input value followed by optional parameters and returns the transformed value.
* There will be one additional argument to the `transform` method for each parameter passed to the pipe.
Your pipe has one such parameter: the `exponent`.
* To tell Angular that this is a pipe, you apply the
`@Pipe` decorator, which you import from the core Angular library.
* The `@Pipe` decorator allows you to define the
pipe name that you'll use within template expressions. It must be a valid JavaScript identifier.
Your pipe's name is `exponentialStrength`.
<div class="alert is-helpful">
## The *PipeTransform* interface
The `transform` method is essential to a pipe.
The `PipeTransform` *interface* defines that method and guides both tooling and the compiler.
Technically, it's optional; Angular looks for and executes the `transform` method regardless.
* Include your pipe in the `declarations` field of the `NgModule` metadata in order for it to be available to a template. See the `app.module.ts` file in the example app (<live-example></live-example>). For details, see [NgModules](guide/ngmodules "NgModules introduction").
* Register your custom pipes. The [Angular CLI](cli "CLI Overview and Command Reference") [`ng generate pipe`](cli/generate#pipe "ng generate pipe in the CLI Command Reference") command registers the pipe automatically.
</div>
Now you need a component to demonstrate the pipe.
### Using the PipeTransform interface
<code-example path="pipes/src/app/power-booster.component.ts" header="src/app/power-booster.component.ts"></code-example>
Implement the [`PipeTransform`](/api/core/PipeTransform "API reference for PipeTransform") interface in your custom pipe class to perform the transformation.
Angular invokes the `transform` method with the value of a binding as the first argument, and any parameters as the second argument in list form, and returns the transformed value.
### Example: Transforming a value exponentially
In a game, you may want to implement a transformation that raises a value exponentially to increase a hero's power.
For example, if the hero's score is 2, boosting the hero's power exponentially by 10 produces a score of 1024.
You can use a custom pipe for this transformation.
The following code example shows two component definitions:
* The `exponential-strength.pipe.ts` component defines a custom pipe named `exponentialStrength` with the `transform` method that performs the transformation.
It defines an argument to the `transform` method (`exponent`) for a parameter passed to the pipe.
* The `power-booster.component.ts` component demonstrates how to use the pipe, specifying a value (`2`) and the exponent parameter (`10`).
Figure 2 shows the output.
<code-tabs>
<code-pane
header="src/app/exponential-strength.pipe.ts"
path="pipes/src/app/exponential-strength.pipe.ts">
</code-pane>
<code-pane
header="src/app/power-booster.component.ts"
path="pipes/src/app/power-booster.component.ts">
</code-pane>
</code-tabs>
<div class="lightbox">
<img src='generated/images/guide/pipes/power-booster.png' alt="Power Booster">
</div>
**Figure 2.** Output from the `exponentialStrength` pipe
<div class="alert is-helpful">
Note the following:
* You use your custom pipe the same way you use built-in pipes.
* You must include your pipe in the `declarations` array of the `AppModule`
* If you choose to inject your pipe into a class, you must provide it in the `providers` array of your `NgModule`.
<div class="callout is-helpful">
<header>
Remember the declarations array
</header>
You must register custom pipes.
If you don't, Angular reports an error.
The [Angular CLI's](cli) generator registers the pipe automatically.
To examine the behavior the `exponentialStrength` pipe in the <live-example></live-example>, change the value and optional exponent in the template.
</div>
{@a change-detection}
## Detecting changes with data binding in pipes
To probe the behavior in the <live-example></live-example>,
change the value and optional exponent in the template.
## Power Boost Calculator
It's not much fun updating the template to test the custom pipe.
Upgrade the example to a "Power Boost Calculator" that combines
your pipe and two-way data binding with `ngModel`.
You use [data binding](/guide/glossary#data-binding "Definition of data binding") with a pipe to display values and respond to user actions.
If the data is a primitive input value, such as `String` or `Number`, or an object reference as input, such as `Date` or `Array`, Angular executes the pipe whenever it detects a change for the input value or reference.
For example, you could change the previous custom pipe example to use two-way data binding with `ngModel` to input the amount and boost factor, as shown in the following code example.
<code-example path="pipes/src/app/power-boost-calculator.component.ts" header="src/app/power-boost-calculator.component.ts">
</code-example>
The `exponentialStrength` pipe executes every time the user changes the "normal power" value or the "boost factor", as shown in Figure 3.
<div class="lightbox">
<img src='generated/images/guide/pipes/power-boost-calculator-anim.gif' alt="Power Boost Calculator">
</div>
**Figure 3.** Changing the amount and boost factor for the `exponentialStrength` pipe
Angular detects each change and immediately runs the pipe.
This is fine for primitive input values.
However, if you change something *inside* a composite object (such as the month of a date, an element of an array, or an object property), you need to understand how change detection works, and how to use an `impure` pipe.
### How change detection works
{@a change-detection}
Angular looks for changes to data-bound values in a [change detection](guide/glossary#change-detection "Definition of change detection") process that runs after every DOM event: every keystroke, mouse move, timer tick, and server response.
The following example, which doesn't use a pipe, demonstrates how Angular uses its default change detection strategy to monitor and update its display of every hero in the `heroes` array.
The example tabs show the following:
* In the `flying-heroes.component.html (v1)` template, the `*ngFor` repeater displays the hero names.
* Its companion component class `flying-heroes.component.ts (v1)` provides heroes, adds heroes into the array, and resets the array.
## Pipes and change detection
<code-tabs>
<code-pane
header="src/app/flying-heroes.component.html (v1)"
region="template-1"
path="pipes/src/app/flying-heroes.component.html">
</code-pane>
<code-pane
header="src/app/flying-heroes.component.ts (v1)"
region="v1"
path="pipes/src/app/flying-heroes.component.ts">
</code-pane>
</code-tabs>
Angular looks for changes to data-bound values through a *change detection* process that runs after every DOM event:
every keystroke, mouse move, timer tick, and server response. This could be expensive.
Angular strives to lower the cost whenever possible and appropriate.
Angular updates the display every time the user adds a hero.
If the user clicks the **Reset** button, Angular replaces `heroes` with a new array of the original heroes and updates the display.
If you add the ability to remove or change a hero, Angular would detect those changes and update the display as well.
Angular picks a simpler, faster change detection algorithm when you use a pipe.
However, executing a pipe to update the display with every change would slow down your app's performance.
So Angular uses a faster change-detection algorithm for executing a pipe, as described in the next section.
<h3 class="no-toc">No pipe</h3>
{@a pure-and-impure-pipes}
In the next example, the component uses the default, aggressive change detection strategy to monitor and update
its display of every hero in the `heroes` array. Here's the template:
### Detecting pure changes to primitives and object references
By default, pipes are defined as *pure* so that Angular executes the pipe only when it detects a *pure change* to the input value.
A pure change is either a change to a primitive input value (such as `String`, `Number`, `Boolean`, or `Symbol`), or a changed object reference (such as `Date`, `Array`, `Function`, or `Object`).
<code-example path="pipes/src/app/flying-heroes.component.html" region="template-1" header="src/app/flying-heroes.component.html (v1)"></code-example>
{@a pure-pipe-pure-fn}
A pure pipe must use a pure function, which is one that processes inputs and returns values without side effects.
In other words, given the same input, a pure function should always return the same output.
With a pure pipe, Angular ignores changes within composite objects, such as a newly added element of an existing array, because checking a primitive value or object reference is much faster than performing a deep check for differences within objects.
Angular can quickly determine if it can skip executing the pipe and updating the view.
The companion component class provides heroes, adds heroes into the array, and can reset the array.
However, a pure pipe with an array as input may not work the way you want.
To demonstrate this issue, change the previous example to filter the list of heroes to just those heroes who can fly.
Use the `FlyingHeroesPipe` in the `*ngFor` repeater as shown in the following code.
The tabs for the example show the following:
<code-example path="pipes/src/app/flying-heroes.component.ts" region="v1" header="src/app/flying-heroes.component.ts (v1)"></code-example>
* The template (`flying-heroes.component.html (flyers)`) with the new pipe.
* The `FlyingHeroesPipe` custom pipe implementation (`flying-heroes.pipe.ts`).
<code-tabs>
<code-pane
header="src/app/flying-heroes.component.html (flyers)"
region="template-flying-heroes"
path="pipes/src/app/flying-heroes.component.html">
</code-pane>
<code-pane
header="src/app/flying-heroes.pipe.ts"
region="pure"
path="pipes/src/app/flying-heroes.pipe.ts">
</code-pane>
</code-tabs>
You can add heroes and Angular updates the display when you do.
If you click the `reset` button, Angular replaces `heroes` with a new array of the original heroes and updates the display.
If you added the ability to remove or change a hero, Angular would detect those changes and update the display as well.
<h3 class="no-toc"><i>FlyingHeroesPipe</i></h3>
Add a `FlyingHeroesPipe` to the `*ngFor` repeater that filters the list of heroes to just those heroes who can fly.
<code-example path="pipes/src/app/flying-heroes.component.html" region="template-flying-heroes" header="src/app/flying-heroes.component.html (flyers)"></code-example>
Here's the `FlyingHeroesPipe` implementation, which follows the pattern for custom pipes described earlier.
<code-example path="pipes/src/app/flying-heroes.pipe.ts" region="pure" header="src/app/flying-heroes.pipe.ts"></code-example>
Notice the odd behavior in the <live-example></live-example>:
when you add flying heroes, none of them are displayed under "Heroes who fly."
Although you're not getting the behavior you want, Angular isn't broken.
It's just using a different change-detection algorithm that ignores changes to the list or any of its items.
Notice how a hero is added:
The app now shows unexpected behavior: When the user adds flying heroes, none of them appear under "Heroes who fly."
This happens because the code that adds a hero does so by pushing it onto the `heroes` array:
<code-example path="pipes/src/app/flying-heroes.component.ts" region="push" header="src/app/flying-heroes.component.ts"></code-example>
The change detector ignores changes to elements of an array, so the pipe doesn't run.
The reason Angular ignores the changed array element is that the *reference* to the array hasn't changed.
Since the array is the same, Angular does not update the display.
You add the hero into the `heroes` array. The reference to the array hasn't changed.
It's the same array. That's all Angular cares about. From its perspective, *same array, no change, no display update*.
To fix that, create an array with the new hero appended and assign that to `heroes`.
This time Angular detects that the array reference has changed.
It executes the pipe and updates the display with the new array, which includes the new flying hero.
If you *mutate* the array, no pipe is invoked and the display isn't updated;
if you *replace* the array, the pipe executes and the display is updated.
The Flying Heroes application extends the
code with checkbox switches and additional displays to help you experience these effects.
One way to get the behavior you want is to change the object reference itself.
You can replace the array with a new array containing the newly changed elements, and then input the new array to the pipe.
In the above example, you can create an array with the new hero appended, and assign that to `heroes`. Angular detects the change in the array reference and executes the pipe.
To summarize, if you mutate the input array, the pure pipe doesn't execute.
If you *replace* the input array, the pipe executes and the display is updated, as shown in Figure 4.
<div class="lightbox">
<img src='generated/images/guide/pipes/flying-heroes-anim.gif' alt="Flying Heroes">
</div>
**Figure 4.** The `flyingHeroes` pipe filtering the display to flying heroes
The above example demonstrates changing a component's code to accommodate a pipe.
Replacing the array is an efficient way to signal Angular to update the display.
When do you replace the array? When the data changes.
That's an easy rule to follow in *this* example
where the only way to change the data is by adding a hero.
More often, you don't know when the data has changed,
especially in applications that mutate data in many ways,
perhaps in application locations far away.
A component in such an application usually can't know about those changes.
Moreover, it's unwise to distort the component design to accommodate a pipe.
Strive to keep the component class independent of the HTML.
The component should be unaware of pipes.
For filtering flying heroes, consider an *impure pipe*.
## Pure and impure pipes
There are two categories of pipes: *pure* and *impure*.
Pipes are pure by default. Every pipe you've seen so far has been pure.
You make a pipe impure by setting its pure flag to false. You could make the `FlyingHeroesPipe`
impure like this:
<code-example path="pipes/src/app/flying-heroes.pipe.ts" region="pipe-decorator" header="src/app/flying-heroes.pipe.ts"></code-example>
Before doing that, understand the difference between pure and impure, starting with a pure pipe.
<h3 class="no-toc">Pure pipes</h3>
Angular executes a *pure pipe* only when it detects a *pure change* to the input value.
A pure change is either a change to a primitive input value (`String`, `Number`, `Boolean`, `Symbol`)
or a changed object reference (`Date`, `Array`, `Function`, `Object`).
Angular ignores changes within (composite) objects.
It won't call a pure pipe if you change an input month, add to an input array, or update an input object property.
This may seem restrictive but it's also fast.
An object reference check is fast&mdash;much faster than a deep check for
differences&mdash;so Angular can quickly determine if it can skip both the
pipe execution and a view update.
For this reason, a pure pipe is preferable when you can live with the change detection strategy.
When you can't, you *can* use the impure pipe.
<div class="alert is-helpful">
Or you might not use a pipe at all.
It may be better to pursue the pipe's purpose with a property of the component,
a point that's discussed later in this page.
</div>
<h3 class="no-toc">Impure pipes</h3>
Angular executes an *impure pipe* during every component change detection cycle.
An impure pipe is called often, as often as every keystroke or mouse-move.
With that concern in mind, implement an impure pipe with great care.
An expensive, long-running pipe could destroy the user experience.
To keep your component simpler and independent of HTML templates that use pipes, you can, as an alternative, use an *impure* pipe to detect changes within composite objects such as arrays, as described in the next section.
{@a impure-flying-heroes}
### Detecting impure changes within composite objects
<h3 class="no-toc">An impure <i>FlyingHeroesPipe</i></h3>
To execute a custom pipe after a change *within* a composite object, such as a change to an element of an array, you need to define your pipe as `impure` to detect impure changes.
Angular executes an impure pipe every time it detects a change with every keystroke or mouse movement.
A flip of the switch turns the `FlyingHeroesPipe` into a `FlyingHeroesImpurePipe`.
The complete implementation is as follows:
<div class="alert is-important">
While an impure pipe can be useful, be careful using one. A long-running impure pipe could dramatically slow down your app.
</div>
Make a pipe impure by setting its `pure` flag to `false`:
<code-example path="pipes/src/app/flying-heroes.pipe.ts" region="pipe-decorator" header="src/app/flying-heroes.pipe.ts"></code-example>
The following code shows the complete implementation of `FlyingHeroesImpurePipe`, which extends `FlyingHeroesPipe` to inherit its characteristics.
The example shows that you don't have to change anything else—the only difference is setting the `pure` flag as `false` in the pipe metadata.
<code-tabs>
<code-pane header="FlyingHeroesImpurePipe" path="pipes/src/app/flying-heroes.pipe.ts" region="impure">
<code-pane
header="src/app/flying-heroes.pipe.ts (FlyingHeroesImpurePipe)"
region="impure"
path="pipes/src/app/flying-heroes.pipe.ts">
</code-pane>
<code-pane header="FlyingHeroesPipe" path="pipes/src/app/flying-heroes.pipe.ts" region="pure">
<code-pane
header="src/app/flying-heroes.pipe.ts (FlyingHeroesPipe)"
region="pure"
path="pipes/src/app/flying-heroes.pipe.ts">
</code-pane>
</code-tabs>
You inherit from `FlyingHeroesPipe` to prove the point that nothing changed internally.
The only difference is the `pure` flag in the pipe metadata.
This is a good candidate for an impure pipe because the `transform` function is trivial and fast.
`FlyingHeroesImpurePipe` is a good candidate for an impure pipe because the `transform` function is trivial and fast:
<code-example path="pipes/src/app/flying-heroes.pipe.ts" header="src/app/flying-heroes.pipe.ts (filter)" region="filter"></code-example>
You can derive a `FlyingHeroesImpureComponent` from `FlyingHeroesComponent`.
As shown in the code below, only the pipe in the template changes.
<code-example path="pipes/src/app/flying-heroes-impure.component.html" header="src/app/flying-heroes-impure.component.html (excerpt)" region="template-flying-heroes"></code-example>
<div class="alert is-helpful">
To confirm that the display updates as the user adds heroes, see the <live-example></live-example>.
The only substantive change is the pipe in the template.
You can confirm in the <live-example></live-example> that the _flying heroes_
display updates as you add heroes, even when you mutate the `heroes` array.
</div>
{@a async-pipe}
<h3 class="no-toc">The impure <i>AsyncPipe</i></h3>
## Unwrapping data from an observable
The Angular `AsyncPipe` is an interesting example of an impure pipe.
The `AsyncPipe` accepts a `Promise` or `Observable` as input
and subscribes to the input automatically, eventually returning the emitted values.
[Observables](/guide/glossary#observable "Definition of observable") let you pass messages between parts of your application.
Observables are recommended for event handling, asynchronous programming, and handling multiple values.
Observables can deliver single or multiple values of any type, either synchronously (as a function delivers a value to its caller) or asynchronously on a schedule.
The `AsyncPipe` is also stateful.
The pipe maintains a subscription to the input `Observable` and
keeps delivering values from that `Observable` as they arrive.
<div class="alert is-helpful">
This next example binds an `Observable` of message strings
For details and examples of observables, see the [Observables Overview](/guide/observables#using-observables-to-pass-values "Using observables to pass values"").
</div>
Use the built-in [`AsyncPipe`](/api/common/AsyncPipe "API description of AsyncPipe") to accept an observable as input and subscribe to the input automatically.
Without this pipe, your component code would have to subscribe to the observable to consume its values, extract the resolved values, expose them for binding, and unsubscribe when the observable is destroyed in order to prevent memory leaks. `AsyncPipe` is an impure pipe that saves boilerplate code in your component to maintain the subscription and keep delivering values from that observable as they arrive.
The following code example binds an observable of message strings
(`message$`) to a view with the `async` pipe.
<code-example path="pipes/src/app/hero-async-message.component.ts" header="src/app/hero-async-message.component.ts">
</code-example>
{@a no-filter-pipe}
## Caching HTTP requests
The Async pipe saves boilerplate in the component code.
The component doesn't have to subscribe to the async data source,
extract the resolved values and expose them for binding,
and have to unsubscribe when it's destroyed
(a potent source of memory leaks).
To [communicate with backend services using HTTP](/guide/http "Communicating with backend services using HTTP"), the `HttpClient` service uses observables and offers the `HTTPClient.get()` method to fetch data from a server.
The aynchronous method sends an HTTP request, and returns an observable that emits the requested data for the response.
<h3 class="no-toc">An impure caching pipe</h3>
As shown in the previous section, you can use the impure `AsyncPipe` to accept an observable as input and subscribe to the input automatically.
You can also create an impure pipe to make and cache an HTTP request.
Write one more impure pipe, a pipe that makes an HTTP request.
Impure pipes are called whenever change detection runs for a component, which could be every few milliseconds for `CheckAlways`.
To avoid performance problems, call the server only when the requested URL changes, as shown in the following example, and use the pipe to cache the server response.
The tabs show the following:
Remember that impure pipes are called every few milliseconds.
If you're not careful, this pipe will punish the server with requests.
* The `fetch` pipe (`fetch-json.pipe.ts`).
* A harness component (`hero-list.component.ts`) for demonstrating the request, using a template that defines two bindings to the pipe requesting the heroes from the `heroes.json` file. The second binding chains the `fetch` pipe with the built-in `JsonPipe` to display the same hero data in JSON format.
In the following code, the pipe only calls the server when the requested URL changes and it caches the server response.
The code uses the [Angular http](guide/http) client to retrieve data:
<code-tabs>
<code-pane
header="src/app/fetch-json.pipe.ts"
path="pipes/src/app/fetch-json.pipe.ts">
</code-pane>
<code-pane
header="src/app/hero-list.component.ts"
path="pipes/src/app/hero-list.component.ts">
</code-pane>
</code-tabs>
In the above example, a breakpoint on the pipe's request for data shows the following:
<code-example path="pipes/src/app/fetch-json.pipe.ts" header="src/app/fetch-json.pipe.ts">
</code-example>
Now demonstrate it in a harness component whose template defines two bindings to this pipe,
both requesting the heroes from the `heroes.json` file.
<code-example path="pipes/src/app/hero-list.component.ts" header="src/app/hero-list.component.ts">
</code-example>
The component renders as the following:
* Each binding gets its own pipe instance.
* Each pipe instance caches its own URL and data and calls the server only once.
The `fetch` and `fetch-json` pipes display the heroes as shown in Figure 5.
<div class="lightbox">
<img src='generated/images/guide/pipes/hero-list.png' alt="Hero List">
</div>
**Figure 5.** The `fetch` and `fetch-json` pipes displaying the heroes
<div class="alert is-helpful">
A breakpoint on the pipe's request for data shows the following:
* Each binding gets its own pipe instance.
* Each pipe instance caches its own URL and data.
* Each pipe instance only calls the server once.
<h3 class="no-toc"><i>JsonPipe</i></h3>
In the previous code sample, the second `fetch` pipe binding demonstrates more pipe chaining.
It displays the same hero data in JSON format by chaining through to the built-in `JsonPipe`.
<div class="callout is-helpful">
<header>
Debugging with the json pipe
</header>
The [JsonPipe](api/common/JsonPipe)
provides an easy way to diagnose a mysteriously failing data binding or
inspect an object for future binding.
The built-in [JsonPipe](api/common/JsonPipe "API description for JsonPipe") provides a way to diagnose a mysteriously failing data binding or to inspect an object for future binding.
</div>
{@a pure-pipe-pure-fn}
<h3 class="no-toc">Pure pipes and pure functions</h3>
A pure pipe uses pure functions.
Pure functions process inputs and return values without detectable side effects.
Given the same input, they should always return the same output.
The pipes discussed earlier in this page are implemented with pure functions.
The built-in `DatePipe` is a pure pipe with a pure function implementation.
So are the `ExponentialStrengthPipe` and `FlyingHeroesPipe`.
A few steps back, you reviewed the `FlyingHeroesImpurePipe`&mdash;an impure pipe with a pure function.
But always implement a *pure pipe* with a *pure function*.
Otherwise, you'll see many console errors regarding expressions that changed after they were checked.
## Next steps
Pipes are a great way to encapsulate and share common display-value
transformations. Use them like styles, dropping them
into your template's expressions to enrich the appeal and usability
of your views.
Explore Angular's inventory of built-in pipes in the [API Reference](api?type=pipe).
Try writing a custom pipe and perhaps contributing it to the community.
{@a no-filter-pipe}
## Appendix: No *FilterPipe* or *OrderByPipe*
Angular doesn't provide pipes for filtering or sorting lists.
Developers familiar with AngularJS know these as `filter` and `orderBy`.
There are no equivalents in Angular.
This isn't an oversight. Angular doesn't offer such pipes because
they perform poorly and prevent aggressive minification.
Both `filter` and `orderBy` require parameters that reference object properties.
Earlier in this page, you learned that such pipes must be [impure](guide/pipes#pure-and-impure-pipes) and that
Angular calls impure pipes in almost every change-detection cycle.
Filtering and especially sorting are expensive operations.
The user experience can degrade severely for even moderate-sized lists when Angular calls these pipe methods many times per second.
`filter` and `orderBy` have often been abused in AngularJS apps, leading to complaints that Angular itself is slow.
That charge is fair in the indirect sense that AngularJS prepared this performance trap
by offering `filter` and `orderBy` in the first place.
The minification hazard is also compelling, if less obvious. Imagine a sorting pipe applied to a list of heroes.
The list might be sorted by hero `name` and `planet` of origin properties in the following way:
<code-example language="html">
&lt;!-- NOT REAL CODE! -->
&lt;div *ngFor="let hero of heroes | orderBy:'name,planet'">&lt;/div>
</code-example>
You identify the sort fields by text strings, expecting the pipe to reference a property value by indexing
(such as `hero['name']`).
Unfortunately, aggressive minification manipulates the `Hero` property names so that `Hero.name` and `Hero.planet`
become something like `Hero.a` and `Hero.b`. Clearly `hero['name']` doesn't work.
While some may not care to minify this aggressively,
the Angular product shouldn't prevent anyone from minifying aggressively.
Therefore, the Angular team decided that everything Angular provides will minify safely.
The Angular team and many experienced Angular developers strongly recommend moving
filtering and sorting logic into the component itself.
The component can expose a `filteredHeroes` or `sortedHeroes` property and take control
over when and how often to execute the supporting logic.
Any capabilities that you would have put in a pipe and shared across the app can be
written in a filtering/sorting service and injected into the component.
If these performance and minification considerations don't apply to you, you can always create your own such pipes
(similar to the [FlyingHeroesPipe](guide/pipes#impure-flying-heroes)) or find them in the community.

View File

@ -52,6 +52,14 @@ Any component created within a lazy loaded modules context, such as by router
Though you can provide services by lazy loading modules, not all services can be lazy loaded. For instance, some modules only work in the root module, such as the Router. The Router works with the global location object in the browser.
As of Angular version 9, you can provide a new instance of a service with each lazy loaded module. The following code adds this functionality to `UserService`.
<code-example path="providers/src/app/user.service.2.ts" header="src/app/user.service.ts"></code-example>
With `providedIn: 'any'`, all eagerly loaded modules share a singleton instance; however, lazy loaded modules each get their own unique instance, as shown in the following diagram.
<img src="generated/images/guide/providers/any-provider.svg" alt="any-provider-scope" class="left">
## Limiting provider scope with components

View File

@ -101,6 +101,7 @@ The following table provides the status for Angular versions under support.
Version | Status | Released | Active Ends | LTS Ends
------- | ------ | ------------ | ------------ | ------------
^10.0.0 | Active | Jun 24, 2020 | Dec 24, 2020 | Dec 24, 2021
^9.0.0 | Active | Feb 06, 2020 | Aug 06, 2020 | Aug 06, 2021
^8.0.0 | LTS | May 28, 2019 | Nov 28, 2019 | Nov 28, 2020

View File

@ -111,7 +111,7 @@ Let's assume that we are routing from the *Home => About*.
The animation code does the following after styling the views:
* `query(':enter style({ left: '-100%'})` matches the view that is added and hides the newly added view by positioning it to the far left.
* `query(':enter', style({ left: '-100%' }))` matches the view that is added and hides the newly added view by positioning it to the far left.
* Calls `animateChild()` on the view that is leaving, to run its child animations.
* Uses `group()` function to make the inner animations run in parallel.
* Within the `group()` function:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
# Schematics for libraries
When you create an Angular library, you can provide and package it with schematics that integrate it with the Angular CLI.
With your schematics, your users can use `ng add` to install an initial version of your library,
With your schematics, your users can use `ng add` to install an initial version of your library,
`ng generate` to create artifacts defined in your library, and `ng update` to adjust their project for a new version of your library that introduces breaking changes.
All three types of schematics can be part of a collection that you package with your library.
@ -115,10 +115,10 @@ When you add a schematic to the collection, you have to point to it in the colle
<code-example header="projects/my-lib/schematics/my-service/schema.json (Schematic JSON Schema)" path="schematics-for-libraries/projects/my-lib/schematics/my-service/schema.json">
</code-example>
* *id* : A unique id for the schema in the collection.
* *title* : A human-readable description of the schema.
* *type* : A descriptor for the type provided by the properties.
* *properties* : An object that defines the available options for the schematic.
* *id*: A unique id for the schema in the collection.
* *title*: A human-readable description of the schema.
* *type*: A descriptor for the type provided by the properties.
* *properties*: An object that defines the available options for the schematic.
Each option associates key with a type, description, and optional alias.
The type defines the shape of the value you expect, and the description is displayed when the user requests usage help for your schematic.
@ -130,9 +130,9 @@ When you add a schematic to the collection, you have to point to it in the colle
<code-example header="projects/my-lib/schematics/my-service/schema.ts (Schematic Interface)" path="schematics-for-libraries/projects/my-lib/schematics/my-service/schema.ts">
</code-example>
* *name* : The name you want to provide for the created service.
* *path* : Overrides the path provided to the schematic. The default path value is based on the current working directory.
* *project* : Provides a specific project to run the schematic on. In the schematic, you can provide a default if the option is not provided by the user.
* *name*: The name you want to provide for the created service.
* *path*: Overrides the path provided to the schematic. The default path value is based on the current working directory.
* *project*: Provides a specific project to run the schematic on. In the schematic, you can provide a default if the option is not provided by the user.
### Add template files
@ -169,10 +169,9 @@ The Schematics framework provides a file templating system, which supports both
The system operates on placeholders defined inside files or paths that loaded in the input `Tree`.
It fills these in using values passed into the `Rule`.
For details of these data structure and syntax, see the [Schematics README](https://github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/README.md).
For details of these data structures and syntax, see the [Schematics README](https://github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/README.md).
1. Create the main file, `index.ts` and add the source code for your schematic factory function.
1. Create the main file `index.ts` and add the source code for your schematic factory function.
1. First, import the schematics definitions you will need. The Schematics framework offers many utility functions to create and use rules when running a schematic.
@ -271,7 +270,6 @@ For more information about rules and utility methods, see [Provided Rules](https
After you build your library and schematics, you can install the schematics collection to run against your project. The steps below show you how to generate a service using the schematic you created above.
### Build your library and schematics
From the root of your workspace, run the `ng build` command for your library.

View File

@ -31,28 +31,27 @@ You can use these events to notify the user of a pending update or to refresh th
### Checking for updates
It's possible to ask the service worker to check if any updates have been deployed to the server. You might choose to do this if you have a site that changes frequently or want updates to happen on a schedule.
It's possible to ask the service worker to check if any updates have been deployed to the server.
The service worker checks for updates during initialization and on each navigation request&mdash;that is, when the user navigates from a different address to your app.
However, you might choose to manually check for updates if you have a site that changes frequently or want updates to happen on a schedule.
Do this with the `checkForUpdate()` method:
<code-example path="service-worker-getting-started/src/app/check-for-update.service.ts" header="check-for-update.service.ts"></code-example>
This method returns a `Promise` which indicates that the update check has completed successfully, though it does not indicate whether an update was discovered as a result of the check. Even if one is found, the service worker must still successfully download the changed files, which can fail. If successful, the `available` event will indicate availability of a new version of the app.
<div class="alert is-important">
In order to avoid negatively affecting the initial rendering, `ServiceWorkerModule` will by default
wait for the app to stabilize, before registering the ServiceWorker script. Constantly polling for
updates, e.g. with `interval()`, will prevent the app from stabilizing and the ServiceWorker
script will never be registered with the browser.
You can avoid that by waiting for the app to stabilize first, before starting to poll for updates
(as shown in the example above).
In order to avoid negatively affecting the initial rendering of the page, `ServiceWorkerModule` waits for up to 30 seconds by default for the app to stabilize, before registering the ServiceWorker script.
Constantly polling for updates, for example, with [setInterval()](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) or RxJS' [interval()](https://rxjs.dev/api/index/function/interval), will prevent the app from stabilizing and the ServiceWorker script will not be registered with the browser until the 30 seconds upper limit is reached.
Note that this is true for any kind of polling done by your application.
Check the {@link ApplicationRef#isStable isStable} documentation for more information.
You can avoid that delay by waiting for the app to stabilize first, before starting to poll for updates, as shown in the example above.
Alternatively, you might want to define a different {@link SwRegistrationOptions#registrationStrategy registration strategy} for the ServiceWorker.
</div>
### Forcing update activation
@ -61,7 +60,12 @@ If the current tab needs to be updated to the latest app version immediately, it
<code-example path="service-worker-getting-started/src/app/prompt-update.service.ts" header="prompt-update.service.ts" region="sw-activate"></code-example>
Doing this could break lazy-loading in currently running apps, especially if the lazy-loaded chunks use filenames with hashes, which change every version.
<div class="alert is-important">
Calling `activateUpdate()` without reloading the page could break lazy-loading in a currently running app, especially if the lazy-loaded chunks use filenames with hashes, which change every version.
Therefore, it is recommended to reload the page once the promise returned by `activateUpdate()` is resolved.
</div>
## More on Angular service workers

View File

@ -25,49 +25,48 @@ To use the Angular framework, you should be familiar with the following:
Knowledge of [TypeScript](https://www.typescriptlang.org/) is helpful, but not required.
To install Angular on your local system, you need the following:
{@a nodejs}
### Node.js
Make sure your development environment includes `Node.js®` and an npm package manager.
* **Node.js**
Angular requires a [current, active LTS, or maintenance LTS](https://nodejs.org/about/releases/) version of `Node.js`. See the `engines` key for the specific version requirements in our [package.json](https://unpkg.com/@angular/cli/package.json).
Angular requires a [current, active LTS, or maintenance LTS](https://nodejs.org/about/releases) version of Node.js.
* To check your version, run `node -v` in a terminal/console window.
<div class="alert is-helpful">
* To get `Node.js`, go to [nodejs.org](https://nodejs.org "Nodejs.org").
For information about specific version requirements, see the `engines` key in the [package.json](https://unpkg.com/@angular/cli/package.json) file.
</div>
For more information on installing Node.js, see [nodejs.org](http://nodejs.org "Nodejs.org").
If you are unsure what version of Node.js runs on your system, run `node -v` in a terminal window.
{@a npm}
### npm package manager
Angular, the Angular CLI, and Angular apps depend on features and functionality provided by libraries that are available as [npm packages](https://docs.npmjs.com/getting-started/what-is-npm). To download and install npm packages, you must have an npm package manager.
* **npm package manager**
This setup guide uses the [npm client](https://docs.npmjs.com/cli/install) command line interface, which is installed with `Node.js` by default.
To check that you have the npm client installed, run `npm -v` in a terminal/console window.
Angular, the Angular CLI, and Angular applications depend on [npm packages](https://docs.npmjs.com/getting-started/what-is-npm) for many features and functions.
To download and install npm packages, you need an npm package manager.
This guide uses the [npm client](https://docs.npmjs.com/cli/install) command line interface, which is installed with `Node.js` by default.
To check that you have the npm client installed, run `npm -v` in a terminal window.
{@a install-cli}
## Step 1: Install the Angular CLI
## Install the Angular CLI
You use the Angular CLI
to create projects, generate application and library code, and perform a variety of ongoing development tasks such as testing, bundling, and deployment.
Install the Angular CLI globally.
To install the CLI using `npm`, open a terminal/console window and enter the following command:
You use the Angular CLI to create projects, generate application and library code, and perform a variety of ongoing development tasks such as testing, bundling, and deployment.
To install the Angular CLI, open a terminal window and run the following command:
<code-example language="sh" class="code-shell">
npm install -g @angular/cli
</code-example>
{@a create-proj}
## Step 2: Create a workspace and initial application
## Create a workspace and initial application
You develop apps in the context of an Angular [**workspace**](guide/glossary#workspace).
@ -86,16 +85,22 @@ The Angular CLI installs the necessary Angular npm packages and other dependenci
The CLI creates a new workspace and a simple Welcome app, ready to run.
<div class="alert is-helpful">
You also have the option to use Angular's strict mode, which can help you write better, more maintainable code.
For more information, see [Strict mode](/guide/strict-mode).
</div>
{@a serve}
## Step 3: Run the application
## Run the application
The Angular CLI includes a server, so that you can easily build and serve your app locally.
The Angular CLI includes a server, so that you can build and serve your app locally.
1. Go to the workspace folder (`my-app`).
1. Navigate to the workspace folder, such as `my-app`.
1. Launch the server by using the CLI command `ng serve`, with the `--open` option.
1. Run the following command:
<code-example language="sh" class="code-shell">
cd my-app
@ -108,7 +113,7 @@ and rebuilds the app as you make changes to those files.
The `--open` (or just `-o`) option automatically opens your browser
to `http://localhost:4200/`.
You will see:
If your installation and setup was successful, you should see a page similar to the following.
<div class="lightbox">

View File

@ -0,0 +1,46 @@
# Strict mode
When you create a new workspace or a project you have an option to create them in a strict mode using the `--strict` flag.
Enabling this flag initializes your new workspace or project with a few new settings that improve maintainability, help you catch bugs ahead of time, and allow the CLI to perform advanced optimizations on your application.
Additionally, applications that use these stricter settings are easier to statically analyze, which can help the `ng update` command refactor code more safely and precisely when you are updating to future versions of Angular.
Specifically, the `strict` flag does the following:
* Enables [`strict` mode in TypeScript](https://www.staging-typescript.org/tsconfig#strict), as well as other strictness flags recommended by the TypeScript team. Specifically, `forceConsistentCasingInFileNames`, `noImplicitReturns`, `noFallthroughCasesInSwitch`.
* Turns on strict Angular compiler flags [`strictTemplates`](guide/angular-compiler-options#stricttemplates) and [`strictInjectionParameters`](guide/angular-compiler-options#strictinjectionparameters)
* [Bundle size budgets](guide/build#configuring-size-budgets) have been reduced by ~75%
* Turns on [`no-any` tslint rule](https://palantir.github.io/tslint/rules/no-any/) to prevent declarations of type `any`
* [Marks your application as side-effect free](https://webpack.js.org/guides/tree-shaking/#mark-the-file-as-side-effect-free) to enable more advanced tree-shaking
You can apply these settings at the workspace and project level.
To create a new workspace and application using the strict mode, run the following command:
<code-example language="sh" class="code-shell">
ng new [project-name] --strict
</code-example>
To create a new application in the strict mode within an existing non-strict workspace, run the following command:
<code-example language="sh" class="code-shell">
ng generate application [project-name] --strict
</code-example>
{@a side-effect}
### Non-local side effects in applications
When you create projects and workspaces using the `strict` mode, you'll notice an additional `package.json` file, located in `src/app/` directory.
This file informs tools and bundlers that the code under this directory is free of non-local side effects. Non-local side effects in the application code are not common and using them is not considered a good coding pattern.
More importantly, code with these types of side effects cannot be optimized, resulting in increased bundle sizes and applications that load more slowly.
If you need more information, the following links may be helpful.
* [Tree-shaking](https://webpack.js.org/guides/tree-shaking/)
* [Dealing with side effects and pure functions in JavaScript](https://dev.to/vonheikemen/dealing-with-side-effects-and-pure-functions-in-javascript-16mg)
* [How to deal with dirty side effects in your pure function JavaScript](https://jrsinclair.com/articles/2018/how-to-deal-with-dirty-side-effects-in-your-pure-functional-javascript/)

View File

@ -821,8 +821,8 @@ 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.
"Template &lt;script&gt;alert("evil never sleeps")&lt;/script&gt; Syntax" is the interpolated evil title.
"Template Syntax" is the property bound evil title.
</code-example>
<hr/>

View File

@ -3,7 +3,7 @@
## Overview of template type checking
Just as TypeScript catches type errors in your code, Angular checks the expressions and bindings within the templates of your application and can report any type errors it finds.
Angular currently has three modes of doing this, depending on the value of the `fullTemplateTypeCheck` and `strictTemplates` flags in the [TypeScript configuration file](guide/typescript-configuration), `tsconfig.json`.
Angular currently has three modes of doing this, depending on the value of the `fullTemplateTypeCheck` and `strictTemplates` flags in the [TypeScript configuration file](guide/typescript-configuration).
### Basic mode
@ -107,7 +107,7 @@ There can also be false positives when the typings of an Angular library are eit
In case of a false positive like these, there are a few options:
* Use the [`$any()` type-cast function](guide/template-syntax#any-type-cast-function) in certain contexts to opt out of type-checking for a part of the expression.
* You can disable strict checks entirely by setting `strictTemplates: false` in the application's TypeScript configuration file, `tsconfig.json`.
* You can disable strict checks entirely by setting `strictTemplates: false` in the application's TypeScript configuration file.
* You can disable certain type-checking operations individually, while maintaining strictness in other aspects, by setting a _strictness flag_ to `false`.
* If you want to use `strictTemplates` and `strictNullChecks` together, you can opt out of strict null type checking specifically for input bindings via `strictNullInputTypes`.

View File

@ -0,0 +1,28 @@
# Debugging tests
If your tests aren't working as you expect them to, you can inspect and debug them in the browser.
<div class="alert is-helpful">
For the sample app that the testing guides describe, see the <live-example name="testing" embedded-style noDownload>sample app</live-example>.
For the tests features in the testing guides, see <live-example name="testing" stackblitz="specs" noDownload>tests</live-example>.
</div>
Debug specs in the browser in the same way that you debug an application.
1. Reveal the Karma browser window. See [Set up testing](guide/testing#set-up-testing) if you need help with this step.
1. Click the **DEBUG** button; it opens a new browser tab and re-runs the tests.
1. Open the browser's “Developer Tools” (`Ctrl-Shift-I` on Windows; `Command-Option-I` in macOS).
1. Pick the "sources" section.
1. Open the `1st.spec.ts` test file (Control/Command-P, then start typing the name of the file).
1. Set a breakpoint in the test.
1. Refresh the browser, and it stops at the breakpoint.
<div class="lightbox">
<img src='generated/images/guide/testing/karma-1st-spec-debug.png' alt="Karma debugging">
</div>
<hr>

View File

@ -0,0 +1,78 @@
{@a attribute-directive}
# Testing Attribute Directives
An _attribute directive_ modifies the behavior of an element, component or another directive.
Its name reflects the way the directive is applied: as an attribute on a host element.
<div class="alert is-helpful">
For the sample app that the testing guides describe, see the <live-example name="testing" embedded-style noDownload>sample app</live-example>.
For the tests features in the testing guides, see <live-example name="testing" stackblitz="specs" noDownload>tests</live-example>.
</div>
## Testing the `HighlightDirective`
The sample application's `HighlightDirective` sets the background color of an element
based on either a data bound color or a default color (lightgray).
It also sets a custom property of the element (`customProperty`) to `true`
for no reason other than to show that it can.
<code-example path="testing/src/app/shared/highlight.directive.ts" header="app/shared/highlight.directive.ts"></code-example>
It's used throughout the application, perhaps most simply in the `AboutComponent`:
<code-example path="testing/src/app/about/about.component.ts" header="app/about/about.component.ts"></code-example>
Testing the specific use of the `HighlightDirective` within the `AboutComponent` requires only the techniques explored in the ["Nested component tests"](guide/testing-components-scenarios#nested-component-tests) section of [Component testing scenarios](guide/testing-components-scenarios).
<code-example path="testing/src/app/about/about.component.spec.ts" region="tests" header="app/about/about.component.spec.ts"></code-example>
However, testing a single use case is unlikely to explore the full range of a directive's capabilities.
Finding and testing all components that use the directive is tedious, brittle, and almost as unlikely to afford full coverage.
_Class-only tests_ might be helpful,
but attribute directives like this one tend to manipulate the DOM.
Isolated unit tests don't touch the DOM and, therefore,
do not inspire confidence in the directive's efficacy.
A better solution is to create an artificial test component that demonstrates all ways to apply the directive.
<code-example path="testing/src/app/shared/highlight.directive.spec.ts" region="test-component" header="app/shared/highlight.directive.spec.ts (TestComponent)"></code-example>
<div class="lightbox">
<img src='generated/images/guide/testing/highlight-directive-spec.png' alt="HighlightDirective spec in action">
</div>
<div class="alert is-helpful">
The `<input>` case binds the `HighlightDirective` to the name of a color value in the input box.
The initial value is the word "cyan" which should be the background color of the input box.
</div>
Here are some tests of this component:
<code-example path="testing/src/app/shared/highlight.directive.spec.ts" region="selected-tests" header="app/shared/highlight.directive.spec.ts (selected tests)"></code-example>
A few techniques are noteworthy:
- The `By.directive` predicate is a great way to get the elements that have this directive _when their element types are unknown_.
- The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:not">`:not` pseudo-class</a>
in `By.css('h2:not([highlight])')` helps find `<h2>` elements that _do not_ have the directive.
`By.css('*:not([highlight])')` finds _any_ element that does not have the directive.
- `DebugElement.styles` affords access to element styles even in the absence of a real browser, thanks to the `DebugElement` abstraction.
But feel free to exploit the `nativeElement` when that seems easier or more clear than the abstraction.
- Angular adds a directive to the injector of the element to which it is applied.
The test for the default color uses the injector of the second `<h2>` to get its `HighlightDirective` instance
and its `defaultColor`.
- `DebugElement.properties` affords access to the artificial custom property that is set by the directive.
<hr>

View File

@ -0,0 +1,57 @@
{@a code-coverage}
# Find out how much code you're testing
The CLI can run unit tests and create code coverage reports.
Code coverage reports show you any parts of your code base that may not be properly tested by your unit tests.
<div class="alert is-helpful">
For the sample app that the testing guides describe, see the <live-example name="testing" embedded-style noDownload>sample app</live-example>.
For the tests features in the testing guides, see <live-example name="testing" stackblitz="specs" noDownload>tests</live-example>.
</div>
To generate a coverage report run the following command in the root of your project.
<code-example language="sh" class="code-shell">
ng test --no-watch --code-coverage
</code-example>
When the tests are complete, the command creates a new `/coverage` folder in the project. Open the `index.html` file to see a report with your source code and code coverage values.
If you want to create code-coverage reports every time you test, you can set the following option in the CLI configuration file, `angular.json`:
```
"test": {
"options": {
"codeCoverage": true
}
}
```
## Code coverage enforcement
The code coverage percentages let you estimate how much of your code is tested.
If your team decides on a set minimum amount to be unit tested, you can enforce this minimum with the Angular CLI.
For example, suppose you want the code base to have a minimum of 80% code coverage.
To enable this, open the [Karma](https://karma-runner.github.io) test platform configuration file, `karma.conf.js`, and add the following in the `coverageIstanbulReporter:` key.
```
coverageIstanbulReporter: {
reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: true,
thresholds: {
statements: 80,
lines: 80,
branches: 80,
functions: 80
}
}
```
The `thresholds` property causes the tool to enforce a minimum of 80% code coverage when the unit tests are run in the project.

View File

@ -0,0 +1,380 @@
# Basics of testing components
A component, unlike all other parts of an Angular application,
combines an HTML template and a TypeScript class.
The component truly is the template and the class _working together_. To adequately test a component, you should test that they work together
as intended.
Such tests require creating the component's host element in the browser DOM,
as Angular does, and investigating the component class's interaction with
the DOM as described by its template.
The Angular `TestBed` facilitates this kind of testing as you'll see in the sections below.
But in many cases, _testing the component class alone_, without DOM involvement,
can validate much of the component's behavior in an easier, more obvious way.
<div class="alert is-helpful">
For the sample app that the testing guides describe, see the <live-example name="testing" embedded-style noDownload>sample app</live-example>.
For the tests features in the testing guides, see <live-example name="testing" stackblitz="specs" noDownload>tests</live-example>.
</div>
{@a component-class-testing}
## Component class testing
Test a component class on its own as you would test a service class.
Component class testing should be kept very clean and simple.
It should test only a single unit.
At first glance, you should be able to understand
what the test is testing.
Consider this `LightswitchComponent` which toggles a light on and off
(represented by an on-screen message) when the user clicks the button.
<code-example
path="testing/src/app/demo/demo.ts"
region="LightswitchComp"
header="app/demo/demo.ts (LightswitchComp)"></code-example>
You might decide only to test that the `clicked()` method
toggles the light's _on/off_ state and sets the message appropriately.
This component class has no dependencies. To test these types of classes, follow the same steps as you would for a service that has no dependencies:
1. Create a component using the new keyword.
2. Poke at its API.
3. Assert expectations on its public state.
<code-example
path="testing/src/app/demo/demo.spec.ts"
region="Lightswitch"
header="app/demo/demo.spec.ts (Lightswitch tests)"></code-example>
Here is the `DashboardHeroComponent` from the _Tour of Heroes_ tutorial.
<code-example
path="testing/src/app/dashboard/dashboard-hero.component.ts"
region="class"
header="app/dashboard/dashboard-hero.component.ts (component)"></code-example>
It appears within the template of a parent component,
which binds a _hero_ to the `@Input` property and
listens for an event raised through the _selected_ `@Output` property.
You can test that the class code works without creating the `DashboardHeroComponent`
or its parent component.
<code-example
path="testing/src/app/dashboard/dashboard-hero.component.spec.ts"
region="class-only"
header="app/dashboard/dashboard-hero.component.spec.ts (class tests)"></code-example>
When a component has dependencies, you may wish to use the `TestBed` to both
create the component and its dependencies.
The following `WelcomeComponent` depends on the `UserService` to know the name of the user to greet.
<code-example
path="testing/src/app/welcome/welcome.component.ts"
region="class"
header="app/welcome/welcome.component.ts"></code-example>
You might start by creating a mock of the `UserService` that meets the minimum needs of this component.
<code-example
path="testing/src/app/welcome/welcome.component.spec.ts"
region="mock-user-service"
header="app/welcome/welcome.component.spec.ts (MockUserService)"></code-example>
Then provide and inject _both the_ **component** _and the service_ in the `TestBed` configuration.
<code-example
path="testing/src/app/welcome/welcome.component.spec.ts"
region="class-only-before-each"
header="app/welcome/welcome.component.spec.ts (class-only setup)"></code-example>
Then exercise the component class, remembering to call the [lifecycle hook methods](guide/lifecycle-hooks) as Angular does when running the app.
<code-example
path="testing/src/app/welcome/welcome.component.spec.ts"
region="class-only-tests"
header="app/welcome/welcome.component.spec.ts (class-only tests)"></code-example>
## Component DOM testing
Testing the component _class_ is as easy as [testing a service](guide/testing-services).
But a component is more than just its class.
A component interacts with the DOM and with other components.
The _class-only_ tests can tell you about class behavior.
They cannot tell you if the component is going to render properly,
respond to user input and gestures, or integrate with its parent and child components.
None of the _class-only_ tests above can answer key questions about how the
components actually behave on screen.
- Is `Lightswitch.clicked()` bound to anything such that the user can invoke it?
- Is the `Lightswitch.message` displayed?
- Can the user actually select the hero displayed by `DashboardHeroComponent`?
- Is the hero name displayed as expected (i.e, in uppercase)?
- Is the welcome message displayed by the template of `WelcomeComponent`?
These may not be troubling questions for the simple components illustrated above.
But many components have complex interactions with the DOM elements
described in their templates, causing HTML to appear and disappear as
the component state changes.
To answer these kinds of questions, you have to create the DOM elements associated
with the components, you must examine the DOM to confirm that component state
displays properly at the appropriate times, and you must simulate user interaction
with the screen to determine whether those interactions cause the component to
behave as expected.
To write these kinds of test, you'll use additional features of the `TestBed`
as well as other testing helpers.
### CLI-generated tests
The CLI creates an initial test file for you by default when you ask it to
generate a new component.
For example, the following CLI command generates a `BannerComponent` in the `app/banner` folder (with inline template and styles):
<code-example language="sh" class="code-shell">
ng generate component banner --inline-template --inline-style --module app
</code-example>
It also generates an initial test file for the component, `banner-external.component.spec.ts`, that looks like this:
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="v1"
header="app/banner/banner-external.component.spec.ts (initial)"></code-example>
<div class="alert is-helpful">
Because `compileComponents` is asynchronous, it uses
the [`async`](api/core/testing/async) utility
function imported from `@angular/core/testing`.
Please refer to the [async](guide/testing-components-scenarios#async) section for more details.
</div>
### Reduce the setup
Only the last three lines of this file actually test the component
and all they do is assert that Angular can create the component.
The rest of the file is boilerplate setup code anticipating more advanced tests that _might_ become necessary if the component evolves into something substantial.
You'll learn about these advanced test features below.
For now, you can radically reduce this test file to a more manageable size:
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="v2"
header="app/banner/banner-initial.component.spec.ts (minimal)"></code-example>
In this example, the metadata object passed to `TestBed.configureTestingModule`
simply declares `BannerComponent`, the component to test.
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="configureTestingModule">
</code-example>
<div class="alert is-helpful">
There's no need to declare or import anything else.
The default test module is pre-configured with
something like the `BrowserModule` from `@angular/platform-browser`.
Later you'll call `TestBed.configureTestingModule()` with
imports, providers, and more declarations to suit your testing needs.
Optional `override` methods can further fine-tune aspects of the configuration.
</div>
{@a create-component}
### _createComponent()_
After configuring `TestBed`, you call its `createComponent()` method.
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="createComponent">
</code-example>
`TestBed.createComponent()` creates an instance of the `BannerComponent`,
adds a corresponding element to the test-runner DOM,
and returns a [`ComponentFixture`](#component-fixture).
<div class="alert is-important">
Do not re-configure `TestBed` after calling `createComponent`.
The `createComponent` method freezes the current `TestBed` definition,
closing it to further configuration.
You cannot call any more `TestBed` configuration methods, not `configureTestingModule()`,
nor `get()`, nor any of the `override...` methods.
If you try, `TestBed` throws an error.
</div>
{@a component-fixture}
### _ComponentFixture_
The [ComponentFixture](api/core/testing/ComponentFixture) is a test harness for interacting with the created component and its corresponding element.
Access the component instance through the fixture and confirm it exists with a Jasmine expectation:
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="componentInstance">
</code-example>
### _beforeEach()_
You will add more tests as this component evolves.
Rather than duplicate the `TestBed` configuration for each test,
you refactor to pull the setup into a Jasmine `beforeEach()` and some supporting variables:
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="v3"
></code-example>
Now add a test that gets the component's element from `fixture.nativeElement` and
looks for the expected text.
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="v4-test-2">
</code-example>
{@a native-element}
### _nativeElement_
The value of `ComponentFixture.nativeElement` has the `any` type.
Later you'll encounter the `DebugElement.nativeElement` and it too has the `any` type.
Angular can't know at compile time what kind of HTML element the `nativeElement` is or
if it even is an HTML element.
The app might be running on a _non-browser platform_, such as the server or a
[Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API),
where the element may have a diminished API or not exist at all.
The tests in this guide are designed to run in a browser so a
`nativeElement` value will always be an `HTMLElement` or
one of its derived classes.
Knowing that it is an `HTMLElement` of some sort, you can use
the standard HTML `querySelector` to dive deeper into the element tree.
Here's another test that calls `HTMLElement.querySelector` to get the paragraph element and look for the banner text:
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="v4-test-3">
</code-example>
{@a debug-element}
### _DebugElement_
The Angular _fixture_ provides the component's element directly through the `fixture.nativeElement`.
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="nativeElement">
</code-example>
This is actually a convenience method, implemented as `fixture.debugElement.nativeElement`.
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="debugElement-nativeElement">
</code-example>
There's a good reason for this circuitous path to the element.
The properties of the `nativeElement` depend upon the runtime environment.
You could be running these tests on a _non-browser_ platform that doesn't have a DOM or
whose DOM-emulation doesn't support the full `HTMLElement` API.
Angular relies on the `DebugElement` abstraction to work safely across _all supported platforms_.
Instead of creating an HTML element tree, Angular creates a `DebugElement` tree that wraps the _native elements_ for the runtime platform.
The `nativeElement` property unwraps the `DebugElement` and returns the platform-specific element object.
Because the sample tests for this guide are designed to run only in a browser,
a `nativeElement` in these tests is always an `HTMLElement`
whose familiar methods and properties you can explore within a test.
Here's the previous test, re-implemented with `fixture.debugElement.nativeElement`:
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="v4-test-4">
</code-example>
The `DebugElement` has other methods and properties that
are useful in tests, as you'll see elsewhere in this guide.
You import the `DebugElement` symbol from the Angular core library.
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="import-debug-element">
</code-example>
{@a by-css}
### _By.css()_
Although the tests in this guide all run in the browser,
some apps might run on a different platform at least some of the time.
For example, the component might render first on the server as part of a strategy to make the application launch faster on poorly connected devices. The server-side renderer might not support the full HTML element API.
If it doesn't support `querySelector`, the previous test could fail.
The `DebugElement` offers query methods that work for all supported platforms.
These query methods take a _predicate_ function that returns `true` when a node in the `DebugElement` tree matches the selection criteria.
You create a _predicate_ with the help of a `By` class imported from a
library for the runtime platform. Here's the `By` import for the browser platform:
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="import-by">
</code-example>
The following example re-implements the previous test with
`DebugElement.query()` and the browser's `By.css` method.
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="v4-test-5">
</code-example>
Some noteworthy observations:
- The `By.css()` static method selects `DebugElement` nodes
with a [standard CSS selector](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_started/Selectors 'CSS selectors').
- The query returns a `DebugElement` for the paragraph.
- You must unwrap that result to get the paragraph element.
When you're filtering by CSS selector and only testing properties of a browser's _native element_, the `By.css` approach may be overkill.
It's often easier and more clear to filter with a standard `HTMLElement` method
such as `querySelector()` or `querySelectorAll()`,
as you'll see in the next set of tests.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
# Testing Pipes
You can test [pipes](guide/pipes) without the Angular testing utilities.
<div class="alert is-helpful">
For the sample app that the testing guides describe, see the <live-example name="testing" embedded-style noDownload>sample app</live-example>.
For the tests features in the testing guides, see <live-example name="testing" stackblitz="specs" noDownload>tests</live-example>.
</div>
## Testing the `TitleCasePipe`
A pipe class has one method, `transform`, that manipulates the input
value into a transformed output value.
The `transform` implementation rarely interacts with the DOM.
Most pipes have no dependence on Angular other than the `@Pipe`
metadata and an interface.
Consider a `TitleCasePipe` that capitalizes the first letter of each word.
Here's an implementation with a regular expression.
<code-example path="testing/src/app/shared/title-case.pipe.ts" header="app/shared/title-case.pipe.ts"></code-example>
Anything that uses a regular expression is worth testing thoroughly.
Use simple Jasmine to explore the expected cases and the edge cases.
<code-example path="testing/src/app/shared/title-case.pipe.spec.ts" region="excerpt" header="app/shared/title-case.pipe.spec.ts"></code-example>
{@a write-tests}
## Writing DOM tests to support a pipe test
These are tests of the pipe _in isolation_.
They can't tell if the `TitleCasePipe` is working properly as applied in the application components.
Consider adding component tests such as this one:
<code-example path="testing/src/app/hero/hero-detail.component.spec.ts" region="title-case-pipe" header="app/hero/hero-detail.component.spec.ts (pipe test)"></code-example>

View File

@ -0,0 +1,199 @@
# Testing services
To check that your services are working as you intend, you can write tests specifically for them.
<div class="alert is-helpful">
For the sample app that the testing guides describe, see the <live-example name="testing" embedded-style noDownload>sample app</live-example>.
For the tests features in the testing guides, see <live-example name="testing" stackblitz="specs" noDownload>tests</live-example>.
</div>
Services are often the easiest files to unit test.
Here are some synchronous and asynchronous unit tests of the `ValueService`
written without assistance from Angular testing utilities.
<code-example path="testing/src/app/demo/demo.spec.ts" region="ValueService" header="app/demo/demo.spec.ts"></code-example>
{@a services-with-dependencies}
## Services with dependencies
Services often depend on other services that Angular injects into the constructor.
In many cases, it's easy to create and _inject_ these dependencies by hand while
calling the service's constructor.
The `MasterService` is a simple example:
<code-example path="testing/src/app/demo/demo.ts" region="MasterService" header="app/demo/demo.ts"></code-example>
`MasterService` delegates its only method, `getValue`, to the injected `ValueService`.
Here are several ways to test it.
<code-example path="testing/src/app/demo/demo.spec.ts" region="MasterService" header="app/demo/demo.spec.ts"></code-example>
The first test creates a `ValueService` with `new` and passes it to the `MasterService` constructor.
However, injecting the real service rarely works well as most dependent services are difficult to create and control.
Instead you can mock the dependency, use a dummy value, or create a
[spy](https://jasmine.github.io/2.0/introduction.html#section-Spies)
on the pertinent service method.
<div class="alert is-helpful">
Prefer spies as they are usually the easiest way to mock services.
</div>
These standard testing techniques are great for unit testing services in isolation.
However, you almost always inject services into application classes using Angular
dependency injection and you should have tests that reflect that usage pattern.
Angular testing utilities make it easy to investigate how injected services behave.
## Testing services with the _TestBed_
Your app relies on Angular [dependency injection (DI)](guide/dependency-injection)
to create services.
When a service has a dependent service, DI finds or creates that dependent service.
And if that dependent service has its own dependencies, DI finds-or-creates them as well.
As service _consumer_, you don't worry about any of this.
You don't worry about the order of constructor arguments or how they're created.
As a service _tester_, you must at least think about the first level of service dependencies
but you _can_ let Angular DI do the service creation and deal with constructor argument order
when you use the `TestBed` testing utility to provide and create services.
{@a testbed}
## Angular _TestBed_
The `TestBed` is the most important of the Angular testing utilities.
The `TestBed` creates a dynamically-constructed Angular _test_ module that emulates
an Angular [@NgModule](guide/ngmodules).
The `TestBed.configureTestingModule()` method takes a metadata object that can have most of the properties of an [@NgModule](guide/ngmodules).
To test a service, you set the `providers` metadata property with an
array of the services that you'll test or mock.
<code-example path="testing/src/app/demo/demo.testbed.spec.ts" region="value-service-before-each" header="app/demo/demo.testbed.spec.ts (provide ValueService in beforeEach)"></code-example>
Then inject it inside a test by calling `TestBed.inject()` with the service class as the argument.
<div class="alert is-helpful">
**Note:** `TestBed.get()` was deprecated as of Angular version 9.
To help minimize breaking changes, Angular introduces a new function called `TestBed.inject()`, which you should use instead.
For information on the removal of `TestBed.get()`,
see its entry in the [Deprecations index](guide/deprecations#index).
</div>
<code-example path="testing/src/app/demo/demo.testbed.spec.ts" region="value-service-inject-it"></code-example>
Or inside the `beforeEach()` if you prefer to inject the service as part of your setup.
<code-example path="testing/src/app/demo/demo.testbed.spec.ts" region="value-service-inject-before-each"> </code-example>
When testing a service with a dependency, provide the mock in the `providers` array.
In the following example, the mock is a spy object.
<code-example path="testing/src/app/demo/demo.testbed.spec.ts" region="master-service-before-each"></code-example>
The test consumes that spy in the same way it did earlier.
<code-example path="testing/src/app/demo/demo.testbed.spec.ts" region="master-service-it">
</code-example>
{@a no-before-each}
## Testing without _beforeEach()_
Most test suites in this guide call `beforeEach()` to set the preconditions for each `it()` test
and rely on the `TestBed` to create classes and inject services.
There's another school of testing that never calls `beforeEach()` and prefers to create classes explicitly rather than use the `TestBed`.
Here's how you might rewrite one of the `MasterService` tests in that style.
Begin by putting re-usable, preparatory code in a _setup_ function instead of `beforeEach()`.
<code-example
path="testing/src/app/demo/demo.spec.ts"
region="no-before-each-setup"
header="app/demo/demo.spec.ts (setup)"></code-example>
The `setup()` function returns an object literal
with the variables, such as `masterService`, that a test might reference.
You don't define _semi-global_ variables (e.g., `let masterService: MasterService`)
in the body of the `describe()`.
Then each test invokes `setup()` in its first line, before continuing
with steps that manipulate the test subject and assert expectations.
<code-example
path="testing/src/app/demo/demo.spec.ts"
region="no-before-each-test"></code-example>
Notice how the test uses
[_destructuring assignment_](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)
to extract the setup variables that it needs.
<code-example
path="testing/src/app/demo/demo.spec.ts"
region="no-before-each-setup-call">
</code-example>
Many developers feel this approach is cleaner and more explicit than the
traditional `beforeEach()` style.
Although this testing guide follows the traditional style and
the default [CLI schematics](https://github.com/angular/angular-cli)
generate test files with `beforeEach()` and `TestBed`,
feel free to adopt _this alternative approach_ in your own projects.
## Testing HTTP services
Data services that make HTTP calls to remote servers typically inject and delegate
to the Angular [`HttpClient`](guide/http) service for XHR calls.
You can test a data service with an injected `HttpClient` spy as you would
test any service with a dependency.
<code-example
path="testing/src/app/model/hero.service.spec.ts"
region="test-with-spies"
header="app/model/hero.service.spec.ts (tests with spies)">
</code-example>
<div class="alert is-important">
The `HeroService` methods return `Observables`. You must
_subscribe_ to an observable to (a) cause it to execute and (b)
assert that the method succeeds or fails.
The `subscribe()` method takes a success (`next`) and fail (`error`) callback.
Make sure you provide _both_ callbacks so that you capture errors.
Neglecting to do so produces an asynchronous uncaught observable error that
the test runner will likely attribute to a completely different test.
</div>
## _HttpClientTestingModule_
Extended interactions between a data service and the `HttpClient` can be complex
and difficult to mock with spies.
The `HttpClientTestingModule` can make these testing scenarios more manageable.
While the _code sample_ accompanying this guide demonstrates `HttpClientTestingModule`,
this page defers to the [Http guide](guide/http#testing-http-requests),
which covers testing with the `HttpClientTestingModule` in detail.

View File

@ -0,0 +1,794 @@
# Testing Utility APIs
This page describes the most useful Angular testing features.
The Angular testing utilities include the `TestBed`, the `ComponentFixture`, and a handful of functions that control the test environment.
The [_TestBed_](#testbed-api-summary) and [_ComponentFixture_](#component-fixture-api-summary) classes are covered separately.
Here's a summary of the stand-alone functions, in order of likely utility:
<table>
<tr>
<th>
Function
</th>
<th>
Description
</th>
</tr>
<tr>
<td style="vertical-align: top">
<code>async</code>
</td>
<td>
Runs the body of a test (`it`) or setup (`beforeEach`) function within a special _async test zone_.
See [discussion above](guide/testing-components-scenarios#async).
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>fakeAsync</code>
</td>
<td>
Runs the body of a test (`it`) within a special _fakeAsync test zone_, enabling
a linear control flow coding style. See [discussion above](guide/testing-components-scenarios#fake-async).
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>tick</code>
</td>
<td>
Simulates the passage of time and the completion of pending asynchronous activities
by flushing both _timer_ and _micro-task_ queues within the _fakeAsync test zone_.
<div class="alert is-helpful">
The curious, dedicated reader might enjoy this lengthy blog post,
["_Tasks, microtasks, queues and schedules_"](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/).
</div>
Accepts an optional argument that moves the virtual clock forward
by the specified number of milliseconds,
clearing asynchronous activities scheduled within that timeframe.
See [discussion above](guide/testing-components-scenarios#tick).
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>inject</code>
</td>
<td>
Injects one or more services from the current `TestBed` injector into a test function.
It cannot inject a service provided by the component itself.
See discussion of the [debugElement.injector](guide/testing-components-scenarios#get-injected-services).
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>discardPeriodicTasks</code>
</td>
<td>
When a `fakeAsync()` test ends with pending timer event _tasks_ (queued `setTimeOut` and `setInterval` callbacks),
the test fails with a clear error message.
In general, a test should end with no queued tasks.
When pending timer tasks are expected, call `discardPeriodicTasks` to flush the _task_ queue
and avoid the error.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>flushMicrotasks</code>
</td>
<td>
When a `fakeAsync()` test ends with pending _micro-tasks_ such as unresolved promises,
the test fails with a clear error message.
In general, a test should wait for micro-tasks to finish.
When pending microtasks are expected, call `flushMicrotasks` to flush the _micro-task_ queue
and avoid the error.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>ComponentFixtureAutoDetect</code>
</td>
<td>
A provider token for a service that turns on [automatic change detection](guide/testing-components-scenarios#automatic-change-detection).
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>getTestBed</code>
</td>
<td>
Gets the current instance of the `TestBed`.
Usually unnecessary because the static class methods of the `TestBed` class are typically sufficient.
The `TestBed` instance exposes a few rarely used members that are not available as
static methods.
</td>
</tr>
</table>
<hr>
{@a testbed-class-summary}
## _TestBed_ class summary
The `TestBed` class is one of the principal Angular testing utilities.
Its API is quite large and can be overwhelming until you've explored it,
a little at a time. Read the early part of this guide first
to get the basics before trying to absorb the full API.
The module definition passed to `configureTestingModule`
is a subset of the `@NgModule` metadata properties.
<code-example language="javascript">
type TestModuleMetadata = {
providers?: any[];
declarations?: any[];
imports?: any[];
schemas?: Array&lt;SchemaMetadata | any[]&gt;;
};
</code-example>
{@a metadata-override-object}
Each override method takes a `MetadataOverride<T>` where `T` is the kind of metadata
appropriate to the method, that is, the parameter of an `@NgModule`,
`@Component`, `@Directive`, or `@Pipe`.
<code-example language="javascript">
type MetadataOverride&lt;T&gt; = {
add?: Partial&lt;T&gt;;
remove?: Partial&lt;T&gt;;
set?: Partial&lt;T&gt;;
};
</code-example>
{@a testbed-methods}
{@a testbed-api-summary}
The `TestBed` API consists of static class methods that either update or reference a _global_ instance of the `TestBed`.
Internally, all static methods cover methods of the current runtime `TestBed` instance,
which is also returned by the `getTestBed()` function.
Call `TestBed` methods _within_ a `beforeEach()` to ensure a fresh start before each individual test.
Here are the most important static methods, in order of likely utility.
<table>
<tr>
<th>
Methods
</th>
<th>
Description
</th>
</tr>
<tr>
<td style="vertical-align: top">
<code>configureTestingModule</code>
</td>
<td>
The testing shims (`karma-test-shim`, `browser-test-shim`)
establish the [initial test environment](guide/testing) and a default testing module.
The default testing module is configured with basic declaratives and some Angular service substitutes that every tester needs.
Call `configureTestingModule` to refine the testing module configuration for a particular set of tests
by adding and removing imports, declarations (of components, directives, and pipes), and providers.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>compileComponents</code>
</td>
<td>
Compile the testing module asynchronously after you've finished configuring it.
You **must** call this method if _any_ of the testing module components have a `templateUrl`
or `styleUrls` because fetching component template and style files is necessarily asynchronous.
See [above](guide/testing-components-scenarios#compile-components).
After calling `compileComponents`, the `TestBed` configuration is frozen for the duration of the current spec.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>createComponent<T></code>
</td>
<td>
Create an instance of a component of type `T` based on the current `TestBed` configuration.
After calling `compileComponent`, the `TestBed` configuration is frozen for the duration of the current spec.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>overrideModule</code>
</td>
<td>
Replace metadata for the given `NgModule`. Recall that modules can import other modules.
The `overrideModule` method can reach deeply into the current testing module to
modify one of these inner modules.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>overrideComponent</code>
</td>
<td>
Replace metadata for the given component class, which could be nested deeply
within an inner module.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>overrideDirective</code>
</td>
<td>
Replace metadata for the given directive class, which could be nested deeply
within an inner module.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>overridePipe</code>
</td>
<td>
Replace metadata for the given pipe class, which could be nested deeply
within an inner module.
</td>
</tr>
<tr>
<td style="vertical-align: top">
{@a testbed-inject}
<code>inject</code>
</td>
<td>
Retrieve a service from the current `TestBed` injector.
The `inject` function is often adequate for this purpose.
But `inject` throws an error if it can't provide the service.
What if the service is optional?
The `TestBed.inject()` method takes an optional second parameter,
the object to return if Angular can't find the provider
(`null` in this example):
<code-example path="testing/src/app/demo/demo.testbed.spec.ts" region="testbed-get-w-null" header="app/demo/demo.testbed.spec.ts"></code-example>
After calling `TestBed.inject`, the `TestBed` configuration is frozen for the duration of the current spec.
</td>
</tr>
<tr>
<td style="vertical-align: top">
{@a testbed-initTestEnvironment}
<code>initTestEnvironment</code>
</td>
<td>
Initialize the testing environment for the entire test run.
The testing shims (`karma-test-shim`, `browser-test-shim`) call it for you
so there is rarely a reason for you to call it yourself.
You may call this method _exactly once_. If you must change
this default in the middle of your test run, call `resetTestEnvironment` first.
Specify the Angular compiler factory, a `PlatformRef`, and a default Angular testing module.
Alternatives for non-browser platforms are available in the general form
`@angular/platform-<platform_name>/testing/<platform_name>`.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>resetTestEnvironment</code>
</td>
<td>
Reset the initial test environment, including the default testing module.
</td>
</tr>
</table>
A few of the `TestBed` instance methods are not covered by static `TestBed` _class_ methods.
These are rarely needed.
{@a component-fixture-api-summary}
## The _ComponentFixture_
The `TestBed.createComponent<T>`
creates an instance of the component `T`
and returns a strongly typed `ComponentFixture` for that component.
The `ComponentFixture` properties and methods provide access to the component,
its DOM representation, and aspects of its Angular environment.
{@a component-fixture-properties}
### _ComponentFixture_ properties
Here are the most important properties for testers, in order of likely utility.
<table>
<tr>
<th>
Properties
</th>
<th>
Description
</th>
</tr>
<tr>
<td style="vertical-align: top">
<code>componentInstance</code>
</td>
<td>
The instance of the component class created by `TestBed.createComponent`.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>debugElement</code>
</td>
<td>
The `DebugElement` associated with the root element of the component.
The `debugElement` provides insight into the component and its DOM element during test and debugging.
It's a critical property for testers. The most interesting members are covered [below](#debug-element-details).
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>nativeElement</code>
</td>
<td>
The native DOM element at the root of the component.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>changeDetectorRef</code>
</td>
<td>
The `ChangeDetectorRef` for the component.
The `ChangeDetectorRef` is most valuable when testing a
component that has the `ChangeDetectionStrategy.OnPush` method
or the component's change detection is under your programmatic control.
</td>
</tr>
</table>
{@a component-fixture-methods}
### _ComponentFixture_ methods
The _fixture_ methods cause Angular to perform certain tasks on the component tree.
Call these method to trigger Angular behavior in response to simulated user action.
Here are the most useful methods for testers.
<table>
<tr>
<th>
Methods
</th>
<th>
Description
</th>
</tr>
<tr>
<td style="vertical-align: top">
<code>detectChanges</code>
</td>
<td>
Trigger a change detection cycle for the component.
Call it to initialize the component (it calls `ngOnInit`) and after your
test code, change the component's data bound property values.
Angular can't see that you've changed `personComponent.name` and won't update the `name`
binding until you call `detectChanges`.
Runs `checkNoChanges` afterwards to confirm that there are no circular updates unless
called as `detectChanges(false)`;
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>autoDetectChanges</code>
</td>
<td>
Set this to `true` when you want the fixture to detect changes automatically.
When autodetect is `true`, the test fixture calls `detectChanges` immediately
after creating the component. Then it listens for pertinent zone events
and calls `detectChanges` accordingly.
When your test code modifies component property values directly,
you probably still have to call `fixture.detectChanges` to trigger data binding updates.
The default is `false`. Testers who prefer fine control over test behavior
tend to keep it `false`.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>checkNoChanges</code>
</td>
<td>
Do a change detection run to make sure there are no pending changes.
Throws an exceptions if there are.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>isStable</code>
</td>
<td>
If the fixture is currently _stable_, returns `true`.
If there are async tasks that have not completed, returns `false`.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>whenStable</code>
</td>
<td>
Returns a promise that resolves when the fixture is stable.
To resume testing after completion of asynchronous activity or
asynchronous change detection, hook that promise.
See [above](guide/testing-components-scenarios#when-stable).
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>destroy</code>
</td>
<td>
Trigger component destruction.
</td>
</tr>
</table>
{@a debug-element-details}
#### _DebugElement_
The `DebugElement` provides crucial insights into the component's DOM representation.
From the test root component's `DebugElement` returned by `fixture.debugElement`,
you can walk (and query) the fixture's entire element and component subtrees.
Here are the most useful `DebugElement` members for testers, in approximate order of utility:
<table>
<tr>
<th>
Member
</th>
<th>
Description
</th>
</tr>
<tr>
<td style="vertical-align: top">
<code>nativeElement</code>
</td>
<td>
The corresponding DOM element in the browser (null for WebWorkers).
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>query</code>
</td>
<td>
Calling `query(predicate: Predicate<DebugElement>)` returns the first `DebugElement`
that matches the [predicate](#query-predicate) at any depth in the subtree.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>queryAll</code>
</td>
<td>
Calling `queryAll(predicate: Predicate<DebugElement>)` returns all `DebugElements`
that matches the [predicate](#query-predicate) at any depth in subtree.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>injector</code>
</td>
<td>
The host dependency injector.
For example, the root element's component instance injector.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>componentInstance</code>
</td>
<td>
The element's own component instance, if it has one.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>context</code>
</td>
<td>
An object that provides parent context for this element.
Often an ancestor component instance that governs this element.
When an element is repeated within `*ngFor`, the context is an `NgForRow` whose `$implicit`
property is the value of the row instance value.
For example, the `hero` in `*ngFor="let hero of heroes"`.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>children</code>
</td>
<td>
The immediate `DebugElement` children. Walk the tree by descending through `children`.
<div class="alert is-helpful">
`DebugElement` also has `childNodes`, a list of `DebugNode` objects.
`DebugElement` derives from `DebugNode` objects and there are often
more nodes than elements. Testers can usually ignore plain nodes.
</div>
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>parent</code>
</td>
<td>
The `DebugElement` parent. Null if this is the root element.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>name</code>
</td>
<td>
The element tag name, if it is an element.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>triggerEventHandler</code>
</td>
<td>
Triggers the event by its name if there is a corresponding listener
in the element's `listeners` collection.
The second parameter is the _event object_ expected by the handler.
See [above](guide/testing-components-scenarios#trigger-event-handler).
If the event lacks a listener or there's some other problem,
consider calling `nativeElement.dispatchEvent(eventObject)`.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>listeners</code>
</td>
<td>
The callbacks attached to the component's `@Output` properties and/or the element's event properties.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>providerTokens</code>
</td>
<td>
This component's injector lookup tokens.
Includes the component itself plus the tokens that the component lists in its `providers` metadata.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>source</code>
</td>
<td>
Where to find this element in the source component template.
</td>
</tr>
<tr>
<td style="vertical-align: top">
<code>references</code>
</td>
<td>
Dictionary of objects associated with template local variables (e.g. `#foo`),
keyed by the local variable name.
</td>
</tr>
</table>
{@a query-predicate}
The `DebugElement.query(predicate)` and `DebugElement.queryAll(predicate)` methods take a
predicate that filters the source element's subtree for matching `DebugElement`.
The predicate is any method that takes a `DebugElement` and returns a _truthy_ value.
The following example finds all `DebugElements` with a reference to a template local variable named "content":
<code-example path="testing/src/app/demo/demo.testbed.spec.ts" region="custom-predicate" header="app/demo/demo.testbed.spec.ts"></code-example>
The Angular `By` class has three static methods for common predicates:
- `By.all` - return all elements.
- `By.css(selector)` - return elements with matching CSS selectors.
- `By.directive(directive)` - return elements that Angular matched to an instance of the directive class.
<code-example path="testing/src/app/hero/hero-list.component.spec.ts" region="by" header="app/hero/hero-list.component.spec.ts"></code-example>
<hr>

File diff suppressed because it is too large Load Diff

View File

@ -15,22 +15,49 @@ that are important to Angular developers, including details about the following
{@a tsconfig}
## TypeScript configuration
## Configuration files
A TypeScript configuration file called `tsconfig.json` guides the compiler as it generates JavaScript files for a project.
This file contains options and flags that are essential for Angular applications.
Typically, the file is found at the [root level of the workspace](guide/file-structure).
A given Angular workspace contains several TypeScript configuration files.
At the root level, there are two main TypeScript configuration files: a `tsconfig.json` file and a `tsconfig.base.json` file.
The `tsconfig.json` file is a ["Solution Style"](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#support-for-solution-style-tsconfigjson-files) TypeScript configuration file.
Code editors and TypeScripts language server use this file to improve development experience.
Compilers do not use this file.
The `tsconfig.json` file contains a list of paths to the other TypeScript configuration files used in the workspace.
<code-example lang="json" header="tsconfig.json" linenums="false">
{
"files": [],
"references": [
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.spec.json"
},
{
"path": "./projects/my-lib/tsconfig.lib.json"
}
]
}
</code-example>
The `tsconfig.base.json` file specifies the base TypeScript and Angular compiler options that all projects in the workspace inherit.
The TypeScript and Angular have a wide range of options which can be used to configure type-checking features and generated output.
For more information, see the [Configuration inheritance with extends](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#configuration-inheritance-with-extends) section of the TypeScript documentation.
<div class="alert is-helpful">
For details about `tsconfig.json`, see the official
[TypeScript wiki](http://www.typescriptlang.org/docs/handbook/tsconfig-json.html).
For more information TypeScript configuration files, see the official [TypeScript wiki](http://www.typescriptlang.org/docs/handbook/tsconfig-json.html)
For details about configuration inheritance, see the [Configuration inheritance with extends](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#configuration-inheritance-with-extends) section.
</div>
The initial `tsconfig.json` for an Angular app typically looks like the following example.
The initial `tsconfig.base.json` for an Angular workspace typically looks like the following example.
<code-example lang="json" header="tsconfig.json" linenums="false">
<code-example lang="json" header="tsconfig.base.json" linenums="false">
{
"compileOnSave": false,
"compilerOptions": {
@ -40,25 +67,22 @@ The initial `tsconfig.json` for an Angular app typically looks like the followin
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"module": "esnext",
"moduleResolution": "node",
"importHelpers": true,
"target": "es2015",
"typeRoots": [
"node_modules/@types"
],
"module": "es2020",
"lib": [
"es2018",
"dom"
]
},
"angularCompilerOptions": {
"strictTemplates": true,
"strictInjectionParameters": true
}
}
</code-example>
### Strict mode
When you create new workspaces and projects, you have the option to use Angular's strict mode, which can help you write better, more maintainable code.
For more information, see [Strict mode](/guide/strict-mode).
{@a noImplicitAny}

View File

@ -48,11 +48,11 @@ src/
app/ ... <i>application code</i>
app.server.module.ts <i>* server-side application module</i>
server.ts <i>* express web server</i>
tsconfig.json <i>TypeScript client configuration</i>
tsconfig.app.json <i>TypeScript client configuration</i>
tsconfig.server.json <i>* TypeScript server configuration</i>
tsconfig.spec.json <i>TypeScript spec configuration</i>
package.json <i>npm configuration</i>
tsconfig.json <i>TypeScript solution style configuration</i>
tsconfig.base.json <i>TypeScript base configuration</i>
tsconfig.app.json <i>TypeScript browser application configuration</i>
tsconfig.server.json <i>TypeScript server application configuration</i>
tsconfig.spec.json <i>TypeScript tests configuration</i>
</code-example>
The files marked with `*` are new and not in the original tutorial sample.

View File

@ -0,0 +1,82 @@
# Updating to Angular version 10
This guide contains information related to updating to version 10 of Angular.
<div class="alert is-helpful">
For information on upgrading to Angular version 9, see [Updating to Angular version 9](https://v9.angular.io/guide/updating-to-version-9).
</div>
## Updating CLI Apps
For step-by-step instructions on how to update to the latest Angular release (and leverage our automated migration tools to do so), use the interactive update guide at [update.angular.io](https://update.angular.io).
If you're curious about the specific migrations being run by the CLI, see the [automated migrations section](#migrations) for details on what code is changing and why.
## Changes and Deprecations in Version 10
<div class="alert is-helpful">
For information about Angular's deprecation and removal practices, see [Angular Release Practices](guide/releases#deprecation-practices "Angular Release Practices: Deprecation practices").
</div>
{@a breaking-changes}
### New Breaking Changes
* Typescript 3.6, 3.7, and 3.8 are no longer supported. Please update to Typescript 3.9.
* Input fields of type `number` fire the `valueChanges` event only once per value change (as opposed to twice in some cases). See [PR 36087](https://github.com/angular/angular/pull/36087).
* The `minLength` and `maxLength` validators only validate values that have a numeric `length` property. See [PR 36157](https://github.com/angular/angular/pull/36157).
* Templates with unknown property bindings or unknown element names now log errors instead of warnings. See [PR 36399](https://github.com/angular/angular/pull/36399).
* `UrlMatcher` can now return `null` values. See [PR 36402](https://github.com/angular/angular/pull/36402).
* Transplanted views now refresh at insertion point only. See [PR 35968](https://github.com/angular/angular/pull/35968).
* Formatting times with the `b` or `B` format codes now supports time periods that cross midnight. See [PR 36611](https://github.com/angular/angular/pull/36611).
* Navigation is canceled for routes with at least one empty resolver. See [PR 24621](https://github.com/angular/angular/pull/24621).
{@a deprecations}
### New Deprecations
| Area | API or Feature | May be removed in |
| ----------------------------- | --------------------------------------------------------------------------- | ----------------- |
| `@angular/core` | [`WrappedValue`](guide/deprecations#wrapped-value) | <!--v10--> v12 |
| browser support | [`IE 9, 10, and IE Mobile`](guide/deprecations#ie-9-10-and-ie-mobile-support) | <!--v10--> v11 |
{@a removals}
### New Removals of Deprecated APIs
The following APIs have been removed starting with version 10.0.0*:
| Package | API | Replacement | Notes |
| ---------------- | -------------- | ----------- | ----- |
| `@angular/core` | Undecorated base classes that use Angular features | Add Angular decorator | See [migration guide](guide/migration-undecorated-classes) for more info |
| `@angular/core` | `ModuleWithProviders` without a generic | `ModuleWithProviders` with a generic | See [migration guide](guide/migration-module-with-providers) for more info |
| `@angular/core` | Style Sanitization | no action needed | See [style sanitization API removal](/guide/deprecations#style-sanitization) for more info
| `@angular/bazel` | [`Bazel builder and schematics`](guide/deprecations#bazelbuilder) | `bazelbuild/rules_nodejs` | [More info](https://github.com/angular/angular/tree/10.0.x/packages/bazel/src/schematics) |
*To see APIs removed in version 9, check out this guide on the [version 9 docs site](https://v9.angular.io/guide/deprecations#removed).
{@a ivy}
## Ivy features and compatibility
Since version 9, Angular Ivy is the default rendering engine. If you haven't heard of Ivy, you can read more about it in the [Angular Ivy guide](guide/ivy).
* Among other features, Ivy introduces more comprehensive type-checking within templates. For details, see [Template Type-checking](guide/template-typecheck).
* For general guidance on debugging and a list of minor changes associated with Ivy, see the [Ivy compatibility guide](guide/ivy-compatibility).
* For help with opting out of Ivy, see the instructions [here](guide/ivy#opting-out-of-angular-ivy).
{@a migrations}
## Automated Migrations for Version 10
Read about the migrations the CLI handles for you automatically:
* [Migrating missing `@Directive()`/`@Component()` decorators](guide/migration-undecorated-classes)
* [Migrating `ModuleWithProviders`](guide/migration-module-with-providers)
* [Solution-style `tsconfig.json` migration](guide/migration-solution-style-tsconfig)
* [`tslib` direct dependency migration](guide/migration-update-libraries-tslib)
* [Update `module` and `target` compiler options migration](guide/migration-update-module-and-target-compiler-options)

View File

@ -1,90 +0,0 @@
# Updating to Angular version 9
This guide contains information related to updating to version 9 of Angular.
## Updating CLI Apps
For step-by-step instructions on how to update to the latest Angular release (and leverage our automated migration tools to do so), use the interactive update guide at [update.angular.io](https://update.angular.io).
If you're curious about the specific migrations being run by the CLI, see the [automated migrations section](#migrations) for details on what code is changing and why.
## Changes and Deprecations in Version 9
<div class="alert is-helpful">
For information about Angular's deprecation and removal practices, see [Angular Release Practices](guide/releases#deprecation-practices "Angular Release Practices: Deprecation practices").
</div>
{@a breaking-changes}
### New Breaking Changes
- Angular now compiles with Ivy by default. See the [Ivy compatibility section](#ivy).
- CLI apps compile in [AOT mode](/guide/aot-compiler) by default (which includes template type-checking).
Users who only built with JIT before may see new type errors.
See our [template type-checking guide](guide/template-typecheck) for more information and debugging tips.
- Typescript 3.4 and 3.5 are no longer supported. Please update to Typescript 3.7.
- `tslib` is now listed as a peer dependency rather than a direct dependency. If you are not using the CLI, you must manually install `tslib`, using `yarn add tslib` or `npm install tslib --save`.
{@a deprecations}
### New Deprecations
| API | Replacement | Notes |
| ------------------------------------------------------------------------| ------------------------------------ | ----- |
| [`entryComponents`](api/core/NgModule#entryComponents) | none | See [`entryComponents`](guide/deprecations#entryComponents) |
| [`CurrencyPipe` - `DEFAULT_CURRENCY_CODE`](api/common/CurrencyPipe#currency-code-deprecation)| `{provide: DEFAULT_CURRENCY_CODE, useValue: 'USD'}` | From v11 the default code will be extracted from the locale data given by `LOCAL_ID`, rather than `USD`. |
| [`ANALYZE_FOR_ENTRY_COMPONENTS`](api/core/ANALYZE_FOR_ENTRY_COMPONENTS) | none | See [`ANALYZE_FOR_ENTRY_COMPONENTS`](guide/deprecations#entryComponents) |
| `ModuleWithProviders` without a generic | `ModuleWithProviders` with a generic | |
| Undecorated base classes that use Angular features | Base classes with `@Directive()` decorator that use Angular features | |
| `esm5` and `fesm5` distribution in `@angular/*` npm packages | `esm2015` and `fesm2015` entrypoints | See [`esm5` and `fesm5`](guide/deprecations#esm5-fesm5) |
| [`TestBed.get`](api/core/testing/TestBed#get) | [`TestBed.inject`](api/core/testing/TestBed#inject) | Same behavior, but type safe. |
{@a removals}
### New Removals of Deprecated APIs
| Package | API | Replacement | Notes |
| ------- | -------------- | ----------- | ----- |
| `@angular/core` | [`Renderer`](https://v8.angular.io/api/core/Renderer) | [`Renderer2`](api/core/Renderer2) | [Migration guide.](guide/migration-renderer) |
| `@angular/core` | [`RootRenderer`](https://v8.angular.io/api/core/RootRenderer) | [`RendererFactory2`](api/core/RendererFactory2) | none |
| `@angular/core` | [`RenderComponentType`](https://v8.angular.io/api/core/RenderComponentType) | [`RendererType2`](api/core/RendererType2) | none |
| `@angular/core` | [`WtfScopeFn`](https://v8.angular.io/api/core/WtfScopeFn) | none | v8 | See [Web Tracing Framework](#wtf) |
| `@angular/core` | [`wtfCreateScope`](https://v8.angular.io/api/core/wtfCreateScope) | none | v8 | See [Web Tracing Framework](guide/deprecations#wtf) |
| `@angular/core` | [`wtfStartTimeRange`](https://v8.angular.io/api/core/wtfStartTimeRange) | none | v8 | See [Web Tracing Framework](guide/deprecations#wtf) |
| `@angular/core` | [`wtfEndTimeRange`](https://v8.angular.io/api/core/wtfEndTimeRange) | none | v8 | See [Web Tracing Framework](guide/deprecations#wtf) |
| `@angular/core` | [`wtfLeave`](https://v8.angular.io/api/core/wtfLeave) | none | v8 | See [Web Tracing Framework](guide/deprecations#wtf) |
| `@angular/common` | `DeprecatedI18NPipesModule` | [`CommonModule`](api/common/CommonModule#pipes) | none |
| `@angular/common` | `DeprecatedCurrencyPipe` | [`CurrencyPipe`](api/common/CurrencyPipe) | none |
| `@angular/common` | `DeprecatedDatePipe` | [`DatePipe`](api/common/DatePipe) | none |
| `@angular/common` | `DeprecatedDecimalPipe` | [`DecimalPipe`](api/common/DecimalPipe) | none |
| `@angular/common` | `DeprecatedPercentPipe` | [`PercentPipe`](api/common/PercentPipe) | none |
| `@angular/forms` | [`NgFormSelectorWarning`](https://v8.angular.io/api/forms/NgFormSelectorWarning) | none |
| `@angular/forms` | `ngForm` element selector | `ng-form` element selector | none |
| `@angular/service-worker` | `versionedFiles` | `files` | In the service worker configuration file `ngsw-config.json`, replace `versionedFiles` with `files`. See [Service Worker Configuration](guide/service-worker-config#assetgroups). |
{@a ivy}
## Ivy features and compatibility
In Version 9, Angular Ivy is the default rendering engine. If you haven't heard of Ivy, you can read more about it in the [Angular Ivy guide](guide/ivy).
* Among other features, Ivy introduces more comprehensive type-checking within templates. For details, see [Template Type-checking](guide/template-typecheck).
* For general guidance on debugging and a list of minor changes associated with Ivy, see the [Ivy compatibility guide](guide/ivy-compatibility).
* For help with opting out of Ivy, see the instructions [here](guide/ivy#opting-out-of-angular-ivy).
{@a migrations}
## Automated Migrations for Version 9
Read about the migrations the CLI handles for you automatically:
- [Migrating from `Renderer` to `Renderer2`](guide/migration-renderer)
- [Migrating missing `@Directive()`/`@Component()` decorators](guide/migration-undecorated-classes)
- [Migrating missing `@Injectable()` decorators and incomplete provider definitions](guide/migration-injectable)
- [Migrating dynamic queries](guide/migration-dynamic-flag)
- [Migrating to the new `$localize` i18n support](guide/migration-localize)
- [Migrating `ModuleWithProviders`](guide/migration-module-with-providers)

View File

@ -308,7 +308,7 @@ So when IE is refreshed (manually or automatically by `ng serve`), sometimes the
## Appendix: Test using `fakeAsync()/async()`
If you use the `fakeAsync()/async()` helper function to run unit tests (for details, read the [Testing guide](guide/testing#async-test-with-fakeasync)), you need to import `zone.js/dist/zone-testing` in your test setup file.
If you use the `fakeAsync()/async()` helper function to run unit tests (for details, read the [Testing guide](guide/testing-components-scenarios#fake-async)), you need to import `zone.js/dist/zone-testing` in your test setup file.
<div class="alert is-important">
If you create project with `Angular/CLI`, it is already imported in `src/test.ts`.

View File

@ -41,6 +41,11 @@ When you create a library project with `ng generate library`, the library projec
</div>
## Strict mode
When you create new workspaces and projects, you have the option to use Angular's strict mode, which can help you write better, more maintainable code.
For more information, see [Strict mode](/guide/strict-mode).
## Project configuration options
The following top-level configuration properties are available for each project, under `projects:<project_name>`.

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@ -204,7 +204,7 @@
"name": "Alyssa Nicoll",
"picture": "alyssa.jpg",
"twitter": "alyssanicoll",
"website": "alyssa.io",
"website": "http://alyssa.io",
"bio": "Alyssa is an Angular Developer Advocate for KUI and a GDE. Her two degrees (Web Design & Development and Psychology) feed her speaking career. She has spoken at over 35 conferences internationally. She is a weekly panelist on Adventures in Angular and Angular Air, which have a combined following of over 16,000 listeners. She enjoys gaming, scuba diving, and has a newborn that fondly goes by 'Mr. Milks'.",
"groups": ["GDE"]
},
@ -228,7 +228,7 @@
"name": "Christoffer Noring",
"picture": "chrisnoring.jpg",
"twitter": "chris_noring",
"website": "softchris.github.io",
"website": "https://softchris.github.io",
"bio": "Chris is a Full Stack Developer at McKinsey. A Google Developer Expert in Web Technologies and Angular. He is also a Nativescript Developer Expert. He is one of the organizers of the Angular conference ngVikings and an author of the book RxJS 5 Ultimate",
"groups": ["GDE"]
},
@ -596,6 +596,13 @@
"twitter": "devjoost",
"bio": "Joost is a Software Engineer from the Netherlands with an interest in open source software who likes to learn something new every day. He works at Blueriq during the day and contributes to Angular in his spare time, by working on the Angular compiler and runtime. He may review your PR even if you never asked for it ;)"
},
"sonukapoor": {
"name": "Sonu Kapoor",
"groups": ["Collaborators"],
"picture": "sonukapoor.jpg",
"website": "https://www.linkedin.com/in/sonu-kapoor/",
"bio": "Sonu is a Software Engineer from Toronto, with a high interest in front-end technologies and algorithms."
},
"jschwarty": {
"name": "Justin Schwartzenberger",
"picture": "justinschwartzenberger.jpg",
@ -655,12 +662,6 @@
"picture": "bonnie.jpg",
"bio": "Bonnie has been specializing in Angular since 2013. She is the founder of ngHouston Angular Meetup and a regular panelist on Angular Air. She is also the very proud parent component of @thelittlestdev!"
},
"globegitter": {
"name": "Markus Padourek",
"groups": ["Collaborators"],
"mentor": "gregmagolan",
"picture": "globegitter.jpg"
},
"ahsanayaz": {
"name": "Muhammad Ahsan Ayaz",
"picture": "ahsanayaz.jpg",
@ -815,5 +816,13 @@
"website": "https://wellwind.idv.tw/blog/",
"bio": "Mike is a full-stack developer, consultant, blogger, instructor, and conference speaker. He has over 10 years of web development experience and passion to share his knowledge.",
"groups": ["GDE"]
},
"ahasall": {
"name": "Amadou Sall",
"picture": "ahasall.jpg",
"groups": ["GDE"],
"twitter": "ahasall",
"website": "https://www.amadousall.com",
"bio": "Amadou is a Frontend Software Engineer from Senegal based in France. He currently works at Air France where he helps developers build better Angular applications. Passionate about web technologies, Amadou is an international speaker, a technical writer, and a Google Developer Expert in Angular."
}
}

View File

@ -13,11 +13,6 @@
</tr>
</thead>
<tbody>
<tr>
<th><a href="https://ngvikings.org/" title="ngVikings">ngVikings</a></th>
<td>Oslo, Norway</td>
<td>May 25-26 conference, 27 workshops, 2020</td>
</tr>
</tbody>
</table>
@ -31,6 +26,12 @@
</tr>
</thead>
<tbody>
<!-- ng-vikings 2020 -->
<tr>
<th><a href="https://ngvikings.org/" title="ngVikings">ngVikings</a></th>
<td>Oslo, Norway</td>
<td>May 25-26 conference, 27 workshops, 2020</td>
</tr>
<!-- ng-conf 2020 -->
<tr>
<th><a href="https://ng-conf.org/" title="ng-conf">ng-conf</a></th>

View File

@ -97,6 +97,11 @@
"Data Libraries": {
"order": 3,
"resources": {
"formly": {
"desc": "Formly is a dynamic (JSON powered) form library, built on top of Angular Reactive Forms.",
"title": "Formly",
"url": "https://formly.dev"
},
"rx-web": {
"desc": "RxWeb Reactive Form Validators provides all types of complex, conditional, cross field, and dynamic validation on validator-based reactive forms, model-based reactive forms, and template driven forms.",
"title": "RxWeb Reactive Form Validators",
@ -236,6 +241,12 @@
"logo": "",
"title": "Protractor",
"url": "https://protractor.angular.io/"
},
"scully": {
"desc": "Scully (Jamstack Toolchain for Angular) makes building, testing, and deploying Jamstack apps extremely simple.",
"title": "Scully",
"logo": "https://raw.githubusercontent.com/scullyio/scully/main/assets/logos/PNG/Green/scullyio-logo-green.png",
"url": "https://scully.io"
}
}
},

View File

@ -506,80 +506,6 @@
"url": "guide/universal",
"title": "Server-side Rendering",
"tooltip": "Render HTML server-side with Angular Universal."
},
{
"title": "Upgrading from AngularJS",
"tooltip": "Incrementally upgrade an AngularJS application to Angular.",
"children": [
{
"url": "guide/upgrade-setup",
"title": "Setup for Upgrading from AngularJS",
"tooltip": "Use code from the Angular QuickStart seed as part of upgrading from AngularJS.",
"hidden": true
},
{
"url": "guide/upgrade",
"title": "Upgrading Instructions",
"tooltip": "Incrementally upgrade an AngularJS application to Angular."
},
{
"url": "guide/upgrade-performance",
"title": "Upgrading for Performance",
"tooltip": "Upgrade from AngularJS to Angular in a more flexible way."
},
{
"url": "guide/ajs-quick-reference",
"title": "AngularJS-Angular Concepts",
"tooltip": "Learn how AngularJS concepts and techniques map to Angular."
}
]
},
{
"title": "Angular Libraries",
"tooltip": "Extending Angular with shared libraries.",
"children": [
{
"url": "guide/libraries",
"title": "Libraries Overview",
"tooltip": "Understand how and when to use or create libraries."
},
{
"url": "guide/using-libraries",
"title": "Using Published Libraries",
"tooltip": "Integrate published libraries into an app."
},
{
"url": "guide/creating-libraries",
"title": "Creating Libraries",
"tooltip": "Extend Angular by creating, publishing, and using your own libraries."
}
]
},
{
"title": "Schematics",
"tooltip": "Using CLI schematics for code generation.",
"children": [
{
"url": "guide/schematics",
"title": "Schematics Overview",
"tooltip": "How the CLI uses schematics to generate code."
},
{
"url": "guide/schematics-authoring",
"title": "Authoring Schematics",
"tooltip": "Understand the structure of a schematic."
},
{
"url": "guide/schematics-for-libraries",
"title": "Schematics for Libraries",
"tooltip": "Use schematics to integrate your library with the Angular CLI."
}
]
},
{
"url": "guide/cli-builder",
"title": "CLI Builders",
"tooltip": "Using builders to customize Angular CLI."
}
]
},
@ -600,28 +526,74 @@
"url": "guide/angular-compiler-options",
"title": "Angular Compiler Options",
"tooltip": "Configuring AOT compilation."
},
{
},
{
"url": "guide/aot-metadata-errors",
"title": "AOT Metadata Errors",
"tooltip": "Troubleshooting AOT compilation."
},
{
"url": "guide/template-typecheck",
"title": "Template Type-checking",
"tooltip": "Template type-checking in Angular."
}
]
},
},
{
"url": "guide/template-typecheck",
"title": "Template Type-checking",
"tooltip": "Template type-checking in Angular."
}
]
},
{
"url": "guide/build",
"title": "Building & Serving",
"tooltip": "Building and serving Angular apps."
},
{
"url": "guide/testing",
"title": "Testing",
"tooltip": "Techniques and practices for testing an Angular app."
"tooltip": "Testing your Angular apps.",
"children": [
{
"url": "guide/testing",
"title": "Intro to Testing",
"tooltip": "Introduction to testing an Angular app."
},
{
"url": "guide/testing-code-coverage",
"title": "Code Coverage",
"tooltip": "Determine how much of your code is tested."
},
{
"url": "guide/testing-services",
"title": "Testing Services",
"tooltip": "How to test services."
},
{
"url": "guide/testing-components-basics",
"title": "Basics of Testing Components",
"tooltip": "The fundamentals of how to test components."
},
{
"url": "guide/testing-components-scenarios",
"title": "Component Testing Scenarios",
"tooltip": "Use cases for testing components."
},
{
"url": "guide/testing-attribute-directives",
"title": "Testing Attribute Directives",
"tooltip": "How to test attribute directives."
},
{
"url": "guide/testing-pipes",
"title": "Testing Pipes",
"tooltip": "Writing tests for pipes."
},
{
"url": "guide/test-debugging",
"title": "Debugging Tests",
"tooltip": "How to debug tests."
},
{
"url": "guide/testing-utility-apis",
"title": "Testing Utility APIs",
"tooltip": "Features of the Angular testing utilities."
}
]
},
{
"url": "guide/deployment",
@ -675,6 +647,11 @@
"url": "guide/browser-support",
"title": "Browser Support",
"tooltip": "Browser support and polyfills guide."
},
{
"url": "guide/strict-mode",
"title": "Strict mode",
"tooltip": "Reference documentation for Angular's strict mode."
}
]
},
@ -736,9 +713,20 @@
"tooltip": "End-to-end tutorials for learning Angular concepts and patterns.",
"children": [
{
"url": "guide/router-tutorial",
"title": "Using Angular Routes in a Single-page Application",
"tooltip": "A tutorial that covers many patterns associated with Angular routing."
"title": "Routing",
"tooltip": "End-to-end tutorials for learning about Angular's router.",
"children": [
{
"url": "guide/router-tutorial",
"title": "Using Angular Routes in a Single-page Application",
"tooltip": "A tutorial that covers many patterns associated with Angular routing."
},
{
"url": "guide/router-tutorial-toh",
"title": "Router tutorial: tour of heroes",
"tooltip": "Explore how to use Angular's router. Based on the Tour of Heroes example."
}
]
},
{
"url": "guide/forms",
@ -762,13 +750,13 @@
"tooltip": "Angular versioning, release, support, and deprecation policies and practices."
},
{
"title": "Updating to Version 9",
"tooltip": "Support for updating your application from version 8 to 9.",
"title": "Updating to Version 10",
"tooltip": "Support for updating your application from version 9 to 10.",
"children": [
{
"url": "guide/updating-to-version-9",
"url": "guide/updating-to-version-10",
"title": "Overview",
"tooltip": "Everything you need to know for updating your application from version 8 to 9."
"tooltip": "Everything you need to know for updating your application from version 9 to 10."
},
{
"url": "guide/ivy-compatibility",
@ -776,29 +764,9 @@
"tooltip": "Details to help you make sure your application is compatible with Ivy."
},
{
"title": "Optional Migrations",
"tooltip": "Optional migration details regarding updating to version 9.",
"title": "Migrations",
"tooltip": "Migration details regarding updating to version 10.",
"children": [
{
"url": "guide/migration-renderer",
"title": "Renderer to Renderer2",
"tooltip": "Migration from the deprecated Renderer API to the newer Renderer2 API."
},
{
"url": "guide/migration-dynamic-flag",
"title": "Dynamic Queries Flag",
"tooltip": "Migration to remove unnecessary `static: false` flag from @ViewChild and @ContentChild queries."
},
{
"url": "guide/migration-injectable",
"title": "Missing @Injectable() Decorators",
"tooltip": "Migration to add missing @Injectable() decorators and incomplete provider definitions."
},
{
"url": "guide/migration-localize",
"title": "$localize Global Import",
"tooltip": "Migration to add an import statement for @angular/localize to polyfills.ts."
},
{
"url": "guide/migration-module-with-providers",
"title": "Missing ModuleWithProviders Generic",
@ -808,6 +776,26 @@
"url": "guide/migration-undecorated-classes",
"title": "Missing @Directive() Decorators",
"tooltip": "Migration to add missing @Directive()/@Component() decorators."
},
{
"url": "guide/migration-injectable",
"title": "Missing @Injectable() Decorators",
"tooltip": "Migration to add missing @Injectable() decorators and incomplete provider definitions."
},
{
"url": "guide/migration-solution-style-tsconfig",
"title": "Solution-style `tsconfig.json`",
"tooltip": "Migration to create a solution-style `tsconfig.json`."
},
{
"url": "guide/migration-update-libraries-tslib",
"title": "`tslib` direct dependency",
"tooltip": "Migration to a direct dependency on the `tslib` npm package."
},
{
"url": "guide/migration-update-module-and-target-compiler-options",
"title": "`module` and `target` compiler options",
"tooltip": "Migration to update `module` and `target` compiler options."
}
]
}
@ -1003,6 +991,10 @@
}
],
"docVersions": [
{
"title": "v9",
"url": "https://v9.angular.io/"
},
{
"title": "v8",
"url": "https://v8.angular.io/"

View File

@ -6,7 +6,7 @@
In this tutorial, you build your own app from the ground up, providing experience with the typical development process, as well as an introduction to basic app-design concepts, tools, and terminology.
If you're completely new to Angular, you might want to try the [**Try it now**](start) quick-start app first.
It is based on a ready-made partially-completed project, which you can examine and modify in the StacBlitz interactive development environment, where you can see the results in real time.
It is based on a ready-made partially-completed project, which you can examine and modify in the StackBlitz interactive development environment, where you can see the results in real time.
The "Try it" tutorial covers the same major topics&mdash;components, template syntax, routing, services, and accessing data via HTTP&mdash;in a condensed format, following the most current best practices.

View File

@ -139,7 +139,7 @@ sets the `heroService` parameter to the singleton instance of `HeroService`.
### Add `getHeroes()`
Create a function to retrieve the heroes from the service.
Create a method to retrieve the heroes from the service.
<code-example path="toh-pt4/src/app/heroes/heroes.component.1.ts" header="src/app/heroes/heroes.component.ts" region="getHeroes">
</code-example>

View File

@ -79,7 +79,8 @@ Replace the default contents of `in-memory-data.service.ts` with the following:
<code-example path="toh-pt6/src/app/in-memory-data.service.ts" region="init" header="src/app/in-memory-data.service.ts"></code-example>
The `in-memory-data.service.ts` file replaces `mock-heroes.ts`, which is now safe to delete.
The `in-memory-data.service.ts` file will take over the function of `mock-heroes.ts`.
However, don't delete `mock-heroes.ts` yet, as you still need it for a few more steps of this tutorial.
When the server is ready, you'll detach the In-memory Web API, and the app's requests will go through to the server.

View File

@ -1,5 +1,6 @@
{
"hosting": {
"target": "aio",
"public": "dist",
"cleanUrls": true,
"redirects": [
@ -122,7 +123,12 @@
// Strip off the `.html` extension, because Firebase will not do this automatically any more
// (unless the new URL points to an existing file, which is not necessarily the case here).
{"type": 301, "source": "/:somePath*/:file.html", "destination": "/:somePath*/:file"},
{"type": 301, "source": "/:topLevelFile.html", "destination": "/:topLevelFile"}
{"type": 301, "source": "/:topLevelFile.html", "destination": "/:topLevelFile"},
// The below paths are referenced in users projects generated by the CLI
{"type": 301, "source": "/config/tsconfig", "destination": "/guide/typescript-configuration"},
{"type": 301, "source": "/config/solution-tsconfig", "destination": "https://devblogs.microsoft.com/typescript/announcing-typescript-3-9/#solution-style-tsconfig"},
{"type": 301, "source": "/config/app-package-json", "destination": "/guide/strict-mode#non-local-side-effects-in-applications"}
],
"rewrites": [
{

View File

@ -147,6 +147,7 @@
"!/styleguide",
"!/styleguide/**",
"!/testing",
"!/testing/**"
"!/testing/**",
"!/config/**"
]
}

View File

@ -87,28 +87,28 @@
},
"private": true,
"dependencies": {
"@angular/animations": "10.0.0-rc.2",
"@angular/cdk": "^9.2.2",
"@angular/common": "10.0.0-rc.2",
"@angular/compiler": "10.0.0-rc.2",
"@angular/core": "10.0.0-rc.2",
"@angular/elements": "10.0.0-rc.2",
"@angular/forms": "10.0.0-rc.2",
"@angular/material": "^9.2.2",
"@angular/platform-browser": "10.0.0-rc.2",
"@angular/platform-browser-dynamic": "10.0.0-rc.2",
"@angular/router": "10.0.0-rc.2",
"@angular/service-worker": "10.0.0-rc.2",
"@angular/animations": "10.0.2",
"@angular/cdk": "10.0.1",
"@angular/common": "10.0.2",
"@angular/compiler": "10.0.2",
"@angular/core": "10.0.2",
"@angular/elements": "10.0.2",
"@angular/forms": "10.0.2",
"@angular/material": "10.0.1",
"@angular/platform-browser": "10.0.2",
"@angular/platform-browser-dynamic": "10.0.2",
"@angular/router": "10.0.2",
"@angular/service-worker": "10.0.2",
"@webcomponents/custom-elements": "1.2.1",
"rxjs": "^6.5.3",
"tslib": "^1.10.0",
"zone.js": "~0.10.3"
},
"devDependencies": {
"@angular-devkit/build-angular": "0.1000.0-rc.2",
"@angular/cli": "10.0.0-rc.2",
"@angular/compiler-cli": "10.0.0-rc.2",
"@angular/language-service": "10.0.0-rc.2",
"@angular-devkit/build-angular": "0.1000.1",
"@angular/cli": "10.0.1",
"@angular/compiler-cli": "10.0.2",
"@angular/language-service": "10.0.2",
"@types/jasmine": "^3.4.2",
"@types/jasminewd2": "^2.0.8",
"@types/lunr": "^2.3.2",
@ -123,7 +123,7 @@
"cross-spawn": "^5.1.0",
"css-selector-parser": "^1.3.0",
"dgeni": "^0.4.11",
"dgeni-packages": "^0.28.3",
"dgeni-packages": "^0.28.4",
"entities": "^1.1.1",
"eslint": "^3.19.0",
"eslint-plugin-jasmine": "^2.2.0",

View File

@ -33,7 +33,7 @@ else
readonly majorVersionStable=${CI_STABLE_BRANCH%%.*}
# Do not deploy if the major version is not less than the stable branch major version
if [[ !( "$majorVersion" -lt "$majorVersionStable" ) ]]; then
if (( $majorVersion >= $majorVersionStable )); then
echo "Skipping deploy of branch \"$CI_BRANCH\" to firebase."
echo "We only deploy archive branches with the major version less than the stable branch: \"$CI_STABLE_BRANCH\""
exit 0
@ -64,16 +64,27 @@ fi
case $deployEnv in
next)
readonly projectId=aio-staging
readonly siteId=$projectId
readonly deployedUrl=https://next.angular.io/
readonly firebaseToken=$CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN
;;
stable)
readonly projectId=angular-io
readonly siteId=$projectId
readonly deployedUrl=https://angular.io/
readonly firebaseToken=$CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN
;;
archive)
readonly projectId=v${majorVersion}-angular-io
# Special case v9-angular-io because its piloting the firebase hosting "multisites" setup
# See https://angular-team.atlassian.net/browse/DEV-125 for more info.
if [[ "$majorVersion" == "9" ]]; then
readonly projectId=aio-staging
readonly siteId=v9-angular-io
else
readonly projectId=v${majorVersion}-angular-io
readonly siteId=$projectId
fi
readonly deployedUrl=https://v${majorVersion}.angular.io/
readonly firebaseToken=$CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN
;;
@ -82,6 +93,7 @@ esac
echo "Git branch : $CI_BRANCH"
echo "Build/deploy mode : $deployEnv"
echo "Firebase project : $projectId"
echo "Firebase site : $siteId"
echo "Deployment URL : $deployedUrl"
if [[ ${1:-} == "--dry-run" ]]; then
@ -92,23 +104,29 @@ fi
(
cd "`dirname $0`/.."
# Build the app
echo "\n\n\n==== Build the aio app ====\n"
yarn build --configuration=$deployEnv --progress=false
# Include any mode-specific files
echo "\n\n\n==== Add any mode-specific files into the aio distribution ====\n"
cp -rf src/extra-files/$deployEnv/. dist/
# Set deployedUrl as parameter in the opensearch description
echo "\n\n\n==== Update opensearch descriptor for aio with the deployedUrl ====\n"
# deployedUrl must end with /
yarn set-opensearch-url $deployedUrl
# Check payload size
echo "\n\n\n==== Check payload size and upload the numbers to firebase db ====\n"
yarn payload-size
# Deploy to Firebase
yarn firebase use "$projectId" --token "$firebaseToken"
yarn firebase deploy --message "Commit: $CI_COMMIT" --non-interactive --token "$firebaseToken"
# Run PWA-score tests
echo "\n\n\n==== Deploy aio to firebase hosting ====\n"
yarn firebase use "${projectId}" --token "$firebaseToken"
yarn firebase target:apply hosting aio $siteId --token "$firebaseToken"
yarn firebase deploy --only hosting:aio --message "Commit: $CI_COMMIT" --non-interactive --token "$firebaseToken"
echo "\n\n\n==== Run PWA-score tests ====\n"
yarn test-pwa-score "$deployedUrl" "$CI_AIO_MIN_PWA_SCORE"
)

View File

@ -68,6 +68,7 @@ function check {
expected="Git branch : master
Build/deploy mode : next
Firebase project : aio-staging
Firebase site : aio-staging
Deployment URL : https://next.angular.io/"
check "$actual" "$expected"
)
@ -103,6 +104,7 @@ Deployment URL : https://next.angular.io/"
expected="Git branch : 4.3.x
Build/deploy mode : stable
Firebase project : angular-io
Firebase site : angular-io
Deployment URL : https://angular.io/"
check "$actual" "$expected"
)
@ -139,10 +141,37 @@ Deployment URL : https://angular.io/"
expected="Git branch : 2.4.x
Build/deploy mode : archive
Firebase project : v2-angular-io
Firebase site : v2-angular-io
Deployment URL : https://v2.angular.io/"
check "$actual" "$expected"
)
(
echo ===== archive - v9-angular-io multisite special case - deploy success
actual=$(
export BASH_ENV=/dev/null
export CI_REPO_OWNER=angular
export CI_REPO_NAME=angular
export CI_PULL_REQUEST=false
export CI_BRANCH=9.1.x
export CI_STABLE_BRANCH=10.0.x
export CI_COMMIT=$(git ls-remote origin 9.1.x | cut -c1-40)
export CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN=XXXXX
$deployToFirebaseDryRun
)
expected="Git branch : 9.1.x
Build/deploy mode : archive
Firebase project : aio-staging
Firebase site : v9-angular-io
Deployment URL : https://v9.angular.io/"
# TODO: This test incorrectly expects the Firebase project to be v9-angular-io.
# v9-angular-io is a "multisites" project currently within the aio-staging project
# This setup is temporary and was created in order to deploy v9.angular.io without
# disruptions.
# See https://angular-team.atlassian.net/browse/DEV-125 for more info.
check "$actual" "$expected"
)
(
echo ===== archive - skip deploy - commit not HEAD
actual=$(

View File

@ -14,11 +14,11 @@
<button mat-button class="hamburger" [class.starting]="isStarting" (click)="sidenav.toggle()" title="Docs menu">
<mat-icon svgIcon="menu"></mat-icon>
</button>
<a class="nav-link home" href="/" [ngSwitch]="isSideBySide">
<a class="nav-link home" href="/" [ngSwitch]="showTopMenu">
<img *ngSwitchCase="true" src="assets/images/logos/angular/logo-nav@2x.png" width="150" height="40" title="Home" alt="Home">
<img *ngSwitchDefault src="assets/images/logos/angular/shield-large.svg" width="37" height="40" title="Home" alt="Home">
</a>
<aio-top-menu *ngIf="isSideBySide" [nodes]="topMenuNodes" [currentNode]="currentNodes?.TopBar"></aio-top-menu>
<aio-top-menu *ngIf="showTopMenu" [nodes]="topMenuNodes" [currentNode]="currentNodes?.TopBar"></aio-top-menu>
<aio-search-box class="search-container" #searchBox (onSearch)="doSearch($event)" (onFocus)="doSearch($event)"></aio-search-box>
<div class="toolbar-external-icons-container">
<a href="https://twitter.com/angular" title="Twitter" aria-label="Angular on twitter">
@ -35,9 +35,9 @@
<mat-sidenav-container class="sidenav-container" [class.starting]="isStarting" [class.has-floating-toc]="hasFloatingToc" role="main">
<mat-sidenav [ngClass]="{'collapsed': !isSideBySide}" #sidenav class="sidenav" [mode]="mode" [opened]="isOpened" (openedChange)="updateHostClasses()">
<aio-nav-menu *ngIf="!isSideBySide" [nodes]="topMenuNarrowNodes" [currentNode]="currentNodes?.TopBarNarrow" [isWide]="false"></aio-nav-menu>
<aio-nav-menu [nodes]="sideNavNodes" [currentNode]="currentNodes?.SideNav" [isWide]="isSideBySide"></aio-nav-menu>
<mat-sidenav [ngClass]="{'collapsed': !dockSideNav}" #sidenav class="sidenav" [mode]="mode" [opened]="isOpened" (openedChange)="updateHostClasses()">
<aio-nav-menu *ngIf="!showTopMenu" [nodes]="topMenuNarrowNodes" [currentNode]="currentNodes?.TopBarNarrow" [isWide]="false"></aio-nav-menu>
<aio-nav-menu [nodes]="sideNavNodes" [currentNode]="currentNodes?.SideNav" [isWide]="dockSideNav"></aio-nav-menu>
<div class="doc-version">
<aio-select (change)="onDocVersionChange($event.index)" [options]="docVersions" [selected]="currentDocVersion"></aio-select>

View File

@ -25,11 +25,9 @@ import { first, mapTo } from 'rxjs/operators';
import { MockLocationService } from 'testing/location.service';
import { MockLogger } from 'testing/logger.service';
import { MockSearchService } from 'testing/search.service';
import { AppComponent } from './app.component';
import { AppComponent, dockSideNavWidth, showFloatingTocWidth, showTopMenuWidth } from './app.component';
import { AppModule } from './app.module';
const sideBySideBreakPoint = 992;
const hideToCBreakPoint = 800;
const startedDelay = 100;
describe('AppComponent', () => {
@ -58,7 +56,7 @@ describe('AppComponent', () => {
component = fixture.componentInstance;
fixture.detectChanges();
component.onResize(sideBySideBreakPoint + 1); // wide by default
component.onResize(showTopMenuWidth + 1); // wide by default
const de = fixture.debugElement;
const docViewerDe = de.query(By.css('aio-doc-viewer'));
@ -99,7 +97,7 @@ describe('AppComponent', () => {
});
it('should be false on narrow screens', () => {
component.onResize(hideToCBreakPoint - 1);
component.onResize(showFloatingTocWidth - 1);
tocService.tocList.next([{}, {}, {}] as TocItem[]);
expect(component.hasFloatingToc).toBe(false);
@ -112,7 +110,7 @@ describe('AppComponent', () => {
});
it('should be true on wide screens unless the toc is empty', () => {
component.onResize(hideToCBreakPoint + 1);
component.onResize(showFloatingTocWidth + 1);
tocService.tocList.next([{}, {}, {}] as TocItem[]);
expect(component.hasFloatingToc).toBe(true);
@ -127,37 +125,47 @@ describe('AppComponent', () => {
it('should be false when toc is empty', () => {
tocService.tocList.next([]);
component.onResize(hideToCBreakPoint + 1);
component.onResize(showFloatingTocWidth + 1);
expect(component.hasFloatingToc).toBe(false);
component.onResize(hideToCBreakPoint - 1);
component.onResize(showFloatingTocWidth - 1);
expect(component.hasFloatingToc).toBe(false);
component.onResize(hideToCBreakPoint + 1);
component.onResize(showFloatingTocWidth + 1);
expect(component.hasFloatingToc).toBe(false);
});
it('should be true when toc is not empty unless the screen is narrow', () => {
tocService.tocList.next([{}, {}, {}] as TocItem[]);
component.onResize(hideToCBreakPoint + 1);
component.onResize(showFloatingTocWidth + 1);
expect(component.hasFloatingToc).toBe(true);
component.onResize(hideToCBreakPoint - 1);
component.onResize(showFloatingTocWidth - 1);
expect(component.hasFloatingToc).toBe(false);
component.onResize(hideToCBreakPoint + 1);
component.onResize(showFloatingTocWidth + 1);
expect(component.hasFloatingToc).toBe(true);
});
});
describe('isSideBySide', () => {
describe('showTopMenu', () => {
it('should be updated on resize', () => {
component.onResize(sideBySideBreakPoint - 1);
expect(component.isSideBySide).toBe(false);
component.onResize(showTopMenuWidth - 1);
expect(component.showTopMenu).toBe(false);
component.onResize(sideBySideBreakPoint + 1);
expect(component.isSideBySide).toBe(true);
component.onResize(showTopMenuWidth + 1);
expect(component.showTopMenu).toBe(true);
});
});
describe('dockSideNav', () => {
it('should be updated on resize', () => {
component.onResize(dockSideNavWidth - 1);
expect(component.dockSideNav).toBe(false);
component.onResize(dockSideNavWidth + 1);
expect(component.dockSideNav).toBe(true);
});
});
@ -185,8 +193,8 @@ describe('AppComponent', () => {
fixture.detectChanges();
};
describe('when side-by-side (wide)', () => {
beforeEach(() => resizeTo(sideBySideBreakPoint + 1)); // side-by-side
describe('when view is wide', () => {
beforeEach(() => resizeTo(dockSideNavWidth + 1)); // wide view
it('should open when navigating to a guide page (guide/pipes)', () => {
navigateTo('guide/pipes');
@ -232,8 +240,8 @@ describe('AppComponent', () => {
});
});
describe('when NOT side-by-side (narrow)', () => {
beforeEach(() => resizeTo(sideBySideBreakPoint - 1)); // NOT side-by-side
describe('when view is narrow', () => {
beforeEach(() => resizeTo(dockSideNavWidth - 1)); // narrow view
it('should be closed when navigating to a guide page (guide/pipes)', () => {
navigateTo('guide/pipes');
@ -286,30 +294,30 @@ describe('AppComponent', () => {
});
});
describe('when changing side-by-side (narrow --> wide)', () => {
describe('when changing from narrow to wide view', () => {
const sidenavDocs = ['api/a/b/c/d', 'guide/pipes'];
const nonSidenavDocs = ['features', 'about'];
sidenavDocs.forEach(doc => {
it(`should open when on a sidenav doc (${doc})`, () => {
resizeTo(sideBySideBreakPoint - 1);
resizeTo(dockSideNavWidth - 1);
navigateTo(doc);
expect(sidenav.opened).toBe(false);
resizeTo(sideBySideBreakPoint + 1);
resizeTo(dockSideNavWidth + 1);
expect(sidenav.opened).toBe(true);
});
});
nonSidenavDocs.forEach(doc => {
it(`should remain closed when on a non-sidenav doc (${doc})`, () => {
resizeTo(sideBySideBreakPoint - 1);
resizeTo(dockSideNavWidth - 1);
navigateTo(doc);
expect(sidenav.opened).toBe(false);
resizeTo(sideBySideBreakPoint + 1);
resizeTo(dockSideNavWidth + 1);
expect(sidenav.opened).toBe(false);
});
});
@ -317,33 +325,33 @@ describe('AppComponent', () => {
describe('when manually opened', () => {
sidenavDocs.forEach(doc => {
it(`should remain opened when on a sidenav doc (${doc})`, () => {
resizeTo(sideBySideBreakPoint - 1);
resizeTo(dockSideNavWidth - 1);
navigateTo(doc);
toggleSidenav();
expect(sidenav.opened).toBe(true);
resizeTo(sideBySideBreakPoint + 1);
resizeTo(dockSideNavWidth + 1);
expect(sidenav.opened).toBe(true);
});
});
nonSidenavDocs.forEach(doc => {
it(`should close when on a non-sidenav doc (${doc})`, () => {
resizeTo(sideBySideBreakPoint - 1);
resizeTo(dockSideNavWidth - 1);
navigateTo(doc);
toggleSidenav();
expect(sidenav.opened).toBe(true);
resizeTo(sideBySideBreakPoint + 1);
resizeTo(showTopMenuWidth + 1);
expect(sidenav.opened).toBe(false);
});
});
});
});
describe('when changing side-by-side (wide --> narrow)', () => {
describe('when changing from wide to narrow view', () => {
const sidenavDocs = ['api/a/b/c/d', 'guide/pipes'];
const nonSidenavDocs = ['features', 'about'];
@ -352,7 +360,7 @@ describe('AppComponent', () => {
navigateTo(doc);
expect(sidenav.opened).toBe(true);
resizeTo(sideBySideBreakPoint - 1);
resizeTo(dockSideNavWidth - 1);
expect(sidenav.opened).toBe(false);
});
});
@ -362,7 +370,7 @@ describe('AppComponent', () => {
navigateTo(doc);
expect(sidenav.opened).toBe(false);
resizeTo(sideBySideBreakPoint - 1);
resizeTo(dockSideNavWidth - 1);
expect(sidenav.opened).toBe(false);
});
});
@ -376,7 +384,7 @@ describe('AppComponent', () => {
async function setupSelectorForTesting(mode?: string) {
createTestingModule('a/b', mode);
await initializeTest();
component.onResize(sideBySideBreakPoint + 1); // side-by-side
component.onResize(dockSideNavWidth + 1); // wide view
selectElement = fixture.debugElement.query(By.directive(SelectComponent));
selectComponent = selectElement.componentInstance;
}

View File

@ -14,6 +14,9 @@ import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
import { first, map } from 'rxjs/operators';
const sideNavView = 'SideNav';
export const showTopMenuWidth = 1048;
export const dockSideNavWidth = 992;
export const showFloatingTocWidth = 800;
@Component({
selector: 'aio-shell',
@ -57,18 +60,17 @@ export class AppComponent implements OnInit {
isStarting = true;
isTransitioning = true;
isFetching = false;
isSideBySide = false;
showTopMenu = false;
dockSideNav = false;
private isFetchingTimeout: any;
private isSideNavDoc = false;
private sideBySideWidth = 992;
sideNavNodes: NavigationNode[];
topMenuNodes: NavigationNode[];
topMenuNarrowNodes: NavigationNode[];
hasFloatingToc = false;
private showFloatingToc = new BehaviorSubject(false);
private showFloatingTocWidth = 800;
tocMaxHeight: string;
private tocMaxHeightOffset = 0;
@ -76,8 +78,8 @@ export class AppComponent implements OnInit {
private currentUrl: string;
get isOpened() { return this.isSideBySide && this.isSideNavDoc; }
get mode() { return this.isSideBySide ? 'side' : 'over'; }
get isOpened() { return this.dockSideNav && this.isSideNavDoc; }
get mode() { return this.dockSideNav && (this.isSideNavDoc || this.showTopMenu) ? 'side' : 'over'; }
// Search related properties
showSearchResults = false;
@ -239,13 +241,14 @@ export class AppComponent implements OnInit {
@HostListener('window:resize', ['$event.target.innerWidth'])
onResize(width: number) {
this.isSideBySide = width >= this.sideBySideWidth;
this.showFloatingToc.next(width > this.showFloatingTocWidth);
this.showTopMenu = width >= showTopMenuWidth;
this.dockSideNav = width >= dockSideNavWidth;
this.showFloatingToc.next(width > showFloatingTocWidth);
if (this.isSideBySide && !this.isSideNavDoc) {
if (this.showTopMenu && !this.isSideNavDoc) {
// If this is a non-sidenav doc and the screen is wide enough so that we can display menu
// items in the top-bar, ensure the sidenav is closed.
// (This condition can only be met when the resize event changes the value of `isSideBySide`
// (This condition can only be met when the resize event changes the value of `showTopMenu`
// from `false` to `true` while on a non-sidenav doc.)
this.sidenav.toggle(false);
}
@ -338,7 +341,7 @@ export class AppComponent implements OnInit {
}
// May be open or closed when wide; always closed when narrow.
this.sidenav.toggle(this.isSideBySide && openSideNav);
this.sidenav.toggle(this.dockSideNav && openSideNav);
}
// Dynamically change height of table of contents container

View File

@ -1,27 +1,31 @@
import { HttpClient } from '@angular/common/http';
import { ErrorHandler } from '@angular/core';
import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser';
import { CustomIconRegistry, SvgIconInfo } from './custom-icon-registry';
describe('CustomIconRegistry', () => {
const fakeHttpClient: HttpClient = {} as any;
const fakeDomSanitizer: DomSanitizer = {} as any;
const fakeDocument: Document = {} as any;
const fakeErrorHandler: ErrorHandler = {handleError: err => console.error(err)};
it('should get the SVG element for a preloaded icon from the cache', () => {
const mockHttp: any = {};
const mockSanitizer: any = {};
const mockDocument: any = {};
const svgSrc = '<svg xmlns="http://www.w3.org/2000/svg" focusable="false" ' +
'viewBox="0 0 24 24"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"/></svg>';
const svgIcons: SvgIconInfo[] = [
{ name: 'test_icon', svgSource: svgSrc }
];
const registry = new CustomIconRegistry(mockHttp, mockSanitizer, mockDocument, svgIcons);
const registry = new CustomIconRegistry(
fakeHttpClient, fakeDomSanitizer, fakeDocument, fakeErrorHandler, svgIcons);
let svgElement: SVGElement|undefined;
registry.getNamedSvgIcon('test_icon').subscribe(el => svgElement = el);
expect(svgElement).toEqual(createSvg(svgSrc));
});
it('should support caching icons with a namespace', () => {
const mockHttp: any = {};
const mockSanitizer: any = {};
const mockDocument: any = {};
const svgSrc1 = '<svg xmlns="http://www.w3.org/2000/svg"><path d="h100" /></svg>';
const svgSrc2 = '<svg xmlns="http://www.w3.org/2000/svg"><path d="h200" /></svg>';
const svgSrc3 = '<svg xmlns="http://www.w3.org/2000/svg"><path d="h300" /></svg>';
@ -31,7 +35,8 @@ describe('CustomIconRegistry', () => {
{ namespace: 'bar', name: 'test_icon', svgSource: svgSrc3 },
];
const registry = new CustomIconRegistry(mockHttp, mockSanitizer, mockDocument, svgIcons);
const registry = new CustomIconRegistry(
fakeHttpClient, fakeDomSanitizer, fakeDocument, fakeErrorHandler, svgIcons);
let svgElement: SVGElement|undefined;
registry.getNamedSvgIcon('test_icon', 'foo').subscribe(el => svgElement = el);
@ -39,9 +44,6 @@ describe('CustomIconRegistry', () => {
});
it('should call through to the MdIconRegistry if the icon name is not in the preloaded cache', () => {
const mockHttp: any = {};
const mockSanitizer: any = {};
const mockDocument: any = {};
const svgSrc = '<svg xmlns="http://www.w3.org/2000/svg" focusable="false" ' +
'viewBox="0 0 24 24"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"/></svg>';
const svgIcons: SvgIconInfo[] = [
@ -49,7 +51,8 @@ describe('CustomIconRegistry', () => {
];
spyOn(MatIconRegistry.prototype, 'getNamedSvgIcon');
const registry = new CustomIconRegistry(mockHttp, mockSanitizer, mockDocument, svgIcons);
const registry = new CustomIconRegistry(
fakeHttpClient, fakeDomSanitizer, fakeDocument, fakeErrorHandler, svgIcons);
registry.getNamedSvgIcon('other_icon');
expect(MatIconRegistry.prototype.getNamedSvgIcon).toHaveBeenCalledWith('other_icon', undefined);

View File

@ -1,4 +1,4 @@
import { InjectionToken, Inject, Injectable, Optional } from '@angular/core';
import { ErrorHandler, InjectionToken, Inject, Injectable, Optional } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { of } from 'rxjs';
import { MatIconRegistry } from '@angular/material/icon';
@ -42,8 +42,8 @@ export class CustomIconRegistry extends MatIconRegistry {
private preloadedSvgElements: SvgIconMap = {[DEFAULT_NS]: {}};
constructor(http: HttpClient, sanitizer: DomSanitizer, @Optional() @Inject(DOCUMENT) document: Document,
@Inject(SVG_ICONS) svgIcons: SvgIconInfo[]) {
super(http, sanitizer, document);
errorHandler: ErrorHandler, @Inject(SVG_ICONS) svgIcons: SvgIconInfo[]) {
super(http, sanitizer, document, errorHandler);
this.loadSvgElements(svgIcons);
}

View File

@ -1,3 +0,0 @@
/* You can add global styles to this file, and also import other style files */
@import './styles/ng-io-theme';
@import './styles/main.scss';

View File

@ -193,6 +193,11 @@ code {
}
}
// The following css rule adds an icon to external links in the docs area.
// The following `folder-*` classes are applied to the `doc-viewer`component when it is displaying docs for these areas of the documentation.
// We add the icon to all external links which are identified as absolute links (those that start with `http` or https`).
// For more info see PR #36601
.folder-api,
.folder-cli,
.folder-docs,
@ -213,6 +218,8 @@ code {
}
}
// The docs-viewer also contain links to GitHub (e.g. the edit this page icon) identified with `.github-links` class.
// We don't want to add the external link icon to these links, so we hide them.
.github-links a {
&[href^="http:"]::after,
&[href^="https:"]::after {

View File

@ -1,4 +1,6 @@
// VARIABLES
$showTopMenuWidth: 1048px;
$hideTopMenuWidth: $showTopMenuWidth - 1;
$hamburgerShownMargin: 0 8px 0 0;
$hamburgerHiddenMargin: 0 16px 0 -64px;
@ -59,9 +61,9 @@ aio-shell.folder-docs mat-toolbar.mat-toolbar,
aio-shell.folder-guide mat-toolbar.mat-toolbar,
aio-shell.folder-start mat-toolbar.mat-toolbar,
aio-shell.folder-tutorial mat-toolbar.mat-toolbar {
@media (min-width: 992px) {
@media (min-width: $showTopMenuWidth) {
.hamburger.mat-button {
// Hamburger shown on non-marketing pages on large screens.
// Hamburger shown on non-marketing pages even on large screens.
margin: $hamburgerShownMargin;
}
}
@ -73,7 +75,7 @@ aio-shell.folder-tutorial mat-toolbar.mat-toolbar {
margin: $hamburgerShownMargin;
padding: 0;
@media (min-width: 992px) {
@media (min-width: $showTopMenuWidth) {
// Hamburger hidden by default on large screens.
// (Will be shown per doc.)
margin: $hamburgerHiddenMargin;
@ -111,7 +113,7 @@ aio-shell.folder-tutorial mat-toolbar.mat-toolbar {
outline-offset: 4px;
}
@media screen and (max-width: 991px) {
@media screen and (max-width: $hideTopMenuWidth) {
padding: 4px 0;
}
@ -125,7 +127,7 @@ aio-shell.folder-tutorial mat-toolbar.mat-toolbar {
top: 12px;
height: 40px;
@media (max-width: 991px) {
@media (max-width: $hideTopMenuWidth) {
&:hover {
transform: scale(1.1);
}
@ -237,6 +239,7 @@ aio-search-box.search-container {
width: 80%;
}
}
@media (max-width: 480px) {
width: 150px;
}

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