Compare commits

...

255 Commits

Author SHA1 Message Date
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
3a43cdefe8 release: cut the v10.0.0-rc.5 release 2020-06-11 15:49:34 -07:00
38c48beddd refactor(elements): add accessor workaround for build-optimizer (#37456)
Build-optimizer currently uses TypeScript 3.6 which is unable to resolve an 'accessor' in 'getTypeOfVariableOrParameterOrPropertyWorker'.

Unfortunately, in Build optimizer we cannot update the version of TypeScript because of https://github.com/microsoft/TypeScript/issues/38412

PR Close #37456
2020-06-11 12:05:35 -07:00
ad5749fb04 build: add @babel/preset-env to dependencies (#37456)
`@babel/preset-env` is needed by for NGCC tests: 3569fdf451/packages/compiler-cli/ngcc/test/BUILD.bazel (L84)

However this is not as a depedency in the angular repo.

PR Close #37456
2020-06-11 12:05:35 -07:00
f6a838e9ee build: update CLI packages to the latest RC version for v10 (#37456)
With this change we update the Angular CLI repo and aio packages to the latest RC version for version 10.

PR Close #37456
2020-06-11 12:05:34 -07:00
a6d1f4aaf1 build: update to typescript 3.9.5 (#37456)
This TypeScript version contains the revert for the classes wrapped in IIFE change that was introduced in version 3.9.

PR Close #37456
2020-06-11 12:05:34 -07:00
eca8d11ee2 fix(ngcc): use annotateForClosureCompiler option (#36652)
Adds @nocollapse to static properties added by ngcc
iff annotateForClosureCompiler is true.

The Closure Compiler will collapse static properties
into the global namespace.  Adding this annotation keeps
the properties attached to their respective object, which
allows them to be referenced via a class's constructor.
The annotation is already added by ngtsc and ngc under the
same option, this commit extends the functionality to ngcc.

Closes #36618.

PR Close #36652
2020-06-11 11:12:56 -07:00
a195b7dbe4 docs: add example links to 'DoCheck' lifeycle hook docs (#36574)
There were some examples for 'DoCheck' in the lifeCycle hooks guide. Added a link to the relevant section of the guide in the 'DoCheck()' api docs.

Fixes #35596

PR Close #36574
2020-06-11 11:09:58 -07:00
083d7ec902 docs: Minor grammar fix: "bug-free" (#36515)
Change documentation to a more grammatically correct format. "bug-free" is preferred over "bug free".

PR Close #36515
2020-06-11 11:07:54 -07:00
9d2d0cae6d docs: remove out of date GDEs (#36467)
Periodic documentation cleanup of GDEs which are no longer in the Angular program.

Removed:
 - "Filip Bruun Bech-Larsen"
 - "Vinci Rufus"
 - "Jeff Cross"

PR Close #36467
2020-06-11 11:04:11 -07:00
c2f4a9bf71 build: remove ngcontainer Docker (#36421)
ngcontainer Dockerfile was noted as deprecated ~2 years ago, we no longer
rely on it anymore nor do we publish it.

PR Close #36421
2020-06-10 12:59:07 -07:00
231095fe8a build: add commit message scope for migration changes (#36390)
This is a proposal commit that adds a separate scope for
migration changes. The motiviation is that migrations aren't
necessarily always affecting `@angular/core`, but are just
stored in the core package for a canonical location when
someone runs `ng update`. Additionally, it rather seems confusing in the
changelog if migration changes are listed under `core`.

PR Close #36390
2020-06-10 12:03:45 -07:00
28a532483a docs: add Mike Huang as a GDE (#36472)
Update the GDE listing with info abbout Mike Huang.
Update the GDE listing with info abbout Mike Huang.

PR Close #36472
2020-06-10 11:53:25 -07:00
83853a215d docs: remove redundant web-worker nav (#37289)
Web- worker was 2 times in the nav pointing towards the same file, just with different names removed one to remove redundancy

PR Close #37289
2020-06-10 11:52:06 -07:00
8248307a99 fix(ngcc): do not scan import expressions in d.ts files (#37503)
It is quite common for the TS compiler to have to add synthetic
types to function signatures, where the developer has not
explicitly provided them.  This results in `import(...)` expressions
appearing in typings files.  For example in `@ngrx/data` there is a
class with a getter that has an implicit type:

```ts
export declare class EntityCollectionServiceBase<...> {
  ...
  get store() {
    return this.dispatcher.store;
  }
  ...
}
```

In the d.ts file for this we get:

```ts
get store(): Store<import("@ngrx/data").EntityCache>;
```

Given that this file is within the `@ngrx/data` package already,
this caused ngcc to believe that there was a circular dependency,
causing it to fail to process the package - and in fact crash!

This commit resolves this problem by ignoring `import()` expressions
when scanning typings programs for dependencies. This ability was
only introduced very recently in a 10.0.0 RC release, and so it has
limited benefit given that up till now ngcc has been able to process
libraries effectively without it. Moreover, in the rare case that a
package does have such a dependency, it should get picked up
by the sync ngcc+CLI integration point.

PR Close #37503
2020-06-10 11:51:19 -07:00
67bd88b19a feat(language-service): Remove HTML entities autocompletion (#37515)
This commit removes the autocompletion feature for HTML entities.
HTML entites are things like `&amp;`, `&lt;` etc.

There are a few reasons for the decision:

1. It is outside the core functionality of Angular LS
2. The implementation relies on regex, which incurs performance cost
3. There isn't much value if users do not already know which entity
   they want to use
4. The list that we provide is not exhaustive

PR Close #37515
2020-06-10 11:50:55 -07:00
9f698b4de0 release: cut the v10.0.0-rc.4 release 2020-06-10 11:31:29 -07:00
742f3d6787 Revert "fix(elements): fire custom element output events during component initialization (#36161)" (#37524)
This reverts commit e9bff5fe9f. Failures
were detected in Google tests due to this commit

PR Close #37524
2020-06-10 17:28:57 +00:00
323651bd38 fix(compiler-cli): downlevel angular decorators to static properties (#37382)
In v7 of Angular we removed `tsickle` from the default `ngc` pipeline.
This had the negative potential of breaking ES2015 output and SSR due
to a limitation in TypeScript.

TypeScript by default preserves type information for decorated constructor
parameters when `emitDecoratorMetadata` is enabled. For example,
consider this snippet below:

```
@Directive()
export class MyDirective {
  constructor(button: MyButton) {}
}

export class MyButton {}
```

TypeScript would generate metadata for the `MyDirective` class it has
a decorator applied. This metadata would be needed in JIT mode, or
for libraries that provide `MyDirective` through NPM. The metadata would
look as followed:

```
let MyDirective = class MyDir {}

MyDirective = __decorate([
  Directive(),
  __metadata("design:paramtypes", [MyButton]),
], MyDirective);

let MyButton = class MyButton {}
```

Notice that TypeScript generated calls to `__decorate` and
`__metadata`. These calls are needed so that the Angular compiler
is able to determine whether `MyDirective` is actually an directive,
and what types are needed for dependency injection.

The limitation surfaces in this concrete example because `MyButton`
is declared after the `__metadata(..)` call, while `__metadata`
actually directly references `MyButton`. This is illegal though because
`MyButton` has not been declared at this point. This is due to the
so-called temporal dead zone in JavaScript. Errors like followed will
be reported at runtime when such file/code evaluates:

```
Uncaught ReferenceError: Cannot access 'MyButton' before initialization
```

As noted, this is a TypeScript limitation because ideally TypeScript
shouldn't evaluate `__metadata`/reference `MyButton` immediately.
Instead, it should defer the reference until `MyButton` is actually
declared. This limitation will not be fixed by the TypeScript team
though because it's a limitation as per current design and they will
only revisit this once the tc39 decorator proposal is finalized
(currently stage-2 at time of writing).

Given this wontfix on the TypeScript side, and our heavy reliance on
this metadata in libraries (and for JIT mode), we intend to fix this
from within the Angular compiler by downleveling decorators to static
properties that don't need to evaluate directly. For example:

```
MyDirective.ctorParameters = () => [MyButton];
```

With this snippet above, `MyButton` is not referenced directly. Only
lazily when the Angular runtime needs it. This mitigates the temporal
dead zone issue caused by a limitation in TypeScript's decorator
metadata output. See: https://github.com/microsoft/TypeScript/issues/27519.

In the past (as noted; before version 7), the Angular compiler by
default used tsickle that already performed this transformation. We
moved the transformation to the CLI for JIT and `ng-packager`, but now
we realize that we can move this all to a single place in the compiler
so that standalone ngc consumers can benefit too, and that we can
disable tsickle in our Bazel `ngc-wrapped` pipeline (that currently
still relies on tsickle to perform this decorator processing).

This transformation also has another positive side-effect of making
Angular application/library code more compatible with server-side
rendering. In principle, TypeScript would also preserve type information
for decorated class members (similar to how it did that for constructor
parameters) at runtime. This becomes an issue when your application
relies on native DOM globals for decorated class member types. e.g.

```
@Input() panelElement: HTMLElement;
```

Your application code would then reference `HTMLElement` directly
whenever the source file is loaded in NodeJS for SSR. `HTMLElement`
does not exist on the server though, so that will become an invalid
reference. One could work around this by providing global mocks for
these DOM symbols, but that doesn't match up with other places where
dependency injection is used for mocking DOM/browser specific symbols.

More context in this issue: #30586. The TL;DR here is that the Angular
compiler does not care about types for these class members, so it won't
ever reference `HTMLElement` at runtime.

Fixes #30106. Fixes #30586. Fixes #30141.
Resolves FW-2196. Resolves FW-2199.

PR Close #37382
2020-06-10 09:24:12 -07:00
9d397eb5a1 Revert "build: remove wombot proxy registry from package.jsons for release (#37378)" (#37495)
This reverts commit 26849ca99d.

PR Close #37495
2020-06-10 08:21:46 -07:00
6114cd2bd4 perf(core): avoid pulling in jit-specific code in aot bundles (#37372) (#37514)
In #29083 a call to `getCompilerFacade` was added to `ApplicationRef` which pulls in a bit of JIT-specific code. Since the code path that calls the function can't be hit for an AOT-compiled app, these changes add an `ngJitMode` guard which will allow for dead code elimination to drop it completely. Testing it out against a new CLI project showed a difference of ~1.2kb.

PR Close #37372

PR Close #37514
2020-06-09 14:49:05 -07:00
d494f7bd5e docs(dev-infra): add comment about what the requiredBaseCommit is (#37509)
Add a comment to describe what the commit was for the given SHA so that we don't have to look it up.

PR Close #37509
2020-06-09 13:29:24 -07:00
ec6a7ab721 docs: wrong links in lifecycle hooks api documentaion (#36557)
lifecycle hooks api detailed documentation contained links which were pointing to onChanges hook only which is removed, made each hook point towards its deafult page link

PR Close #36557
2020-06-09 11:16:43 -07:00
ad6d2b4619 docs(core): fix path referenced in comments of both compiler facade interface files (#37370)
Previously the comments for these files referenced a path to "packages/core/src/render3/jit/compiler_facade_interface.ts" that does not exist in the current codebase.

This PR corrects the path in these comments.

PR Close #37370
2020-06-09 08:28:26 -07:00
c093390010 fix(dev-infra): local changes check not working (#37489)
Looks like we broke the `hasLocalChanges` check in the git client
when we moved it over from the merge script. The problem is that
we are using `git` in the first argument of `git.run`. That
means that we under-the-hood run `git git <..>`.

This commit fixes that, but also switches to a better variant
for ensuring no local changes because it exits with non-zero
when there are local changes.

PR Close #37489
2020-06-09 08:27:32 -07:00
acd69f2be2 fix(dev-infra): rebase pr script not working (#37489)
The dev-infra rebase PR script currently does not work due to
the following issues:

1. The push refspec is incorrect. It refers to the `base` of the PR, and
not to the `head` of the PR.
2. The push `--force-with-lease` option does not work in a detached head
as no remote-tracking branch is set up.

PR Close #37489
2020-06-09 08:27:32 -07:00
5d2f341653 fix(dev-infra): incorrect token sanitization when no token is specified (#37489)
We recently moved over the git client from the merge script to the
common dev-infra utils. This made specifying a token optional, but
it looks like the logic for sanitizing messages doesn't account
for that, and we currently add `<TOKEN>` between every message
character. e.g.

```
Executing: git <TOKEN>g<TOKEN>i<TOKEN>t<TOKEN>
<TOKEN>s<TOKEN>t<TOKEN>a<TOKEN>t<TOKEN>u<TOKEN>s<TOKEN>
```

PR Close #37489
2020-06-09 08:27:32 -07:00
420d1c35f5 fix(platform-server): correctly handle absolute relative URLs (#37341)
Previously, we would simply prepend any relative URL with the HREF
for the current route (pulled from document.location). However,
this does not correctly account for the leading slash URLs that
would otherwise be parsed correctly in the browser, or the
presence of a base HREF in the DOM.

Therefore, we use the built-in URL implementation for NodeJS,
which implements the WHATWG standard that's used in the browser.
We also pull the base HREF from the DOM, falling back on the full
HREF as the browser would, to form the correct request URL.

Fixes #37314

PR Close #37341
2020-06-09 08:27:00 -07:00
08647267bb fix(common): prevent duplicate URL change notifications (#37459)
Prevent duplicate notifications from being emitted when multiple URL change listeners are registered using SpyLocation#onUrlChange.

Use `@internal` annotation for the `_urlChangeSubscription` properties instead of the `private` access modifier. Otherwise, we get in trouble because of  `SpyLocation implements Location`.

PR Close #37459
2020-06-09 08:26:34 -07:00
215d50d2f6 test(common): prefer TestBed.inject over inject (#37459)
Use the strongly typed TestBed.inject rather than the weakly typed inject test utility function. Reuse injected dependency variables between sibling test cases.

PR Close #37459
2020-06-09 08:26:34 -07:00
bf2cb6fa48 feat(language-service): TS references from template items (#37437)
Keen and I were talking about what it would take to support getting
references at a position in the current language service, since it's
unclear when more investment in the Ivy LS will be available. Getting TS
references from a template is trivial -- we simply need to get the
definition of a symbol, which is already handled by the language
service, and ask the TS language service to give us the references for
that definition.

This doesn't handle references in templates, but that could be done in a
subsequent pass.

Part of https://github.com/angular/vscode-ng-language-service/issues/29

PR Close #37437
2020-06-08 17:23:49 -07:00
e97a2d4123 fix(language-service): Improve signature selection by finding exact match (#37494)
The function signature selection algorithm is totally naive. It'd
unconditionally pick the first signature if there are multiple
overloads. This commit improves the algorithm by returning an exact
match if one exists.

PR Close #37494
2020-06-08 17:23:12 -07:00
585e3f6adc fix(router): Fix relative link generation from empty path components (#37446)
Partial resubmit of #26243
Fixes incorrect url tree generation for empty path components with children.
Adds a test to demonstrate the failure of createUrlTree for those routes.
Fixes #13011
Fixes #35687

PR Close #37446
2020-06-08 17:15:38 -07:00
7f77ce1a48 release: cut the v10.0.0-rc.3 release 2020-06-08 17:03:59 -07:00
a1616ce181 docs: add note on publishing libraries in ivy (#36556)
Libraries are still build using view engine even after Ivy being the default engine for building angular apps. Added note on why libraries are built using VE and how they will be automatically compiled in Ivy using ngcc making it compatible for both

Fixes #35625

PR Close #36556
2020-06-08 15:05:52 -07:00
1c22dff714 docs(docs-infra): fix small typo (#37258)
The style guide docs had a typo "Alerts and Calllouts". Callouts is
spelled with two l's, not three. This PR fixes the typo.

PR Close #37258
2020-06-08 14:42:50 -07:00
8d1d6e8f70 docs: place download section in toh to the top (#36567)
this is part of a larger effort to standardise download sections on angular.io

This commit partially addresses #35459

PR Close #36567
2020-06-08 11:41:52 -07:00
e7f4aba5a3 docs(service-worker): add staleWhileRevalidate strategy (#37301)
There is great workaround for implementing staleWhileRevalidate strategy in service-worker by setting strategy to freshness and timeout to 0u. Documented this in service worker config where all other strategies are documented

Fixes #20402

PR Close #37301
2020-06-08 11:41:20 -07:00
fdbe9f5d9f refactor(core): assert TNode is not a container when setting attribute on element (#37111)
This PR provides a more helpful error than the one currently present:
`el.setAttribute is not a function`. It is not valid to have directives with host bindings
on `ng-template` or `ng-container` nodes. VE would silently ignore this, while Ivy
attempts to set the attribute and throws an error because these are comment nodes
and do not have `setAttribute` functionality.

It is better to throw a helpful error than to silently ignore this because
putting a directive with host binding on an `ng-template` or `ng-container` is most often a mistake.
Developers should be made aware that the host binding will have no effect in these cases.

Note that an error is already thrown in Ivy, as mentioned above, so this
is not a breaking change and can be merged to both master and patch.

Resolves #35994

PR Close #37111
2020-06-08 11:21:05 -07:00
8bead6bfdd test(language-service): Remove all markers from test project (#37475)
This commit removes all markers from the inline template in
`AppComponent` and external template in `TemplateReference`.

Test scenarios should be colocated with the test cases themselves.
Besides, many existing cases are invalid. For example, if we want to
test autocomplete for HTML element, the existing test case is like:
```
<~{cursor} h1>
```
This doesn't make much sense, becasue the language service already sees
the `h1` tag in the template. The correct test case should be:
```
<~{cursor
```
IMO, this reflects the real-world use case better.

This commit also uncovers a bug in the way HTML entities autocompletion
is done. There's an off-by-one error in which a cursor that immediately
trails the ampersand character fails to trigger HTML entities
autocompletion.

PR Close #37475
2020-06-08 10:25:43 -07:00
52dda73dbb ci: remove IgorMinar from reviewers list for pullapprove fallback group (#36456)
Historically we have had a pullapprove group `fallback` which acted as
a catch all for files which did not match any other groups.  This
group assigned reviews to IgorMinar, however it was not apparent that
this group was assigned.  This change removes this assignment.  This
group as active should always coincide with failures of the pullapprove
verification script. We continue to have this group as a secondary test
ensuring all files in the repo are captured by the pullapprove config.

PR Close #36456
2020-06-08 10:07:45 -07:00
31b3888a2f style(ngcc): post-merge review tidy up (#37461)
This commit tidies up a few of the code comments from a recent commit to
help improve the clarity of the algorithm.

PR Close #37461
2020-06-08 09:32:11 -07:00
6f938470c2 fix(service-worker): Don't stay locked in EXISTING_CLIENTS_ONLY if corrupted data (#37453)
**Problem**

After #31109 and #31865, it's still possible to get locked in state
`EXISTING_CLIENTS_ONLY`, without any possibility to get out (even by
pushing new updates on the server).
More specifically, if control doc `/latest` of `ngsw:/:db:control` once
gets a bad value, then the service worker will fail early, and won't be
able to overwrite `/latest` with new, valid values (the ones from future
updates).

For example, once in this state, URL `/ngsw/state` will show:

    NGSW Debug Info:
    Driver state: EXISTING_CLIENTS_ONLY (Degraded due to failed initialization: Invariant violated (initialize): latest hash 8b75… has no known manifest
    Error: Invariant violated (initialize): latest hash 8b75… has no known manifest
        at Driver.<anonymous> (https://my.app/ngsw-worker.js:2302:27)
        at Generator.next (<anonymous>)
        at fulfilled (https://my.app/ngsw-worker.js:175:62))
    Latest manifest hash: 8b75…
    Last update check: 22s971u

... with hash `8b75…` corresponding to no installed version.

**Solution**

Currently, when such a case happens, the service worker [simply fails
with an assertion][1]. Because this failure happens early, and is not
handled, the service worker is not able to update `/latest` to new
installed app versions.

I propose to detect this corrupted case (a `latest` hash that doesn't
match any installed version) a few lines above, so that the service
worker can correctly call its [already existing cleaning code][2].

[1]: https://github.com/angular/angular/blob/3569fdf/packages/service-worker/worker/src/driver.ts#L559-L563
[2]: https://github.com/angular/angular/blob/3569fdf/packages/service-worker/worker/src/driver.ts#L505-L519

This change successfully fixes the problem described above.

Unit test written with the help of George Kalpakas. Thank you!

PR Close #37453
2020-06-08 09:31:35 -07:00
776c4afc03 fix(dev-infra): await setup in runBenchmark (#37428)
* Fix for issue #36986.
* Changes runBenchmark into an async function.
* Awaits config.setup in runBenchmark.

PR Close #37428
2020-06-08 09:17:35 -07:00
536dd647c6 build: update to latest stable Chromium 83.0.4103 in both rules_webtesting and puppeteer (#37427)
Also added in detailed instructions of the process to determine the URLs corresponding to Chromium version desired

PR Close #37427
2020-06-08 09:16:40 -07:00
51d581ab27 build: upgrade to bazel 3.2.0 and rules_nodejs 1.7.0 (#37358)
Upgrade to rely on bazel version 3.2.0 and rules_nodejs 1.7.0.  This
is part of a routine update as new versions become available.

PR Close #37358
2020-06-08 09:15:50 -07:00
75294e7dad ci: special case tooling-cli-shared-api review group (#37467)
The new tooling-cli-shared-api is used to guard changes to packages/compiler-cli/src/tooling.ts
which is a private API sharing channel between Angular FW and CLI.

Changes to this file should be rare and explicitly approved by at least two members
of the CLI team.

PR Close #37467
2020-06-05 19:23:53 -07:00
04bada7a9d ci: extend and update the reviewer groups (#37467)
Update the pullapprove config to require multiple reviews for sensitive groups in order
to force distribution of knowledge and improve the review quality.

PR Close #37467
2020-06-05 19:23:53 -07:00
2349143477 fix(dev-infra): properly determine oauth scopes for git client token (#37462)
Resubmit of b2bd38699b since
85b6c94cc6 accidentally reverted
the fix due to rebasing most likely.

PR Close #37462
2020-06-05 11:04:37 -07:00
e9bff5fe9f fix(elements): fire custom element output events during component initialization (#36161)
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 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. Ensuring `NgElementImpl` subscribes to `NgElementStrategy#events`
   before calling `NgElementStrategy#connect()` (which initializes the
   component instance).

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)

Fixes #36141

PR Close #36161
2020-06-05 10:36:39 -07:00
411cb0cb92 refactor(elements): remove unnecessary non-null assertions and as any type-casts (#36161)
This commit removes some unnecessary non-null assertions (`!`) and
`as any` type-casts from the `elements` package.

PR Close #36161
2020-06-05 10:36:39 -07:00
53e1fb3554 refactor(dev-infra): move GitClient to common util (#37318)
Moves GitClient from merge script into common utils for unified
method of performing git actions throughout the ng-dev toolset.

PR Close #37318
2020-06-05 09:46:40 -07:00
2cb3b66640 fix(ngcc): find decorated constructor params on IIFE wrapped classes (#37436)
Now in TS 3.9, classes in ES2015 can be wrapped in an IIFE.
This commit ensures that we still find the static properties that contain
decorator information, even if they are attached to the adjacent node
of the class, rather than the implementation or declaration.

Fixes #37330

PR Close #37436
2020-06-05 09:22:04 -07:00
5af3144330 refactor(dev-infra): use the exec() helper from utils/shelljs whenever possible (#37444)
There is an `exec()` helper provided by `utils/shelljs.ts`, which is a
wrapper around ShellJS' `exec()` with some default options (currently
`silent: true`). The intention is to avoid having to pass these options
to every invocation of the `exec()` function.

This commit updates all code inside `dev-infra/` to use this helper
whenever possible).

NOTE: For simplicity, the `utils/shelljs` helper does not support some
      of the less common call signatures of the original `exec()`
      helper, so in some cases we still need to use the original.

PR Close #37444
2020-06-05 09:21:18 -07:00
e4043cbb3a docs: fix minor error in the "Structural directives" guide (#37452)
The sample code used in this guide uses [class.od]="odd".
But, in another portion of the guide, [ngClass]="odd" is mentioned instead.

PR Close #37452
2020-06-05 09:20:43 -07:00
fff424a35f fix(common): prevent duplicate URL change notifications (#37404)
Prevent duplicate notifications from being emitted when multiple URL change listeners are registered using Location#onUrlChange.

PR Close #37404
2020-06-04 16:45:06 -07:00
b5d1c8b05a docs: fix various typos (#37443)
This change just fixes various typos and misspellings across several docs.

I've included also a fix for an issue surfaced via #37423.

Closes #37423

PR Close #37443
2020-06-04 16:03:55 -07:00
d713e33cc4 style(dev-infra): correct tslint failures in dev-infra directory (#37233)
Fixes tslint failures in dev-infra directory as the directory is now
part of the tslint enforced files.

PR Close #37233
2020-06-04 12:44:46 -07:00
3d327d25f0 build: add dev-infra to tslint selected files (#37233)
Adds the dev-infra files to the scope of files on which tslint is
enforced.  This will allow for better code management/conformance.

PR Close #37233
2020-06-04 12:44:46 -07:00
077283bf0f fix(dev-infra): clean up usages within pullapprove tooling (#37338)
Clean up pullapprove tooling to use newly created common utils.
Additionally, use newly created logging levels rather than
verbose flagging.

PR Close #37338
2020-06-04 12:43:45 -07:00
9ec25ea036 refactor(dev-infra): change required base commit sha (#37424)
Update the commit sha to require that PRs have been rebased beyond the one which has new header requirements so we don't get failures after merging

PR Close #37424
2020-06-04 10:44:14 -07:00
878cfe669c fix(dev-infra): properly determine oauth scopes for git client token (#37439)
We recently added a better reporting mechanism for oauth tokens
in the dev-infra git util. Unfortunately the logic broke as part
of addressing PR review feedback. Right now, always the empty
promise from `oauthScopes` will be used as `getAuthScopes` considers
it as the already-requested API value. This is not the case as
the default promise is also truthy. We should just fix this by making
the property nullable.

PR Close #37439
2020-06-04 10:42:53 -07:00
5f0be3cb2e feat(dev-infra): Add oauth scope check to ensure necessary permissions for merge tooling (#37421)
Adds an assertion that the provided TOKEN has OAuth scope permissions for `repo`
as this is required for all merge attempts.

On failure, provides detailed error message with remediation steps for the user.

PR Close #37421
2020-06-04 09:35:59 -07:00
9e28e14c08 fix(dev-infra): ensure ts-node is registered with commonjs as module (#37422)
We recently added support for automatic registration of `ts-node`
when the dev-infra configuration is loaded.

In addition to registering ts-node, we should also ensure that the
`commonjs` module is set up. By default, `ts-node` would use ES module
imports that are not supported by default in NodeJS.

PR Close #37422
2020-06-04 09:34:33 -07:00
954d002884 feat(dev-infra): migrate release tool to use new logging system (#37422)
Migrate the release tool in ng-dev to use new logging system rather
than directly calling console.* to create a better experience
for users.

PR Close #37422
2020-06-04 09:34:32 -07:00
0a48591e53 feat(dev-infra): migrate ts-circular-dependencies tool to use new logging system (#37422)
Migrate the ts-circular-dependencies tool in ng-dev to use new logging system rather
than directly calling console.* to create a better experience
for users.

PR Close #37422
2020-06-04 09:34:32 -07:00
d37c723951 feat(dev-infra): migrate merge tool to use new logging system (#37422)
Migrate the merge tool in ng-dev to use new logging system rather
than directly calling console.* to create a better experience
for users.

PR Close #37422
2020-06-04 09:34:32 -07:00
9078ca557e feat(dev-infra): migrate ng-dev utils to use new logging system (#37422)
Migrate the ng-dev utils to use new logging system rather
than directly calling console.* to create a better experience
for users.

PR Close #37422
2020-06-04 09:34:32 -07:00
2be1ef6ba0 feat(dev-infra): migrate pullapprove tool to use new logging system (#37422)
Migrate the pullapprove tool in ng-dev to use new logging system rather
than directly calling console.* to create a better experience
for users.

PR Close #37422
2020-06-04 09:34:32 -07:00
47c02efccb feat(dev-infra): migrate rebase tool to use new logging system (#37422)
Migrate the rebase tool in ng-dev to use new logging system rather
than directly calling console.*  to create a better experience
for users.

PR Close #37422
2020-06-04 09:34:32 -07:00
d7ecfb432a feat(dev-infra): migrate discover-new-conflicts tool to use new logging system (#37422)
Migrate the discover-new-conflicts tool in ng-dev to use new logging system
rather than directly calling console.* to create a better experience
for users.

PR Close #37422
2020-06-04 09:34:32 -07:00
59abf4a33f feat(dev-infra): migrate commit-message tool to use new logging system (#37422)
Migrate the commit-message tool in ng-dev to use new logging system rather
than directly calling console.* to create a better experience
for users.

PR Close #37422
2020-06-04 09:34:32 -07:00
d6e715e726 feat(dev-infra): migrate format tool to use new logging system (#37422)
Migrate the formatting tool in ng-dev to use new logging system rather
than directly calling console.* to create a better experience
for users.

PR Close #37422
2020-06-04 09:34:32 -07:00
fcfcd1037c feat(dev-infra): add group functions to logging system and remove color param (#37422)
Adds .group and .groupEnd functions to each of the logging functions
to allow creating groups in the logged output.  Additionally removes
the color parameter from logging functions, in favor of the color
being applied to the string at the call site.

PR Close #37422
2020-06-04 09:34:31 -07:00
f3ccd29e7b feat(ngcc): implement a program-based entry-point finder (#37075)
This finder is designed to only process entry-points that are reachable
by the program defined by a tsconfig.json file.

It is triggered by calling `mainNgcc()` with the `findEntryPointsFromTsConfigProgram`
option set to true. It is ignored if a `targetEntryPointPath` has been
provided as well.

It is triggered from the command line by adding the `--use-program-dependencies`
option, which is also ignored if the `--target` option has been provided.

Using this option can speed up processing in cases where there is a large
number of dependencies installed but only a small proportion of the
entry-points are actually imported into the application.

PR Close #37075
2020-06-04 09:22:40 -07:00
5c0bdae809 fix(ngcc): capture dynamic import expressions as well as declarations (#37075)
Previously we only checked for static import declaration statements.
This commit also finds import paths from dynamic import expressions.

Also this commit should speed up processing: Previously we were parsing
the source code contents into a `ts.SourceFile` and then walking the parsed
AST to find import paths.
Generating an AST is unnecessary work and it is faster and creates less
memory pressure to just scan the source code contents with the TypeScript
scanner, identifying import paths from the tokens.

PR Close #37075
2020-06-04 09:22:40 -07:00
838902556b refactor(ngcc): move shared code into DependencyHostBase (#37075)
The various dependency hosts had a lot of duplicated code.
This commit refactors them to move this into the base class.

PR Close #37075
2020-06-04 09:22:40 -07:00
c6872c02d8 fix(ngcc): ensure that more dependencies are found by EsmDependencyHost (#37075)
Previously this host was skipping files if they had imports that spanned
multiple lines, or if the import was a dynamic import expression.

PR Close #37075
2020-06-04 09:22:40 -07:00
819982ea20 docs: add blank line before header (#37391)
Currently, `Formatting your source code` is not being formatted as a header because of a missing empty line.
PR Close #37391
2020-06-04 09:20:26 -07:00
f9daa136c3 perf(ngcc): cache parsed tsconfig between runs (#37417)
This commit will store a cached copy of the parsed tsconfig
that can be reused if the tsconfig path is the same.

This will improve the ngcc "noop" case, where there is no processing
to do, when the entry-points have already been processed.
Previously we were parsing this config every time we checked for
entry-points to process, which can take up to seconds in some
cases.

Resolves #36882

PR Close #37417
2020-06-04 09:19:38 -07:00
6a0d2ed6c8 ci(docs-infra): skip deploying RC version when lexicographically smaller than stable (#37426)
The angular.io production deployment script (`deploy-to-firebase.sh`)
compares the major version corresponding to the current branch (e.g.
`8` for branch `8.1.x`) against the major stable version (e.g. `9` if
the current stable version is `9.1.0`). It then uses the result of that
comparison to determine whether the current branch corresponds to a
newer version than stable (i.e. an RC version) and thus should not be
deployed or to an older version and thus may need to be deployed to an
archive vX.angular.io project.

Previously, the script was using string comparison (`<`) to compare the
two major versions. This could produce incorrect results for an RC major
version that is numerically greater than the stable but
lexicographically smaller. For example, 10 vs 9 (10 is numerically
greater but lexicographically smaller than 9).
Example of a CI job that incorrectly tried to deploy an RC branch to
production: https://circleci.com/gh/angular/angular/726414

This commit fixes it by switching to an integer comparison (i.e. using
the `-lt` operator).

PR Close #37426
2020-06-04 09:17:29 -07:00
2c1f35e794 fix(language-service): Recover from error in analyzing Ng Modules (#37108)
In place of failing to return analyzed Ng Modules when the analyzer
fails, return the previously-analyzed Ng Modules (which may be empty)
and log an error.

Closes https://github.com/angular/vscode-ng-language-service/issues/777

PR Close #37108
2020-06-03 15:56:19 -07:00
5345e8da45 docs: update the stackblitz in the GitHub Issue template (#37219)
This commit updates the bug report stackblitz template for opening a new
issue based on the current angular release.

Closes #37063

PR Close #37219
2020-06-03 15:55:44 -07:00
e35269dd87 docs: update file header to be correct (#37425)
The file header should be Google LLC rather than Google Inc. because it is now an LLC after Alphabet Holdings was formed.

PR Close #37425
2020-06-03 15:31:29 -07:00
60a03b7ef7 refactor(compiler-cli): extract NgCompilerAdapter interface (#37118)
`NgCompiler` is the heart of ngtsc and can be used to analyze and compile
Angular programs in a variety of environments. Most of these integrations
rely on `NgProgram` and the creation of an `NgCompilerHost` in order to
create a `ts.Program` with the right shape for `NgCompiler`.

However, certain environments (such as the Angular Language Service) have
their own mechanisms for creating `ts.Program`s that don't make use of a
`ts.CompilerHost`. In such environments, an `NgCompilerHost` does not make
sense.

This commit breaks the dependency of `NgCompiler` on `NgCompilerHost` and
extracts the specific interface of the host on which `NgCompiler` depends
into a new interface, `NgCompilerAdapter`. This interface includes methods
from `ts.CompilerHost`, the `ExtendedTsCompilerHost`, as well as APIs from
`NgCompilerHost`.

A consumer such as the language service can implement this API without
needing to jump through hoops to create an `NgCompilerHost` implementation
that somehow wraps its specific environment.

PR Close #37118
2020-06-03 13:29:45 -07:00
305b5a3887 fix(compiler-cli): use ModuleWithProviders type if static eval fails (#37126)
When the compiler encounters a function call within an NgModule imports
section, it attempts to resolve it to an NgModule-annotated class by
looking at the function body and evaluating the statements there. This
evaluation can only understand simple functions which have a single
return statement as their body. If the function the user writes is more
complex than that, the compiler won't be able to understand it and
previously the PartialEvaluator would return a "DynamicValue" for
that import.

With this change, in the event the function body resolution fails the
PartialEvaluator will now attempt to use its foreign function resolvers to
determine the correct result from the function's type signtaure instead. If
the function is annotated with a correct ModuleWithProviders type, the
compiler will be able to understand the import without static analysis of
the function body.

PR Close #37126
2020-06-03 13:23:16 -07:00
bc549361d3 fix(core): infinite loop if injectable using inheritance has a custom decorator (#37022)
If we detect that an injectable class is inheriting from another injectable, we generate code that looks something like this:

```
const baseFactory = ɵɵgetInheritedFactory(Child);

@Injectable()
class Parent {}

@Injectable()
class Child extends Parent {
  static ɵfac = (t) => baseFactory(t || Child)
}
```

This usually works fine, because the `ɵɵgetInheritedFactory` resolves to the factory of `Parent`, but the logic can break down if the `Child` class has a custom decorator. Custom decorators can return a new class that extends the original once, which means that the `ɵɵgetInheritedFactory` call will now resolve to the factory of the `Child`, causing an infinite loop.

These changes fix the issue by changing the inherited factory resolution logic so that it walks up the prototype chain class-by-class, while skipping classes that have the same factory as the class that was passed in.

Fixes #35733.

PR Close #37022
2020-06-03 13:16:26 -07:00
084b627f2e refactor(dev-infra): small changes and fixes (#36800)
Rename bazel workspace from npm_dev_infra to npm_angular_dev_infra_private to make it clear that this package is private to angular.
Change driver-utilities module_name to match the new bazel workspace name.
Correct a comment by rewording it from "deployed version" to "published version".
Fix merge conflicts in tmpl-package.json
Make "//packages/bazel/src:esm5.bzl" replacement more generalized so that importing from "//packages/bazel" works.
Deleted "dev_infra/*" path from modules/benchmarks tsconfig.
Moved //dev-infra/benchmark/browsers to //dev-infra/browsers.

PR Close #36800
2020-06-03 13:12:31 -07:00
6755d00601 revert: "revert: "build(core): use dev-infra's component_benchmark to show PoC (#36434)" (#36798)" (#36800)
This reverts commit 90a2796a7e.

PR Close #36800
2020-06-03 13:12:31 -07:00
cba1da3e44 revert: "revert: "build(dev-infra): update package.json and :npm_package (#36434)" (#36798)" (#36800)
This reverts commit f5ff2068a4.

PR Close #36800
2020-06-03 13:12:31 -07:00
7be8bb1489 revert: "revert: "feat(dev-infra): exposed new rule 'component_benchmark' via dev_infra (#36434)" (#36798)" (#36800)
This reverts commit ad8c4cdd75.

PR Close #36800
2020-06-03 13:12:31 -07:00
c7c0c1f626 refactor(forms): use a type guard to get rid of casts (#32541)
Use an explicit type guard when checking if a given object is of type AbstractControlOptions,
instead of a simple function returning a boolean value. This allows us to remove manual type
casting when using this function, relying instead on TypeScript to infer correct types.

PR Close #32541
2020-06-03 12:29:26 -07:00
3aa4629f92 docs: refactor template-driven forms doc as a tutorial (#36732)
rework content to meet current documentation standards and conventions, structure as tutorial document type

PR Close #36732
2020-06-03 12:27:28 -07:00
2d86dbb090 docs: update aio in support for #BlackLivesMatter (#37409)
Update angular.io in support for #BlackLivesMatter. The PR updates the
styles of the landing page and changes the current survey notification.

PR Close #37409
2020-06-03 11:20:57 -07:00
91767ff0f9 ci: temporarily disable Android 10 browser unit tests on Saucelabs (#37399)
Disabling Android 10 browser unit tests on Saucelabs due to errors.

After remediation from Saucelabs to correct the discovered failures, this change can be reverted to renable the tests on Android 10.

Example of failures seen:

```
02 06 2020 14:03:05.048:INFO [SaucelabsLauncher]: Chrome 10.0 (Android) session at https://saucelabs.com/tests/54f5fb181db644a3b4779187c2309000

02 06 2020 14:03:06.869:INFO [Chrome Mobile 74.0.3729 (Android 0.0.0)]: Disconnected browser returned on socket E-bi0p0NKtghk-HcAAAO with id 85563367.

Chrome Mobile 74.0.3729 (Android 0.0.0) ERROR: Error: XHR error loading http://angular-ci.local:9876/base/node_modules/rxjs/internal/operators/zip.js

	Error loading http://angular-ci.local:9876/base/node_modules/rxjs/internal/operators/zip.js as "../internal/operators/zip" from http://angular-ci.local:9876/base/node_modules/rxjs/operators/index.js

Error: XHR error loading http://angular-ci.local:9876/base/node_modules/rxjs/internal/operators/zip.js

    at error (http://angular-ci.local:9876/base/node_modules/systemjs/dist/system.src.js?1c6a6c12fec50a8db7aeebe8e06e2b70135c0615:1028:16)

    at XMLHttpRequest.xhr.onreadystatechange [as __zone_symbol__ON_PROPERTYreadystatechange] (http://angular-ci.local:9876/base/node_modules/systemjs/dist/system.src.js?1c6a6c12fec50a8db7aeebe8e06e2b70135c0615:1036:13)

    at XMLHttpRequest.wrapFn (http://angular-ci.local:9876/base/dist/bin/packages/zone.js/npm_package/dist/zone.js?942d01da94828e1c75e8527fa8d06f363d6379ce:809:43)

    at ZoneDelegate.invokeTask (http://angular-ci.local:9876/base/dist/bin/packages/zone.js/npm_package/dist/zone.js?942d01da94828e1c75e8527fa8d06f363d6379ce:432:35)

    at Zone.runTask (http://angular-ci.local:9876/base/dist/bin/packages/zone.js/npm_package/dist/zone.js?942d01da94828e1c75e8527fa8d06f363d6379ce:201:55)

    at ZoneTask.invokeTask [as invoke] (http://angular-ci.local:9876/base/dist/bin/packages/zone.js/npm_package/dist/zone.js?942d01da94828e1c75e8527fa8d06f363d6379ce:514:38)

    at invokeTask (http://angular-ci.local:9876/base/dist/bin/packages/zone.js/npm_package/dist/zone.js?942d01da94828e1c75e8527fa8d06f363d6379ce:1722:18)

    at XMLHttpRequest.globalZoneAwareCallback (http://angular-ci.local:9876/base/dist/bin/packages/zone.js/npm_package/dist/zone.js?942d01da94828e1c75e8527fa8d06f363d6379ce:1748:21)
```

PR Close #37399
2020-06-02 17:32:34 -04:00
078b004ecc docs(core): remove v10 mention from @Injectable warning (#37383)
In v9, we started showing a console warning when
instantiating a token that inherited its @Injectable
decorator rather than providing its own. This warning
said that the pattern would become an error in v10.

However, we have decided to wait until at least v11
to throw in this case, so this commit updates the
warning to be less prescriptive about the exact
version when the pattern will no longer be supported.

PR Close #37383
2020-06-02 17:30:58 -04:00
930d204d83 perf(ngcc): allow immediately reporting a stale lock file (#37250)
Currently, if an ngcc process is killed in a manner that it doesn't clean
up its lock file (or is killed too quickly) the compiler reports that it
is waiting on the PID of a process that doesn't exist, and that it will
wait up to a maximum of N seconds. This PR updates the locking code to
additionally check if the process exists, and if it does not it will
immediately bail out, and print the location of the lock file so a user
may clean it up.

PR Close #37250
2020-06-02 17:30:03 -04:00
8d82cdfc77 docs: refactor forms overview (#36919)
Reorganize and edit content of existing form overview to conform to current doc standards and styles

PR Close #36919
2020-06-02 17:29:15 -04:00
cb6996b5c3 build: fix integration payload sizes 2020-06-02 12:06:52 -07:00
a4f7740332 docs(router): fix a typo in example code (#37309)
The code in the example docs used TestBed.configureTestModule instead of TestBed.configureTestingModule.

PR Close #37309
2020-06-01 17:19:46 -04:00
ba0faa2f77 refactor(core): remove looseIdentical in favor of built-in Object.is (#37191)
Remove `looseIdentical` implementation and instead use the ES2015 `Object.is` in its place.
They behave exactly the same way except for `+0`/`-0`.
`looseIdentical(+0, -0)` => `true`
`Object.is(+0, -0)` => `false`

Other than the difference noted above, this is not be a breaking change because:
1. `looseIdentical` is a private API
2. ES2015 is listed as a mandatory polyfill in the [browser support
guide](https://angular.io/guide/browser-support#mandatory-polyfills)
3. Also note that `Ivy` already uses `Object.is` in `bindingUpdated`.

PR Close #37191
2020-06-01 17:19:17 -04:00
3e68029522 test(language-service): disable ivy ls tests on CI (#37348)
This commit disables the tests for Ivy version of language service on CI
because the compiler APIs are not yet stable, so language service should
not assert against its behavipr.

PR Close #37348
2020-06-01 17:18:51 -04:00
b4e26b5828 fix(ngcc): do not inline source-maps for non-inline typings source-maps (#37363)
Inline source-maps in typings files can impact IDE performance
so ngcc should only add such maps if the original typings file
contains inline source-maps.

Fixes #37324

PR Close #37363
2020-06-01 17:18:31 -04:00
15cf7fcac2 docs(core): fix typo in decorators.ts relating to the use of Object.defineProperty. (#37369)
Previously there was a typo in a comment within the PropDecorator function relating to and justifying the use of Object.defineProperty. This PR clears up the wording that comment

PR Close #37369
2020-06-01 17:18:08 -04:00
24ff0eb13b docs: fix typo in deprecations (#37379)
This PR fixes a typo in the deprecations guide, changing 'dropped support for of Windows 10...' to 'dropped support for Windows 10...'

PR Close #37379
2020-06-01 17:17:44 -04:00
cf86f72eb7 release: cut the v10.0.0-rc.2 release 2020-06-01 10:51:58 -07:00
61486f14f1 build: remove wombot proxy registry from package.jsons for release (#37378)
Due to an outage with the proxy we rely on for publishing, we need
to temporarily directly publish to NPM using our own angular
credentials again.

PR Close #37378
2020-06-01 12:41:19 -04:00
d16a7f3ecc fix(core): reenable decorator downleveling for Angular npm packages (#37317)
In #37221 we disabled tsickle passes from transforming the tsc output that is used to publish all
Angular framework and components packages (@angular/*).

This change however revealed a bug in the ngc that caused __decorate and __metadata calls to still
be emitted in the JS code even though we don't depend on them.

Additionally it was these calls that caused code in @angular/material packages to fail at runtime
due to circular dependency in the emitted decorator code documeted as
https://github.com/microsoft/TypeScript/issues/27519.

This change partially rolls back #37221 by reenabling the decorator to static fields (static
properties) downleveling.

This is just a temporary workaround while we are also fixing root cause in `ngc` - tracked as
FW-2199.

Resolves FW-2198.
Related to FW-2196

PR Close #37317
2020-05-29 18:52:01 -04:00
82761ec50e docs: Mention Bazel builder and schematics in Deprecations section (#37190)
This commit adds Bazel builder and schematics to the global list of
deprecations in Angular. A link to the migration doc is added.

PR Close #37190
2020-05-28 21:35:41 -04:00
235bfa77a9 docs(bazel): Mention Architect prototype and Slack Channel (#37190)
This commit adds a link to the Bazel prototype for orchestrating
multiple CLI architects and also adds a link to the #angular channel in
the Bazel Slack workspace.

PR Close #37190
2020-05-28 21:35:41 -04:00
299ae1bb1c docs: Cleanup Bazel schematics deprecation doc (#37190)
This commit improves some wording in the deprecation doc for Bazel
builder and schematics in `@angular/bazel` and fixes the formatting.

PR Close #37190
2020-05-28 21:35:41 -04:00
80f7522dab refactor(bazel): Remove schematics and builder from package.json (#37190)
This commit removes the fields for ng-add, schematics and builder from
package.json of `@angular/bazel`.

PR Close #37190
2020-05-28 21:35:41 -04:00
028921e369 docs: Add guide/bazel to Service Worker navigationUrls (#37190)
This commit adds an exception for "guide/bazel" to the navigationUrls in
the Service Worker config. This is needed for redirection to work.

PR Close #37190
2020-05-28 21:35:41 -04:00
a4e11bb524 docs: Redirect /guide/bazel to deprecation doc in Angular repo (#37190)
This commit adds a 301 redirect for /guide/bazel on angular.io to the
deprecation doc for Angular Bazel schematics in Angular repo.

PR Close #37190
2020-05-28 21:35:41 -04:00
a4131752d2 test: remove Bazel schematics integration test (#37190)
This commit removes the integration test for schematics in
`@angular/bazel` that is used to generate a Bazel builder. The Bazel
builder has been deprecated.

PR Close #37190
2020-05-28 21:35:40 -04:00
060dcfbba1 ci: Remove aio/content/guide/bazel.md from pullapprove (#37190)
This commit removes aio/content/guide/bazel.md from the Bazel list in
pullapprove since Bazel builder has been deprecated and the doc has been
deleted.

PR Close #37190
2020-05-28 21:35:40 -04:00
4be7008f80 docs: Remove 'Building with Bazel' section (#37190)
This commit removes "Building with Bazel" section from angular.io
navigation list and Angular CLI landing page.

PR Close #37190
2020-05-28 21:35:40 -04:00
4a0d05515e refactor(bazel): Remove Schematics for Bazel Builder (#37190)
This commit removes `ng-add` and `ng-new` schematics for the Bazel
Builder, and update the corresponding BUILD files.

PR Close #37190
2020-05-28 21:35:40 -04:00
83ab99c746 docs: Remove Bazel builder from @angular/bazel (#37190)
This commit adds a deprecation doc for Bazel builder in
`@angular/bazel` and removes the corresponding guide in angular.io.

PR Close #37190
2020-05-28 21:35:40 -04:00
270da1f69f build(docs-infra): upgrade cli command docs sources to 14af4e07c (#37310)
Updating [angular#10.0.x](https://github.com/angular/angular/tree/10.0.x) from [cli-builds#10.0.x](https://github.com/angular/cli-builds/tree/10.0.x).

##
Relevant changes in [commit range](200a21f8a...14af4e07c):

**Modified**
- help/generate.json

PR Close #37310
2020-05-28 18:43:44 -04:00
6b0e46e36c docs: fix typo in committer.md (#37171)
Fix a type of COMMITTER.md, the url of the pullapprove service should be https://docs.pullapprove.com/,
now the document has an additional `https` prefix.

PR Close #37171
2020-05-28 18:43:05 -04:00
3642707145 build: use static patch value for targetting branches in merge config (#37299)
Due to the desired patch branch (10.0.x) being on a semver version
that is unreleased as stable (there is no 10.0.0 on latest, it is on
next) our logic for determining target patch branches does not work.

This change is a workaround to unblock merging in the repo while a
longer term answer is discovered.

PR Close #37299
2020-05-28 15:18:20 -07:00
0ea76edfd8 build: migrate ng-dev config to .ng-dev directory (#37299)
Migrate to using .ng-dev directory for ng-dev configuration to allow
better management of the configuration using multiple files.  The
intention is to prevent the config file from becoming unruly.

PR Close #37299
2020-05-28 15:18:20 -07:00
d493a83b2b docs(platform-server): fix renderModule usage guidance with Ivy (#37296)
Before the introduction of the Ivy renderer, users would compile
their applications and use the resulting factories for SSR, since
these post-compilation artifacts ensured faster delivery. Thus,
using the original module as the rendering entrypoint was
considered suboptimal and was discouraged.

However, with the introduction of Ivy, this guidance is no longer
applicable since these factories are no longer generated.
Comparable speed is achieved using the factory-less module
renderer, and so we update the guiance in the docs for the method.

PR Close #37296
2020-05-28 16:07:32 -04:00
f1721d5cef build: update requiredBaseCommit for patch branch merges (#37316)
Updates the requiredBaseCommit for merging to patch branch to the
latest commit message validation fix found in the 10.0.x branch.

Previously, the patch branch commit used was for the 9.1.x branch.

PR Close #37316
2020-05-28 16:06:08 -04:00
5b3fd6aa82 docs: add IE mobile to deprecated browsers (#37313)
Mobile versions of IE should also be deprecated, as the same reasons for deprecating IE 9 and 10 apply.

PR Close #37313
2020-05-27 17:23:18 -04:00
6f829180f7 build: update license headers to reference Google LLC (#37205)
Update the license headers throughout the repository to reference Google LLC
rather than Google Inc, for the required license headers.

PR Close #37205
2020-05-26 14:27:01 -04:00
27b95ba64a build: Update file-header lint rule to Google LLC (#37205)
Update the file-header lint rule to properly reference Google LLC
rather than Google Inc, for the required headers.

PR Close #37205
2020-05-26 14:27:01 -04:00
ef405b1e90 build: deprecate old merge script (#37247)
Deprecate the old merge script as it no longer correctly chooses
the patch branch due to relying on numerical sorting order from
git.  Git actually provides a lexicographical sorting order.  This
that 9.0.x will be chosen rather than 10.0.x as it is sorted based
the 9 vs 1, rather than 9 vs 10.

PR Close #37247
2020-05-26 14:25:44 -04:00
441073bad5 feat(dev-infra): expose script for determining merge branches (#37217)
The components repo and framework repository follow the same patch
branch concept. We should be able to share a script for determining
these merge branches.

Additonally the logic has been improved compared to the old merge script because
we no longer consult `git ls-remote` unless really needed. Currently,
`git ls-remote` is always consulted, even though not necessarily needed.

This can slow down the merge script and the caretaker process when a
couple of PRs are merged (personally saw around ~4 seconds per merge).

Additionally, the new logic is more strict and will ensure (in most
cases) that no wrong patch/minor branch is determined. Previously,
the script just used the lexicographically greatest patch branch.
This _could_ be wrong when a new patch branch has been created too
early, or by accident.

PR Close #37217
2020-05-21 10:38:19 -07:00
4637 changed files with 54956 additions and 61767 deletions

View File

@ -1,3 +1,3 @@
2.1.1
3.2.0
# [NB: this comment has to be after the first line, see https://github.com/bazelbuild/bazelisk/issues/117]
# When updating the Bazel version you also need to update the RBE toolchains version in package.bzl

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

@ -67,9 +67,6 @@ var_10: &only_on_master
# **NOTE 1**: Pin to exact images using an ID (SHA). See https://circleci.com/docs/2.0/circleci-images/#using-a-docker-image-id-to-pin-an-image-to-a-fixed-version.
# (Using the tag in not necessary when pinning by ID, but include it anyway for documentation purposes.)
# **NOTE 2**: If you change the version of the docker images, also change the `cache_key` suffix.
# **NOTE 3**: If you change the version of the `*-browsers` docker image, make sure the
# `--versions.chrome` arg in `integration/bazel-schematics/test.sh` specifies a
# ChromeDriver version that is compatible with the Chrome version in the image.
executors:
default-executor:
parameters:
@ -120,7 +117,7 @@ commands:
sudo apt-get update
# Install GTK+ graphical user interface (libgtk-3-0), advanced linux sound architecture (libasound2)
# and network security service libraries (libnss3) & X11 Screen Saver extension library (libssx1)
# which are dependendies of chrome & needed for karma & protractor headless chrome tests.
# which are dependencies of chrome & needed for karma & protractor headless chrome tests.
# This is a very small install which takes around 7s in comparing to using the full
# circleci/node:x.x.x-browsers image.
sudo apt-get -y install libgtk-3-0 libasound2 libnss3 libxss1
@ -163,7 +160,7 @@ commands:
description: Sets up a domain that resolves to the local host.
steps:
- run:
name: Preparing environment for running tests on Saucelabs.
name: Preparing environment for running tests on Sauce Labs.
command: |
# For SauceLabs jobs, we set up a domain which resolves to the machine which launched
# the tunnel. We do this because devices are sometimes not able to properly resolve
@ -175,13 +172,13 @@ commands:
setSecretVar SAUCE_ACCESS_KEY $(echo $SAUCE_ACCESS_KEY | rev)
- run:
# Sets up a local domain in the machine's host file that resolves to the local
# host. This domain is helpful in Saucelabs tests where devices are not able to
# host. This domain is helpful in Sauce Labs tests where devices are not able to
# properly resolve `localhost` or `127.0.0.1` through the sauce-connect tunnel.
name: Setting up alias domain for local host.
command: echo "127.0.0.1 $SAUCE_LOCALHOST_ALIAS_DOMAIN" | sudo tee -a /etc/hosts
# Normally this would be an individual job instead of a command.
# But startup and setup time for each invidual windows job are high enough to discourage
# But startup and setup time for each individual windows job are high enough to discourage
# many small jobs, so instead we use a command for setup unless the gain becomes significant.
setup_win:
description: Setup windows node environment
@ -599,8 +596,8 @@ jobs:
- run:
name: Decrypt github credentials
# We need ensure that the same default digest is used for encoding and decoding with
# openssl. Openssl versions might have different default digests which can cause
# decryption failures based on the installed openssl version. https://stackoverflow.com/a/39641378/4317734
# OpenSSL. OpenSSL versions might have different default digests which can cause
# decryption failures based on the installed OpenSSL version. https://stackoverflow.com/a/39641378/4317734
command: 'openssl aes-256-cbc -d -in .circleci/github_token -md md5 -k "${KEY}" -out ~/.git_credentials'
- run: ./scripts/ci/publish-build-artifacts.sh

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));
});
}

View File

@ -32,13 +32,13 @@ Existing issues often contain information about workarounds, resolution, or prog
## 🔬 Minimal Reproduction
<!--
Please create and share minimal reproduction of the issue starting with this template: https://stackblitz.com/fork/angular-issue-repro2
Please create and share minimal reproduction of the issue starting with this template: https://stackblitz.com/fork/angular-ivy
-->
<!-- ✍️--> https://stackblitz.com/...
<!--
If StackBlitz is not suitable for reproduction of your issue, please create a minimal GitHub repository with the reproduction of the issue.
A good way to make a minimal reproduction is to create a new app via `ng new repro-app` and add the minimum possible code to show the problem.
A good way to make a minimal reproduction is to create a new app via `ng new repro-app` and add the minimum possible code to show the problem.
Share the link to the repo below along with step-by-step instructions to reproduce the problem, as well as expected and actual behavior.
Issues that don't have enough info and can't be reproduced will be closed.

View File

@ -1,11 +1,10 @@
import {exec} from 'shelljs';
import {MergeConfig} from './dev-infra/pr/merge/config';
import {MergeConfig} from '../dev-infra/pr/merge/config';
// The configuration for `ng-dev commit-message` commands.
const commitMessage = {
'maxLength': 120,
'minBodyLength': 100,
'minBodyLengthExcludes': ['docs'],
'types': [
'build',
'ci',
@ -34,6 +33,7 @@ const commitMessage = {
'http',
'language-service',
'localize',
'migrations',
'ngcc',
'packaging',
'platform-browser',
@ -53,24 +53,16 @@ const commitMessage = {
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',
'**/*.{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
@ -82,33 +74,11 @@ const github = {
name: 'angular',
};
/**
* Gets the name of the current patch branch. The patch branch is determined by
* looking for upstream branches that follow the format of `{major}.{minor}.x`.
*/
const getPatchBranchName = (): string => {
const branches =
exec(
`git ls-remote --heads https://github.com/${github.owner}/${github.name}.git`,
{silent: true})
.trim()
.split('\n');
for (let i = branches.length - 1; i >= 0; i--) {
const branchName = branches[i];
const matches = branchName.match(/refs\/heads\/([0-9]+\.[0-9]+\.x)/);
if (matches !== null) {
return matches[1];
}
}
throw Error('Could not determine patch branch name.');
};
// 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 = () => {
const patchBranch = getPatchBranchName();
// TODO: resume dynamically determining patch branch
const patch = '10.0.x';
const config: MergeConfig = {
githubApiMerge: false,
claSignedLabel: 'cla: yes',
@ -121,18 +91,19 @@ const merge = () => {
},
{
pattern: 'PR target: patch-only',
branches: [patchBranch],
branches: [patch],
},
{
pattern: 'PR target: master & patch',
branches: ['master', patchBranch],
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.
'master': '4341743b4a6d7e23c6f944aa9e34166b701369a1',
[patchBranch]: '2a53f471592f424538802907aca1f60f1177a86d'
// These SHAs are the commits that update the required license text in the header.
'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a',
[patch]: '27b95ba64a5d99757f4042073fd1860e20e3ed24'
},
};
return config;

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.
####################################################################################
@ -80,8 +47,8 @@
# Used for approving minor changes, large-scale refactorings, and in emergency situations.
#
# IgorMinar
# jelbourn
# josephperrott
# kara
# mhevery
#
# =========================================================
@ -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
@ -203,13 +229,13 @@ groups:
- alxhub
- AndrewKushnir
- JoostK
- kara
# =========================================================
# Framework: Compiler / ngcc
# =========================================================
fw-ngcc:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -226,6 +252,7 @@ groups:
# Framework: Migrations
# =========================================================
fw-migrations:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -235,13 +262,13 @@ groups:
- alxhub
- crisbeto
- devversion
- kara
# =========================================================
# Framework: Core
# =========================================================
fw-core:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -352,7 +379,7 @@ groups:
- alxhub
- AndrewKushnir
- atscott
- kara
- ~kara # do not request reviews from Kara, but allow her to approve PRs
- mhevery
- pkozlowski-opensource
@ -361,6 +388,7 @@ groups:
# Framework: Http
# =========================================================
fw-http:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -382,6 +410,7 @@ groups:
# Framework: Elements
# =========================================================
fw-elements:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -402,6 +431,7 @@ groups:
# Framework: Forms
# =========================================================
fw-forms:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -434,6 +464,7 @@ groups:
# Framework: i18n
# =========================================================
fw-i18n:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -467,6 +498,7 @@ groups:
# Framework: Platform Server
# =========================================================
fw-platform-server:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -486,6 +518,7 @@ groups:
# Framework: Router
# =========================================================
fw-router:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -508,6 +541,7 @@ groups:
# Framework: Service Worker
# =========================================================
fw-service-worker:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -535,6 +569,7 @@ groups:
# Framework: Upgrade
# =========================================================
fw-upgrade:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -565,6 +600,7 @@ groups:
# Framework: Testing
# =========================================================
fw-testing:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -579,7 +615,6 @@ groups:
users:
- AndrewKushnir
- IgorMinar
- kara
- pkozlowski-opensource
@ -587,6 +622,7 @@ groups:
# Framework: Benchmarks
# =========================================================
fw-benchmarks:
<<: *defaults
conditions:
- *can-be-global-approved
- >
@ -596,7 +632,6 @@ groups:
reviewers:
users:
- IgorMinar
- kara
- pkozlowski-opensource
@ -604,6 +639,7 @@ groups:
# Framework: Playground
# =========================================================
fw-playground:
<<: *defaults
conditions:
- *can-be-global-approved
- >
@ -613,13 +649,15 @@ groups:
reviewers:
users:
- IgorMinar
- kara
- jelbourn
- pkozlowski-opensource
# =========================================================
# Framework: Security
# =========================================================
fw-security:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -637,18 +675,25 @@ groups:
users:
- IgorMinar
- mhevery
- jelbourn
- pkozlowski-opensource
reviews:
request: -1 # request reviews from everyone
required: 2 # require at least 2 approvals
reviewed_for: required
# =========================================================
# Bazel
# =========================================================
bazel:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'packages/bazel/**',
'aio/content/guide/bazel.md'
])
reviewers:
users:
@ -661,6 +706,7 @@ groups:
# Language Service
# =========================================================
language-service:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -680,6 +726,7 @@ groups:
# zone.js
# =========================================================
zone-js:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -698,6 +745,7 @@ groups:
# Benchpress
# =========================================================
benchpress:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -708,12 +756,14 @@ groups:
reviewers:
users:
- alxhub
- josephperrott
# =========================================================
# Integration Tests
# =========================================================
integration-tests:
<<: *defaults
conditions:
- *can-be-global-approved
- >
@ -724,7 +774,6 @@ groups:
users:
- IgorMinar
- josephperrott
- kara
- mhevery
@ -732,6 +781,7 @@ groups:
# Docs: Gettings Started & Tutorial
# =========================================================
docs-getting-started-and-tutorial:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -764,6 +814,7 @@ groups:
# Docs: Marketing
# =========================================================
docs-marketing:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -786,6 +837,7 @@ groups:
# Docs: Observables
# =========================================================
docs-observables:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -811,6 +863,7 @@ groups:
# Docs: Packaging, Tooling, Releasing
# =========================================================
docs-packaging-and-releasing:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -830,20 +883,47 @@ 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'
])
reviewers:
users:
- IgorMinar
- kara
- jelbourn
# =========================================================
# Tooling: Compiler API shared with Angular CLI
#
# Changing this API might break Angular CLI, so we require
# the CLI team to approve changes here.
# =========================================================
tooling-cli-shared-api:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'packages/compiler-cli/src/tooling.ts'
])
reviewers:
users:
- alan-agius4
- clydin
- kyliau
- IgorMinar
reviews:
request: -1 # request reviews from everyone
required: 2 # require at least 2 approvals
reviewed_for: required
# =========================================================
# Docs: CLI
# =========================================================
docs-cli:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -860,8 +940,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:
@ -874,6 +958,7 @@ groups:
# Docs: CLI Libraries
# =========================================================
docs-libraries:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -894,6 +979,7 @@ groups:
# Docs: Schematics
# =========================================================
docs-schematics:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -916,6 +1002,7 @@ groups:
# Docs-infra
# =========================================================
docs-infra:
<<: *defaults
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
@ -945,14 +1032,16 @@ 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/**',
'.github/**',
'.ng-dev/**',
'.vscode/**',
'.yarn/**',
'dev-infra/**',
@ -968,8 +1057,6 @@ groups:
'docs/TOOLS.md',
'docs/TRIAGE_AND_LABELS.md',
'goldens/*',
'modules/e2e_util/e2e_util.ts',
'modules/e2e_util/perf_util.ts',
'modules/*',
'packages/*',
'packages/examples/test-utils/**',
@ -977,15 +1064,10 @@ groups:
'packages/examples/*',
'scripts/**',
'third_party/**',
'tools/brotli-cli/**',
'tools/browsers/**',
'tools/build/**',
'tools/circular_dependency_test/**',
'tools/contributing-stats/**',
'tools/components/**',
'tools/gulp-tasks/**',
'tools/ng_rollup_bundle/**',
'tools/ngcontainer/**',
'tools/npm/**',
'tools/npm_integration_test/**',
'tools/rxjs/**',
@ -1015,6 +1097,7 @@ groups:
# Public API
# =========================================================
public-api:
<<: *defaults
conditions:
- *can-be-global-approved
- >
@ -1029,14 +1112,21 @@ groups:
])
reviewers:
users:
- alxhub
- IgorMinar
- kara
- jelbourn
- pkozlowski-opensource
reviews:
request: -1 # request reviews from everyone
required: 3 # require at least 3 approvals
reviewed_for: required
# ================================================
# Size tracking
# ================================================
size-tracking:
<<: *defaults
conditions:
- *can-be-global-approved
- >
@ -1045,14 +1135,21 @@ groups:
])
reviewers:
users:
- alxhub
- IgorMinar
- kara
- jelbourn
- pkozlowski-opensource
reviews:
request: -1 # request reviews from everyone
required: 2 # require at least 2 approvals
reviewed_for: required
# ================================================
# Circular dependencies
# ================================================
circular-dependencies:
<<: *defaults
conditions:
- *can-be-global-approved
- >
@ -1062,8 +1159,9 @@ groups:
reviewers:
users:
- IgorMinar
- jelbourn
- josephperrott
- kara
- pkozlowski-opensource
####################################################################################
@ -1074,6 +1172,7 @@ groups:
# Code Ownership
# =========================================================
code-ownership:
<<: *defaults
conditions:
- *can-be-global-approved
- >
@ -1089,12 +1188,33 @@ 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.
#
# The PullApprove CI check should fail if a PR has no `active` groups, as
# this indicates the PR is modifying a file that has no owner.
#
# This is enforced through the pullapprove verification check done
# as part of the CircleCI lint job. Failures in this lint job should be
# fixed as part of the PR. This can be done by updating the
# `.pullapprove.yml` file cover the unmatched path.
# The pullapprove verification script is part of the ng-dev tool and can be
# run locally with the command: `yarn -s ng-dev pullapprove verify`
#
# For cases in which the verification check fails to ensure coverage, this
# group will be active. The expectation is that this should be remedied
# before merging the PR as described above. In an emergency situation
# `global-approvers` can still approve PRs that match this `fallback` rule,
# but that should be an exception and not an expectation.
conditions:
- *can-be-global-approved
# Groups which are found to have matching conditions are `active`
# according to PullApprove. If no groups are matched and considered
# active, we still want to have a review occur.
- len(groups.active) == 0
reviewers:
users:
- IgorMinar
# The following groups have no conditions and will be `active` on all PRs
# - `global-approvers`
# - `global-docs-approvers`
#
# Since this means the minimum number of active groups a PR can have is 2, this
# `fallback` group should be matched anytime the number of active groups is at or
# below this minimum. This work as a protection to ensure that pullapprove does
# not incidently mark a PR as passing without meeting the review criteria.
- len(groups.active) <= 2

View File

@ -2,7 +2,6 @@ package(default_visibility = ["//visibility:public"])
exports_files([
"LICENSE",
"protractor-perf.conf.js",
"karma-js.conf.js",
"browser-providers.conf.js",
"scripts/ci/track-payload-size.sh",
@ -25,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

@ -22,7 +22,7 @@ Do not open issues for general support questions as we want to keep GitHub issue
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.
@ -42,7 +42,9 @@ Please consider what kind of change it is:
* 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.
and help you to craft the change so that it is successfully accepted into the project. **Note**:
Adding a new topic to the documentation, or significantly re-writing a topic, counts as a major
feature.
* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
## <a name="submit"></a> Submission Guidelines
@ -55,7 +57,7 @@ We want to fix all the issues as soon as possible, but before fixing a bug we ne
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 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.
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.
@ -68,7 +70,7 @@ 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.
Discussing the design upfront helps to ensure that we're ready to accept your work.
1. Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
We cannot accept code without this. Make sure you sign with the primary email address of the Git identity that has been granted access to the Angular repository.
1. Fork the angular/angular repo.
@ -83,8 +85,7 @@ Before you submit your Pull Request (PR) consider the following guidelines:
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.
[commit message conventions](#commit). Adherence to these conventions is necessary because release notes are automatically generated from these messages.
```shell
git commit -a
@ -179,13 +180,13 @@ Samples: (even more [samples](https://github.com/angular/angular/commits/master)
docs(changelog): update changelog to beta.5
```
```
fix(release): need to depend on latest rxjs and zone.js
fix(release): need to depend on the latest rxjs and zone.js
The version in our package.json gets copied to the one we publish, and users need the latest of these.
```
### 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.
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.
### Type
Must be one of the following:
@ -236,6 +237,7 @@ There are currently a few exceptions to the "use package name" rule:
* **docs-infra**: used for docs-app (angular.io) related changes within the /aio directory of the
repo
* **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
@ -279,7 +281,7 @@ changes to be accepted, the CLA must be signed. It's a quick process, we promise
* 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.
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>

View File

@ -8,8 +8,8 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# Fetch rules_nodejs so we can install our npm dependencies
http_archive(
name = "build_bazel_rules_nodejs",
sha256 = "f9e7b9f42ae202cc2d2ce6d698ccb49a9f7f7ea572a78fd451696d03ef2ee116",
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/1.6.0/rules_nodejs-1.6.0.tar.gz"],
sha256 = "84abf7ac4234a70924628baa9a73a5a5cbad944c4358cf9abdb4aab29c9a5b77",
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/1.7.0/rules_nodejs-1.7.0.tar.gz"],
)
# Check the rules_nodejs version and download npm dependencies
@ -17,7 +17,7 @@ http_archive(
# assert on that.
load("@build_bazel_rules_nodejs//:index.bzl", "check_rules_nodejs_version", "node_repositories", "yarn_install")
check_rules_nodejs_version(minimum_version_string = "1.6.0")
check_rules_nodejs_version(minimum_version_string = "1.7.0")
# Setup the Node.js toolchain
node_repositories(
@ -64,7 +64,7 @@ load("@io_bazel_rules_webtesting//web:repositories.bzl", "web_test_repositories"
web_test_repositories()
load("//tools/browsers:browser_repositories.bzl", "browser_repositories")
load("//dev-infra/browsers:browser_repositories.bzl", "browser_repositories")
browser_repositories()
@ -91,17 +91,18 @@ rbe_autoconfig(
# Need to specify a base container digest in order to ensure that we can use the checked-in
# platform configurations for the "ubuntu16_04" image. Otherwise the autoconfig rule would
# need to pull the image and run it in order determine the toolchain configuration. See:
# https://github.com/bazelbuild/bazel-toolchains/blob/1.1.2/configs/ubuntu16_04_clang/versions.bzl
base_container_digest = "sha256:1ab40405810effefa0b2f45824d6d608634ccddbf06366760c341ef6fbead011",
# https://github.com/bazelbuild/bazel-toolchains/blob/3.2.0/configs/ubuntu16_04_clang/versions.bzl
base_container_digest = "sha256:5e750dd878df9fcf4e185c6f52b9826090f6e532b097f286913a428290622332",
# Note that if you change the `digest`, you might also need to update the
# `base_container_digest` to make sure marketplace.gcr.io/google/rbe-ubuntu16-04-webtest:<digest>
# and marketplace.gcr.io/google/rbe-ubuntu16-04:<base_container_digest> have
# the same Clang and JDK installed. Clang is needed because of the dependency on
# @com_google_protobuf. Java is needed for the Bazel's test executor Java tool.
digest = "sha256:0b8fa87db4b8e5366717a7164342a029d1348d2feea7ecc4b18c780bc2507059",
digest = "sha256:f743114235a43355bf8324e2ba0fa6a597236fe06f7bc99aaa9ac703631c306b",
env = clang_env(),
registry = "marketplace.gcr.io",
# We can't use the default "ubuntu16_04" RBE image provided by the autoconfig because we need
# a specific Linux kernel that comes with "libx11" in order to run headless browser tests.
repository = "google/rbe-ubuntu16-04-webtest",
use_checked_in_confs = "Force",
)

View File

@ -109,9 +109,3 @@ Options that specify files can be given as absolute paths, or as paths relative
The [ng generate](cli/generate) and [ng add](cli/add) commands take as an argument the artifact or library to be generated or added to the current project.
In addition to any general options, each artifact or library defines its own options in a *schematic*.
Schematic options are supplied to the command in the same format as immediate command options.
### Building with Bazel
Optionally, you can configure the Angular CLI to use [Bazel](https://docs.bazel.build) as the build tool. For more information, see [Building with Bazel](guide/bazel).

View File

@ -3,7 +3,7 @@ import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { AppComponent } from './app.component';
import { HeroFormComponent } from './hero-form/hero-form.component';
@NgModule({

View File

@ -200,13 +200,4 @@
(ngModelChange)="model.name = $event">
TODO: remove this: {{model.name}}
<!-- #enddocregion ngModel-3-->
<hr>
<!-- #docregion ngModelName-2 -->
<input type="text" class="form-control" id="name"
required
[(ngModel)]="model.name" name="name"
#spy>
<br>TODO: remove this: {{spy.className}}
<!-- #enddocregion ngModelName-2 -->
</div>

View File

@ -2,7 +2,7 @@
// #docregion , v1, final
import { Component } from '@angular/core';
import { Hero } from '../hero';
import { Hero } from '../hero';
@Component({
selector: 'app-hero-form',

View File

@ -13,13 +13,13 @@ import { searchUrl } from '../package-search/package-search.service';
/**
* If request is cachable (e.g., package search) and
* If request is cacheable (e.g., package search) and
* response is in cache return the cached response as observable.
* If has 'x-refresh' header that is true,
* then also re-run the package search, using response from next(),
* returning an observable that emits the cached response first.
*
* If not in cache or not cachable,
* If not in cache or not cacheable,
* pass request through to next()
*/
// #docregion v1
@ -28,8 +28,8 @@ export class CachingInterceptor implements HttpInterceptor {
constructor(private cache: RequestCache) {}
intercept(req: HttpRequest<any>, next: HttpHandler) {
// continue if not cachable.
if (!isCachable(req)) { return next.handle(req); }
// continue if not cacheable.
if (!isCacheable(req)) { return next.handle(req); }
const cachedResponse = this.cache.get(req);
// #enddocregion v1
@ -51,11 +51,11 @@ export class CachingInterceptor implements HttpInterceptor {
// #enddocregion v1
/** Is this request cachable? */
function isCachable(req: HttpRequest<any>) {
// Only GET requests are cachable
/** Is this request cacheable? */
function isCacheable(req: HttpRequest<any>) {
// Only GET requests are cacheable
return req.method === 'GET' &&
// Only npm package search is cachable in this app
// Only npm package search is cacheable in this app
-1 < req.url.indexOf(searchUrl);
}

View File

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

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

@ -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

@ -1,122 +0,0 @@
# Building with Bazel
This guide explains how to build and test Angular apps with Bazel.
<div class="alert is-helpful">
This guide assumes you are already familiar with developing and building Angular applications using the [CLI](cli).
It describes features which are part of Angular Labs, and are not considered a stable, supported API.
</div>
## Using Bazel with the Angular CLI
The `@angular/bazel` package provides a builder that allows Angular CLI to use Bazel as the build tool.
To opt-in an existing application, run
```sh
ng add @angular/bazel
```
To use Bazel in a new application, first install `@angular/bazel` globally
```sh
npm install -g @angular/bazel
```
then create the new application with
```sh
ng new --collection=@angular/bazel
```
Now when you use Angular CLI build commands such as `ng build` and `ng serve`,
Bazel is used behind the scenes.
Outputs from Bazel appear in the `dist/bin` folder.
> The command-line output includes extra logging from Bazel.
> We plan to reduce this in the future.
### Removing Bazel
If you need to opt-out from using Bazel, you can restore the backup files:
- `/angular.json.bak` replaces `/angular.json`
## Advanced configuration
<div class="alert is-helpful">
Editing the Bazel configuration may prevent you opting out of Bazel.
Custom behaviors driven by Bazel won't be available in other Builders.
This section assumes you are familiar with [Bazel](https://docs.bazel.build).
</div>
You can manually adjust the Bazel configuration to:
* customize the build steps
* parallellize the build for scale and incrementality
Create the initial Bazel configuration files by running the following command:
```sh
ng build --leaveBazelFilesOnDisk
```
Now you'll find new files in the Angular workspace:
* `/WORKSPACE` tells Bazel how to download external dependencies.
* `/BUILD.bazel` and `/src/BUILD.bazel` tell Bazel about your source code.
You can find a full-featured example with custom Bazel configurations at https://github.com/bazelbuild/rules_nodejs/tree/master/examples/angular.
Documentation for using Bazel for frontend projects is linked from https://docs.bazel.build/versions/master/bazel-and-javascript.html.
## Running Bazel directly
In some cases you'll want to bypass the Angular CLI builder, and run the Bazel CLI directly.
The Bazel tool is managed by the `@bazel/bazelisk` package (similar to how Node.js can be managed by `nvm`).
You can install it globally to get the `bazelisk` command in your path, or use `$(npm bin)/bazelisk` in place of bazelisk below.
The common commands in Bazel are:
* `bazelisk build [targets]`: Compile the default output artifacts of the given targets.
* `bazelisk test [targets]`: For whichever `*_test` targets are found in the patterns, run the tests.
* `bazelisk run [target]`: Compile the program represented by target, and then run it.
To repeat the command any time the inputs change (watch mode), replace `bazelisk` with `ibazel` in these commands.
The output locations are printed in the output.
Full documentation for the Bazel CLI is at https://docs.bazel.build/versions/master/command-line-reference.html.
## Querying the build graph
Because Bazel constructs a graph out of your targets, you can find lots of useful information.
Using the graphviz optional dependency, you'll have a program `dot`, which you can use with `bazel query`:
```bash
$ bazel query --output=graph ... | dot -Tpng > graph.png
```
See https://docs.bazel.build/versions/master/query-how-to.html for more details on `bazel query`.
## Customizing `BUILD.bazel` files
"Rules" are like plugins for Bazel. Many rule sets are available. This guide documents the ones maintained by the Angular team at Google.
Rules are used in `BUILD.bazel` files, which are markers for the packages in your workspace. Each `BUILD.bazel` file declares a separate package to Bazel, though you can have more coarse-grained distributions so that the packages you publish (for example, to `npm`) can be made up of many Bazel packages.
In the `BUILD.bazel` file, each rule must first be imported, using the `load` statement. Then the rule is called with some attributes, and the result of calling the rule is that you've declared to Bazel how it can derive some outputs given some inputs and dependencies. Then later, when you run a `bazel` command line, Bazel loads all the rules you've declared to determine an absolute ordering of what needs to be run. Note that only the rules needed to produce the requested output will actually be executed.
A list of common rules for frontend development is documented in the README at https://github.com/bazelbuild/rules_nodejs/.

View File

@ -54,16 +54,17 @@ Angular supports most recent browsers. This includes the following specific vers
</td>
<td>
<div> 11, 10*, 9* ("compatibility view" mode not supported) </div>
<div>*deprecated in v10, see the <a href="/guide/deprecations#ie-9-10">deprecations guide</a>.</div>
<div>*deprecated in v10, see the {@link guide/deprecations#ie-9-10-and-mobile deprecations guide}.</div>
</td>
</tr>
<tr>
<tr>
<td>
IE Mobile
IE Mobile*
</td>
<td>
11
<div>*deprecated in v10, see the {@link guide/deprecations#ie-9-10-and-mobile deprecations guide}.</div>
</td>
</tr>
<tr>

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

@ -109,7 +109,9 @@ To learn more, see [Schematics Overview](guide/schematics) and [Schematicsfor
## Publishing your library
Use the Angular CLI and the npm package manager to build and publish your library as an npm package. It is not recommended to publish Ivy libraries to NPM repositories. Before publishing a library to NPM, build it using the `--prod` flag which will use the older compiler and runtime known as View Engine instead of Ivy.
Use the Angular CLI and the npm package manager to build and publish your library as an npm package.
Before publishing a library to NPM, build it using the `--prod` flag which will use the older compiler and runtime known as View Engine instead of Ivy.
<code-example language="bash">
ng build my-lib --prod
@ -119,6 +121,14 @@ npm publish
If you've never published a package in npm before, you must create a user account. Read more in [Publishing npm Packages](https://docs.npmjs.com/getting-started/publishing-npm-packages).
<div class="alert is-important">
For now, it is not recommended to publish Ivy libraries to NPM because Ivy generated code is not backward compatible with View Engine, so apps using View Engine will not be able to consume them. Furthermore, the internal Ivy instructions are not yet stable, which can potentially break consumers using a different Angular version from the one used to build the library.
When a published library is used in an Ivy app, the Angular CLI will automatically convert it to Ivy using a tool known as the Angular compatibility compiler (`ngcc`). Thus, by publishing your libraries using the View Engine compiler ensures that they can be transparently consumed by both View Engine and Ivy apps.
</div>
{@a lib-assets}
## Managing assets in a library

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

@ -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

@ -35,6 +35,7 @@ v9 - v12
| Area | API or Feature | May be removed in |
| ----------------------------- | --------------------------------------------------------------------------- | ----------------- |
| `@angular/bazel` | [`Bazel builder and schematics`](#bazelbuilder) | v10 |
| `@angular/common` | [`ReflectiveInjector`](#reflectiveinjector) | <!--v8--> v11 |
| `@angular/common` | [`CurrencyPipe` - `DEFAULT_CURRENCY_CODE`](api/common/CurrencyPipe#currency-code-deprecation) | <!--v9--> v11 |
| `@angular/core` | [`CollectionChangeRecord`](#core) | <!--v7--> v11 |
@ -59,7 +60,7 @@ v9 - v12
| `@angular/core/testing` | [`TestBed.get`](#testing) | <!--v9--> v12 |
| `@angular/router` | [`ActivatedRoute` params and `queryParams` properties](#activatedroute-props) | unspecified |
| template syntax | [`/deep/`, `>>>`, and `::ng-deep`](#deep-component-style-selector) | <!--v7--> unspecified |
| browser support | [`IE 9 and 10`](#ie-9-10) | <!--v10--> v11 |
| browser support | [`IE 9 and 10, IE mobile`](#ie-9-10-and-mobile) | <!--v10--> v11 |
@ -160,7 +161,11 @@ Tip: In the [API reference section](api) of this doc site, deprecated APIs are i
This section lists all of the currently-deprecated features, which includes template syntax, configuration options, and any other deprecations not listed in the [Deprecated APIs](#deprecated-apis) section above. It also includes deprecated API usage scenarios or API combinations, to augment the information above.
{@a bazelbuilder}
### Bazel builder and schematics
Bazel builder and schematics were introduced in Angular Labs to let users try out Bazel without having to manage Bazel version and BUILD files.
This feature has been deprecated. For more information, please refer to the [migration doc](https://github.com/angular/angular/blob/master/packages/bazel/src/schematics/README.md).
{@a wtf}
### Web Tracing Framework integration
@ -459,17 +464,17 @@ export class MyModule {
```
{@a ie-9-10}
### IE 9 and 10 support
{@a ie-9-10-and-mobile}
### IE 9, 10, and IE mobile support
Support for IE 9 and 10 has been deprecated and will be removed in a future version.
Support for IE 9 and 10 has been deprecated, as well as support for IE Mobile. These will be dropped in a future version.
Supporting outdated browsers like these increases bundle size, code complexity, and test load, and also requires time and effort that could be spent on improvements to the framework.
For example, fixing issues can be more difficult, as a straightforward fix for modern browsers could break old ones that have quirks due to not receiving updates from vendors.
The final decision was made on three key points:
* __Vendor support__: Microsoft dropped support of IE 9 and 10 on 1/12/16, meaning they no longer provide security updates or technical support.
* __Usage statistics__: We looked at usage trends for IE 9 and 10 from various sources and all indicated that usage percentages were extremely small (fractions of 1%).
* __Feedback from partners__: We also reached out to some of our Angular customers and none expressed concern about dropping IE 9 and 10 support.
* __Vendor support__: Microsoft dropped support of IE 9 and 10 on 1/12/16, meaning they no longer provide security updates or technical support. Additionally, Microsoft dropped support for Windows 10 Mobile in December 2019.
* __Usage statistics__: We looked at usage trends for IE 9 and 10 (as well as IE Mobile) from various sources and all indicated that usage percentages were extremely small (fractions of 1%).
* __Feedback from partners__: We also reached out to some of our Angular customers and none expressed concern about dropping IE 9, 10, nor IE Mobile support.
{@a wrapped-value}
@ -485,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

@ -931,7 +931,7 @@ If you do, be sure to set the `id` attribute - not the `name` attribute! The doc
</div>
## Alerts and Calllouts
## Alerts and Callouts
Alerts and callouts present warnings, extra detail or references to other pages. They can also be used to provide commentary that _enriches_ the reader's understanding of the content being presented.

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).

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

@ -4,22 +4,27 @@ Handling user input with forms is the cornerstone of many common applications. A
Angular provides two different approaches to handling user input through forms: reactive and template-driven. Both capture user input events from the view, validate the user input, create a form model and data model to update, and provide a way to track changes.
Reactive and template-driven forms process and manage form data differently. Each offers different advantages.
**In general:**
* **Reactive forms** are more robust: they're more scalable, reusable, and testable. If forms are a key part of your application, or you're already using reactive patterns for building your application, use reactive forms.
* **Template-driven forms** are useful for adding a simple form to an app, such as an email list signup form. They're easy to add to an app, but they don't scale as well as reactive forms. If you have very basic form requirements and logic that can be managed solely in the template, use template-driven forms.
This guide provides information to help you decide which type of form works best for your situation. It introduces the common building blocks used by both approaches. It also summarizes the key differences between the two approaches, and demonstrates those differences in the context of setup, data flow, and testing.
<div class="alert is-helpful">
## Prerequisites
**Note:** For complete information about each kind of form, see [Reactive Forms](guide/reactive-forms) and [Template-driven Forms](guide/forms).
This guide assumes that you have a basic understanding of the following.
</div>
* [TypeScript](https://www.typescriptlang.org/docs/home.html "The TypeScript language") and HTML5 programming.
## Key differences
* Angular app-design fundamentals, as described in [Angular Concepts](guide/architecture "Introduction to Angular concepts.").
* The basics of [Angular template syntax](guide/architecture-components#template-syntax "Template syntax intro").
## Choosing an approach
Reactive forms and template-driven forms process and manage form data differently. Each approach offers different advantages.
* **Reactive forms** provide direct, explicit access to the underlying forms object model. Compared to template-driven forms, they are more robust: they're more scalable, reusable, and testable. If forms are a key part of your application, or you're already using reactive patterns for building your application, use reactive forms.
* **Template-driven forms** rely on directives in the template to create and manipulate the underlying object model. They are useful for adding a simple form to an app, such as an email list signup form. They're easy to add to an app, but they don't scale as well as reactive forms. If you have very basic form requirements and logic that can be managed solely in the template, template-driven forms could be a good fit.
### Key differences
The table below summarizes the key differences between reactive and template-driven forms.
@ -30,17 +35,33 @@ The table below summarizes the key differences between reactive and template-dri
||Reactive|Template-driven|
|--- |--- |--- |
|Setup (form model)|More explicit, created in component class|Less explicit, created by directives|
|Data model|Structured|Unstructured|
|Predictability|Synchronous|Asynchronous|
|Form validation|Functions|Directives|
|Mutability|Immutable|Mutable|
|Scalability|Low-level API access|Abstraction on top of APIs|
|[Setup of form model](#setup) | Explicit, created in component class | Implicit, created by directives |
|[Data model](#data-flow-in-forms) | Structured and immutable | Unstructured and mutable |
|Predictability | Synchronous | Asynchronous |
|[Form validation](#validation) | Functions | Directives |
## Common foundation
### Scalability
Both reactive and template-driven forms share underlying building blocks.
If forms are a central part of your application, scalability is very important. Being able to reuse form models across components is critical.
Reactive forms are more scalable than template-driven forms. They provide direct access to the underlying form API, and synchronous access to the form data model, making creating large-scale forms easier.
Reactive forms require less setup for testing, and testing does not require deep understanding of change detection to properly test form updates and validation.
Template-driven forms focus on simple scenarios and are not as reusable.
They abstract away the underlying form API, and provide only asynchronous access to the form data model.
The abstraction of template-driven forms also affects testing.
Tests are deeply reliant on manual change detection execution to run properly, and require more setup.
{@a setup}
## Setting up the form model
Both reactive and template-driven forms track value changes between the form input elements that users interact with and the form data in your component model.
The two approaches share underlying building blocks, but differ in how you create and manage the common form-control instances.
### Common form foundation classes
Both reactive and template-driven forms are built on the following base classes.
* `FormControl` tracks the value and validation status of an individual form control.
@ -50,59 +71,59 @@ Both reactive and template-driven forms share underlying building blocks.
* `ControlValueAccessor` creates a bridge between Angular `FormControl` instances and native DOM elements.
See the [Form model setup](#setup-the-form-model) section below for an introduction to how these control instances are created and managed with reactive and template-driven forms. Further details are provided in the [data flow section](#data-flow-in-forms) of this guide.
{@a setup-the-form-model}
## Form model setup
Reactive and template-driven forms both use a form model to track value changes between Angular forms and form input elements. The examples below show how the form model is defined and created.
### Setup in reactive forms
Here's a component with an input field for a single control implemented using reactive forms.
With reactive forms, you define the form model directly in the component class.
The `[formControl]` directive links the explicitly created `FormControl` instance to a specific form element in the view, using an internal value accessor.
The following component implements an input field for a single control, using reactive forms. In this example, the form model is the `FormControl` instance.
<code-example path="forms-overview/src/app/reactive/favorite-color/favorite-color.component.ts">
</code-example>
The source of truth provides the value and status of the form element at a given point in time. In reactive forms, the form model is the source of truth. In the example above, the form model is the `FormControl` instance.
Figure 1 shows how, in reactive forms, the form model is the source of truth; it provides the value and status of the form element at any given point in time, through the `[formControl]` directive on the input element.
**Figure 1.** *Direct access to forms model in a reactive form.*
<div class="lightbox">
<img src="generated/images/guide/forms-overview/key-diff-reactive-forms.png" alt="Reactive forms key differences">
</div>
With reactive forms, the form model is explicitly defined in the component class. The reactive form directive (in this case, `FormControlDirective`) then links the existing `FormControl` instance to a specific form element in the view using a value accessor (`ControlValueAccessor` instance).
### Setup in template-driven forms
Here's the same component with an input field for a single control implemented using template-driven forms.
In template-driven forms, the form model is implicit, rather than explicit. The directive `NgModel` creates and manages a `FormControl` instance for a given form element.
The following component implements the same input field for a single control, using template-driven forms.
<code-example path="forms-overview/src/app/template/favorite-color/favorite-color.component.ts">
</code-example>
In template-driven forms, the source of truth is the template.
In a template-driven form the source of truth is the template. You do not have direct programmatic access to the `FormControl` instance, as shown in Figure 2.
**Figure 2.** *Indirect access to forms model in a template-driven form.*
<div class="lightbox">
<img src="generated/images/guide/forms-overview/key-diff-td-forms.png" alt="Template-driven forms key differences">
</div>
The abstraction of the form model promotes simplicity over structure. The template-driven form directive `NgModel` is responsible for creating and managing the `FormControl` instance for a given form element. It's less explicit, but you no longer have direct control over the form model.
{@a data-flow-in-forms}
## Data flow in forms
When building forms in Angular, it's important to understand how the framework handles data flowing from the user or from programmatic changes. Reactive and template-driven forms follow two different strategies when handling form input. The data flow examples below begin with the favorite color input field example from above, and then show how changes to favorite color are handled in reactive forms compared to template-driven forms.
When an application contains a form, Angular must keep the view in sync with the component model and the component model in sync with the view.
As users change values and make selections through the view, the new values must be reflected in the data model.
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.
### Data flow in reactive forms
As described above, in reactive forms each form element in the view is directly linked to a form model (`FormControl` instance). Updates from the view to the model and from the model to the view are synchronous and aren't dependent on the UI rendered. The diagrams below use the same favorite color example to demonstrate how data flows when an input field's value is changed from the view and then from the model.
In reactive forms each form element in the view is directly linked to the form model (a `FormControl` instance). Updates from the view to the model and from the model to the view are synchronous and do not depend on how the UI is rendered.
<div class="lightbox">
<img src="generated/images/guide/forms-overview/dataflow-reactive-forms-vtm.png" alt="Reactive forms data flow - view to model" width="100%">
</div>
The steps below outline the data flow from view to model.
The view-to-model diagram shows how data flows when an input field's value is changed from the view through the following steps.
1. The user types a value into the input element, in this case the favorite color *Blue*.
1. The form input element emits an "input" event with the latest value.
@ -111,25 +132,25 @@ The steps below outline the data flow from view to model.
1. Any subscribers to the `valueChanges` observable receive the new value.
<div class="lightbox">
<img src="generated/images/guide/forms-overview/dataflow-reactive-forms-mtv.png" alt="Reactive forms data flow - model to view" width="100%">
<img src="generated/images/guide/forms-overview/dataflow-reactive-forms-vtm.png" alt="Reactive forms data flow - view to model">
</div>
The steps below outline the data flow from model to view.
The model-to-view diagram shows how a programmatic change to the model is propagated to the view through the following steps.
1. The user calls the `favoriteColorControl.setValue()` method, which updates the `FormControl` value.
1. The `FormControl` instance emits the new value through the `valueChanges` observable.
1. Any subscribers to the `valueChanges` observable receive the new value.
1. The control value accessor on the form input element updates the element with the new value.
### Data flow in template-driven forms
In template-driven forms, each form element is linked to a directive that manages the form model internally. The diagrams below use the same favorite color example to demonstrate how data flows when an input field's value is changed from the view and then from the model.
<div class="lightbox">
<img src="generated/images/guide/forms-overview/dataflow-td-forms-vtm.png" alt="Template-driven forms data flow - view to model" width="100%">
<img src="generated/images/guide/forms-overview/dataflow-reactive-forms-mtv.png" alt="Reactive forms data flow - model to view">
</div>
The steps below outline the data flow from view to model when the input value changes from *Red* to *Blue*.
### Data flow in template-driven forms
In template-driven forms, each form element is linked to a directive that manages the form model internally.
The view-to-model diagram shows how data flows when an input field's value is changed from the view through the following steps.
1. The user types *Blue* into the input element.
1. The input element emits an "input" event with the value *Blue*.
@ -141,10 +162,10 @@ The steps below outline the data flow from view to model when the input value ch
is updated to the value emitted by the `ngModelChange` event (*Blue*).
<div class="lightbox">
<img src="generated/images/guide/forms-overview/dataflow-td-forms-mtv.png" alt="Template-driven forms data flow - model to view" width="100%">
<img src="generated/images/guide/forms-overview/dataflow-td-forms-vtm.png" alt="Template-driven forms data flow - view to model" width="100%">
</div>
The steps below outline the data flow from model to view when the `favoriteColor` changes from *Blue* to *Red*.
The model-to-view diagram shows how data flows from model to view when the `favoriteColor` changes from *Blue* to *Red*, through the following steps
1. The `favoriteColor` value is updated in the component.
1. Change detection begins.
@ -156,6 +177,30 @@ The steps below outline the data flow from model to view when the `favoriteColor
1. Any subscribers to the `valueChanges` observable receive the new value.
1. The control value accessor updates the form input element in the view with the latest `favoriteColor` value.
<div class="lightbox">
<img src="generated/images/guide/forms-overview/dataflow-td-forms-mtv.png" alt="Template-driven forms data flow - model to view" width="100%">
</div>
### Mutability of the data model
The change-tracking method plays a role in the efficiency of your application.
* **Reactive forms** keep the data model pure by providing it as an immutable data structure.
Each time a change is triggered on the data model, the `FormControl` instance returns a new data model rather than updating the existing data model.
This gives you the ability to track unique changes to the data model through the control's observable.
Change detection is more efficient because it only needs to update on unique changes.
Because data updates follow reactive patterns, you can integrate with observable operators to transform data.
* **Template-driven** forms rely on mutability with two-way data binding to update the data model in the component as changes are made in the template.
Because there are no unique changes to track on the data model when using two-way data binding, change detection is less efficient at determining when updates are required.
The difference is demonstrated in the previous examples that use the favorite-color input element.
* With reactive forms, the **`FormControl` instance** always returns a new value when the control's value is updated.
* With template-driven forms, the **favorite color property** is always modified to its new value.
{@a validation}
## Form validation
Validation is an integral part of managing any set of forms. Whether you're checking for required fields or querying an external API for an existing username, Angular provides a set of built-in validators as well as the ability to create custom validators.
@ -167,36 +212,37 @@ For more information, see [Form Validation](guide/form-validation).
## Testing
Testing plays a large part in complex applications and a simpler testing strategy is useful when validating that your forms function correctly. Reactive forms and template-driven forms have different levels of reliance on rendering the UI to perform assertions based on form control and form field changes. The following examples demonstrate the process of testing forms with reactive and template-driven forms.
Testing plays a large part in complex applications. A simpler testing strategy is useful when validating that your forms function correctly.
Reactive forms and template-driven forms have different levels of reliance on rendering the UI to perform assertions based on form control and form field changes.
The following examples demonstrate the process of testing forms with reactive and template-driven forms.
### Testing reactive forms
Reactive forms provide a relatively easy testing strategy because they provide synchronous access to the form and data models, and they can be tested without rendering the UI. In these tests, status and data are queried and manipulated through the control without interacting with the change detection cycle.
Reactive forms provide a relatively easy testing strategy because they provide synchronous access to the form and data models, and they can be tested without rendering the UI.
In these tests, status and data are queried and manipulated through the control without interacting with the change detection cycle.
The following tests use the favorite color components mentioned earlier to verify the data flows from view to model and model to view for a reactive form.
The following tests use the favorite-color components from previous examples to verify the view-to-model and model-to-view data flows for a reactive form.
The following test verifies the data flow from view to model.
**Verifying view-to-model data flow**
<code-example path="forms-overview/src/app/reactive/favorite-color/favorite-color.component.spec.ts" region="view-to-model" header="Favorite color test - view to model">
</code-example>
Here are the steps performed in the view to model test.
The first example performs the following steps to verify the view-to-model data flow.
1. Query the view for the form input element, and create a custom "input" event for the test.
1. Set the new value for the input to *Red*, and dispatch the "input" event on the form input element.
1. Assert that the component's `favoriteColorControl` value matches the value from the input.
The following test verifies the data flow from model to view.
<code-example path="forms-overview/src/app/reactive/favorite-color/favorite-color.component.spec.ts" region="model-to-view" header="Favorite color test - model to view">
<code-example path="forms-overview/src/app/reactive/favorite-color/favorite-color.component.spec.ts" region="view-to-model" header="Favorite color test - view to model">
</code-example>
Here are the steps performed in the model to view test.
The next example performs the following steps to verify the model-to-view data flow.
1. Use the `favoriteColorControl`, a `FormControl` instance, to set the new value.
1. Query the view for the form input element.
1. Assert that the new value set on the control matches the value in the input.
<code-example path="forms-overview/src/app/reactive/favorite-color/favorite-color.component.spec.ts" region="model-to-view" header="Favorite color test - model to view">
</code-example>
### Testing template-driven forms
Writing tests with template-driven forms requires a detailed knowledge of the change detection process and an understanding of how directives run on each cycle to ensure that elements are queried, tested, or changed at the correct time.
@ -228,46 +274,17 @@ Here are the steps performed in the model to view test.
1. Query the view for the form input element.
1. Assert that the input value matches the value of the `favoriteColor` property in the component instance.
## Mutability
The change tracking method plays a role in the efficiency of your application.
* **Reactive forms** keep the data model pure by providing it as an immutable data structure. Each time a change is triggered on the data model, the `FormControl` instance returns a new data model rather than updating the existing data model. This gives you the ability to track unique changes to the data model through the control's observable. This provides one way for change detection to be more efficient because it only needs to update on unique changes. It also follows reactive patterns that integrate with observable operators to transform data.
* **Template-driven** forms rely on mutability with two-way data binding to update the data model in the component as changes are made in the template. Because there are no unique changes to track on the data model when using two-way data binding, change detection is less efficient at determining when updates are required.
The difference is demonstrated in the examples above using the **favorite color** input element.
* With reactive forms, the **`FormControl` instance** always returns a new value when the control's value is updated.
* With template-driven forms, the **favorite color property** is always modified to its new value.
## Scalability
If forms are a central part of your application, scalability is very important. Being able to reuse form models across components is critical.
* **Reactive forms** provide access to low-level APIs and synchronous access to the form model, making creating large-scale forms easier.
* **Template-driven** forms focus on simple scenarios, are not as reusable, abstract away the low-level APIs, and provide asynchronous access to the form model. The abstraction with template-driven forms also surfaces in testing, where testing reactive forms requires less setup and no dependence on the change detection cycle when updating and validating the form and data models during testing.
## Final thoughts
Choosing a strategy begins with understanding the strengths and weaknesses of the options presented. Low-level API and form model access, predictability, mutability, straightforward validation and testing strategies, and scalability are all important considerations in choosing the infrastructure you use to build your forms in Angular. Template-driven forms are similar to patterns in AngularJS, but they have limitations given the criteria of many modern, large-scale Angular apps. Reactive forms minimize these limitations. Reactive forms integrate with reactive patterns already present in other areas of the Angular architecture, and complement those requirements well.
## Next steps
To learn more about reactive forms, see the following guides:
* [Reactive Forms](guide/reactive-forms)
* [Form Validation](guide/form-validation#reactive-form-validation)
* [Dynamic Forms](guide/dynamic-form)
* [Reactive forms](guide/reactive-forms)
* [Form validation](guide/form-validation#reactive-form-validation)
* [Dynamic forms](guide/dynamic-form)
To learn more about template-driven forms, see the following guides:
* [Template-driven Forms](guide/forms#template-driven-forms)
* [Form Validation](guide/form-validation#template-driven-validation)
* [Building a template-driven form](guide/forms) tutorial
* [Form validation](guide/form-validation#template-driven-validation)
* `NgForm` directive API reference

View File

@ -1,389 +1,234 @@
# Template-driven forms
Forms are the mainstay of business applications.
You use forms to log in, submit a help request, place an order, book a flight,
schedule a meeting, and perform countless other data-entry tasks.
In developing a form, it's important to create a data-entry experience that guides the
user efficiently and effectively through the workflow.
<div class="alert is-helpful">
For the sample app that this page describes, see the <live-example></live-example>.
</div>
## Introduction to Template-driven forms
Developing forms requires design skills (which are out of scope for this page), as well as framework support for
*two-way data binding, change tracking, validation, and error handling*,
which you'll learn about on this page.
This page shows you how to build a simple form from scratch. Along the way you'll learn how to:
* Build an Angular form with a component and template.
* Use `ngModel` to create two-way data bindings for reading and writing input-control values.
* Track state changes and the validity of form controls.
* Provide visual feedback using special CSS classes that track the state of the controls.
* Display validation errors to users and enable/disable form controls.
* Share information across HTML elements using template reference variables.
# Building a template-driven form
{@a template-driven}
You can build forms by writing templates in the Angular [template syntax](guide/template-syntax) with
the form-specific directives and techniques described in this page.
This tutorial shows you how to create a template-driven form whose control elements are bound to data properties, with input validation to maintain data integrity and styling to improve the user experience.
Template-driven forms use [two-way data binding](guide/architecture-components#data-binding "Intro to 2-way data binding") to update the data model in the component as changes are made in the template and vice versa.
<div class="alert is-helpful">
You can also use a reactive (or model-driven) approach to build forms.
However, this page focuses on template-driven forms.
Angular supports two design approaches for interactive forms. You can build forms by writing templates using Angular [template syntax and directives](guide/glossary#template "Definition of template terms") with the form-specific directives and techniques described in this tutorial, or you can use a reactive (or model-driven) approach to build forms.
Template-driven forms are suitable for small or simple forms, while reactive forms are more scalable and suitable for complex forms.
For a comparison of the two approaches, see [Introduction to Forms](guide/forms-overview "Overview of Angular forms.")
</div>
You can build almost any form with an Angular template&mdash;login forms, contact forms, and pretty much any business form.
You can lay out the controls creatively, bind them to data, specify validation rules and display validation errors,
You can build almost any kind of form with an Angular template&mdash;login forms, contact forms, and pretty much any business form.
You can lay out the controls creatively and bind them to the data in your object model.
You can specify validation rules and display validation errors,
conditionally enable or disable specific controls, trigger built-in visual feedback, and much more.
Angular makes the process easy by handling many of the repetitive, boilerplate tasks you'd
otherwise wrestle with yourself.
This tutorial shows you how to build a form from scratch, using a simplified sample form like the one from the [Tour of Heroes tutorial](tutorial "Tour of Heroes") to illustrate the techniques.
You'll learn to build a template-driven form that looks like this:
<div class="alert is-helpful">
Run or download the example app: <live-example></live-example>.
</div>
## Objectives
This tutorial teaches you how to do the following:
* Build an Angular form with a component and template.
* Use `ngModel` to create two-way data bindings for reading and writing input-control values.
* Provide visual feedback using special CSS classes that track the state of the controls.
* Display validation errors to users and enable or disable form controls based on the form status.
* Share information across HTML elements using [template reference variables](guide/template-syntax#template-reference-variables-var).
## Prerequisites
Before going further into template-driven forms, you should have a basic understanding of the following.
* TypeScript and HTML5 programming.
* Angular app-design fundamentals, as described in [Angular Concepts](guide/architecture "Introduction to Angular concepts.").
* The basics of [Angular template syntax](guide/template-syntax "Template syntax guide").
* The form-design concepts that are presented in [Introduction to Forms](guide/forms-overview "Overview of Angular forms.").
{@a intro}
## Build a template-driven form
Template-driven forms rely on directives defined in the `FormsModule`.
* The `NgModel` directive reconciles value changes in the attached form element with changes in the data model, allowing you to respond to user input with input validation and error handling.
* The `NgForm` directive creates a top-level `FormGroup` instance and binds it to a `<form>` element to track aggregated form value and validation status.
As soon as you import `FormsModule`, this directive becomes active by default on all `<form>` tags. You don't need to add a special selector.
* The `NgModelGroup` directive creates and binds a `FormGroup` instance to a DOM element.
### The sample application
The sample form in this guide is used by the *Hero Employment Agency* to maintain personal information about heroes.
Every hero needs a job. This form helps the agency match the right hero with the right crisis.
<div class="lightbox">
<img src="generated/images/guide/forms/hero-form-1.png" alt="Clean Form">
</div>
The *Hero Employment Agency* uses this form to maintain personal information about heroes.
Every hero needs a job. It's the company mission to match the right hero with the right crisis.
The form highlights some design features that make it easier to use. For instance, the two required fields have a green bar on the left to make them easy to spot. These fields have initial values, so the form is valid and the **Submit** button is enabled.
Two of the three fields on this form are required. Required fields have a green bar on the left to make them easy to spot.
If you delete the hero name, the form displays a validation error in an attention-grabbing style:
As you work with this form, you will learn how to include validation logic, how to customize the presentation with standard CSS, and how to handle error conditions to ensure valid input.
If the user deletes the hero name, for example, the form becomes invalid. The app detects the changed status, and displays a validation error in an attention-grabbing style.
In addition, the **Submit** button is disabled, and the "required" bar to the left of the input control changes from green to red.
<div class="lightbox">
<img src="generated/images/guide/forms/hero-form-2.png" alt="Invalid, Name Required">
</div>
Note that the *Submit* button is disabled, and the "required" bar to the left of the input control changes from green to red.
### Step overview
<div class="alert is-helpful">
In the course of this tutorial, you bind a sample form to data and handle user input using the following steps.
You can customize the colors and location of the "required" bar with standard CSS.
1. Build the basic form.
* Define a sample data model.
* Include required infrastructure such as the `FormsModule`.
2. Bind form controls to data properties using the `ngModel` directive and two-way data-binding syntax.
* Examine how `ngModel` reports control states using CSS classes.
* Name controls to make them accessible to `ngModel`.
3. Track input validity and control status using `ngModel`.
* 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.
* Disable the **Submit** button until the form is valid.
* After submit, swap out the finished form for different content on the page.
</div>
{@a step1}
You'll build this form in small steps:
## Build the form
1. Create the `Hero` model class.
1. Create the component that controls the form.
1. Create a template with the initial form layout.
1. Bind data properties to each form control using the `ngModel` two-way data-binding syntax.
1. Add a `name` attribute to each form-input control.
1. Add custom CSS to provide visual feedback.
1. Show and hide validation-error messages.
1. Handle form submission with *ngSubmit*.
1. Disable the forms *Submit* button until the form is valid.
You can recreate the sample application from the code provided here, or you can examine or download the <live-example></live-example>.
## Setup
1. The provided sample application creates the `Hero` class which defines the data model reflected in the form.
Create a new project named <code>angular-forms</code>:
<code-example path="forms/src/app/hero.ts" header="src/app/hero.ts"></code-example>
<code-example language="sh" class="code-shell">
2. The form layout and details are defined in the `HeroFormComponent` class.
ng new angular-forms
<code-example path="forms/src/app/hero-form/hero-form.component.ts" header="src/app/hero-form/hero-form.component.ts (v1)" region="v1"></code-example>
</code-example>
The component's `selector` value of "app-hero-form" means you can drop this form in a parent
template using the `<app-hero-form>` tag.
## Create the Hero model class
3. The following code creates a new hero instance, so that the initial form can show an example hero.
As users enter form data, you'll capture their changes and update an instance of a model.
You can't lay out the form until you know what the model looks like.
<code-example path="forms/src/app/hero-form/hero-form.component.ts" region="SkyDog"></code-example>
A model can be as simple as a "property bag" that holds facts about a thing of application importance.
That describes well the `Hero` class with its three required fields (`id`, `name`, `power`)
and one optional field (`alterEgo`).
This demo uses dummy data for `model` and `powers`. In a real app, you would inject a data service to get and save real data, or expose these properties as inputs and outputs.
Using the Angular CLI command [`ng generate class`](cli/generate), generate a new class named `Hero`:
4. The application enables the Forms feature and registers the created form component.
<code-example language="sh" class="code-shell">
<code-example path="forms/src/app/app.module.ts" header="src/app/app.module.ts"></code-example>
ng generate class Hero
5. The form is displayed in the application layout defined by the root component's template.
</code-example>
<code-example path="forms/src/app/app.component.html" header="src/app/app.component.html"></code-example>
With this content:
The initial template defines the layout for a form with two form groups and a submit button.
The form groups correspond to two properties of the Hero data model, name and alterEgo. Each group has a label and a box for user input.
<code-example path="forms/src/app/hero.ts" header="src/app/hero.ts"></code-example>
* The **Name** `<input>` control element has the HTML5 `required` attribute.
* The **Alter Ego** `<input>` control element does not because `alterEgo` is optional.
It's an anemic model with few requirements and no behavior. Perfect for the demo.
The **Submit** button has some classes on it for styling.
At this point, the form layout is all plain HTML5, with no bindings or directives.
The TypeScript compiler generates a public field for each `public` constructor parameter and
automatically assigns the parameters value to that field when you create heroes.
6. The sample form uses some style classes from [Twitter Bootstrap](http://getbootstrap.com/css/): `container`, `form-group`, `form-control`, and `btn`.
To use these styles, the app's style sheet imports the library.
The `alterEgo` is optional, so the constructor lets you omit it; note the question mark (?) in `alterEgo?`.
<code-example path="forms/src/styles.1.css" header="src/styles.css"></code-example>
You can create a new hero like this:
7. The form makes the hero applicant choose one superpower from a fixed list of agency-approved powers.
The predefined list of `powers` is part of the data model, maintained internally in `HeroFormComponent`.
The Angular [NgForOf directive](api/common/NgForOf "API reference") iterates over the data values to populate the `<select>` element.
<code-example path="forms/src/app/hero-form/hero-form.component.ts" region="SkyDog"></code-example>
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (powers)" region="powers"></code-example>
## Create a form component
An Angular form has two parts: an HTML-based _template_ and a component _class_
to handle data and user interactions programmatically.
Begin with the class because it states, in brief, what the hero editor can do.
Using the Angular CLI command [`ng generate component`](cli/generate), generate a new component named `HeroForm`:
<code-example language="sh" class="code-shell">
ng generate component HeroForm
</code-example>
With this content:
<code-example path="forms/src/app/hero-form/hero-form.component.ts" header="src/app/hero-form/hero-form.component.ts (v1)" region="v1"></code-example>
Theres nothing special about this component, nothing form-specific,
nothing to distinguish it from any component you've written before.
Understanding this component requires only the Angular concepts covered in previous pages.
* The code imports the Angular core library and the `Hero` model you just created.
* The `@Component` selector value of "app-hero-form" means you can drop this form in a parent
template with a `<app-hero-form>` tag.
* The `templateUrl` property points to a separate file for the template HTML.
* You defined dummy data for `model` and `powers`, as befits a demo.
Down the road, you can inject a data service to get and save real data
or perhaps expose these properties as inputs and outputs
(see [Input and output properties](guide/template-syntax#inputs-outputs) on the
[Template Syntax](guide/template-syntax) page) for binding to a
parent component. This is not a concern now and these future changes won't affect the form.
* You added a `diagnostic` property to return a JSON representation of the model.
It'll help you see what you're doing during development; you've left yourself a cleanup note to discard it later.
## Revise *app.module.ts*
`app.module.ts` defines the application's root module. In it you identify the external modules you'll use in the application
and declare the components that belong to this module, such as the `HeroFormComponent`.
Because template-driven forms are in their own module, you need to add the `FormsModule` to the array of
`imports` for the application module before you can use forms.
Update it with the following:
<code-example path="forms/src/app/app.module.ts" header="src/app/app.module.ts"></code-example>
<div class="alert is-helpful">
There are two changes:
1. You import `FormsModule`.
1. You add the `FormsModule` to the list of `imports` defined in the `@NgModule` decorator. This gives the application
access to all of the template-driven forms features, including `ngModel`.
</div>
<div class="alert is-important">
If a component, directive, or pipe belongs to a module in the `imports` array, _don't_ re-declare it in the `declarations` array.
If you wrote it and it should belong to this module, _do_ declare it in the `declarations` array.
</div>
## Revise *app.component.html*
`AppComponent` is the application's root component. It will host the new `HeroFormComponent`.
Replace the contents of its template with the following:
<code-example path="forms/src/app/app.component.html" header="src/app/app.component.html"></code-example>
<div class="alert is-helpful">
There are only two changes.
The `template` is simply the new element tag identified by the component's `selector` property.
This displays the hero form when the application component is loaded.
Don't forget to remove the `name` field from the class body as well.
</div>
## Create an initial HTML form template
Update the template file with the following contents:
<code-example path="forms/src/app/hero-form/hero-form.component.html" region="start" header="src/app/hero-form/hero-form.component.html"></code-example>
The language is simply HTML5. You're presenting two of the `Hero` fields, `name` and `alterEgo`, and
opening them up for user input in input boxes.
The *Name* `<input>` control has the HTML5 `required` attribute;
the *Alter Ego* `<input>` control does not because `alterEgo` is optional.
You added a *Submit* button at the bottom with some classes on it for styling.
*You're not using Angular yet*. There are no bindings or extra directives, just layout.
<div class="alert is-helpful">
In template driven forms, if you've imported `FormsModule`, you don't have to do anything
to the `<form>` tag in order to make use of `FormsModule`. Continue on to see how this works.
</div>
The `container`, `form-group`, `form-control`, and `btn` classes
come from [Twitter Bootstrap](http://getbootstrap.com/css/). These classes are purely cosmetic.
Bootstrap gives the form a little style.
<div class="callout is-important">
<header>
Angular forms don't require a style library
</header>
Angular makes no use of the `container`, `form-group`, `form-control`, and `btn` classes or
the styles of any external library. Angular apps can use any CSS library or none at all.
</div>
To add the stylesheet, open `styles.css` and add the following import line at the top:
<code-example path="forms/src/styles.1.css" header="src/styles.css"></code-example>
## Add powers with _*ngFor_
The hero must choose one superpower from a fixed list of agency-approved powers.
You maintain that list internally (in `HeroFormComponent`).
You'll add a `select` to the
form and bind the options to the `powers` list using `ngFor`,
a technique seen previously in the [Displaying Data](guide/displaying-data) page.
Add the following HTML *immediately below* the *Alter Ego* group:
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (powers)" region="powers"></code-example>
This code repeats the `<option>` tag for each power in the list of powers.
The `pow` template input variable is a different power in each iteration;
you display its name using the interpolation syntax.
{@a ngModel}
## Two-way data binding with _ngModel_
Running the app right now would be disappointing.
If you run the app right now, you see the list of powers in the selection control. The input elements are not yet bound to data values or events, so they are still blank and have no behavior.
<div class="lightbox">
<img src="generated/images/guide/forms/hero-form-3.png" alt="Early form with no binding">
</div>
{@a ngModel}
You don't see hero data because you're not binding to the `Hero` yet.
You know how to do that from earlier pages.
[Displaying Data](guide/displaying-data) teaches property binding.
[User Input](guide/user-input) shows how to listen for DOM events with an
event binding and how to update a component property with the displayed value.
## Bind input controls to data properties
Now you need to display, listen, and extract at the same time.
The next step is to bind the input controls to the corresponding `Hero` properties with two-way data binding, so that they respond to user input by updating the data model, and also respond to programmatic changes in the data by updating the display.
You could use the techniques you already know, but
instead you'll use the new `[(ngModel)]` syntax, which
makes binding the form to the model easy.
The `ngModel` directive declared in the `FormsModule` lets you bind controls in your template-driven form to properties in your data model.
When you include the directive using the syntax for two-way data binding, `[(ngModel)]`, Angular can track the value and user interaction of the control and keep the view synced with the model.
Find the `<input>` tag for *Name* and update it like this:
1. Edit the template file `hero-form.component.html`.
2. Find the `<input>` tag next to the **Name** label.
3. Add the `ngModel` directive, using two-way data binding syntax `[(ngModel)]="..."`.
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (excerpt)" region="ngModelName-1"></code-example>
<div class="alert is-helpful">
You added a diagnostic interpolation after the input tag
so you can see what you're doing.
You left yourself a note to throw it away when you're done.
This example has a temporary diagnostic interpolation after each input tag, `{{model.name}}`, to show the current data value of the corresponding property.
The note reminds you to remove the diagnostic lines when you have finished observing the two-way data binding at work.
</div>
Focus on the binding syntax: `[(ngModel)]="..."`.
{@a ngForm}
You need one more addition to display the data. Declare
a template variable for the form. Update the `<form>` tag with
`#heroForm="ngForm"` as follows:
### Access the overall form status
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (excerpt)" region="template-variable"></code-example>
When you imported the `FormsModule` in your component, Angular automatically created and attached an [NgForm](api/forms/NgForm "API reference for NgForm") directive to the `<form>` tag in the template (because `NgForm` has the selector `form` that matches `<form>` elements).
The variable `heroForm` is now a reference to the `NgForm` directive that governs the form as a whole.
To get access to the `NgForm` and the overall form status, declare a [template reference variable](guide/template-syntax#template-reference-variables-var).
<div class="alert is-helpful">
1. Edit the template file `hero-form.component.html`.
{@a ngForm}
2. Update the `<form>` tag with a template reference variable, `#heroForm`, and set its value as follows.
### The _NgForm_ directive
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (excerpt)" region="template-variable"></code-example>
What `NgForm` directive?
You didn't add an [NgForm](api/forms/NgForm) directive.
The `heroForm` template variable is now a reference to the `NgForm` directive instance that governs the form as a whole.
Angular did. Angular automatically creates and attaches an `NgForm` directive to the `<form>` tag.
3. Run the app.
The `NgForm` directive supplements the `form` element with additional features.
It holds the controls you created for the elements with an `ngModel` directive
and `name` attribute, and monitors their properties, including their validity.
It also has its own `valid` property which is true only *if every contained
control* is valid.
4. Start typing in the **Name** input box.
</div>
As you add and delete characters, you can see them appear and disappear from the data model.
For example:
If you ran the app now and started typing in the *Name* input box,
adding and deleting characters, you'd see them appear and disappear
from the interpolated text.
At some point it might look like this:
<div class="lightbox">
<img src="generated/images/guide/forms/ng-model-in-action.png" alt="ngModel in action">
</div>
<div class="lightbox">
<img src="generated/images/guide/forms/ng-model-in-action.png" alt="ngModel in action">
</div>
The diagnostic line that shows interpolated values demonstrates that values are really flowing from the input box to the model and back again.
The diagnostic is evidence that values really are flowing from the input box to the model and
back again.
### Naming control elements
<div class="alert is-helpful">
When you use `[(ngModel)]` on an element, you must define a `name` attribute for that element.
Angular uses the assigned name to register the element with the `NgForm` directive attached to the parent `<form>` element.
That's *two-way data binding*.
For more information, see
[Two-way binding with NgModel](guide/template-syntax#ngModel) on the
the [Template Syntax](guide/template-syntax) page.
The example added a `name` attribute to the `<input>` element and set it to "name",
which makes sense for the hero's name.
Any unique value will do, but using a descriptive name is helpful.
</div>
1. Add similar `[(ngModel)]` bindings and `name` attributes to **Alter Ego** and **Hero Power**.
Notice that you also added a `name` attribute to the `<input>` tag and set it to "name",
which makes sense for the hero's name. Any unique value will do, but using a descriptive name is helpful.
Defining a `name` attribute is a requirement when using `[(ngModel)]` in combination with a form.
2. You can now remove the diagnostic messages that show interpolated values.
<div class="alert is-helpful">
3. To confirm that two-way data binding works for the entire hero model, add a new binding at the top to the component's `diagnostic` property.
Internally, Angular creates `FormControl` instances and
registers them with an `NgForm` directive that Angular attached to the `<form>` tag.
Each `FormControl` is registered under the name you assigned to the `name` attribute.
Read more in the previous section, [The NgForm directive](guide/forms#ngForm).
</div>
Add similar `[(ngModel)]` bindings and `name` attributes to *Alter Ego* and *Hero Power*.
You'll ditch the input box binding message
and add a new binding (at the top) to the component's `diagnostic` property.
Then you can confirm that two-way data binding works *for the entire hero model*.
After revision, the core of the form should look like this:
After these revisions, the form template should look like the following:
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (excerpt)" region="ngModel-2"></code-example>
<div class="alert is-helpful">
* Notice that each `<input>` element has an `id` property. This is used by the `<label>` element's `for` attribute to match the label to its input control. This is a [standard HTML feature](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label).
* Each input element has an `id` property that is used by the `label` element's `for` attribute
to match the label to its input control.
* Each input element has a `name` property that is required by Angular forms to register the control with the form.
</div>
* Each `<input>` element also has the required `name` property that Angular uses to register the control with the form.
If you run the app now and change every hero model property, the form might display like this:
@ -391,18 +236,15 @@ If you run the app now and change every hero model property, the form might disp
<img src="generated/images/guide/forms/ng-model-in-action-2.png" alt="ngModel in action">
</div>
The diagnostic near the top of the form
confirms that all of your changes are reflected in the model.
The diagnostic near the top of the form confirms that all of your changes are reflected in the model.
*Delete* the `{{diagnostic}}` binding at the top as it has served its purpose.
4. When you have observed the effects, you can delete the `{{diagnostic}}` binding.
## Track control state and validity with _ngModel_
## Track control states
Using `ngModel` in a form gives you more than just two-way data binding. It also tells
you if the user touched the control, if the value changed, or if the value became invalid.
The *NgModel* directive doesn't just track state; it updates the control with special Angular CSS classes that reflect the state.
You can leverage those class names to change the appearance of the control.
The `NgModel` directive on a control tracks the state of that control.
It tells you if the user touched the control, if the value changed, or if the value became invalid.
Angular sets special CSS classes on the control element to reflect the state, as shown in the following table.
<table>
@ -472,38 +314,32 @@ You can leverage those class names to change the appearance of the control.
</table>
Temporarily add a [template reference variable](guide/template-syntax#ref-vars) named `spy`
to the _Name_ `<input>` tag and use it to display the input's CSS classes.
You use these CSS classes to define the styles for your control based on its status.
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (excerpt)" region="ngModelName-2"></code-example>
### Observe control states
Now run the app and look at the _Name_ input box.
Follow these steps *precisely*:
To see how the classes are added and removed by the framework, open the browser's developer tools and inspect the `<input>` element that represents the hero name.
1. Look but don't touch.
1. Click inside the name box, then click outside it.
1. Add slashes to the end of the name.
1. Erase the name.
1. Using your browser's developer tools, find the `<input>` element that corresponds to the **Name** input box.
You can see that the element has multiple CSS classes in addition to "form-control".
The actions and effects are as follows:
2. When you first bring it up, the classes indicate that it has a valid value, that the value has not been changed since initialization or reset, and that the control has not been visited since initialization or reset.
<div class="lightbox">
<img src="generated/images/guide/forms/control-state-transitions-anim.gif" alt="Control State Transition">
</div>
```
<input ... class="form-control ng-untouched ng-pristine ng-valid" ...>
```
You should see the following transitions and class names:
3. Take the following actions on the **Name** `<input>` box, and observe which classes appear.
* Look but don't touch. The classes indicate that it is untouched, pristine, and valid.
* Click inside the name box, then click outside it. The control has now been visited, and the element has the `ng-touched` class instead of the `ng-untouched` class.
* Add slashes to the end of the name. It is now touched and dirty.
* Erase the name. This makes the value invalid, so the `ng-invalid` class replaces the `ng-valid` class.
<div class="lightbox">
<img src="generated/images/guide/forms/ng-control-class-changes.png" alt="Control state transitions">
</div>
### Create visual feedback for states
The `ng-valid`/`ng-invalid` pair is the most interesting, because you want to send a
strong visual signal when the values are invalid. You also want to mark required fields.
To create such visual feedback, add definitions for the `ng-*` CSS classes.
*Delete* the `#spy` template reference variable and the `TODO` as they have served their purpose.
## Add custom CSS for visual feedback
The `ng-valid`/`ng-invalid` pair is particularly interesting, because you want to send a
strong visual signal when the values are invalid.
You also want to mark required fields.
You can mark required fields and invalid data at the same time with a colored bar
on the left of the input box:
@ -512,20 +348,25 @@ on the left of the input box:
<img src="generated/images/guide/forms/validity-required-indicator.png" alt="Invalid Form">
</div>
You achieve this effect by adding these class definitions to a new `forms.css` file
that you add to the project as a sibling to `index.html`:
To change the appearance in this way, take the following steps.
<code-example path="forms/src/assets/forms.css" header="src/assets/forms.css"></code-example>
1. Add definitions for the `ng-*` CSS classes.
Update the `<head>` of `index.html` to include this style sheet:
2. Add these class definitions to a new `forms.css` file.
<code-example path="forms/src/index.html" header="src/index.html (styles)" region="styles"></code-example>
3. Add the new file to the project as a sibling to `index.html`:
## Show and hide validation error messages
<code-example path="forms/src/assets/forms.css" header="src/assets/forms.css"></code-example>
You can improve the form. The _Name_ input box is required and clearing it turns the bar red.
That says something is wrong but the user doesn't know *what* is wrong or what to do about it.
Leverage the control's state to reveal a helpful message.
4. In the `index.html` file, update the `<head>` tag to include the new style sheet.
<code-example path="forms/src/index.html" header="src/index.html (styles)" region="styles"></code-example>
### Show and hide validation error messages
The **Name** input box is required and clearing it turns the bar red.
That indicates that something is wrong, but the user doesn't know what is wrong or what to do about it.
You can provide a helpful message by checking for and responding to the control's state.
When the user deletes the name, the form should look like this:
@ -533,166 +374,135 @@ When the user deletes the name, the form should look like this:
<img src="generated/images/guide/forms/name-required-error.png" alt="Name required">
</div>
To achieve this effect, extend the `<input>` tag with the following:
The **Hero Power** select box is also required, but it doesn't need this kind of error handling because the selection box already constrains the selection to valid values.
* A [template reference variable](guide/template-syntax#ref-vars).
* The "*is required*" message in a nearby `<div>`, which you'll display only if the control is invalid.
To define and show an error message when appropriate, take the following steps.
Here's an example of an error message added to the _name_ input box:
1. Extend the `<input>` tag with a template reference variable that you can use to access the input box's Angular control from within the template. In the example, the variable is `#name="ngModel"`.
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (excerpt)" region="name-with-error-msg"></code-example>
<div class="alert is-helpful">
You need a template reference variable to access the input box's Angular control from within the template.
Here you created a variable called `name` and gave it the value "ngModel".
The template reference variable (`#name`) is set to `"ngModel"` because that is the value of the [`NgModel.exportAs`](api/core/Directive#exportAs) property. This property tells Angular how to link a reference variable to a directive.
<div class="alert is-helpful">
</div>
Why "ngModel"?
A directive's [exportAs](api/core/Directive) property
tells Angular how to link the reference variable to the directive.
You set `name` to `ngModel` because the `ngModel` directive's `exportAs` property happens to be "ngModel".
</div>
You control visibility of the name error message by binding properties of the `name`
2. Add a `<div>` that contains a suitable error message.
3. Show or hide the error message by binding properties of the `name`
control to the message `<div>` element's `hidden` property.
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (hidden-error-msg)" region="hidden-error-msg"></code-example>
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (hidden-error-msg)" region="hidden-error-msg"></code-example>
In this example, you hide the message when the control is valid or pristine;
"pristine" means the user hasn't changed the value since it was displayed in this form.
4. Add a conditional error message to the _name_ input box, as in the following example.
This user experience is the developer's choice. Some developers want the message to display at all times.
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (excerpt)" region="name-with-error-msg"></code-example>
<div class="callout is-helpful">
<header>Illustrating the "pristine" state</header>
In this example, you hide the message when the control is either valid or *pristine*.
Pristine means the user hasn't changed the value since it was displayed in this form.
If you ignore the `pristine` state, you would hide the message only when the value is valid.
If you arrive in this component with a new (blank) hero or an invalid hero,
you'll see the error message immediately, before you've done anything.
Some developers want the message to display only when the user makes an invalid change.
Hiding the message while the control is "pristine" achieves that goal.
You'll see the significance of this choice when you add a new hero to the form.
You might want the message to display only when the user makes an invalid change.
Hiding the message while the control is in the `pristine` state achieves that goal.
You'll see the significance of this choice when you add a new hero to the form in the next step.
The hero *Alter Ego* is optional so you can leave that be.
</div>
Hero *Power* selection is required.
You can add the same kind of error handling to the `<select>` if you want,
but it's not imperative because the selection box already constrains the
power to valid values.
## Add a new hero
Now you'll add a new hero in this form.
Place a *New Hero* button at the bottom of the form and bind its click event to a `newHero` component method.
This exercise shows how you can respond to a native HTML button-click event by adding to the model data.
To let form users add a new hero, you will add a **New Hero** button that responds to a click event.
<code-example path="forms/src/app/hero-form/hero-form.component.html" region="new-hero-button-no-reset" header="src/app/hero-form/hero-form.component.html (New Hero button)"></code-example>
1. In the template, place a "New Hero" `<button>` element at the bottom of the form.
2. In the component file, add the hero-creation method to the hero data model.
<code-example path="forms/src/app/hero-form/hero-form.component.ts" region="new-hero" header="src/app/hero-form/hero-form.component.ts (New Hero method)"></code-example>
<code-example path="forms/src/app/hero-form/hero-form.component.ts" region="new-hero" header="src/app/hero-form/hero-form.component.ts (New Hero method)"></code-example>
Run the application again, click the *New Hero* button, and the form clears.
The *required* bars to the left of the input box are red, indicating invalid `name` and `power` properties.
That's understandable as these are required fields.
The error messages are hidden because the form is pristine; you haven't changed anything yet.
3. Bind the button's click event to a hero-creation method, `newHero()`.
Enter a name and click *New Hero* again.
The app displays a _Name is required_ error message.
You don't want error messages when you create a new (empty) hero.
Why are you getting one now?
<code-example path="forms/src/app/hero-form/hero-form.component.html" region="new-hero-button-no-reset" header="src/app/hero-form/hero-form.component.html (New Hero button)"></code-example>
Inspecting the element in the browser tools reveals that the *name* input box is _no longer pristine_.
The form remembers that you entered a name before clicking *New Hero*.
Replacing the hero object *did not restore the pristine state* of the form controls.
4. Run the application again and click the **New Hero** button.
You have to clear all of the flags imperatively, which you can do
by calling the form's `reset()` method after calling the `newHero()` method.
The form clears, and the *required* bars to the left of the input box are red, indicating invalid `name` and `power` properties.
Notice that the error messages are hidden. This is because the form is pristine; you haven't changed anything yet.
<code-example path="forms/src/app/hero-form/hero-form.component.html" region="new-hero-button-form-reset" header="src/app/hero-form/hero-form.component.html (Reset the form)"></code-example>
5. Enter a name and click **New Hero** again.
Now clicking "New Hero" resets both the form and its control flags.
Now the app displays a _Name is required_ error message, because the input box is no longer pristine.
The form remembers that you entered a name before clicking **New Hero**.
6. To restore the pristine state of the form controls, clear all of the flags imperatively by calling the form's `reset()` method after calling the `newHero()` method.
<code-example path="forms/src/app/hero-form/hero-form.component.html" region="new-hero-button-form-reset" header="src/app/hero-form/hero-form.component.html (Reset the form)"></code-example>
Now clicking **New Hero** resets both the form and its control flags.
<div class="alert is-helpful">
See the [User Input](guide/user-input) guide for more information about listening for DOM events with an event binding and updating a corresponding component property.
</div>
## Submit the form with _ngSubmit_
The user should be able to submit this form after filling it in.
The *Submit* button at the bottom of the form
does nothing on its own, but it will
trigger a form submit because of its type (`type="submit"`).
The **Submit** button at the bottom of the form does nothing on its own, but it does
trigger a form-submit event because of its type (`type="submit"`).
To respond to this event, take the following steps.
A "form submit" is useless at the moment.
To make it useful, bind the form's `ngSubmit` event property
to the hero form component's `onSubmit()` method:
1. Bind the form's [`ngSubmit`](api/forms/NgForm#properties) event property to the hero-form component's `onSubmit()` method.
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (ngSubmit)" region="ngSubmit"></code-example>
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (ngSubmit)" region="ngSubmit"></code-example>
You'd already defined a template reference variable,
`#heroForm`, and initialized it with the value "ngForm".
Now, use that variable to access the form with the Submit button.
2. Use the template reference variable, `#heroForm` to access the form that contains the **Submit** button and create an event binding.
You will bind the form property that indicates its overall validity to the **Submit** button's `disabled` property.
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (submit-button)" region="submit-button"></code-example>
You'll bind the form's overall validity via
the `heroForm` variable to the button's `disabled` property
using an event binding. Here's the code:
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (submit-button)" region="submit-button"></code-example>
If you run the application now, you find that the button is enabled&mdash;although
3. Run the application now. Notice that the button is enabled&mdash;although
it doesn't do anything useful yet.
Now if you delete the Name, you violate the "required" rule, which
is duly noted in the error message.
The *Submit* button is also disabled.
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.
Not impressed? Think about it for a moment. What would you have to do to
wire the button's enable/disabled state to the form's validity without Angular's help?
For you, it was as simple as this:
You didn't have to explicitly wire the button's enabled state to the form's validity.
The `FormsModule` did this automatically when you defined a template reference variable on the enhanced form element, then referred to that variable in the button control.
1. Define a template reference variable on the (enhanced) form element.
2. Refer to that variable in a button many lines away.
### Respond to form submission
## Toggle two form regions (extra credit)
To show a response to form submission, you can hide the data entry area and display something else in its place.
Submitting the form isn't terribly dramatic at the moment.
<div class="alert is-helpful">
An unsurprising observation for a demo. To be honest,
jazzing it up won't teach you anything new about forms.
But this is an opportunity to exercise some of your newly won
binding skills.
If you aren't interested, skip to this page's conclusion.
</div>
For a more strikingly visual effect,
hide the data entry area and display something else.
Wrap the form in a `<div>` and bind
1. Wrap the entire form in a `<div>` and bind
its `hidden` property to the `HeroFormComponent.submitted` property.
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (excerpt)" region="edit-div"></code-example>
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (excerpt)" region="edit-div"></code-example>
The main form is visible from the start because the
`submitted` property is false until you submit the form,
as this fragment from the `HeroFormComponent` shows:
* The main form is visible from the start because the `submitted` property is false until you submit the form, as this fragment from the `HeroFormComponent` shows:
<code-example path="forms/src/app/hero-form/hero-form.component.ts" header="src/app/hero-form/hero-form.component.ts (submitted)" region="submitted"></code-example>
<code-example path="forms/src/app/hero-form/hero-form.component.ts" header="src/app/hero-form/hero-form.component.ts (submitted)" region="submitted"></code-example>
When you click the *Submit* button, the `submitted` flag becomes true and the form disappears
as planned.
* When you click the **Submit** button, the `submitted` flag becomes true and the form disappears.
Now the app needs to show something else while the form is in the submitted state.
Add the following HTML below the `<div>` wrapper you just wrote:
2. To show something else while the form is in the submitted state, add the following HTML below the new `<div>` wrapper.
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (excerpt)" region="submitted"></code-example>
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (excerpt)" region="submitted"></code-example>
There's the hero again, displayed read-only with interpolation bindings.
This `<div>` appears only while the component is in the submitted state.
This `<div>`, which shows a read-only hero with interpolation bindings, appears only while the component is in the submitted state.
The HTML includes an *Edit* button whose click event is bound to an expression
The alternative display includes an *Edit* button whose click event is bound to an expression
that clears the `submitted` flag.
When you click the *Edit* button, this block disappears and the editable form reappears.
3. Click the *Edit* button to switch the display back to the editable form.
## Summary
The Angular form discussed in this page takes advantage of the following
framework features to provide support for data modification, validation, and more:
framework features to provide support for data modification, validation, and more.
* An Angular HTML form template.
* A form component class with a `@Component` decorator.
@ -700,8 +510,8 @@ framework features to provide support for data modification, validation, and mor
* Template-reference variables such as `#heroForm` and `#name`.
* `[(ngModel)]` syntax for two-way data binding.
* The use of `name` attributes for validation and form-element change tracking.
* The reference variables `valid` property on input controls to check if a control is valid and show/hide error messages.
* Controlling the *Submit* button's enabled state by binding to `NgForm` validity.
* The reference variables `valid` property on input controls to check if a control is valid and show or hide error messages.
* Controlling the **Submit** button's enabled state by binding to `NgForm` validity.
* Custom CSS classes that provide visual feedback to users about invalid controls.
Heres the code for the final version of the application:
@ -741,4 +551,3 @@ Heres the code for the final version of the application:
</code-pane>
</code-tabs>

View File

@ -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

@ -1,6 +1,6 @@
# Communicating with backend services using HTTP
Most front-end applications need to communicate with a server over the HTTP protocol, in order to download or upload data and accesss other back-end services.
Most front-end applications need to communicate with a server over the HTTP protocol, in order to download or upload data and access other back-end services.
Angular provides a simplified client HTTP API for Angular applications, the `HttpClient` service class in `@angular/common/http`.
The HTTP client service offers the following major features.
@ -63,7 +63,7 @@ Look at the `AppModule` _imports_ to see how it is configured.
## Requesting data from a server
Use the [`HTTPClient.get()`](api/common/http/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 when the response is received.
The asynchronous method sends an HTTP request, and returns an Observable that emits the requested data when the response is received.
The return type varies based on the `observe` and `responseType` values that you pass to the call.
The `get()` method takes two arguments; the endpoint URL from which to fetch, and an *options* object that you can use to configure the request.
@ -805,16 +805,16 @@ The `CachingInterceptor` in the following example demonstrates this approach.
header="app/http-interceptors/caching-interceptor.ts)">
</code-example>
* The `isCachable()` function determines if the request is cachable.
In this sample, only GET requests to the npm package search api are cachable.
* The `isCacheable()` function determines if the request is cacheable.
In this sample, only GET requests to the npm package search api are cacheable.
* If the request is not cachable, the interceptor simply forwards the request
* If the request is not cacheable, the interceptor simply forwards the request
to the next handler in the chain.
* If a cachable request is found in the cache, the interceptor returns an `of()` _observable_ with
* If a cacheable request is found in the cache, the interceptor returns an `of()` _observable_ with
the cached response, by-passing the `next` handler (and all other interceptors downstream).
* If a cachable request is not in cache, the code calls `sendRequest()`.
* If a cacheable request is not in cache, the code calls `sendRequest()`.
This function creates a [request clone](#immutability) without headers, because the npm API forbids them.
The function then forwards the clone of the request to `next.handle()` which ultimately calls the server and returns the server's response.

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

@ -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,54 @@
# 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

@ -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

@ -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

@ -193,6 +193,21 @@ The Angular service worker can use either of two caching strategies for data res
* `freshness` optimizes for currency of data, preferentially fetching requested data from the network. Only if the network times out, according to `timeout`, does the request fall back to the cache. This is useful for resources that change frequently; for example, account balances.
<div class="alert is-helpful">
You can also emulate a third strategy, [staleWhileRevalidate](https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#stale-while-revalidate), which returns cached data (if available), but also fetches fresh data from the network in the background for next time.
To use this strategy set `strategy` to `freshness` and `timeout` to `0u` in `cacheConfig`.
This will essentially do the following:
1. Try to fetch from the network first.
2. If the network request does not complete after 0ms (i.e. immediately), fall back to the cache (ignoring cache age).
3. Once the network request completes, update the cache for future requests.
4. If the resource does not exist in the cache, wait for the network request anyway.
</div>
### `cacheQueryOptions`
See [assetGroups](#assetgroups) for details.

View File

@ -107,7 +107,7 @@ Notice that all of the files the browser needs to render this application are ca
<div class="alert is-helpful">
Pay attention to two key points:
1. The generated `ngsw-config.json` includes a limited list of cachable fonts and images extentions. In some cases, you might want to modify the glob pattern to suit your needs.
1. The generated `ngsw-config.json` includes a limited list of cacheable fonts and images extentions. In some cases, you might want to modify the glob pattern to suit your needs.
1. If `resourcesOutputPath` or `assets` paths are modified after the generation of configuration file, you need to change the paths manually in `ngsw-config.json`.
</div>

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.
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).
<div class="alert is-helpful">
* To check your version, run `node -v` in a terminal/console window.
For information about specific version requirements, see the `engines` key in the [package.json](https://unpkg.com/@angular/cli/package.json) file.
* To get `Node.js`, go to [nodejs.org](https://nodejs.org "Nodejs.org").
</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

@ -251,7 +251,7 @@ You enable these features in the string assigned to `ngFor`, which you write in
Everything _outside_ the `ngFor` string stays with the host element
(the `<div>`) as it moves inside the `<ng-template>`.
In this example, the `[ngClass]="odd"` stays on the `<div>`.
In this example, the `[class.odd]="odd"` stays on the `<div>`.
</div>

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

@ -93,7 +93,7 @@ Adopt these two conventions in your own projects for _every kind_ of test file.
## Set up continuous integration
One of the best ways to keep your project bug free is through a test suite, but it's easy to forget to run tests all the time.
One of the best ways to keep your project bug-free is through a test suite, but it's easy to forget to run tests all the time.
Continuous integration (CI) servers let you set up your project repository so that your tests run on every commit and pull request.
There are paid CI services like Circle CI and Travis CI, and you can also host your own for free using Jenkins and others.

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

@ -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: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 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"]
},
@ -323,14 +323,6 @@
"bio": "Sander is a versed developer with over 4 decades of practice under his belt. He is also an Google Developer Expert for web, specializing in Angular. Organizer of meetups and conferences. Helping out others wherever he can. When he is not breathing code, he is fiddling around with IOT, photography, science and anything that might vaguely is gadget-like! Thinks he a master of the grill, but in reality you probably don't get a food-poisoning ;) Also, and actually the most important thing to him, he is a father of 4, and has the most patient girlfriend in the universe.",
"groups": ["GDE"]
},
"filipbech": {
"name": "Filip Bruun Bech-Larsen",
"picture": "filipbech.jpg",
"twitter": "filipbech",
"website": "http://filipbech.github.io/",
"bio": "Filip is a Frontend developer from Denmark. He works at IMPACT, delivering large-scale, high-performance e-commerce to international clients - most often build in Angular. He runs the local Angular usergroup - ngAarhus, and gives talks/workshops around and beyond the country of Denmark.",
"groups": ["GDE"]
},
"cironunes": {
"name": "Ciro Nunes",
"picture": "cironunes.jpg",
@ -400,14 +392,6 @@
"bio": "GDE (Google Developer Expert) Angular and Web Technologies, Women Who Code KL Director, Jecelyn specializes in professional application development with technologies, including Angular, HTML5, Typescript, JavaScript, CSS, C#, NodeJs, Cloud and ASP.NET.",
"groups": ["GDE"]
},
"areai51": {
"name": "Vinci Rufus",
"picture": "vincirufus.jpg",
"twitter": "areai51",
"website": "https://developers.google.com/experts/people/vinci-rufus",
"bio": "Director of Experience Technology at SapientRazorfish. Consults various brands on their frontend and mobile web architecture. A speaker at various forums and mentor at Launchpad Accelerator and ngGirls India. Spends free time playing with Angular, Preact, web-components ",
"groups": ["GDE"]
},
"tchatel": {
"name": "Thierry Chatel",
"picture": "thierrychatel.jpg",
@ -520,14 +504,6 @@
"bio": "Brian is a software engineer and GDE in Angular with a passion for learning, writing, speaking, teaching and mentoring. Brian has been building web applications for over 20 years and has long been a fanboy of JavaScript. When not in front of his Macbook Pro Brian is in the Rocky Mountains skiing or hiking.",
"groups": ["GDE"]
},
"jeffbcross": {
"name": "Jeff Cross",
"picture": "jeff-cross.jpg",
"twitter": "jeffbcross",
"website": "https://nrwl.io/",
"bio": "Jeff is an Angular Consultant at nrwl.io where he helps enterprise teams succeed with Angular. Prior to founding Nrwl, Jeff was one of the earliest members of the Angular Core Team at Google, and contributed to many of the early state management and performance efforts of AngularJS and Angular.",
"groups": ["GDE"]
},
"keilla": {
"name": "Keilla Menezes Fernandes",
"picture": "keilla.jpg",
@ -620,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",
@ -831,5 +814,21 @@
"bio": "Cindy is a Program Manager on the Angular team at Google. She is passionate about improving team processes and overall execution. She enjoys dance fitness, movies and travel.",
"groups": ["Angular"],
"lead": "juleskremer"
},
"wellwind": {
"name": "Mike Huang",
"picture": "wellwind.jpg",
"twitter": "wellwind",
"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

@ -254,11 +254,6 @@
"title": "Reactive Forms",
"tooltip": "Create a reactive form using FormBuilder, groups, and arrays."
},
{
"url": "guide/forms",
"title": "Template-driven Forms",
"tooltip": "Create a template-driven form using directives and Angular template syntax."
},
{
"url": "guide/form-validation",
"title": "Validate form input",
@ -511,85 +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."
},
{
"url": "guide/web-worker",
"title": "Web Workers in Angular",
"tooltip": "Implement background processing with web workers."
}
]
},
@ -628,11 +544,6 @@
"title": "Building & Serving",
"tooltip": "Building and serving Angular apps."
},
{
"url": "guide/bazel",
"title": "Building with Bazel",
"tooltip": "How to set up your environment to build and test with Bazel."
},
{
"url": "guide/testing",
"title": "Testing",
@ -690,6 +601,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."
}
]
},
@ -754,6 +670,11 @@
"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/forms",
"title": "Building a Template-driven Form",
"tooltip": "Create a template-driven form using directives and Angular template syntax."
}
]
},
@ -772,13 +693,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",
@ -786,29 +707,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",
@ -818,6 +719,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."
}
]
}
@ -1013,6 +934,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

@ -9,6 +9,11 @@ In this part of the tutorial, you'll do the following:
3. Serve the application.
4. Make changes to the application.
<div class="alert is-helpful">
For the sample app that this page describes, see the <live-example></live-example>.
</div>
## Set up your environment
@ -113,9 +118,6 @@ Open `src/styles.css` and add the code below to the file.
## Final code review
The source code for this tutorial and the complete _Tour of Heroes_ global styles
are available in the <live-example></live-example>.
Here are the code files discussed on this page.
<code-tabs>

View File

@ -4,6 +4,12 @@ The application now has a basic title.
Next you will create a new component to display hero information
and place that component in the application shell.
<div class="alert is-helpful">
For the sample app that this page describes, see the <live-example></live-example>.
</div>
## Create the heroes component
Using the Angular CLI, generate a new component named `heroes`.
@ -201,7 +207,7 @@ Note that `AppModule` declares both application components, `AppComponent` and
## Final code review
Your app should look like this <live-example></live-example>. Here are the code files discussed on this page.
Here are the code files discussed on this page.
<code-tabs>

View File

@ -3,6 +3,12 @@
In this page, you'll expand the Tour of Heroes app to display a list of heroes, and
allow users to select a hero and display the hero's details.
<div class="alert is-helpful">
For the sample app that this page describes, see the <live-example></live-example>.
</div>
## Create mock heroes
@ -220,8 +226,6 @@ The finished `<li>` looks like this:
## Final code review
Your app should look like this <live-example></live-example>.
Here are the code files discussed on this page, including the `HeroesComponent` styles.
<code-tabs>

View File

@ -10,6 +10,12 @@ In this page, you'll take the first step in that direction by moving the hero de
The `HeroesComponent` will only present the list of heroes.
The `HeroDetailComponent` will present details of a selected hero.
<div class="alert is-helpful">
For the sample app that this page describes, see the <live-example></live-example>.
</div>
## Make the `HeroDetailComponent`
Use the Angular CLI to generate a new component named `hero-detail`.
@ -136,7 +142,7 @@ without touching the parent `HeroesComponent`.
## Final code review
Here are the code files discussed on this page and your app should look like this <live-example></live-example>.
Here are the code files discussed on this page.
<code-tabs>

View File

@ -5,6 +5,13 @@ The Tour of Heroes `HeroesComponent` is currently getting and displaying fake da
After the refactoring in this tutorial, `HeroesComponent` will be lean and focused on supporting the view.
It will also be easier to unit-test with a mock service.
<div class="alert is-helpful">
For the sample app that this page describes, see the <live-example></live-example>.
</div>
## Why services
Components shouldn't fetch or save data directly and they certainly shouldn't knowingly present fake data.
@ -132,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>
@ -387,7 +394,7 @@ the selection. Use the "clear" button to clear the message history.
## Final code review
Here are the code files discussed on this page and your app should look like this <live-example></live-example>.
Here are the code files discussed on this page.
<code-tabs>

View File

@ -7,6 +7,12 @@ There are new requirements for the Tour of Heroes app:
* When users click a hero name in either view, navigate to a detail view of the selected hero.
* When users click a *deep link* in an email, open the detail view for a particular hero.
<div class="alert is-helpful">
For the sample app that this page describes, see the <live-example></live-example>.
</div>
When youre done, users will be able to navigate the app like this:
<div class="lightbox">
@ -466,7 +472,7 @@ from heroes list to the mini detail to the hero details and back to the heroes a
## Final code review
Here are the code files discussed on this page and your app should look like this <live-example></live-example>.
Here are the code files discussed on this page.
{@a approutingmodule}
{@a appmodule}

View File

@ -7,7 +7,11 @@ Angular's `HttpClient`.
* Users can add, edit, and delete heroes and save these changes over HTTP.
* Users can search for heroes by name.
When you're done with this page, the app should look like this <live-example></live-example>.
<div class="alert is-helpful">
For the sample app that this page describes, see the <live-example></live-example>.
</div>
## Enable HTTP services
@ -75,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.
@ -519,8 +524,6 @@ If you enter characters that match any existing hero names, you'll see something
## Final code review
Your app should look like this <live-example></live-example>.
Here are the code files discussed on this page (all in the `src/app/` folder).
{@a heroservice}

View File

@ -1,5 +1,6 @@
{
"hosting": {
"target": "aio",
"public": "dist",
"cleanUrls": true,
"redirects": [
@ -18,6 +19,7 @@
{"type": 301, "source": "/docs/*/latest/quickstart.html", "destination": "/start"},
{"type": 301, "source": "/docs/*/latest/guide/server-communication.html", "destination": "/guide/http"},
{"type": 301, "source": "/docs/*/latest/guide/style-guide.html", "destination": "/guide/styleguide"},
{"type": 301, "source": "/guide/bazel", "destination": "https://github.com/angular/angular/blob/master/packages/bazel/src/schematics/README.md"},
{"type": 301, "source": "/guide/cli-quickstart", "destination": "/start"},
{"type": 301, "source": "/guide/service-worker-getstart", "destination": "/guide/service-worker-getting-started"},
{"type": 301, "source": "/guide/service-worker-comm", "destination": "/guide/service-worker-communications"},
@ -121,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

@ -94,6 +94,7 @@
"!/api/testing/**",
"!/docs/?*",
"!/docs/*/**",
"!/guide/bazel",
"!/guide/change-log",
"!/getting-started",
"!/getting-started.html",
@ -146,6 +147,7 @@
"!/styleguide",
"!/styleguide/**",
"!/testing",
"!/testing/**"
"!/testing/**",
"!/config/**"
]
}

View File

@ -23,7 +23,7 @@
"build-local-with-viewengine": "yarn ~~build",
"prebuild-local-with-viewengine-ci": "node scripts/switch-to-viewengine && yarn setup-local-ci",
"build-local-with-viewengine-ci": "yarn ~~build --progress=false",
"extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js 200a21f8a",
"extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js 14af4e07c",
"lint": "yarn check-env && yarn docs-lint && ng lint && yarn example-lint && yarn tools-lint",
"test": "yarn check-env && ng test",
"pree2e": "yarn check-env && yarn update-webdriver",
@ -87,28 +87,28 @@
},
"private": true,
"dependencies": {
"@angular/animations": "10.0.0-next.5",
"@angular/animations": "10.0.0-rc.2",
"@angular/cdk": "^9.2.2",
"@angular/common": "10.0.0-next.5",
"@angular/compiler": "10.0.0-next.5",
"@angular/core": "10.0.0-next.5",
"@angular/elements": "10.0.0-next.5",
"@angular/forms": "10.0.0-next.5",
"@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-next.5",
"@angular/platform-browser-dynamic": "10.0.0-next.5",
"@angular/router": "10.0.0-next.5",
"@angular/service-worker": "10.0.0-next.5",
"@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",
"@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-next.3",
"@angular/cli": "10.0.0-next.3",
"@angular/compiler-cli": "10.0.0-next.5",
"@angular/language-service": "10.0.0-next.5",
"@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",
"@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",
@ -154,7 +154,7 @@
"lunr": "^2.1.0",
"npm-run-all": "^4.1.5",
"protractor": "~5.4.4",
"puppeteer": "2.1.1",
"puppeteer": "3.3.0",
"rehype": "^6.0.0",
"rehype-slug": "^2.0.0",
"remark": "^9.0.0",
@ -165,7 +165,7 @@
"tree-kill": "^1.1.0",
"ts-node": "^8.4.1",
"tslint": "~6.1.0",
"typescript": "~3.8.3",
"typescript": "~3.9.5",
"uglify-js": "^3.0.15",
"unist-util-filter": "^0.2.1",
"unist-util-source": "^1.0.1",
@ -175,4 +175,4 @@
"xregexp": "^4.0.0",
"yargs": "^7.0.2"
}
}
}

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" < "$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

@ -5,13 +5,9 @@
</div>
<mat-toolbar color="primary" class="app-toolbar no-print" [class.transitioning]="isTransitioning">
<mat-toolbar-row class="notification-container">
<aio-notification notificationId="survey-march-2020" expirationDate="2020-04-15" [dismissOnContentClick]="true" (dismissed)="notificationDismissed()">
<a href="https://goo.gle/angular-survey-2020">
<mat-icon class="icon" svgIcon="insert_comment" aria-label="Announcement"></mat-icon>
<span class="message">Help Angular by taking a <b>1 minute survey</b>!</span>
<span class="action-button">Go to survey</span>
</a>
<mat-toolbar-row class="notification-container blm-message">
<aio-notification notificationId="blm-2020" expirationDate="2022-04-15" [dismissOnContentClick]="true" (dismissed)="notificationDismissed()">
#BlackLivesMatter
</aio-notification>
</mat-toolbar-row>
<mat-toolbar-row>

View File

@ -401,7 +401,10 @@ describe('DocViewerComponent', () => {
expect(loadElementsSpy.calls.argsFor(1)).toEqual([docViewer.nextViewContainer]);
});
it('should unsubscribe from the previous "embed" observable when unsubscribed from', () => {
// This test sometimes incorrectly fails on CI.
// Reported in https://github.com/angular/angular/issues/37629.
// Investigated in https://github.com/angular/angular/pull/37637.
xit('should unsubscribe from the previous "embed" observable when unsubscribed from', () => {
const obs = new ObservableWithSubscriptionSpies();
loadElementsSpy.and.returnValue(obs);
@ -436,7 +439,10 @@ describe('DocViewerComponent', () => {
expect(swapViewsSpy).toHaveBeenCalledWith(addTitleAndTocSpy);
});
it('should unsubscribe from the previous "swap" observable when unsubscribed from', () => {
// This test sometimes incorrectly fails on CI.
// Reported in https://github.com/angular/angular/issues/37629.
// Investigated in https://github.com/angular/angular/pull/37637.
xit('should unsubscribe from the previous "swap" observable when unsubscribed from', () => {
const obs = new ObservableWithSubscriptionSpies();
swapViewsSpy.and.returnValue(obs);

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

@ -183,8 +183,8 @@ section#intro {
// ANGULAR LINE
.background-sky {
background-color: $blue;
background: $bluegradient;
background-color: $black;
background: $black;
color: $white;
}

View File

@ -20,9 +20,16 @@ mat-toolbar.mat-toolbar {
}
}
.blm-message {
text-align: center;
justify-content: center;
background: #2d2d2d;
font-size: 0.75em;
}
// HOME PAGE OVERRIDE: TOPNAV TOOLBAR
aio-shell.page-home mat-toolbar.mat-toolbar {
background-color: $blue;
background-color: $black;
@media (min-width: 481px) {
&:not(.transitioning) {

View File

@ -52,16 +52,18 @@ aio-contributor {
transition: all .3s;
perspective: 800px;
&:hover {
transform: translate3d(0,-3px,0);
box-shadow: 0 8px 8px rgba(10, 16, 20, 0.24), 0 0 8px rgba(10, 16, 20, 0.12);
@media (hover) {
&:hover {
transform: translate3d(0,-3px,0);
box-shadow: 0 8px 8px rgba(10, 16, 20, 0.24), 0 0 8px rgba(10, 16, 20, 0.12);
.contributor-image {
transform: scale(1.05);
}
.contributor-image {
transform: scale(1.05);
}
.contributor-info {
opacity: 1;
.contributor-info {
opacity: 1;
}
}
}

View File

@ -0,0 +1,52 @@
import { by, element } from 'protractor';
import { SitePage } from './app.po';
describe('api-list', () => {
const apiSearchInput = element(by.css('aio-api-list .form-search input'));
const apiStatusDropdown = element(by.css('aio-api-list aio-select[label="Status:"]'));
const apiTypeDropdown = element(by.css('aio-api-list aio-select[label="Type:"]'));
let page: SitePage;
beforeEach(() => {
page = new SitePage();
page.navigateTo('api');
});
it('should find AnimationSequenceMetadata when searching by partial word anima', () => {
expect(page.getApiSearchResults()).toContain('HttpEventType');
apiSearchInput.clear();
apiSearchInput.sendKeys('anima');
expect(page.getApiSearchResults()).not.toContain('HttpEventType');
expect(page.getApiSearchResults()).toContain('AnimationSequenceMetadata');
});
it('should find getLocaleDateTimeFormat when searching by partial word date', () => {
expect(page.getApiSearchResults()).toContain('formatCurrency');
apiSearchInput.clear();
apiSearchInput.sendKeys('date');
expect(page.getApiSearchResults()).not.toContain('formatCurrency');
expect(page.getApiSearchResults()).toContain('getLocaleDateTimeFormat');
});
it('should find LowerCasePipe when searching for type pipe', () => {
expect(page.getApiSearchResults()).toContain('getLocaleDateTimeFormat');
page.clickDropdownItem(apiTypeDropdown, 'Pipe');
expect(page.getApiSearchResults()).not.toContain('getLocaleDateTimeFormat');
expect(page.getApiSearchResults()).toContain('LowerCasePipe');
});
it('should find ElementRef when searching for status Security Risk', () => {
expect(page.getApiSearchResults()).toContain('getLocaleDateTimeFormat');
page.clickDropdownItem(apiStatusDropdown, 'Security Risk');
expect(page.getApiSearchResults()).not.toContain('getLocaleDateTimeFormat');
expect(page.getApiSearchResults()).toContain('ElementRef');
});
});

View File

@ -83,4 +83,16 @@ export class SitePage {
browser.wait(ExpectedConditions.presenceOf(results.first()), 8000);
return results.map(link => link && link.getText());
}
getApiSearchResults() {
const results = element.all(by.css('aio-api-list .api-item'));
browser.wait(ExpectedConditions.presenceOf(results.first()), 2000);
return results.map(elem => elem && elem.getText());
}
clickDropdownItem(dropdown: ElementFinder, itemName: string){
dropdown.element(by.css('.form-select-button')).click();
const menuItem = dropdown.element(by.cssContainingText('.form-select-dropdown li', itemName));
menuItem.click();
}
}

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