Compare commits

...

223 Commits

Author SHA1 Message Date
Alex Rickabaugh f0b94f5b48 release: cut the v14.0.1 release (#46308)
PR Close #46308
2022-06-08 13:06:03 -07:00
Adrien Crivelli 31d6f32f76 docs(router): Complete QueryParamsHandling documentation (#46286)
`QueryParamsHandling` has a third possibility which is the default behavior,
and it was not documented until now.

PR Close #46286
2022-06-08 12:40:57 -07:00
Alan Agius 34ba41f1aa docs: remove azure builder reference (#46285)
This builder is not compatible with newer versions of the Angular CLI.

See https://github.com/angular/angular-cli/issues/23255 for more context

PR Close #46285
2022-06-08 12:40:23 -07:00
Paul Gschwendtner 5b7c131658 build: update dev-infra shared code to latest revision (#46291)
Updates dev-infra to the latest revision. This revision supports
for custom release prechecks and performs the release build
before the staging, verifying integrity later. This has various
benefits for stability and making the less less relucant to build
issues that mess up a previously-merged staging PR.

PR Close #46291
2022-06-07 10:43:39 -07:00
Renovate Bot 6abe57fedd build: update dependency magic-string to v0.26.2 (#46279)
PR Close #46279
2022-06-07 10:43:12 -07:00
George Kalpakas 1f31dae40d build(docs-infra): update dependencies in docs examples package.json files (#46248)
This is a follow-up to #46227 to update the dependency version ranges in
the docs examples `package.json` files.

PR Close #46248
2022-06-07 10:42:43 -07:00
Paul Gschwendtner 862aafbec9 refactor(common): include locale extra data in closure locale file (#46167)
The recent update to CLDR 41 highlighted (internally) that some time
formats have changed to rely on locale-specific day periods. In
particular the `zh_TW` (or canonical: `zh_Hant`) has changed some
time formats/patterns from the universal `AM/PM` symbols (`a`) to `B`.

The `b`/`B` symbols rely on locale-specific day period rules. This data
is only extracted from CLDR into the so-called extra locale data that
Angular provides.

To fix this, and to be able to reverse the internal workaround that
doesn't allow us to use the actual CLDR 41 data here, we always provide
the locale extra data when conditonally loading CLDR data based on
`goog.LOCALE`.

This will result in additional payload cost that locale-specific JS
bundles have to pay, but the only alternative would be to break
Angular's `b`/`B` symbol support in favor of falling back to `AM/PM`
rules (similar to how Closure Libray itself does it).

For our external users (something I want to note here), they will be
able to load the extra data easily (like it was possible before).
Angular has some good erroring if the extra data is required. Most of
our users will always use the global locale files anyway (the Angular
CLI always uses them). These come with the extra data by default.

Resources:

- https://github.com/unicode-org/cldr/commit/0d538327d1ea2a31d1614d8989007b97a3ee5021
- https://github.com/unicode-org/cldr/blob/0d538327d1ea2a31d1614d8989007b97a3ee5021/common/main/zh_Hant.xml
- https://github.com/angular/angular/blob/6a4353cb40227330be2a5685adca485a8b8e8a0b/packages/common/src/i18n/format_date.ts#L609-L639
- https://cldr.unicode.org/translation/date-time/date-time-symbols
- https://cs.github.com/angular/angular-cli/blob/4be7cdce8283a177b92594bb7b34b4718d0a39c3/packages/angular_devkit/build_angular/src/utils/i18n-options.ts?q=%22locales%2Fglobal%22#L23

PR Close #46167
2022-06-07 10:14:14 -07:00
Andrew Kushnir b20e470704 test: add an internal helper to populate document.head before a test (#46250)
This commit reuses the logic of the `withBody` helper and implements the `withHead` based on it.The helper method is useful for tests that rely on a certain tags being present in document's `<head>` element.

PR Close #46250
2022-06-06 16:12:32 -07:00
Andrew Kushnir 6862438711 refactor(core): rename a file to avoid old terminology (to avoid mentioning render3) (#46250)
This commit renames the packages/private/testing/src/render3.ts -> packages/private/testing/src/utils.ts to avoid using the `render3` term as it used to differentiate VE and Ivy, which is no longer relevant.

PR Close #46250
2022-06-06 16:12:32 -07:00
Alan Agius 9f5558cb2a docs: mark version 13 as LTS in releases guide (#46268)
Verson 13 is now in LTS.

PR Close #46268
2022-06-06 11:48:06 -07:00
mgechev 43e4ba42b2 docs: add i18n video to the overview page (#46273)
PR Close #46273
2022-06-06 11:46:50 -07:00
Renovate Bot 19da41308f build: lock file maintenance (#46270)
PR Close #46270
2022-06-06 11:46:28 -07:00
Phalgun Vaddepalli 9b5cc21ff7 docs: removed outdated migration documentation (#46257)
Fixes #46236

PR Close #46257
2022-06-06 11:42:52 -07:00
Andrew Kushnir 5408a1e130 docs: annotate more APIs with the @developerPreview tag (#46234)
This commit updates a few more standalone-related APIs with the `@developerPreview` tag.

PR Close #46234
2022-06-06 11:37:56 -07:00
Andrew Kushnir b52daff813 refactor(core): export missing util function (#46274)
This commit exports the `isHostComponentStandalone` function and also changes a location where it's imported from. The function was moved recently in a different PR, which caused some conflicts after merging other PRs that relied on the old structure.

PR Close #46274
2022-06-06 11:35:25 -07:00
wellWINeo ef12d56cf1 docs: fix duplicate in CHANGELOG (#46267)
PR Close #46267
2022-06-06 10:18:33 -07:00
dario-piotrowicz d17c7ddbb8 docs: change wrong alters to callouts (#46262)
change the alerts present in the docs to callouts so
that their header can be properly rendered
(since alters don't support have headers)

PR Close #46262
2022-06-06 10:17:53 -07:00
dario-piotrowicz 8c32114df3 refactor(core): fix eaither typo in transitiveScopesFor comment (#46261)
fix the 'eaither' typo (instead of 'either') in the tsdoc comment
for the transitiveScopesFor function

PR Close #46261
2022-06-06 10:17:01 -07:00
Kristiyan Kostadinov b00d237c0e fix(bazel): update API extractor version (#46259)
`@angular/bazel` currently uses an older version of `@microsoft/api-extractor` which is causing downstream issues in Components. These changes bump up to a version that has a fix.

Context: https://github.com/angular/components/pull/25027

PR Close #46259
2022-06-06 10:16:05 -07:00
Fabrizio Fallico e7ff714189 docs: fix missing closing div in http page (#46258)
PR Close #46258
2022-06-06 10:15:37 -07:00
Jelle Bruisten d023270472 docs: fix typo in the CHANGELOG (#46255)
Fixes a type made in the CHANGELOG.md under the 14.0.0 at router release notes
PR Close #46255
2022-06-06 10:14:46 -07:00
Dylan Hunn dde0b7f4b3 fix(forms): allow FormBuilder.group(...) to accept optional fields. (#46253)
Consider the case in which `FormBuilder` is used to construct a group with an optional field:

```
const controls = { name: fb.control('') };
const foo: FormGroup<{
  name: FormControl<string | null>;
  address?: FormControl<string | null>;
}> = fb.group<{
  name: FormControl<string | null>;
  address?: FormControl<string | null>;
}>(controls);
```

Today, with fully strict TypeScript settings, the above will not compile:

```
Types of property 'controls' are incompatible.
Type '{ name: FormControl<string | null>; address?: FormControl<FormGroup<SubFormControls> | null | undefined> | undefined; }' is not assignable to type '{ name: FormControl<string | null>; address?: FormGroup<SubFormControls> | undefined; }'.
```

Notice that the `fb.group(...)` is calculating the following type for address: `address?: FormControl<FormGroup<string|null>`. This is clearly wrong -- an extraneous `FormControl` has been added!

This is coming from the calculation of the result type of `fb.group(...)`. In the type definition, if we cannot detect the outer control type, [we assume it's just an unwrapped value, and automatically wrap it in `FormControl`](https://github.com/angular/angular/blob/14.0.0/packages/forms/src/form_builder.ts#L66).

Because the optional `{address?: FormControl<string|null>}` implicitly makes the RHS have type `FormControl<string|null>|undefined`, [the relevant condition is not satisfied](https://github.com/angular/angular/blob/14.0.0/packages/forms/src/form_builder.ts#L55). In particular, the condition expects just `FormGroup<T>`, not `FormGroup<T>|undefined`. So we assume `T` is a value type, and it gets wrapped with `FormControl`.

The solution is to add the cases where `undefined` is included in the union type when detecting which control `T` is (if any).

PR Close #46253
2022-06-06 10:14:20 -07:00
dario-piotrowicz 765090adf6 refactor(core): add helpful info in the pipe not found error message (#46247)
Add info to the pipe not found error message so to give some help to the developer for
resolving the problem more efficiently

(Note: this change also distinguishes the case in which the hosting component is standalone)

PR Close #46247
2022-06-06 10:13:28 -07:00
dario-piotrowicz 66040711ee refactor(core): split RuntimeError unit test up (#46239)
split the single RuntimeError utils test testing about the correct
formatting of errors in multiple separate unit tests (for better
granularity and clearness)

PR Close #46239
2022-06-06 10:12:06 -07:00
dario-piotrowicz 9df8ceafd8 refactor(core): improve the runtime errors formatting (#46239)
the formatted error messages always include a period separator between the
provided error message and the find-more suffix, this is not always
desirable as it may add periods when they shoud not be, so improve the
formatting by checking and applying the period only if the provided message
doesn't end with a character which already represents a separator

additionally also improve the formatting by trimming the provided error
message

note that such trimming needs to be performed before the separator check
so that for example an error message like `"some error! "` doesn't produce
`"some error! ."` but it successfully produces "some error!"

PR Close #46239
2022-06-06 10:12:06 -07:00
Dylan Hunn 90fa5fee7a docs(forms): Amend the FormGroupDirective docs to indicate it also works with FormRecord. (#46235)
It is currently unclear which directive to use for FormRecord. This commit amends the docs to explicitly state that the group directives can and should be used with records.

PR Close #46235
2022-06-06 10:11:16 -07:00
dario-piotrowicz 03f840535b refactor(core): improve code around element validation (#46175)
improve code regarding element validation by creating a new file
exporting validation functions and not exporting utils previously
globally available

PR Close #46175
2022-06-06 10:10:41 -07:00
Renovate Bot dee2ba900e build: lock file maintenance (#46104)
PR Close #46104
2022-06-03 10:23:36 -07:00
Krzysztof Platis 0cc2b89efa docs: fix release notes for v14.0.0 - remove notice "fixes 45350" from breaking changes (#46238)
PR Close #46238
2022-06-03 10:09:54 -07:00
dario-piotrowicz 7206e3f4f9 docs: update outdated link title for structural directives guide (#46228)
amend the aio glossary using as the structural-directives guide link's title the
outdated heading of that guide (changed in PR #44895)

PR Close #46228
2022-06-03 10:08:16 -07:00
dario-piotrowicz f708c87c7d docs: replace wrong NgFor with NgForOf (#46228)
amend the aio structural-directives guide incorrectly mentioning
`NgFor` instead of `NgForOf` as a structural directive

PR Close #46228
2022-06-03 10:08:15 -07:00
Andrew Scott 9cff09ea1f test(router): illustrate canceling of intermediate results in canLoad (#46231)
This adds a test to illustrate the "canceling" behavior we get from the
`Observable` chain in the Router. A new navigation cancels ongoing ones,
and that means also preventing intermediate results in user guards from
executing. This test is important when thinking about future refactors
which might attempt to change the details of how the `applyRedirects`
operator executes.

PR Close #46231
2022-06-03 10:06:54 -07:00
Kristiyan Kostadinov f30179d973 refactor(core): don't use patched data in LifecycleHooksFeature (#46237)
We don't need to read patched data off the component instance since we already know what the `LView` is.

PR Close #46237
2022-06-03 10:06:20 -07:00
San Leen b52b40ee2c docs: update navigation update-to-latest for v14 (#46246)
This commit adds content related to Angular v14 to the title and  tooltip of `navigation.json -> guide/update-to-latest-version` .
PR Close #46246
2022-06-03 09:52:15 -07:00
Alex Rickabaugh ed570453da build(docs-infra): update to 14.0.0 (#46227)
This commit updates AIO to use the published 14.0.0 packages, as the final
step after the release.

PR Close #46227
2022-06-02 14:45:33 -07:00
George Kalpakas 36983a469a build(docs-infra): upgrade cli command docs sources to 847de3e7b (#46209)
Updating [angular#14.0.x](https://github.com/angular/angular/tree/14.0.x) from
[cli-builds#14.0.x](https://github.com/angular/cli-builds/tree/14.0.x).

##
Relevant changes in
[commit range](https://github.com/angular/cli-builds/compare/ecde3a2ae...847de3e7b):

**Modified**
- help/completion.json

PR Close #46209
2022-06-02 13:44:42 -07:00
Paul Gschwendtner 9a0a7bac21 perf(bazel): reduce input files for ng_package rollup and type bundle actions (#46187)
We currently use all the ESM2020 and type sources as inputs for rollup
and type bundle actions, respectively. This is a source of slowness in
Bazel sandboxed builds because many unused files will be linked/made
available for many concurrently-running actions.

We should limit the inputs only to what is assumed to be used. We cannot
know exactly and need to include transitive types from `node_modules`,
but that is an inevitable construct with the current Bazel rules.

Note that the external node modules could still bring in a lot of files,
like in Material where the `.d.ts` files for all locales are brought
into the sandbox (from `@angular/common`). We likely would need to
remove these files in a postinstall for now, to speed up actions,
similar to how we did it for RxJS in all repositories. These are known
to be not used in the components repo.

PR Close #46187
2022-06-02 13:43:22 -07:00
JoostK 67aca23bd4 refactor(common): remove unused method in internal SubscriptionStrategy interface (#46128)
The `onDestroy` method was not being called so this commit removes it entirely.

PR Close #46128
2022-06-02 13:42:38 -07:00
JoostK f35f01984a refactor(common): clear ChangeDetectorRef when AsyncPipe is destroyed (#46128)
To mitigate the effect of Observables with memory leak, this change clears
the `ChangeDetectorRef` when the `AsyncPipe` is destroyed. This avoids any
leak within the `Observable` to retain the view data. A test has been added
to verify that this change works correctly with promises that resolve _after_
the pipe has been destroyed.

Note: this is not marked as fix as `AsyncPipe` itself is _not_ leaking any
memory.

Closes #17624

PR Close #46128
2022-06-02 13:42:38 -07:00
JoostK d627b8f10b refactor(common): improve type of AsyncPipe._strategy field (#46128)
The field's type does not account for the `null` value that is assigned
in the field's initializer. This commit includes `null` in the type for
better type-safety. Exising reads are updated with a non-null assertion
operation in places where initialization is known to have occurred.

PR Close #46128
2022-06-02 13:42:38 -07:00
Kristiyan Kostadinov b497aa0cf7 refactor(core): minor ComponentDef improvements (#46093)
Makes the following improvements in the runtime:
* Uses the unique ID of the component definition to keep track of its injector in the `StandaloneFeature`, instead of the definition itself. This reduces the amount of memory we can leak, if something doesn't get cleaned up.
* Changes the naming and description of the `ComponentDef.id` to reflect what it is used for.

PR Close #46093
2022-06-02 13:41:28 -07:00
Kristiyan Kostadinov 19b4cc969d refactor(core): remove unused error handler logic (#46216)
There's some old logic in the error handler that tries to read an `ngErrorHandler` property off of the errors that are being logged. As far as I can tell, this is a ViewEngine leftover and it isn't actually being used anywhere.

PR Close #46216
2022-06-02 13:40:17 -07:00
Kristiyan Kostadinov 420fb46ad6 refactor(core): clean up closure deoptimization (#46149)
In #45445 function inlining had to be disabled on one of our instructions, because Closure wasn't optimizing it correctly, causing an error at runtime. The error has been resolved so we can remove the deoptimization hint.

PR Close #46149
2022-06-02 13:39:51 -07:00
Alex Rickabaugh 127e794885 fix(docs-infra): correct developer preview link (#46225)
The developer preview link was previously prefixed with the Github URL for
Angular's repo. However, it's meant to go to a guide page on AIO itself.
This commit removes the link prefix.

PR Close #46225
2022-06-02 12:35:14 -07:00
mgechev de49652fd7 docs: add blog post to the v14 release in changelog (#46226)
PR Close #46226
2022-06-02 12:33:28 -07:00
Alex Rickabaugh 6280a98ff1 release: cut the v14.0.0 release (#46223)
PR Close #46223
2022-06-02 09:53:02 -07:00
Alex Rickabaugh bf6b44be35 docs(core): mark the standalone APIs as Developer Preview (#46050)
This commit adds the new `@developerPreview` tag to all of the standalone
component related APIs. With this, AIO will show an API status label which
links to the documentation on Developer Preview.

PR Close #46050
2022-06-01 16:01:59 -07:00
Alex Rickabaugh c2c520341f feat(docs-infra): add @developerPreview tag for APIs in developer preview (#46050)
This commit adds a tag processor for `@developerPreview`. Adding this tag to
an exported symbol or to a decorator parameter causes an API status tag to
be shown for the API which links to the Developer Preview documentation.

PR Close #46050
2022-06-01 16:01:59 -07:00
Alex Rickabaugh e813f3c7e9 docs: replace Angular Labs with Developer Preview docs (#46050)
This commit updates the releasing/versioning doc on angular.io to cover the
new "Developer Preview" concept. This replaces the old section on the no-
longer-relevant "Angular Labs".

PR Close #46050
2022-06-01 16:01:59 -07:00
Andrew Kushnir 536939e138 docs(core): improve standalone-related docs and add more usage examples (#46202)
This commit updates the `bootstrapApplication` and the `importProvidersFrom` function docs with additional content that includes usage examples.

PR Close #46202
2022-06-01 11:08:04 -07:00
Andrew Scott 083a9c4dc4 docs(router): Adjust example for scrollPositionRestoration (#46201)
This makes a small update to the example so that it shows a use-case
that's not already covered by the 'enabled' option. The existing example
would get identical behavior to `scrollPositionRestoration: 'enabled'`
with `anchorScrolling: 'enabled'`.

The updated example shows a use-case for when custom scrolling _would_
be needed. For example, when data is fetched because it is not available
immediately or through a resolver. This is one of the cases described in #24547

This update is sufficient to address all of the documentation problems
noted in the aforementioned issue. Another fix should be made to address
the problem that scroll restoration needs to be delayed until after CD
has run so the update block of the activated component's template is
run.

PR Close #46201
2022-06-01 11:06:53 -07:00
George Looshch d982fa7da2 docs: replace double dashes with m-dashes, fix typos (#46174)
Fixes #46173

PR Close #46174
2022-06-01 11:02:43 -07:00
Andrew Scott 763c5f8991 release: cut the v14.0.0-rc.3 release (#46205) 2022-05-31 16:46:22 -07:00
Alex Rickabaugh 0111f6c75e docs: update release and update guides for v14 (#46200)
This commit adds content related to Angular v14 to the `releases.md` and
`update-to-latest-version.md` guides on AIO.

PR Close #46200
2022-05-31 15:17:22 -07:00
Andrew Kushnir c90193475f docs: add the Standalone guide link to API docs of component/directive/pipe decorators (#46184)
This commit adds the Standalone guide link to the `@Component`, `@Directive` and `@Pipe` decorator properties related to standalone functionality to improve discoverability of the guide as well as providing extra context in API docs.

PR Close #46184
2022-05-31 13:56:58 -07:00
Andrew Kushnir 51baa0b448 docs(core): improve inject function docs (#46168)
This commit updates the `inject` function docs by:
- rephrasing a description to include more usage cases
- adding usage examples
- making a function itself a public API (vs its alias const that was used previously)

PR Close #46168
2022-05-31 13:55:15 -07:00
Andrew Kushnir 19db22e911 test: drop no longer needed postinstall step from integration test apps (#46182)
This commit removed no longer needed postinstall step (to run ngcc) from integration test apps, to avoid extra processing.

PR Close #46182
2022-05-31 12:06:17 -07:00
Billy Lando fa358feef0 docs: replace broken <br/> from service worker (#46193)
PR Close #46193
2022-05-31 12:02:37 -07:00
Paul Gschwendtner 1dd58b5e2a ci: github robot should consider closure-locale.ts file as g3-synced file (#46177)
A recent PR to the Angular common closure-locale file generation
highlighted that the GitHub robot does currently not consider the
`closure-locale.ts` file as relevant for g3. The file is synced into
g3 and the robot should reflect that.

Note: The exclude/include patterns currently will include some of the
legacy/backwards-compatibility locale files, but these will never change
and can be removed in v15. For now it is acceptable to not overly
complicate the exclude/include lists for few files that never change.

PR Close #46177
2022-05-31 12:00:16 -07:00
Rune Andersen Hartvig 0a68506d77 docs: fix template example (#46170)
Fix a typo that prevents an example to show.
PR Close #46170
2022-05-31 11:59:49 -07:00
Matt Shaffer b8c15eb257 docs: rename stage to staging (#46164)
PR Close #46164
2022-05-31 11:59:20 -07:00
Matt Shaffer 416d535d1e docs: update example file name (#46164)
PR Close #46164
2022-05-31 11:59:20 -07:00
Andrew Kushnir ba9f30c9a6 fix(core): include component name into unknown element/property error message (#46160)
This commit adds the component name into unknown element/property error message, so that it's easier to find a location of a template where the problem happened.

Closes #46080.

PR Close #46160
2022-05-27 11:45:49 -07:00
Pawel Kozlowski 5dee53b352 docs: create a dedicated page for the NG0203 error (#46166)
Adds a dedicated error page for NG0203 (injection context).

PR Close #46166
2022-05-27 10:15:56 -07:00
Pawel Kozlowski 35653ce337 fix(core): add more details to the MISSING_INJECTION_CONTEXT error (#46166)
The MISSING_INJECTION_CONTEXT runtime error can be thrown when the
inject function is used outside of the class creation context.
Before this change we've only used a vague terms of the
'injection context'. This commit extends the error message to
indicate that we really talk about the class construction context.

PR Close #46166
2022-05-27 10:15:56 -07:00
George Kalpakas 12938577ef build(docs-infra): upgrade cli command docs sources to ecde3a2ae (#46158)
Updating [angular#14.0.x](https://github.com/angular/angular/tree/14.0.x) from
[cli-builds#14.0.x](https://github.com/angular/cli-builds/tree/14.0.x).

##
Relevant changes in
[commit range](https://github.com/angular/cli-builds/compare/b71844f36...ecde3a2ae):

**Modified**
- help/completion.json

PR Close #46158
2022-05-27 10:13:34 -07:00
Andrew Kushnir 560188bf12 fix(core): update unknown property error to account for standalone components in AOT (#46159)
This commit updates the error message to use correct info depending on whether a component is standalone or not. Previously we were always referring to @NgModules as a place to fix the issue, but not we also mention @Component when needed (for standalone components).

PR Close #46159
2022-05-27 10:12:27 -07:00
dario-piotrowicz d7c358139e docs: change wrong alert to callout (#46145)
change the alert present in the lifecycicle-hook docs to a callout so
that its header can be properly rendered (since alters don't support have headers)

PR Close #46145
2022-05-27 09:30:24 -07:00
Ian Gregory 568269f124 docs: close lightbox div to fix page display (#46155)
PR Close #46155
2022-05-26 17:42:54 -07:00
mgechev 136358f1a0 docs: fix incorrect title in the roadmap (#46140)
Ensure we're using h3 titles for consistency.

PR Close #46140
2022-05-26 17:42:26 -07:00
Alex Rickabaugh 724e88e042 fix(compiler-cli): preserve forwardRef for component scopes (#46139)
Angular generally supports cycles between components in the same NgModule.
We have a mechanism of moving the component scope declaration into the
NgModule file in this case. This ensures that Angular never itself
introduces an import which creates a cycle.

What happens if the cycle already exists in the user's program, though, is a
bit different. In these cases, the "correct" emit for Angular is to generate
the component scope (whether direct or remote) inside of a closure, to
prevent evaluating the scope's references until module evaluation is
complete and all cyclic imports have been resolved. We don't want to do this
for *all* scopes because the code size cost of emitting a function wrapper
is non-zero.

In this fix, we take the presence of a `forwardRef` in a component's
`imports` or in an NgModule `declarations` or `imports` as a sign that
component scopes emitted into those files need to be protected against
cyclic references. In a future commit, we may introduce a warning or error
if cyclic imports are not protected behind `forwardRef` in these cases, but
this will take some time to implement.

PR Close #46139
2022-05-26 17:42:02 -07:00
George Kalpakas 1798ce99b6 build(docs-infra): be able to resolve root-relative image URLs in getImageDimensions() (#46138)
Previously, `getImageDimensions()` would try to resolve image URLs
relative to the base path using `path.resolve()`. This resulted in
root-relative URLs (i.e. URLs starting with `/`) being treated as
absolute filesystem paths and thus resolving incorrectly
([example failure][1]).

This commit fixes it by using `.join()` instead, which is more
appropriate in this case. (Originally discussed [here][2].)

[1]: https://circleci.com/gh/angular/angular/1173150
[2]: https://github.com/angular/angular/pull/46134#issuecomment-1137191996

PR Close #46138
2022-05-26 11:25:10 -07:00
Andrew Kushnir 0bc77f4cab fix(core): better error message when unknown property is present (#46147)
Prior to this commit, the error message that was produced for the unknown property situation, din't contain extra info on how the problem can be fixed. This commit adds more info to the error message and makes it similar to the one we use during the AOT compilation.

PR Close #46147
2022-05-26 11:24:47 -07:00
Alex Rickabaugh 542d4c7805 release: cut the v14.0.0-rc.2 release (#46143)
PR Close #46143
2022-05-25 13:53:23 -07:00
Alex Rickabaugh ff172d2818 docs: release notes for the v13.3.10 release (#46142)
PR Close #46142
2022-05-25 13:43:01 -07:00
dario-piotrowicz ddce357d1d fix(core): improve TestBed declarations standalone error message (#45999)
improve the error message developers get when adding a standalone
component in the TestBed.configureTestingModule's declarations array,
by making more clear the fact that this error originated from the
TestBed call

resolves #45923

PR Close #45999
2022-05-25 12:20:52 -07:00
Renovate Bot ce66cfc765 build: update angular (#46120)
PR Close #46120
2022-05-25 12:18:05 -07:00
Kristiyan Kostadinov ab90d8dcc2 build: update to TypeScript 4.7 final (#46132)
Bumps up the repo to the final version of TypeScript 4.7. Also updates AIO to 4.7.

PR Close #46132
2022-05-25 11:37:12 -07:00
dario-piotrowicz af21c5f008 docs: fix &hellip; presented in aio code docs (#46123)
the symbol `&hellip;` displays correctly in code-example blocks and in
plain html text, it does however not work correctly for code espressed
using backticks, fix such occurrences by replacing `&hellip;` with `...`

PR Close #46123
2022-05-25 11:30:31 -07:00
mgechev 2360708cc0 docs: update the Angular roadmap as of May 2022 (#46117)
* Update project completion status
* Update project description based on state
* Add new projects to the future section

PR Close #46117
2022-05-25 11:23:56 -07:00
dario-piotrowicz 05fd839eb1 refactor(compiler-cli): fix "for to" typo in code comment (#46113)
fix the typo/extra for in a code comment saying
"this is used for to determine" so that it only says
"this is used to determine"

PR Close #46113
2022-05-24 10:52:20 -07:00
dario-piotrowicz 4204936b49 docs: replace wrong hyphen with # in aio cheatsheet (#46125)
replace the hyphen symbol wrongly used in the aio cheatsheet
doc to create a template variable with the proper # symbol

PR Close #46125
2022-05-24 10:49:55 -07:00
Roopesh Chinnakampalli 60a9910f05 docs: corrected the misspelled word (#46126)
innovation -> invocation
PR Close #46126
2022-05-24 10:47:48 -07:00
David Schmidt 97fe33866e docs: fix FormRecord example (#46124)
PR Close #46124
2022-05-24 10:47:07 -07:00
Aristeidis Bampakos c578aeec74 docs: align lightbox elements together (#46107)
Align lightbox `div` elements so that the image appears inside the lightbox correctly.

PR Close #46107
2022-05-24 10:45:55 -07:00
Jan Kuehle 21a04ef5be perf(bazel): use allowedInputs to avoid fs.stat (#46069)
Call tsc_wrapped's fileExists function instead of TypeScript's.

tsc_wrapped (used internally by ngc-wrapped) has an optimization under
bazel to avoid file system calls where possible. It takes advantage
bazelOpts.allowedInputs, which contains a list of all files available
for compilation.

File system calls can be quite slow depending on the file system. In
google3 I saw a 38 seconds compilation, which spent 6 seconds just doing
fs.stat calls during module resolution. Those fs.stat calls are entirely
gone after with this change.

PR Close #46069
2022-05-24 10:39:17 -07:00
dario-piotrowicz e03eb282cb docs: move all bazel testing info to a single location (#46084)
instead of presenting the same (or similar information) in both the
DEVELOPER.md and the BAZEL.md files, more all the information in the
BAZEL file and refer to that section in the DEVELOPER file

PR Close #46084
2022-05-23 13:59:08 -07:00
dario-piotrowicz d7912ca7d6 docs: update directives info to include standalone (#46078)
update the directives api doc to inform developers that
directives can also be declared as standalone

PR Close #46078
2022-05-23 13:54:11 -07:00
A. J. Javier 8cccc830d2 docs: fix angularfire2 hyperlink (#46046)
PR Close #46046
2022-05-23 13:52:14 -07:00
JoostK 21f1d5979d refactor(compiler-cli): report better error when a ModuleWithProviders call occurs within Component.imports (#46009)
This commit improves the reported error when importing e.g. `RouterModule.forRoot()`
from within `Component.imports`. Such import is not supported, as standalone components
can only refer to other standalone entities or NgModules in their `imports` array;
`ModuleWithProviders` are not supported as `Component.imports` is meant to be used
for the compilation scope of the component, _not_ for configuring DI.

Closes #46003

PR Close #46009
2022-05-23 13:50:06 -07:00
JoostK 61bfb7afba refactor(compiler-cli): extract ModuleWithProviders analysis out of NgModule handler (#46009)
This commit moves the foreign function resolver logic for detecting a
`ModuleWithProviders` in a return type position of a function call, as the logic can
then be reused for standalone components in a subsequent commit.

PR Close #46009
2022-05-23 13:50:06 -07:00
dario-piotrowicz bf340479ca feat(docs-infra): add group role and label for aio-notification (#45770)
add a role and an aria-label to the aio-notification component so that
it can be handled better by assistive technologies

resolves #44345

PR Close #45770
2022-05-23 13:48:31 -07:00
dario-piotrowicz 3654d7ab1a docs: make structural directives guide generic (#44895)
tweak the current structural directives guide (currently mainly targeted
at the creation of custom structural directives) so that is more generic
and a point of reference for structural directives in general

this also includes the re-addition of the one-per-element section
removed in PR #40015

resolves #44786

PR Close #44895
2022-05-23 13:44:43 -07:00
Aristeidis Bampakos b5ecae307e docs: remove broken code from TOH tutorial (#46105)
At the end of Part 2 of the Tour or Heroes tutorial, there is a code sample that is broken. It looks like it was added by mistake because it is not related to the summary.
PR Close #46105
2022-05-23 13:31:26 -07:00
Paul Gschwendtner c7683e1cbd ci: fix formatting for babel_ast_host.ts file after recent changes (#46082)
The formatting of the `babel_ast_host.ts` file is invalid due to a
recently-merged PR. The PR had a passing `lint` state but this seemed
to just appear like this because the Git comparison range on upstream
branches can become invalid (due to a known bug in CircleCI -- reported)

PR Close #46082
2022-05-23 13:30:39 -07:00
dario-piotrowicz 933f1945ed docs: add standalone details to NG8001 (#46079)
improve the degubbing section of the NG8001 error by including details
about standalone components

PR Close #46079
2022-05-23 13:28:49 -07:00
Tom Raithel 8ea4e1e6eb docs: fix division by zero in progress events example (#46077)
If the `event.total` is undefined, this line would have generated a `NaN` due to division by zero. I suppose, that a `0` would be more suitable for this case.

PR Close #46077
2022-05-23 13:27:48 -07:00
Paul Gschwendtner 3dec816276 build: fix unbound variable error in build artifact script (#46076)
We recently had a couple of issues with the shallowing of snapshot
git repositories. In an attempt to fix this, parts of the publish
script of the COMP repo have been used, but variables have not been
updated properly.

This commit fixes an unbound variable, avoiding errors when snapshots
are published for a new branch (e.g. when we branch-off).

PR Close #46076
2022-05-23 13:26:35 -07:00
Nathan Nontell 060d36f67a docs(docs-infra): update createComponent description to fix incorrect method name and invalid use of html escaping (#46074)
PR Close #46074
2022-05-23 13:21:48 -07:00
George Kalpakas 82399133cb build(docs-infra): update Angular Material to v14.0.0-rc.0 in AIO (#45997)
Update angular.io to the latest prerelease version of Angular Material
(v14.0.0-rc.0).

PR Close #45997
2022-05-23 13:20:11 -07:00
George Kalpakas c92b242f22 build(docs-infra): update Angular CLI/framework to v14.0.0-rc.0 in AIO (#45997)
Update angular.io to the latest prerelease versions of Angular CLI and
framework (v14.0.0-rc.0).

Also update angular.io to more closely align with new CLI apps. See also
the [diff][1] between a basic v13.0.0-next.9 CLI app and a v14.0.0-rc.0
one.

[1]: https://github.com/cexbrayat/angular-cli-diff/compare/13.0.0-next.9...14.0.0-rc.0

PR Close #45997
2022-05-23 13:20:11 -07:00
George Kalpakas 9d1f489542 build(docs-infra): update AIO payload sizes (#45997)
Update the AIO payload sizes to better see the impact in size of changes
in subsequent commits.

PR Close #45997
2022-05-23 13:20:11 -07:00
George Kalpakas 7059655a0b build(docs-infra): update Angular CLI/framework to v14.0.0-rc.0 in docs examples (#45997)
Update the docs examples to the latest prerelease versions of Angular
CLI and framework (v14.0.0-rc.0).

Also update the example apps to more closely align with new CLI apps.
See also the [diff][1] between a basic v13.0.0-rc.3 CLI app and a
v14.0.0-rc.0 one.

[1]: https://github.com/cexbrayat/angular-cli-diff/compare/13.0.0-rc.3...14.0.0-rc.0

PR Close #45997
2022-05-23 13:20:11 -07:00
dario-piotrowicz f2e5234e07 fix(compiler-cli): update unknown tag error for aot standalone components (#45919)
update the error message presented during aot compilation when an unrecognized
tag/element is found in a standalone component so that it does not mention
the ngModule anymore

Note: the jit variant is present in PR #45920

resolves #45818

PR Close #45919
2022-05-23 13:18:49 -07:00
Jerome Kruse 2949ae340c docs: update service-worker-config to more clearly describe behavior (#45909)
Fixes #45280

PR Close #45909
2022-05-23 13:17:53 -07:00
Andrew Kushnir 3172b4cc99 fix(core): produce proper error message for unknown props on <ng-template>s (#46068)
Currently for cases when an unknown structural directive is applied to `<ng-template>`s, an error message thrown by the framework doesn't contain a tag name, for example:

```
NG0303: Can't bind to 'unknownDir' since it isn't a known property of 'null'.
```

The underlying reason is that the tag name for the `<ng-template>` is not produced (`null` is useed as a value) by the compiler in case of inline templates and runtime logic relies on this effect.

This commit handles this situation when an error message is thrown, as the fastest way to improve the error message. More refactoring would be needed to avoid relying on the mentioned effect at runtime.

PR Close #46068
2022-05-23 10:03:24 -07:00
Thomas Mair 42db488ed7 fix(docs-infra): add member name to search index without ignore list (#46060)
Previously classs, interface and enum members where filtered with the default word ignore list. This lead to  poor search results if a search for a member on the ignore list was performed.

PR Close #46060
2022-05-23 09:56:10 -07:00
J Rob Gant 45ed2b7584 docs: Remove outdated note (#46022)
Component.styles can now use SCSS or LESS preprocessors.

PR Close #46022
2022-05-23 09:53:42 -07:00
Doug Parker b11a939e21 docs: add demo video for Angular CLI autocompletion doc (#45995)
The CLI autocompletion doc added in https://github.com/angular/angular-cli/pull/23146 includes a demo GIF, but AIO currently has no infrastructure to pull assets like images from the CLI repository, so this demo needs to be stored directly in AIO on this repository.

PR Close #45995
2022-05-23 09:30:45 -07:00
dario-piotrowicz df339d8abf fix(core): update unknown tag error for jit standalone components (#45920)
update the error message presented during jit compilation when an unrecognized
tag/element is found in a standalone component so that it does not mention
the ngModule anymore

Note: the aot variant is present in PR #45919

resolves #45818

PR Close #45920
2022-05-23 09:27:08 -07:00
Andrew Kushnir 701405fa71 fix(core): handle AOT-compiled standalone components in TestBed correctly (#46052)
Previously, the code in TestBed didn't take into account the fact that the `cmp.dependencies` array after the AOT compilation might contain regular (NgModule-based) Components/Directive/Pipes. As a result, some NgModule-specific code paths were invoked for non-NgModule types, thus leading to errors.

This commit updates the code to handle AOT-compiled structure of standalone components correctly.

PR Close #46052
2022-05-23 09:25:08 -07:00
Andrew Kushnir 4f1a813596 fix(core): restore NgModule state correctly after TestBed overrides (#46049)
This commit updates the NgModule logic to account for a case when a type has more than one generated def. This is a common situation for NgModules which have at least two: ɵmod and ɵinj. Previously, the second def was not stored before applying overrides, thus leaving it modified after the test, leaking the state as a result. This fix ensures that we store all defs before applying any overrides.

PR Close #46049
2022-05-23 09:23:12 -07:00
Pawel Kozlowski 2c52284e44 docs: add guide to standalone components preview (#46058)
Add a new page in developers guide section with the general
overview of the standalone components, directives and pipes
Additional APIs (bootstrapApplication, router, DI) as also
covered.

PR Close #46058
2022-05-23 09:15:06 -07:00
Joey Perrott 183b5f3fde build: update saucelabs key (#46089)
Update the saucelabs key for the newly generated key

PR Close #46089
2022-05-21 20:21:41 +00:00
Joey Perrott ad93c28889 build: update saucelabs key (#46088)
Update the saucelabs key for the newly generated key

PR Close #46088
2022-05-21 20:11:02 +00:00
Paul Gschwendtner f02ba99820 reactor(compiler-cli): account for babel types change (#45967)
This commit accounts for the Babel types changes. Some properties
can now also be `undefined` so existing checks/assertions had to
be adjusted to also capture `undefined` (along with `null`).

Additionally, in preparation for a new ECMA proposal, Babel types
seem to have been updated to include private names in object property
keys. This is not necessarily the case for object expressions, but
could be for object patterns (in the future -- when implemented).

More details: https://github.com/babel/babel/pull/14304 and
https://github.com/tc39/proposal-destructuring-private.

PR Close #45967
2022-05-20 14:18:10 -07:00
Paul Gschwendtner 45eb491a25 build: update api-extractor to avoid crash for properties without explicit type (#45967)
API extractor crashes got fixed with
https://github.com/microsoft/rushstack/pull/3424.

PR Close #45967
2022-05-20 14:18:10 -07:00
Paul Gschwendtner 054cb99421 build: lock file maintenance to avoid node module differences for babel types (#45967)
We recently updated Babel and the Bazel types but this actually
resulted in duplicates, causing differences between what people
seen in their IDE vs. what Bazel builds.

This commit removes the lock file and generates it fully fresh,
deduping dependencies and also fixing the differences between
local IDE and Bazel.

As part of this we also need to update/fixup one assertion on the
Babel node path types, because the node start/end can now also
be `undefined`.

PR Close #45967
2022-05-20 14:18:10 -07:00
Renovate Bot 05f0cd7727 build: update all non-major dependencies (#45967)
PR Close #45967
2022-05-20 14:18:10 -07:00
Dylan Hunn 2e96cede3e fix(forms): Warn on FormControls that are constructed with both options and asyncValidators.
DEPRECATED:

It is now deprecated to provide *both* `AbstractControlOption`s and an async validators argument to a FormControl. Previously, the async validators would just be silently dropped, resulting in a probably buggy forms. Now, the constructor call is deprecated, and Angular will print a warning in devmode.
2022-05-19 15:50:18 -07:00
Dylan Hunn 39be06037d fix(forms): Add a nonNullable option to FormControl for consistency.
DEPRECATED:

The `initialValueIsDefault` option has been deprecated and replaced with the otherwise-identical `nonNullable` option, for the sake of naming consistency.
2022-05-19 15:50:08 -07:00
George Kalpakas 2bc65351b4 docs: fix inline JSDoc tags (@see --> @link) (#46040)
In some places, the [@see][1] JSDoc tag was incorrectly used instead of
the [@link][2] inline tag, leading to warnings during doc generation and
the `@see` tags being ignored (and thus shown in the docs as is).
Replace the `@see` tags with the intended `@link` tags.

[1]: https://jsdoc.app/tags-see.html
[2]: https://jsdoc.app/tags-inline-link.html

PR Close #46040
2022-05-19 13:32:20 -07:00
Jessica Janiuk 8869fce1a4 release: cut the v14.0.0-rc.1 release (#46044) 2022-05-18 12:06:27 -07:00
Andrew Scott 74ff3b55c1 test(router): Add tests for initialNavigation: enabledBlocking (#45733)
Adds additional tests to verify `enabledBlocking` functionality. The
initial attempt to fix #44355 would have broken the scenario where a new
navigation cancels the initial navigation. We also cannot rely on
`NavigationError` like the example workaround in that issue report is
doing because there won't be one if a guard simply rejects
the initial nav (#16211).

PR Close #45733
2022-05-18 08:57:30 -07:00
Alex Rickabaugh 35f20afcac fix(compiler-cli): use existing imports for standalone dependencies (#46029)
This commit fixes a small issue in the logic around the calculation of
template scopes for standalone components. These scopes include a
`Reference` for each dependency of a standalone component, which is used to
generate references to that dependency in various contexts.

Previously, the `Reference` used for a dependency was the one generated from
its own metadata. For example, a referenced directive used the `Reference`
that was created when analyzing the directive declaration itself. This still
works, as the compiler is always able to emit a reference to any valid
`Reference`. However, it's not optimal.

The `Reference` which should be used instead is the one generated from
analyzing the standalone component's `imports` array, which has knowledge of
how the dependency is referenced from within the standalone component's file
itself. This allows the compiler to skip creating a new import for the
dependency when emitting the standalone component, and use the existing,
user-authored import instead. This saves on code size and avoids taxing the
bundler with unnecessary imports.

PR Close #46029
2022-05-18 08:55:32 -07:00
Alex Rickabaugh a524a50361 fix(compiler-cli): handle standalone components with cycles (#46029)
The Angular compiler performs cycle detection when generating imports within
component files. This was previously necessary as reifying dependencies
discovered via NgModules into the component output could add imports that
weren't present in the original component and potentially create cycles.
Doing this could cause order-of-execution issues with existing user imports,
so the compiler detects this case and falls back to an alternative way of
specifying component dependencies that doesn't risk creating cycles.

For standalone components, Angular does not need to add new imports to the
component file as the user has already explicitly referenced dependencies
in the `@Component.imports`. As a result, the cycle detection can be
skipped.

Correctly authoring a program with import cycles is always challenging. One
side of a cyclic import will always initially evaluate to `undefined`, and
this can result in errors in the component definition when this happens
within component `imports`.

Our compiler _could_ detect the cycle and choose to wrap the component
dependencies in an automatic closure instead, avoiding any issues with
`undefined` during an eager evaluation. However, this commit makes an active
choice not to do that as it only serves to mask the problems with cyclic
imports. Future refactorings may cause the "other half" of the cycle to
break. Users should instead be aware of the potential problems with cycles
and explicitly defer evaluations with `forwardRef` where needed. This
ensures that future implementations of Angular compilation which may not be
able to automatically detect import cycles and correct accordingly can still
compile such components.

PR Close #46029
2022-05-18 08:55:31 -07:00
Dylan Hunn 37dbe55945 revert "fix(forms): Value and RawValue should be part of the public API." (#46023)
As per discussion on #fw-forms, this reverts #45978 (although the more in-depth comments were kept).

PR Close #46023
2022-05-17 22:48:03 +00:00
Dylan Hunn cb479bfa46 docs(forms): Make some fixes to typed forms docs: (#46023)
* `FormRecord` jsdocs should now appear on a.io
* The `{@see foo#bar}` syntax previously did not work, and has been replace with backticks

PR Close #46023
2022-05-17 22:48:03 +00:00
George Kalpakas 5a04963305 docs: explicitly specify a version in the CLI install command (#46020)
Update the CLI install command in the CLI overview page to explicitly
specify a version. This ensures that the version installed is
appropriate for the version of the docs (e.g. installing CLI v12.x when
following the v12 docs) and it consistent with the `setup-local` guide.

PR Close #46020
2022-05-17 18:28:32 +00:00
George Kalpakas f92add1157 fix(docs-infra): correctly style the CLI version in code snippet (#46020)
Some CLI versions (such as `@next`) are not parsed (and thus not
formatted) correctly in code snippets. Fix this by explicitly adding an
appropriate CSS class to the `<aio-angular-dist-tag>` elements to let
PrettyPrint know how to style this token.

PR Close #46020
2022-05-17 18:28:32 +00:00
Bob Watson 338de1b4cf docs: remove Narco from hero list in code, text, and images (#46008)
Fixes issue #45769

Removes the malevolent comic book character, "Narco," from the list of heroes. This change removes the reference from the code, text and screenshots used in the documentation and makes other minor edits as necessary.

PR Close #46008
2022-05-17 17:47:05 +00:00
Renovate Bot 79025a69ba build: update angular (#46016)
PR Close #46016
2022-05-17 08:58:58 -07:00
Virginia Dooley add2bb8e89 docs: add template overview doc (#45897)
Organize bottom list into cards.

PR Close #45897
2022-05-16 16:07:35 -07:00
Virginia Dooley 29ac86deb8 docs: update links and TOC (#45897)
Update links and TOC for updated content.

PR Close #45897
2022-05-16 16:07:35 -07:00
Virginia Dooley 2d444db6b4 docs: updated Property binding doc (#45897)
Refined and edited as a task-based document with the assistance
of the SME
Add missing prerequisites and what's next sections

PR Close #45897
2022-05-16 16:07:35 -07:00
Virginia Dooley b8e27fafa1 docs: updated Event binding doc (#45897)
Document updated with the assistance of the SME.
Add missing prerequisites and what's next sections
Make suggested changes to Event binding doc.

PR Close #45897
2022-05-16 16:07:35 -07:00
Virginia Dooley 97e90f8470 docs: new binding overview doc (#45897)
New binding overview doc. Content derived from existing docs.
Make changes suggested in PR for binding overview doc.
Deleted bottom paragraph from Binding overview per comments made by
atscott and alxhub.

PR Close #45897
2022-05-16 16:07:35 -07:00
Virginia Dooley c14c5fcb86 docs: Text interpolation doc amended to be task-based (#45897)
Rewrite document as task-based
Add prerequisites and What's next sections.
Content edited with the assistance of the SME.

PR Close #45897
2022-05-16 16:07:35 -07:00
Virginia Dooley af5b3c181a docs: new Pipes in templates doc (#45897)
New using a Pipe in a template document.
Content taken from the original Pipes document.
Content edited with the assistance of the SME.

PR Close #45897
2022-05-16 16:07:35 -07:00
Virginia Dooley 3e2b443b20 docs: Pipes transform data new doc (#45897)
New Transforming data with pipes document.
Content taken from the original Pipes document.
Content edited with the assistance of the SME.

PR Close #45897
2022-05-16 16:07:35 -07:00
Virginia Dooley 29ad2aa44b docs: Understanding pipes new doc (#45897)
New overview file using the Understanding… format.
The original Pipes document was considered too long and
was broken down into several separate topics.
Content edited with the assistance of the SME.

PR Close #45897
2022-05-16 16:07:35 -07:00
Virginia Dooley 063fc8cde3 docs: new Template expressions overview doc (#45897)
Create a new Template expressions overview doc in the Understanding...
format.

PR Close #45897
2022-05-16 16:07:35 -07:00
Virginia Dooley 4b2c3617d0 docs: class-binding created as a separate task-based doc (#45897)
Class and style binding was pulled out of Attribute, class, and style
binding doc and put in its own doc.
Content edited with the assistance of the SME.
Prerequisites and What's next sections were added.

PR Close #45897
2022-05-16 16:07:35 -07:00
Virginia Dooley e56e6d6166 docs: Attribute binding changed to include attribute binding only (#45897)
Attribute document broken down into two separate documents:
1) Attribute binding
2) Class and style binding
Content edited with the assistance of the SME.

PR Close #45897
2022-05-16 16:07:34 -07:00
Virginia Dooley 5879e4616f docs: Understanding template variables updated (#45897)
This converts the "Template variables" doc to the new "Understanding"
format and remove some irrelevant content.

PR Close #45897
2022-05-16 16:07:34 -07:00
Joey Perrott 3c690bc1e9 build: use updated commit sha for github actions (#46010)
Update the commit sha for the dev-infra github actions.

PR Close #46010
2022-05-16 14:12:21 -07:00
Dylan Hunn 018550ed50 fix(forms): Value and RawValue should be part of the public API. (#45978)
Consider a typed group for storing contact information:

```
declare interface ContactControls {
	name: FormControl<string|null>;
}

contactForm: FormGroup<ContactControls> = ...;

saveForm(form: FormGroup<ContactControls>) {
	service.newContact(contactForm.value);
}
```

What should be the type of `newContact`? The answer, of course, is the value type:

```
declare interface Contact {
	name: string|null;
}

class ContactService {
	newContact(c: Contact) {}
}
```

This is quite redundant, and therefore, we should allow the value type to be generated automatically. We already have the helper types to do this -- we just need to document and export them. Then, this becomes possible:

```
class ContactService {
	newContact(c: RawValue<FormGroup<ContactControls>>) {}
}
```

PR Close #45978
2022-05-16 18:36:54 +00:00
4javier 39a1364e43 docs(devtools): add firefox extension references (#45985)
add a link to recent deployed firefox extension and use less specific terminology
PR Close #45985
2022-05-16 18:04:52 +00:00
Andrew Kushnir 9b97b840af refactor(core): avoid code duplication in standalone-related logic (#45949)
This commit updates the standalone-related logic to address the feedback from previous code reviews (specifically: https://github.com/angular/angular/pull/45687#discussion_r854499586).

PR Close #45949
2022-05-16 10:05:23 -07:00
Andrew Kushnir 5e71f2abc0 refactor(core): tree-shake away a DI error message string in prod bundles (#45994)
This commit adds the `ngDevMode` check to tree-shake away an error message string (which also retains a reference to an extra function).

PR Close #45994
2022-05-16 10:04:57 -07:00
ivanwonder 3ae133c69e fix(language-service): Fix detection of Angular for v14+ projects (#45998)
In v14, the .d.ts file for angular core is now "index.d.ts" rather than "core.d.ts".

This change happened in https://github.com/ng-packagr/ng-packagr/commit/c6f6e4d701d31e3d9e8636703ede731c3790778b

PR Close #45998
2022-05-16 10:03:53 -07:00
mariu 9cd2626e63 docs: add transparency to Ecosystem image (#45993)
PR Close #45993
2022-05-16 09:37:37 -07:00
George Kalpakas f1a15dadfa test(docs-infra): ensure examples are split correctly across shards (#46005)
Previously, the examples were split across shards based on the order in
which `globby()` returned them. This was based on the assumption that
`globby()`/the OS would list files in a deterministic order. However, it
turns out that examples can be listed in different orders between
executions, leading in them not being split correctly across shards on
CI (which further means that some examples may be tested multiple times
and others may not be tested at all).
You can see an example [here][1], where the `getting-started` example is
tested in both the 4th and 5th shards.

This commit fixes this by explicitly sorting the examples based on their
path.

[1]: https://circleci.com/gh/angular/angular/1165448

PR Close #46005
2022-05-16 09:35:46 -07:00
Joey Perrott 333c23d0d9 build: set up post approval changes commit action (#46006)
This action will enforce that all pull requests receive an approval from
at least one googler on the final commit for the pull request. Historically,
we have allowed all post approval changes regardless of authorship. Moving
forward, with this change, we will only allow known googlers to perform
post approval changes.

When a post approval change occurs by a non-googler, the action will
automatically rerequest a review from the latest googler who provided
an approval on the change.

PR Close #46006
2022-05-16 09:33:36 -07:00
celinetunc 19018ca61e docs: add selin tunc to contributors (#45989)
PR Close #45989
2022-05-13 15:05:04 -07:00
Pavan Kumar Jadda bcef46d83e docs: adds ngx-cookie-service library to resources list (#45955)
PR Close #45955
2022-05-13 20:08:11 +00:00
Andrew Scott 77c9508e51 refactor(router): Only create the Route injector when the path matches (#45990)
Currently, the `Router` will create the `EnvironmentInjector` for a
`Route` with `providers` as soon as it _attempts_ to match segments to
the `Route`. Instead, this change updates the logic to only create the
injector once we have confirmed that the `Route` matches. Note that this
will include partial matches where the final navigation still fails with
a "cannot match any routes to segment" error. We need to maintain the
injector hierarchy so we still need to create parent injectors before
descending into the child routes and determining if there is a full
match or just a partial one.

resolves #45988

PR Close #45990
2022-05-13 12:19:16 -07:00
Alex Rickabaugh 3f7ecec59b fix(core): set correct context for inject() for component ctors (#45991)
The `inject()` function was introduced with Ivy to support imperative
injection in factory/constructor contexts, such as directive or service
constructors as well as factory functions defined in `@Injectable` or
`InjectionToken`. However, `inject()` in a component/directive constructor
did not work due to a flaw in the logic for creating the internal factory
for components/directives.

The original intention of this logic was to keep `ɵɵdirectiveInject` tree-
shakable for applications which don't use any component-level DI. However,
this breaks the `inject()` functionality for component/directive
constructors.

This commit fixes that issue and adds tests for all the various cases in
which `inject()` should function. As a result `ɵɵdirectiveInject` is no
longer tree-shakable, but that's totally acceptable as any application that
uses `*ngIf` or `*ngFor` already contains this function. It's possible to
change how `inject()` works to restore this tree-shakability if needed.

PR Close #45991
2022-05-13 11:57:44 -07:00
Evan Lee 45fedb50c4 docs: remove Angular 11 from support table (#45980)
PR Close #45980
2022-05-13 11:18:52 -07:00
Kristiyan Kostadinov 25fde5db4c build: update to TypeScript 4.7 RC (#45966)
Bumps up the repo to the RC version of TypeScript 4.7.

PR Close #45966
2022-05-13 09:36:46 -07:00
Joey Perrott 42ab829684 build: manually unshallow the repo for builds publishing, use absolute paths (#45979)
Use the absolute path for the artifacts directory, as well as encapsulate the clone
vs init logic to prevent it from changing directories.

Manually remove the shallow marker so that git does not recognize this as a shallow repo.

PR Close #45979
2022-05-13 09:07:53 -07:00
Joey Perrott 4e82bcd08c build: use clone instead of init for creating the builds commit changes (#45975)
Rather than using git init to create an empty repo and then shallow fetch the
repo for a specific branch, we shallow clone the repository itself for the branch.
This prevents us from running into the issue of Github denying the push because it
comes from a shallow branch which does not map back to the repository.

PR Close #45975
2022-05-12 20:31:46 +00:00
Joey Perrott d7ad280941 build: set the default branch of the ephemeral repo for publishing build artifacts to main (#45974)
It looks like because the primary branch for our ephemeral repos doesn't match the build repos
we are pushing to it causes errors around shallow clones.  This attempts to prevent this.

PR Close #45974
2022-05-12 19:39:38 +00:00
Andrew Scott 9cd8e50848 fix(language-service): Prevent TSServer from removing templates from project (#45965)
As part of the `updateProjectIfDirty` process and inside `updateNonInferredProjectFiles`
TS Server will remove the template files that we added as roots in
`readResource`.
https://sourcegraph.com/github.com/microsoft/TypeScript@c300fea3250abd7f75920d95a58d9e742ac730ee/-/blob/src/server/editorServices.ts?L2363

The external files are added to the list here so ensuring that the
templates are included in the `getExternalFiles` will prevent this from
happening
https://sourcegraph.com/github.com/microsoft/TypeScript@c300fea3250abd7f75920d95a58d9e742ac730ee/-/blob/src/server/editorServices.ts?L2395:18

PR Close #45965
2022-05-12 09:25:21 -07:00
George Kalpakas b056f1b823 fix(docs-infra): do not detect a running job as failed (#45948)
Previously, the preview server would incorrectly identify a running
`aio_preview` CI job as failed and therefore skip creating a preview.
This happened because it only checked whether the job's status is
`success`, failing to account for the fact that the job would have a
`running` status.
(This bug was accidentally introduced in #45934.)

This commit avoids the problem by getting rid of the job status check
altogether. This check does not offer any benefit, since the CI job will
always be in a `running` state (i.e. neither successfully completed nor
failed).

PR Close #45948
2022-05-12 09:02:06 -07:00
Roy Dorombozi 1c0d0f0579 refactor(bazel): add support for starlark's unused_inputs_list (#45946)
This change adds the capability of ngc_wrapped to emit an
unused_inputs_list file that could be used by starlark.

We are making this change because in situations where angular modules
depend on angular modules, it becomes very easy for a single change to
trigger a long cascading set of angular builds since each angular rule
depends on the transitive closure of input files.

With this change in place, and once it is properly configured, bazel
will update the set of inputs to a build rule after it is built once
removing any of the inputs specified in this list, making incremental
builds quicker by skipping any rebuilds that only had changes to unused
inputs.

This logic should be, and is likely duplicated in tsc_wrapped to solve
the same problem in pure TypeScript situations, ideally we could use the
same implementation one day.

In addition, its possible that tree artifacts are not as supported as
we'd like, and where this change should mark entire directories as
unused, we may get better performance gains by enumerating the directory
and being more explicit about specific inputs which are unused.

PR Close #45946
2022-05-11 11:21:56 -07:00
Dylan Hunn ffbf6b67ac docs: Add a guide for typed forms. (#45939)
Create a new page, which describes the basic features of the new reactive forms types, and describes how to migrate to them.

PR Close #45939
2022-05-11 11:14:25 -07:00
Andrew Kushnir c3c82b69fb release: cut the v14.0.0-rc.0 release 2022-05-11 10:31:39 -07:00
Ted.chang f70b84f755 docs: add NGX-YOUI website to resources list (#45810)
PR Close #45810
2022-05-10 16:03:38 -07:00
Andrew Kushnir 51e3722e77 test(core): reset Testability getter after each test (#45947)
This commit updates the Testability-related tests to reset the testability getter class after each test to avoid leaking the state between tests. This should improve the stability of the testability tests that are currently flaky on CI.

PR Close #45947
2022-05-10 16:02:53 -07:00
Renovate Bot 1d3cf22abb build: update angular to f557392 (#45941)
PR Close #45941
2022-05-10 13:36:12 -07:00
Andrew Kushnir 23c4c9601e perf(platform-browser): avoid including Testability by default in bootstrapApplication (#45885)
The Testability-related logic was refactored in https://github.com/angular/angular/pull/45657 to become tree-shaking-friendly: it was decoupled from the core providers of the `BrowserModule`. This commit updates the newly-introduced `bootstrapApplication` function to exclude Testability-providers by default (note: the Testability is still included in the NgModule-based bootstrap).

In order to add the Testability to the app bootstrapped via `bootstrapApplication`, the `provideProtractorTestingSupport` function is introduced.

PR Close #45885
2022-05-10 13:34:29 -07:00
Dylan Hunn 9f6fa5b746 fix(forms): Prevent FormBuilder from distributing unions to control types. (#45942)
Previously, using `FormBuilder` with a union type would produce unions of *controls*:

```
// `foo` has type `FormControl<string>|FormControl<number>`.
const c = fb.nonNullable.group({foo: 'bar' as string | number});
```

This actually works in many cases, due to how extraordinarily powerful Typescript's distributive types are (e.g. `value` still has type `string|number`), but it is subtly incorrect. Here is a code example that exposes the reason the inference is incorrect. It exploits the fact that Typescript will not "un-distribute" a type, producing an obviously spurious error:

```
// fc gets an inferred distributive union type `FormControl<string> | FormControl<number>`
let fc = c.controls.foo;
// Error: Type 'FormControl<string | number>' is not assignable to type 'FormControl<string> | FormControl<number>'.
fc = new FormControl<string|number>('', {initialValueIsDefault: true});
```

Instead, we want the union to apply to the *values*:

```
// `foo` should have type `FormControl<string|number>`.
const c = fb.nonNullable.group({foo: 'bar' as string | number});
```

Essentially, we want to prevent Typescript from distributing the type. [As specified in the handbook](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types):

> Typically, distributivity is the desired behavior. To avoid that behavior, you can surround each side of the extends keyword with square brackets.

This PR applies this suggestion to `FormBuilder`'s type inference.

Fixes #45912.

PR Close #45942
2022-05-10 12:36:37 -07:00
Kristiyan Kostadinov 7dd6450a26 refactor(core): remove ManualOnPush change detection (#45943)
We've had a TODO to expose ManualOnPush for a long time, but it hasn't moved since then. These changes remove it since it would be easy to re-introduce if we wanted to, it frees up an extra space in the flags bitmap and it removes some `render3` tests that we won't have to migrate to `TestBed`.

PR Close #45943
2022-05-10 09:37:07 -07:00
Andrew Scott 13fad9febe fix(language-service): Add resource files as roots to their associated projects (#45601)
When an external template is read, adds the template file to to the project which contains.
This is necessary to keep the projects open when navigating away from HTML files.
Since a `tsconfig` cannot express including non-TS files,
we need another way to indicate the template files are considered part of the project.

Note that this does not ensure that the project in question _directly_ contains the component
file. That is, the project might just include the component file through the program rather
than directly in the `include` glob of the `tsconfig`. This distinction is somewhat important
because the TypeScript language service/server prefers projects which _directly_ contain the TS
file (see `projectContainsInfoDirectly` in the TS codebase). What this means it that there can
possibly be a different project used between the TS and HTML files.

For example, in Nx projects, the referenced configs are `tsconfig.app.json` and
`tsconfig.editor.json`. `tsconfig.app.json` comes first in the base `tsconfig.json` and
contains the entry point of the app. `tsconfig.editor.json` contains the `**.ts` glob of all TS
files. This means that `tsconfig.editor.json` will be preferred by the TS server for TS files
but the `tsconfig.app.json` will be used for HTML files since it comes first and we cannot
effectively express `projectContainsInfoDirectly` for HTML files.

We could consider also updating the language server implementation to attempt
to select the project to use for the template file based on which project
contains its component file directly, using either the internal `project.projectContainsInfoDirectly`
or as a workaround, check `project.isRoot(componentTsFile)`.

Finally, keeping the projects open is hugely important in the solution style config case like
Nx. When a TS file is opened, TypeScript will only retain `tsconfig.editor.json` and not
`tsconfig.app.json`. However, if our extension does not also know to select
`tsconfig.editor.json`, it will automatically select `tsconfig.app.json` since it is defined
first in the `tsconfig.json` file. So we need to teach TS server that we are (1) interested in
keeping projects open when there is an HTML file open and (2) optionally attempt to do this
_only_ for projects that we know the TS language service will prioritize in TS files (i.e.,
attempt to only keep `tsconfig.editor.json` open and allow `tsconfig.app.json` to close)
and prioritize that project for all requests.

fixes https://github.com/angular/vscode-ng-language-service/issues/1623
fixes https://github.com/angular/vscode-ng-language-service/issues/876

PR Close #45601
2022-05-10 09:36:30 -07:00
Dylan Hunn 5d13e58aed fix(forms): Allow NonNullableFormBuilder to be injected. (#45904)
Based on early feedback, calling `fb.nonNullable.group(...)` continues to be clunky for a form with many such groups. Allowing `NonNullableFormBuilder` to be directly injected enables the following:

```
constructor(private fb: NonNullableFormBuilder) {}
```

PR Close #45904
2022-05-09 17:31:48 -07:00
mgechev 4a173eb3f8 docs: simplify the DevTools readme and add publishing instructions (#45905)
Remove duplicate information. Add publishing instructions for Firefox
and Chrome.

PR Close #45905
2022-05-09 13:58:06 -07:00
mgechev 8e9efbd1f2 docs: add the change detection guide to the navigation and pullapprove (#45880)
PR Close #45880
2022-05-09 13:56:38 -07:00
mgechev f76bf8a27d docs: add a guide on using OnPush change detection strategy (#45880)
Explain how to use OnPush change detection strategy and what are the
different edge cases. Looks into several different scenarios and covers
the behavior of OnPush for each one of them.

PR Close #45880
2022-05-09 13:56:38 -07:00
mgechev 6984dde030 docs: add a guide on optimizing slow computations (#45880)
Add a guide that explains:
- How we can slow the change detection down
- How to discover slow computations with Angular DevTools
- Explain how to fix slow computations

PR Close #45880
2022-05-09 13:56:38 -07:00
mgechev 9afb6e31a4 docs: add guide on how to run code outside of NgZone (#45880)
Explain the relationship between Angular and Zone.js. Covers how to
discover code that triggers change detection more often than we have to
run it and explain how to run code outside the Angular zone.

PR Close #45880
2022-05-09 13:56:38 -07:00
mgechev fbf6f1f9bf docs: add general change detection overview (#45880)
Add a few paragraphs with introduction to how change detection works
referencing a video for further details.

PR Close #45880
2022-05-09 13:56:38 -07:00
Andrew Kushnir 13eb6ca1bf ci: enable the aio_preview CircleCI job (#45935)
This reverts commit dbc0dababa, since the fix has landed in https://github.com/angular/angular/commit/c4340970c7a6419eee28804c9b82254dbcf59315.

PR Close #45935
2022-05-09 12:33:36 -07:00
JayMartMedia 6ec6c87ce1 docs: remove unnecesarry backslash from pipes documentation (#45916)
There was an extra backslash in the description of the pipe character. This could be misleading as people could think that the backslash is a pipe character.

PR Close #45916
2022-05-09 12:08:06 -07:00
JayMartMedia bfe6985d1e docs: fix bold text in start-data (#45916)
PR Close #45916
2022-05-09 12:08:06 -07:00
JoostK e9317aee71 perf(core): allow checkNoChanges mode to be tree-shaken in production (#45913)
This commit guards all logic that exists for the `checkNoChanges` mode
with `ngDevMode` checks such that the logic can be tree-shaken.

PR Close #45913
2022-05-09 12:04:04 -07:00
Cédric Exbrayat fbf42ed9d8 refactor(core): declare TestModuleMetadata as an interface (#45891)
This allows the documentation for the options `errorOnUnknownElements` and `errorOnUnknownProperties` to be displayed in the docs.
They aren't currently displayed, as `TestModuleMetadata` is a type and not an interface.
See https://next.angular.io/api/core/testing/TestModuleMetadata

PR Close #45891
2022-05-09 11:56:18 -07:00
Andrew Kushnir 216af1c234 ci: update NgBot to sync internal and external configs (#45915)
There was a difference in the set of paths between check/sync scripts internally and externally.
This commit aligns both configurations.

PR Close #45915
2022-05-09 11:55:40 -07:00
Thomas Mair a267484cde refactor(docs-infra): remove unnecessary types for stemmer dependency (#45831)
NOTE:
Since version 2.0.0 stemmer includes its own typings (see https://github.com/words/stemmer/commit/cd6fd9a0319bd7f44dc09ed40614fa807fe28535)

PR Close #45831
2022-05-09 11:54:58 -07:00
George Kalpakas 57d1bc09be fix(docs-infra): handle CircleCI API v2 responses in preview server (#45934)
In PR #45349 we switched to using version 2 of the CircleCI API. It
turns out that this version of the API (in addition to different URLs)
also returns different info from some endpoints, which we have failed to
account for.

More specifically, the v2 API response for a job does not contain info
that we need in [BuildRetriever][1].

As an example, see the API responses for an `aio_preview` run:
- [API v1.1][2]
- [API v2][3]

This commit updates the code to handle API v2 responses. In addition,
since the info we need is not present in the job info (as it was with
the previous version of the API), we now also retrieve the pipeline
info.

NOTE:
This issue did not manifest earlier, because the preview server code on
the VM was not updated to the latest version (that tried to use API v2)
due to a different error. This error was fixed with PR #45895, which
allowed the preview server to be updated on the VM and uncovered the API
v2 incompatibility.

[1]: https://github.com/angular/angular/blob/baa3e18812127e7266580f4cd202a4cb3204cbcb/aio/aio-builds-setup/dockerbuild/scripts-js/lib/preview-server/build-retriever.ts#L39-L45
[2]: https://circleci.com/api/v1.1/project/github/angular/angular/1163816
[3]: https://circleci.com/api/v2/project/gh/angular/angular/job/1163816

Fixes #45931

PR Close #45934
2022-05-09 11:54:12 -07:00
Andrew Kushnir ac7f0460f9 ci: enable Android 12 for tests on CI (#45926)
This commit updates SauceLabs config to use Android 12 and drop Android 10, so we maintain 2 most recent versions according to https://angular.io/guide/browser-support.

Closes #45925.

PR Close #45926
2022-05-09 11:26:10 -07:00
dario-piotrowicz 4d27448f21 docs(docs-infra): clarify toh-2 error message (#45878)
the second step of the tour of heroes refers to a runtime error which
generally isn't presented to new users since it gets caught by the
TypeScript compiler's strict mode, clarify such detail so not to confuse
readers

resolves #45759

PR Close #45878
2022-05-09 11:23:28 -07:00
George Kalpakas eae93b235f docs: fix code snippets in TOH (part 5) "Final code review" section (#45830)
Fixes #45736

PR Close #45830
2022-05-09 11:18:21 -07:00
George Kalpakas 883194a3f8 docs: fix ellipsis in code-snippet in creating-libraries guide (#45820)
When hard-coding content in a `<code-example>` tag inside an `.md` file,
the content is treated as HTML by the Markdown processor and thus any
characters with special meaning in HTML have to be encoded (or replaced
with HTML entities).

However, the content that is embedded into `<code-example>` tags via
docregions is treated as text (since it is not parsed by the Markdown
processor) and thus should not have encoded characters or HTML entities.

PR Close #45820
2022-05-09 11:08:49 -07:00
Andrew Kushnir 663c1f905e ci: disable aio_preview CircleCI job temporarily (#45932)
This commit disables the `aio_preview` CircleCI job temporarily, since it's failing after switching to CircleCI API v2. It will be enabled back once the code is updated. More info can be found here: https://github.com/angular/angular/issues/45931

PR Close #45932
2022-05-09 11:06:54 -07:00
ᚷᛁᛟᚱᚷᛁ ᛒᚨᛚᚨᚲᚻᚨᛞᛉᛖ eb511d9c3f docs: remove redundant word (#45910)
PR Close #45910
2022-05-06 09:52:21 -07:00
Paul Gschwendtner 141bb16632 ci: update github robot config to reflect update in syncing (#45907)
The `ng_module` Starlark code is not used internally, just
`ngc-wrapped`.

PR Close #45907
2022-05-06 09:51:49 -07:00
George Kalpakas 74a2e2e2ec fix(ngcc): cope with packages following APF v14+ (#45833)
In PR #45405, the Angular Package Format (APF) was updated so that
secondary entry-points (such as `@angular/common/http`) do not have
their own `package.json` file, as they used to. Instead, the paths to
their various formats and types are exposed via the primary
`package.json` file's `exports` property. As an example, see the v13
[@angular/common/http/package.json][1] and compare it with the v14
[@angular/common/package.json > exports][2].

Previously, `ngcc` was not able to analyze such v14+ entry-points and
would instead error as it considered such entry-points missing.

This commit addresses the issue by detecting this situation and
synthesizing a `package.json` file for the secondary entry-points based
on the `exports` property of the primary `package.json` file. This data
is only used by `ngcc` in order to determine that the entry-point does
not need further processing, since it is already in Ivy format.

[1]: https://unpkg.com/browse/@angular/common@13.3.5/http/package.json
[2]: https://unpkg.com/browse/@angular/common@14.0.0-next.15/package.json

PR Close #45833
2022-05-06 09:51:14 -07:00
George Kalpakas 018b917602 refactor(ngcc): move loadPackageJson() and related types to utils.ts (#45833)
Move the `loadPackageJson()` helper (and associated generic types, such
as `JsonObject`) from `packages/entry_point.ts` to `utils.ts` and also
rename it to `loadJson()`. This way, they can be used in other places in
future commits, without introducing cyclical dependencies.

PR Close #45833
2022-05-06 09:51:14 -07:00
George Kalpakas 06bfcb2be3 refactor(ngcc): remove unused dependencies (#45833)
Remove some unused dependencies from `ngcc` source code.

PR Close #45833
2022-05-06 09:51:14 -07:00
dario-piotrowicz 323ef1ebf7 docs(docs-infra): improve clarity of toh-pt2 li>button code (#45858)
in the tour of heros part 2 guide the addition of a button with spans is
slighly unclear, so update the code to make things more clear

resolves #45760

PR Close #45858
2022-05-05 16:58:47 -07:00
mgechev fe2855167a docs: update the Angular DevTools supported version in docs and README (#45902)
Ensure we document we support Angular v12 or older. Also remove Ivy as
a requirement because that's implicit.

PR Close #45902
2022-05-05 16:56:46 -07:00
Andrew Kushnir ff2dc4a719 test(platform-browser): refactor flaky test (#45906)
This commit updates a flaky test related to the Testability. The tests are only flaky in Chrome on Android.

PR Close #45906
2022-05-05 16:56:12 -07:00
Andrew Kushnir 86f0213303 ci: update the list of excluded paths in NgBot config (#45901)
This commit aligns the NgBot config that is used to determine whether a presubmit is needed with its internal version.

PR Close #45901
2022-05-05 15:45:50 -07:00
Paul Gschwendtner d48e0ccc01 fix(bazel): speed up d.ts bundling by configuring worker (#45900)
Speeds up the `d.ts` bundling by configuring it as a Bazel
persistent worker. Also improve logging for the ng packager
rule to make it easier to spot which actions/bundles take
up significant time.

Type bundling will occur for every entry-point so for machines
with rather limited cores/threads, this will be useful to save
NodeJS boot and resolution time.

PR Close #45900
2022-05-05 15:35:14 -07:00
AleksanderBodurri f94055dee6 build(devtools): Optimize prod build for Angular DevTools (#45886)
Uses `createEsbuildAngularOptimizePlugin` from dev-infra-private and passes in `GLOBAL_DEFS_FOR_TERSER_WITH_AOT` into a new esbuild prod configuration. Notably, this removes references to `ngDevMode` from the final build and enables minification.

PR Close #45886
2022-05-05 15:33:14 -07:00
mgechev 7604585cd3 docs: update the Angular DevTools auto-generated READMEs (#45884)
Replace the auto-generated READMEs in the different Angular DevTools
submodules with brief descriptions.

PR Close #45884
2022-05-05 15:29:27 -07:00
mgechev af36adf540 refactor(devtools): remove support for v11 and older versions of Angular (#45883)
In Angular v12 we introduced debugging APIs sufficient for DevTools.
Prior to that Angular DevTools accesses the logical data structures of
Ivy directly, which sometimes produces suboptimal results and skips
dynamically inserted content.

With the end of v11's LTS, we'll support only Angular v12 and up.

PR Close #45883
2022-05-05 15:28:42 -07:00
George Kalpakas 58a8bd3df2 build(docs-infra): remove unused Docker artifacts when updating the preview server (#45895)
Update the `update-preview-server.sh` script that is used to update the
PR preview server to also remove unused Docker images and containers
after the update. This avoids having unused Docker artifacts grow
uncontrolled and fill up the VM disk drive.

PR Close #45895
2022-05-05 14:49:16 -07:00
George Kalpakas c793efd9b7 test(docs-infra): update preview server serify-setup tests to match implementation (#45895)
Update the mocks used in the `verify-setup` tests of the PR preview
server to account for changes made in PR #45349. These tests run to
verify that a newly built docker container works as expected before
deploying it to the preview server, so having them fail prevents the
preview server from updating automatically.

NOTE:
These tests are currently not run on CI due to complications with
running Docker inside Docker.

PR Close #45895
2022-05-05 14:49:16 -07:00
Paul Gschwendtner f6543c25aa build: use vendored yarn script for installing Sass repositories (#45892)
Fixes the Bazel analysis warning and the fact that Yarn is unnecessarily
downloaded by `rules_nodejs`.

```
DEBUG: /home/circleci/.cache/bazel/_bazel_circleci/9ce5c2144ecf75d11717c0aa41e45a8d/external/build_bazel_rules_nodejs/index.bzl:73:14: yarn_install#yarn attribute not set and no repository named 'yarn' exists; installing default yarn
```

PR Close #45892
2022-05-05 13:56:38 -07:00
Will 保哥 3f9faad356 docs: fix a markdown syntax error in aio/content/marketing/analytics.md (#45898)
PR Close #45898
2022-05-05 11:51:00 -07:00
Andrew Kushnir 40bf2a6a81 refactor(core): make Testability compatible with tree-shaking (#45657)
This commit refactors the `Testability`-related logic to extract the necessary providers into a separate array, so that it can later become it's own NgModule (or exposed as an array of providers) and be excluded from the new APIs by default.

PR Close #45657
2022-05-05 11:50:23 -07:00
Andrew Kushnir dcea70fab7 refactor(core): rename internal bootstrap function (#45896)
This commit renames an internal function that implements the core bootstrap logic. The function is exported as a private symbol (with `ɵ`), but in order to avoid any possible confusion, we include "internal" into the function name as well.

PR Close #45896
2022-05-05 10:55:56 -07:00
Renovate Bot 1e4e9ee9a7 build: update dependency @types/chrome to ^0.0.184 (#45849)
PR Close #45849
2022-05-05 10:16:12 -07:00
Renovate Bot d80018b7ca build: update angular (#45848)
PR Close #45848
2022-05-05 10:09:05 -07:00
Andrew Scott 8786c609f8 refactor(docs-infra): Redirect old document title guide to new router feature (#45857)
The "set-document-title" guide was in place to direct developers to the
`Title` service for managing page titles. Managing the title is now
available in the `Router` package and is much easier. This change
deletes the old guide and redirects it to the section in the router
guide about setting the page title.

PR Close #45857
2022-05-04 16:37:16 -07:00
Paul Gschwendtner d93ca6cc81 build: remove outdated/obsolete github PR utility scripts (#45868)
Removes scripts and documentation for tools which are no longer
actively used and likely do not work anyway at this point.

All of our PR-related tooling has moved into the `yarn ng-dev` command.
The `PR_REVIEW` markdown file is deleted since it was soley about
the legacy review scripts and the PR review workflow also does not
seem like the common/standard workflow Angular team members follow.

PR Close #45868
2022-05-04 16:29:27 -07:00
George Kalpakas 4dbcf9766b build(docs-infra): upgrade cli command docs sources to b71844f36 (#45871)
Updating [angular#main](https://github.com/angular/angular/tree/main) from
[cli-builds#main](https://github.com/angular/cli-builds/tree/main).

##
Relevant changes in
[commit range](https://github.com/angular/cli-builds/compare/f258be5be...b71844f36):

**Modified**
- help/completion.json

PR Close #45871
2022-05-04 16:25:57 -07:00
Paul Gschwendtner e586cb8124 build: clean up references to old master branch (#45856)
Cleans up all references to the `master` branch we renamed to
`main` across Angular.

PR Close #45856
2022-05-04 16:23:33 -07:00
Paul Gschwendtner de008f1149 ci: invalidate cache for windows job to prune unused nested node_modules (#45872)
An additional issue with the current approach of how Yarn and Bazel
interact, Yarn 1.x. does not prune unused nested `node_modules`. This
can throw-off the Bazel NodeJS rules because they (correctly) would not
expect such a nested folder.

This seems to happen in some caches currently, so we invalidate the
cache. Its worth seeing if we should rather cache the Yarn cache
folder on Windows as well, but for now this will remain as is.

Yarn 2.x+ will solve this for us, by addressing the root-cause.
Dev-Infra already has Yarn 2.x+ running, so it's not far from happening.

PR Close #45872
2022-05-04 16:20:57 -07:00
Paul Gschwendtner 0c61ea426a build: disable bazel nodejs linker to improve stability on windows (#45872)
The NodeJS Bazel linker does not work well on Windows because there
is no sandboxing and linker processes from different tests will attempt
to modify the same `node_modules`, causing concurrency race conditions
and resulting in flakiness.

PR Close #45872
2022-05-04 16:20:57 -07:00
Dylan Hunn 967e9345b3 release: cut the v14.0.0-next.16 release (#45875)
PR Close #45875
2022-05-04 13:55:01 -07:00
463 changed files with 13596 additions and 10412 deletions
+3 -7
View File
@@ -31,8 +31,8 @@ var_3: &cache_key v6-angular-node-14-{{ checksum "month.txt" }}-{{ checksum ".ba
var_4: &cache_key_fallback v6-angular-node-14-{{ checksum "month.txt" }}-{{ checksum ".bazelversion" }}
# Windows needs its own cache key because binaries in node_modules are different.
var_3_win: &cache_key_win v7-angular-win-node-14-{{ checksum "month.txt" }}-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}
var_4_win: &cache_key_win_fallback v7-angular-win-node-14-{{ checksum "month.txt" }}-{{ checksum ".bazelversion" }}
var_3_win: &cache_key_win v8-angular-win-node-14-{{ checksum "month.txt" }}-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}
var_4_win: &cache_key_win_fallback v8-angular-win-node-14-{{ checksum "month.txt" }}-{{ checksum ".bazelversion" }}
# Cache key for the `components-repo-unit-tests` job. **Note** when updating the SHA in the
# cache keys also update the SHA for the "COMPONENTS_REPO_COMMIT" environment variable.
@@ -64,8 +64,6 @@ var_10: &only_on_main_branch
branches:
only:
- main
# TODO(BRANCH_RENAME_CLEANUP): remove
- master
# Filter to run a job on all releasable branches.
var_11: &only_release_branches
@@ -73,8 +71,6 @@ var_11: &only_release_branches
branches:
only:
- main
# TODO(BRANCH_RENAME_CLEANUP): remove
- master
- /\d+\.\d+\.x/
# CircleCI orbs
@@ -308,7 +304,7 @@ jobs:
path: dist/bin/packages/core/test/bundling/todo/bundle.min.js.br
destination: core/todo/bundle.br
# NOTE: This is currently limited to master builds only. See the `monitoring` configuration.
# NOTE: This is currently limited to main builds only. See the `monitoring` configuration.
saucelabs:
executor:
name: default-executor
+1 -1
View File
@@ -51,7 +51,7 @@ setSecretVar CI_SECRET_PAYLOAD_FIREBASE_TOKEN "$ANGULAR_PAYLOAD_TOKEN";
# Define SauceLabs environment variables for CircleCI.
####################################################################################################
setPublicVar SAUCE_USERNAME "angular-framework";
setSecretVar SAUCE_ACCESS_KEY "0c731274ed5f-cbc9-16f4-021a-9835e39f";
setSecretVar SAUCE_ACCESS_KEY "f4bf7c639c5a-c6bb-d6a4-a4b5-800aa111";
# TODO(josephperrott): Remove environment variables once all saucelabs tests are via bazel method.
setPublicVar SAUCE_LOG_FILE /tmp/angular/sauce-connect.log
setPublicVar SAUCE_READY_FILE /tmp/angular/sauce-connect-ready-file.lock
-8
View File
@@ -101,14 +101,6 @@ function getRefFromBranchList(gitOutput) {
return 1;
}
// TODO(BRANCH_RENAME_CLEANUP): remove
if (a === 'master') {
return -1;
}
if (b === 'master') {
return 1;
}
const aIsSemver = semverRegex.test(a);
const bIsSemver = semverRegex.test(b);
if (aIsSemver && bIsSemver) {
+1 -1
View File
@@ -10,5 +10,5 @@ contact_links:
url: https://github.com/angular/components/issues/new/choose
about: Issues and feature requests for Angular Material
- name: Support Request
url: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
url: https://github.com/angular/angular/blob/main/CONTRIBUTING.md#question
about: Questions and requests for support
+1 -1
View File
@@ -1,7 +1,7 @@
## PR Checklist
Please check if your PR fulfills the following requirements:
- [ ] The commit message follows our guidelines: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
- [ ] The commit message follows our guidelines: https://github.com/angular/angular/blob/main/CONTRIBUTING.md#commit
- [ ] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)
+18 -4
View File
@@ -42,13 +42,26 @@ merge:
exclude:
- 'packages/*'
- 'packages/bazel/*'
- 'packages/bazel/src/*'
- 'packages/bazel/src/api-extractor/**'
- 'packages/bazel/src/ng_package/**'
- 'packages/bazel/src/builders/**'
- 'packages/bazel/src/ng_module/**'
- 'packages/bazel/src/ng_package/**'
- 'packages/bazel/src/protractor/**'
- 'packages/bazel/src/schematics/**'
- 'packages/bazel/src/types_bundle/**'
- 'packages/compiler-cli/src/ngcc/**'
- 'packages/compiler-cli/linker/**'
- 'packages/compiler-cli/ngcc/**'
- 'packages/compiler-cli/src/ngtsc/sourcemaps/**'
# 'private' mostly contains entrypoints for 3P Angular.
# Note that 'private/migrations' _is_ used.
- 'packages/compiler-cli/private/bazel.ts'
- 'packages/compiler-cli/private/localize.ts'
- 'packages/compiler-cli/private/tooling.ts'
- 'packages/compiler-cli/private/babel.d.ts'
# google3 defines its own binary entrypoints.
- 'packages/compiler-cli/src/bin/**'
- 'packages/docs/**'
- 'packages/elements/schematics/**'
- 'packages/examples/**'
@@ -56,7 +69,8 @@ merge:
- 'packages/localize/**'
- 'packages/private/**'
- 'packages/service-worker/**'
- 'packages/common/locales/**'
- 'packages/common/locales/generate-locales-tool/**'
- 'packages/common/locales/index.bzl'
- 'packages/http/**'
- '**/.gitignore'
- '**/.gitkeep'
@@ -97,7 +111,7 @@ merge:
# whether the PR shouldn't have a conflict with the base branch
noConflict: true
# list of labels that a PR needs to have, checked with a regexp (e.g. "target:" will work for the label "target: master")
# list of labels that a PR needs to have, checked with a regexp.
requiredLabels:
- 'target: *'
@@ -119,7 +133,7 @@ merge:
# the comment that will be added when the merge label is added despite failing checks, leave empty or set to false to disable
# {{MERGE_LABEL}} will be replaced by the value of the mergeLabel option
# {{PLACEHOLDER}} will be replaced by the list of failing checks
mergeRemovedComment: "I see that you just added the `{{MERGE_LABEL}}` label, but the following checks are still failing:\n{{PLACEHOLDER}}\n\n**If you want your PR to be merged, it has to pass all the CI checks.**\n\nIf you can't get the PR to a green state due to flakes or broken master, please try rebasing to master and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help."
mergeRemovedComment: "I see that you just added the `{{MERGE_LABEL}}` label, but the following checks are still failing:\n{{PLACEHOLDER}}\n\n**If you want your PR to be merged, it has to pass all the CI checks.**\n\nIf you can't get the PR to a green state due to flakes or broken `main`, please try rebasing to `main` and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help."
# options for the triage plugin
triage:
+8 -1
View File
@@ -13,6 +13,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2
- uses: angular/dev-infra/github-actions/commit-message-based-labels@a7d07a6f66c05791fdde2dd372da4ba55c1d524b
- uses: angular/dev-infra/github-actions/commit-message-based-labels@91ba217766e28a53c469d5ca43a76e37af64e3f1
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
post_approval_changes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2
- uses: angular/dev-infra/github-actions/post-approval-changes@91ba217766e28a53c469d5ca43a76e37af64e3f1
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
+1 -1
View File
@@ -14,6 +14,6 @@ jobs:
if: github.repository == 'angular/angular'
runs-on: ubuntu-latest
steps:
- uses: angular/dev-infra/github-actions/feature-request@a7d07a6f66c05791fdde2dd372da4ba55c1d524b
- uses: angular/dev-infra/github-actions/feature-request@91ba217766e28a53c469d5ca43a76e37af64e3f1
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
+1 -1
View File
@@ -14,6 +14,6 @@ jobs:
if: github.repository == 'angular/angular'
runs-on: ubuntu-latest
steps:
- uses: angular/dev-infra/github-actions/lock-closed@a7d07a6f66c05791fdde2dd372da4ba55c1d524b
- uses: angular/dev-infra/github-actions/lock-closed@91ba217766e28a53c469d5ca43a76e37af64e3f1
with:
lock-bot-key: ${{ secrets.LOCK_BOT_PRIVATE_KEY }}
+1 -5
View File
@@ -4,11 +4,7 @@ on:
schedule:
- cron: '0 0 * * 0'
push:
branches: [
main,
# TODO(BRANCH_RENAME_CLEANUP): remove
master,
]
branches: [main]
workflow_dispatch:
# Declare default permissions as read only.
+3 -3
View File
@@ -74,7 +74,7 @@ Fixes #<issue number>
# =============================
#
# The full specification of the Angular Commit Message Format can be found at
# https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
# https://github.com/angular/angular/blob/main/CONTRIBUTING.md#commit
#
# The following is an excerpt of the specification with the most commonly needed info.
#
@@ -108,10 +108,10 @@ Fixes #<issue number>
# │ platform-browser-dynamic|platform-server|router|service-worker|
# │ upgrade|zone.js|packaging|changelog|docs-infra|migrations|ngcc|ve|
# │ devtools
# │ https://github.com/angular/angular/blob/master/CONTRIBUTING.md#scope
# │ https://github.com/angular/angular/blob/main/CONTRIBUTING.md#scope
# │
# └─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
# https://github.com/angular/angular/blob/master/CONTRIBUTING.md#type
# https://github.com/angular/angular/blob/main/CONTRIBUTING.md#type
#
#
# Commit Message Body
+15 -4
View File
@@ -236,6 +236,12 @@ groups:
'aio/content/images/guide/attribute-directives/**',
'aio/content/guide/bootstrapping.md',
'aio/content/examples/bootstrapping/**',
'aio/content/guide/change-detection.md',
'aio/content/guide/change-detection-zone-pollution.md',
'aio/content/guide/change-detection-slow-computations.md',
'aio/content/guide/change-detection-skipping-subtrees.md',
'aio/content/images/guide/change-detection/**',
'aio/content/guide/class-binding.md',
'aio/content/guide/cheatsheet.md',
'aio/content/guide/component-interaction.md',
'aio/content/examples/component-interaction/**',
@@ -287,6 +293,7 @@ groups:
'aio/content/guide/ngmodule-faq.md',
'aio/content/guide/ngmodule-vs-jsmodule.md',
'aio/content/guide/module-types.md',
'aio/content/guide/template-overview.md',
'aio/content/guide/template-syntax.md',
'aio/content/guide/built-in-template-functions.md',
'aio/content/examples/built-in-template-functions/**',
@@ -297,6 +304,7 @@ groups:
'aio/content/examples/interpolation/**',
'aio/content/examples/template-syntax/**',
'aio/content/images/guide/template-syntax/**',
'aio/content/guide/binding-overview.md',
'aio/content/guide/binding-syntax.md',
'aio/content/examples/binding-syntax/**',
'aio/content/guide/property-binding.md',
@@ -314,20 +322,22 @@ groups:
'aio/content/guide/inputs-outputs.md',
'aio/content/examples/inputs-outputs/**',
'aio/content/images/guide/inputs-outputs/**',
'aio/content/guide/understanding-template-expr-overview.md',
'aio/content/guide/template-expression-operators.md',
'aio/content/examples/template-expression-operators/**',
'aio/content/guide/pipes.md',
'aio/content/guide/pipes-custom-data-trans.md',
'aio/content/guide/pipes-overview.md',
'aio/content/guide/pipes-transform-data.md',
'aio/content/guide/pipe-template.md',
'aio/content/examples/pipes/**',
'aio/content/images/guide/pipes/**',
'aio/content/guide/providers.md',
'aio/content/examples/providers/**',
'aio/content/images/guide/providers/**',
'aio/content/guide/singleton-services.md',
'aio/content/guide/set-document-title.md',
'aio/content/examples/set-document-title/**',
'aio/content/images/guide/set-document-title/**',
'aio/content/guide/sharing-ngmodules.md',
'aio/content/guide/standalone-components.md',
'aio/content/guide/structural-directives.md',
'aio/content/examples/structural-directives/**',
'aio/content/guide/svg-in-templates.md',
@@ -436,6 +446,7 @@ groups:
'aio/content/examples/forms-overview/**',
'aio/content/images/guide/forms-overview/**',
'aio/content/guide/form-validation.md',
'aio/content/guide/typed-forms.md',
'aio/content/examples/form-validation/**',
'aio/content/images/guide/form-validation/**',
'aio/content/guide/dynamic-form.md',
@@ -975,6 +986,7 @@ groups:
'aio/content/examples/setup/**',
'aio/content/guide/build.md',
'aio/content/images/guide/build/**',
'aio/content/images/guide/cli/**',
'aio/content/guide/cli-builder.md',
'aio/content/examples/cli-builder/**',
'aio/content/guide/deployment.md',
@@ -985,7 +997,6 @@ groups:
'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:
+1 -1
View File
@@ -1,4 +1,4 @@
load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary")
load("//tools:defaults.bzl", "nodejs_binary")
package(default_visibility = ["//visibility:public"])
+297 -514
View File
@@ -1,50 +1,338 @@
<a name="13.3.6"></a>
# 13.3.6 (2022-05-04)
<a name="14.0.1"></a>
# 14.0.1 (2022-06-08)
### forms
| Commit | Type | Description |
| -- | -- | -- |
| [dde0b7f4b3](https://github.com/angular/angular/commit/dde0b7f4b3bc658b67a97644c8655252803be663) | fix | allow FormBuilder.group(...) to accept optional fields. ([#46253](https://github.com/angular/angular/pull/46253)) |
## Special Thanks
Andrew Kushnir, Andrew Scott, George Kalpakas, Paul Gschwendtner, Pawel Kozlowski, Ryan Day and dario-piotrowicz
Adrien Crivelli, Alan Agius, Alex Rickabaugh, Andrew Kushnir, Andrew Scott, Dylan Hunn, Fabrizio Fallico, George Kalpakas, Jelle Bruisten, JoostK, Kristiyan Kostadinov, Krzysztof Platis, Paul Gschwendtner, Phalgun Vaddepalli, San Leen, dario-piotrowicz, mgechev and wellWINeo
<!-- CHANGELOG SPLIT MARKER -->
<a name="14.0.0-next.15"></a>
# 14.0.0-next.15 (2022-04-27)
<a name="14.0.0"></a>
# 14.0.0 (2022-06-02)
[Blog post "Angular v14 is now available"](http://goo.gle/angular-v14).
## Breaking Changes
### animations
- The `AnimationDriver.getParentElement` method has become required, so any
implementors of this interface are now required to provide an implementation
for this method. This breakage is unlikely to affect application developers,
as `AnimationDriver` is not expected to be implemented in user code.
### common
- Adds new required class member that any implementors of the LocationStrategy will need to satisfy.
Location does not depend on PlatformLocation anymore.
### compiler
- Keyframes names are now prefixed with the component's "scope name".
For example, the following keyframes rule in a component definition,
whose "scope name" is host-my-cmp:
@keyframes foo { ... }
will become:
@keyframes host-my-cmp_foo { ... }
Any TypeScript/JavaScript code which relied on the names of keyframes rules
will no longer match.
The recommended solutions in this case are to either:
- change the component's view encapsulation to the `None` or `ShadowDom`
- define keyframes rules in global stylesheets (e.g styles.css)
- define keyframes rules programmatically in code.
### core
- Support for Node.js v12 has been removed as it will become EOL on 2022-04-30. Please use Node.js v14.15 or later.
- TypeScript versions older than 4.6 are no longer supported.
- Forms [email] input coercion
Forms [email] input value will be considered as true if it is defined with any value rather
than false and 'false'.
- Since Ivy, TestBed doesn't use AOT summaries. The `aotSummaries` fields in TestBed APIs were present, but unused. The fields were deprecated in previous major version and in v14 those fields are removed. The `aotSummaries` fields were completely unused, so you can just drop them from the TestBed APIs usage.
### forms
- Forms classes accept a generic.
Forms model classes now accept a generic type parameter. Untyped versions of these classes are available to opt-out of the new, stricter behavior.
- objects with a length key set to zero will no longer validate as empty.
This is technically a breaking change, since objects with a key `length` and value `0` will no longer validate as empty. This is a very minor change, and any reliance on this behavior is probably a bug anyway.
### http
- Queries including + will now actually query for + instead of space.
Most workarounds involving custom codecs will be unaffected.
Possible server-side workarounds will need to be undone.
- JSONP will throw an error when headers are set on a reques
JSONP does not support headers being set on requests. Before when
a request was sent to a JSONP backend that had headers set the headers
were ignored. The JSONP backend will now throw an error if it
receives a request that has any headers set. Any uses of JSONP
on requests with headers set will need to remove the headers
to avoid the error.
### platform-browser
- This change may cause a breaking change in unit tests that are implicitly depending on a specific
number and sequence of change detections in order for their assertions to pass.
- This may break invalid calls to `TransferState` methods.
This tightens parameter types of `TransferState` usage, and is a minor breaking change which may reveal existing problematic calls.
### router
- The type of `Route.pathMatch` is now more strict. Places that use
`pathMatch` will likely need to be updated to have an explicit
`Route`/`Routes` type so that TypeScript does not infer the type as
`string`.
- When returning a `Promise` from the
`LoadChildrenCallback`, the possible type is now restricted to
`Type<any>|NgModuleFactory<any>` rather than `any`.
- `initialNavigation: 'enabled'` was deprecated in v11 and is replaced by
`initialNavigation: 'enabledBlocking'`.
- The type of `component` on `ActivatedRoute` and `ActivatedRouteSnapshot`
includes `string`. In reality, this is not the case. The component
cannot be anything other than a component class.
- * The type of `initialUrl` is set to `string|UrlTree` but in reality,
the `Router` only sets it to a value that will always be `UrlTree`
* `initialUrl` is documented as "The target URL passed into the
`Router#navigateByUrl()` call before navigation" but the value
actually gets set to something completely different. It's set to the
current internal `UrlTree` of the Router at the time navigation
occurs.
With this change, there is no exact replacement for the old value of
`initialUrl` because it was never intended to be exposed.
`Router.url` is likely the best replacement for this.
In more specific use-cases, tracking the `finalUrl` between successful
navigations can also be used as a replacement.
- Lazy loaded configs are now also validated once loaded like the
initial set of routes are. Lazy loaded modules which have invalid Route
configs will now error. Note that this is only done in dev mode so
there is no production impact of this change.
- When a guard returns a `UrlTree`, the router would previously schedule
the redirect navigation within a `setTimeout`. This timeout is now removed,
which can result in test failures due to incorrectly written tests.
Tests which perform navigations should ensure that all timeouts are
flushed before making assertions. Tests should ensure they are capable
of handling all redirects from the original navigation.
### bazel
- Previously, resolvers were waiting to be completed
before proceeding with the navigation and the Router would take the last
value emitted from the resolver.
The router now takes only the first emitted value by the resolvers
and then proceeds with navigation. This is now consistent with `Observables`
returned by other guards: only the first value is used.
### zone.js
- in TaskTrackingZoneSpec track a periodic task until it is cancelled
The breaking change is scoped only to the plugin
`zone.js/plugins/task-tracking`. If you used `TaskTrackingZoneSpec` and
checked the pending macroTasks e.g. using `(this.ngZone as any)._inner
._parent._properties.TaskTrackingZone.getTasksFor('macroTask')`, then
its behavior slightly changed for periodic macrotasks. For example,
previously the `setInterval` macrotask was no longer tracked after its
callback was executed for the first time. Now it's tracked until
the task is explicitly cancelled, e.g with `clearInterval(id)`.
## Deprecations
### common
- The `ngModuleFactory` input of the `NgComponentOutlet` directive is deprecated in favor of a newly added `ngModule` input. The `ngModule` input accepts references to the NgModule class directly, without the need to resolve module factory first.
### forms
- The `initialValueIsDefault` option has been deprecated and replaced with the otherwise-identical `nonNullable` option, for the sake of naming consistency.
- It is now deprecated to provide *both* `AbstractControlOption`s and an async validators argument to a FormControl. Previously, the async validators would just be silently dropped, resulting in a probably buggy forms. Now, the constructor call is deprecated, and Angular will print a warning in devmode.
### router
- The `resolver` argument of the `RouterOutletContract.activateWith` function and the `resolver` field of the `OutletContext` class are deprecated. Passing component factory resolvers are no longer needed. The `ComponentFactoryResolver`-related symbols were deprecated in `@angular/core` package since v13.
### animations
| Commit | Type | Description |
| -- | -- | -- |
| [68597bb0ca](https://github.com/angular/angular/commit/68597bb0ca958445655653a0a3cb206c01c7e0b3) | feat | speed up dev-turnaround by bundling types only when packaging ([#45405](https://github.com/angular/angular/pull/45405)) |
| [970a3b5c70](https://github.com/angular/angular/commit/970a3b5c70fee29aa40945836ebeb464d75438e4) | fix | add this_is_bazel marker ([#45728](https://github.com/angular/angular/pull/45728)) |
| [a6fa37bc6e](https://github.com/angular/angular/commit/a6fa37bc6e705fee48f555d4b8022915094e8b16) | feat | make validateStyleProperty check dev-mode only ([#45570](https://github.com/angular/angular/pull/45570)) |
| [79d334b138](https://github.com/angular/angular/commit/79d334b1385685d0fd1451534df2ed3cbaefa0b6) | feat | provide warnings for non-animatable CSS properties ([#45212](https://github.com/angular/angular/pull/45212)) |
| [f8dc660605](https://github.com/angular/angular/commit/f8dc66060591e1ce42265a7862c3df16e40b05e1) | fix | allow animations with unsupported CSS properties ([#44729](https://github.com/angular/angular/pull/44729)) |
| [2a75754ee8](https://github.com/angular/angular/commit/2a75754ee823032e651bc596887a2186dc6846ae) | fix | apply default params when resolved value is null or undefined ([#45339](https://github.com/angular/angular/pull/45339)) |
| [e46b379204](https://github.com/angular/angular/commit/e46b37920438d84bff895498c0a102dd1ffba178) | fix | implement missing transition delay ([#44799](https://github.com/angular/angular/pull/44799)) |
| [5c7c56bc85](https://github.com/angular/angular/commit/5c7c56bc859b195bf6710f6c1479d9e18dde35b1) | perf | improve algorithm to balance animation namespaces ([#45057](https://github.com/angular/angular/pull/45057)) |
| [4c778cdb28](https://github.com/angular/angular/commit/4c778cdb28de128c6ddecd2fd6cb6257d675500b) | perf | made errors in the animations package tree shakeable ([#45004](https://github.com/angular/angular/pull/45004)) |
| [7a81481fb2](https://github.com/angular/angular/commit/7a81481fb29e94b550db7ad68270eccf26bb2743) | perf | Remove generic objects in favor of Maps ([#44482](https://github.com/angular/angular/pull/44482)) |
| [6642e3c8fd](https://github.com/angular/angular/commit/6642e3c8fd7d3b5ed22710667b2c41a46f14eda8) | perf | remove no longer needed CssKeyframes classes ([#44903](https://github.com/angular/angular/pull/44903)) |
| [59559fdbac](https://github.com/angular/angular/commit/59559fdbacc00bee380b1e88c79d08b6e856ebbe) | refactor | make `AnimationDriver.getParentElement` required ([#45114](https://github.com/angular/angular/pull/45114)) |
### common
| Commit | Type | Description |
| -- | -- | -- |
| [31d7c3bd71](https://github.com/angular/angular/commit/31d7c3bd71fdab3fef1b4615ecb8124fe6c165bd) | feat | add getState method to LocationStrategy interface ([#45648](https://github.com/angular/angular/pull/45648)) |
| [c89cf63059](https://github.com/angular/angular/commit/c89cf63059370bba43717483e3d9627499dfe815) | feat | support NgModule as an input to the NgComponentOutlet ([#44815](https://github.com/angular/angular/pull/44815)) |
| [38c03a2035](https://github.com/angular/angular/commit/38c03a20358db3f8621c023b98e627cd385731c0) | feat | support years greater than 9999 ([#43622](https://github.com/angular/angular/pull/43622)) |
| [bedb257afc](https://github.com/angular/angular/commit/bedb257afc1ca12eb221536ea44ade960e62cda0) | fix | cleanup URL change listeners when the root view is removed ([#44901](https://github.com/angular/angular/pull/44901)) |
| [10691c626b](https://github.com/angular/angular/commit/10691c626bf381bedfa278e9d50ab922b4b656cd) | fix | properly cast http param values to strings ([#42643](https://github.com/angular/angular/pull/42643)) |
| [05d50b849b](https://github.com/angular/angular/commit/05d50b849bb891c37c3eefab81a45099057dfd78) | perf | make `NgLocalization` token tree-shakable ([#45118](https://github.com/angular/angular/pull/45118)) |
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [bb8d7091c6](https://github.com/angular/angular/commit/bb8d7091c64a785758ae347b1a9bcdeeed95897c) | fix | exclude empty styles from emitted metadata ([#45459](https://github.com/angular/angular/pull/45459)) |
| [4d6a1d6722](https://github.com/angular/angular/commit/4d6a1d672210219328b33f4f96210870563066ee) | fix | scope css keyframes in emulated view encapsulation ([#42608](https://github.com/angular/angular/pull/42608)) |
| [f03e313f24](https://github.com/angular/angular/commit/f03e313f24465cbe9ce99aa5f9f482a6c6b5485f) | fix | scope css keyframes in emulated view encapsulation ([#42608](https://github.com/angular/angular/pull/42608)) |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [9cf14ff03d](https://github.com/angular/angular/commit/9cf14ff03dc7a848413b323dfb943fcd26f1217e) | feat | exclude abstract classes from `strictInjectionParameters` requirement ([#44615](https://github.com/angular/angular/pull/44615)) |
| [0072eb48ba](https://github.com/angular/angular/commit/0072eb48ba1c6f549703988b7fd7ba3e09058048) | feat | initial implementation of standalone components ([#44812](https://github.com/angular/angular/pull/44812)) |
| [2142ffd295](https://github.com/angular/angular/commit/2142ffd295de491eb8582c2eb1712b5b48044f24) | feat | propagate `standalone` flag to runtime ([#44973](https://github.com/angular/angular/pull/44973)) |
| [6f653e05f9](https://github.com/angular/angular/commit/6f653e05f985141ae4d2d90af78b2bc001595661) | feat | standalone types imported into NgModule scopes ([#44973](https://github.com/angular/angular/pull/44973)) |
| [752ddbc165](https://github.com/angular/angular/commit/752ddbc165359c2ff987c24f715d0a36fd604ec0) | feat | Support template binding to protected component members ([#45823](https://github.com/angular/angular/pull/45823)) |
| [3d13343975](https://github.com/angular/angular/commit/3d133439754cbf5d5a20bb3c714c8673c848e465) | fix | better error messages for NgModule structural issues ([#44973](https://github.com/angular/angular/pull/44973)) |
| [046dad1a8d](https://github.com/angular/angular/commit/046dad1a8d878ea537a6e2ef5f5ef24a85a2cf02) | fix | fix issue with incremental tracking of APIs for pipes ([#45672](https://github.com/angular/angular/pull/45672)) |
| [27b4af7240](https://github.com/angular/angular/commit/27b4af7240ea964d1e4d51b83118f10321163627) | fix | full side-effectful registration of NgModules with ids ([#45024](https://github.com/angular/angular/pull/45024)) |
| [32c625d027](https://github.com/angular/angular/commit/32c625d0279d9fd55178ced47c45969da533eedc) | fix | handle forwardRef in imports of standalone component ([#45869](https://github.com/angular/angular/pull/45869)) |
| [06050ac2b4](https://github.com/angular/angular/commit/06050ac2b4937836096fb331ec71bacb5a1fc231) | fix | handle inline type-check blocks in nullish coalescing extended check ([#45454](https://github.com/angular/angular/pull/45454)) |
| [a524a50361](https://github.com/angular/angular/commit/a524a50361bb408cf8baf8ff209378a1db967545) | fix | handle standalone components with cycles ([#46029](https://github.com/angular/angular/pull/46029)) |
| [724e88e042](https://github.com/angular/angular/commit/724e88e042b1a89691d48879673b5e1b161c3d9a) | fix | preserve `forwardRef` for component scopes ([#46139](https://github.com/angular/angular/pull/46139)) |
| [9cfea3d522](https://github.com/angular/angular/commit/9cfea3d522c0e4a34bb3a5d0fa9d04f64de39b49) | fix | report invalid imports in standalone components during resolve phase ([#45827](https://github.com/angular/angular/pull/45827)) |
| [c0778b4dfc](https://github.com/angular/angular/commit/c0778b4dfc1c107543b3db6f1958814a0812c7df) | fix | Support resolve animation name from the DTS ([#45107](https://github.com/angular/angular/pull/45107)) |
| [f2e5234e07](https://github.com/angular/angular/commit/f2e5234e078b6d4771d07e8b28b8098f1faeb176) | fix | update unknown tag error for aot standalone components ([#45919](https://github.com/angular/angular/pull/45919)) |
| [35f20afcac](https://github.com/angular/angular/commit/35f20afcac4877963e4a3e5d85b67ed8cb000af9) | fix | use existing imports for standalone dependencies ([#46029](https://github.com/angular/angular/pull/46029)) |
| [8155428ba6](https://github.com/angular/angular/commit/8155428ba65c38c0c15f2666727202a7b360c1bd) | perf | ignore the module.id anti-pattern for NgModule ids ([#45024](https://github.com/angular/angular/pull/45024)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [174ce7dd13](https://github.com/angular/angular/commit/174ce7dd13f6d8f941d3aa0b843559614cb68b0c) | feat | add `ApplicationRef.destroy` method ([#45624](https://github.com/angular/angular/pull/45624)) |
| [5771b18a98](https://github.com/angular/angular/commit/5771b18a989c3c75d713ffb75cd7c047c63e4090) | feat | add the `bootstrapApplication` function ([#45674](https://github.com/angular/angular/pull/45674)) |
| [69018c9f42](https://github.com/angular/angular/commit/69018c9f42d14c1c7aa8271b406d6d247de1c564) | feat | allow for injector to be specified when creating an embedded view ([#45156](https://github.com/angular/angular/pull/45156)) |
| [94c949a60a](https://github.com/angular/angular/commit/94c949a60ad0de1f5385ec97f2c1933cb1d55f22) | feat | allow for injector to be specified when creating an embedded view ([#45156](https://github.com/angular/angular/pull/45156)) |
| [e702cafcf2](https://github.com/angular/angular/commit/e702cafcf2fef53968ef52ce17cb343f3a12bb53) | feat | allow to throw on unknown elements in tests ([#45479](https://github.com/angular/angular/pull/45479)) |
| [6662a97c61](https://github.com/angular/angular/commit/6662a97c61f133a14f2d117f71e4d2b8f4a83c32) | feat | allow to throw on unknown elements in tests ([#45479](https://github.com/angular/angular/pull/45479)) |
| [a6675925b0](https://github.com/angular/angular/commit/a6675925b0b6f313d4932a753bd4aa4cb473b5f3) | feat | allow to throw on unknown properties in tests ([#45853](https://github.com/angular/angular/pull/45853)) |
| [6eaaefd22e](https://github.com/angular/angular/commit/6eaaefd22ebb95ee896a62237832ff2f2defdee0) | feat | drop support for Node.js 12 ([#45286](https://github.com/angular/angular/pull/45286)) |
| [c9d566ce4b](https://github.com/angular/angular/commit/c9d566ce4b6e9097d9eceb7ac3964a0b25c404ad) | feat | drop support for TypeScript 4.4 and 4.5 ([#45394](https://github.com/angular/angular/pull/45394)) |
| [b568a5e708](https://github.com/angular/angular/commit/b568a5e708579f5035f40c7218fbba39ad6b3065) | feat | implement `importProvidersFrom` function ([#45626](https://github.com/angular/angular/pull/45626)) |
| [d5a6cd1111](https://github.com/angular/angular/commit/d5a6cd11110c78762a8e6115a718f5851508dbf2) | feat | implement EnvironmentInjector with adapter to NgModuleRef ([#45626](https://github.com/angular/angular/pull/45626)) |
| [5a10fc4f82](https://github.com/angular/angular/commit/5a10fc4f8287d448c88ce2f6c97c48307af34af1) | feat | implement standalone directives, components, and pipes ([#45687](https://github.com/angular/angular/pull/45687)) |
| [e461f716d4](https://github.com/angular/angular/commit/e461f716d4b736829d53de26ba6dddb58f476746) | feat | move ANIMATION_MODULE_TYPE injection token into core ([#44970](https://github.com/angular/angular/pull/44970)) |
| [94bba76a4a](https://github.com/angular/angular/commit/94bba76a4a9594a5eb90e581f407f1b70697e715) | feat | support TypeScript 4.6 ([#45190](https://github.com/angular/angular/pull/45190)) |
| [29039fcdbc](https://github.com/angular/angular/commit/29039fcdbcb8cab040d88dabe2dcb1abae34cb4e) | feat | support TypeScript 4.7 ([#45749](https://github.com/angular/angular/pull/45749)) |
| [225e4f2dbe](https://github.com/angular/angular/commit/225e4f2dbeac5982982fb94eac65ea931c44247a) | feat | triggerEventHandler accept optional eventObj ([#45279](https://github.com/angular/angular/pull/45279)) |
| [401dec46eb](https://github.com/angular/angular/commit/401dec46eb71e33ae3ef185b8f92ed2b3b7661fd) | feat | update TestBed to recognize Standalone Components ([#45809](https://github.com/angular/angular/pull/45809)) |
| [35653ce337](https://github.com/angular/angular/commit/35653ce337b59336ebb06f07dfed027e5037ed06) | fix | add more details to the MISSING_INJECTION_CONTEXT error ([#46166](https://github.com/angular/angular/pull/46166)) |
| [d36fa111eb](https://github.com/angular/angular/commit/d36fa111eb677d504a9952d8b4ca53560cadd04d) | fix | avoid Closure Compiler error in restoreView ([#45445](https://github.com/angular/angular/pull/45445)) |
| [0bc77f4cab](https://github.com/angular/angular/commit/0bc77f4cabb3fe76accb120f7aba57ebfee9262b) | fix | better error message when unknown property is present ([#46147](https://github.com/angular/angular/pull/46147)) |
| [f3eb7d9ecb](https://github.com/angular/angular/commit/f3eb7d9ecb9a82e7396cca658e3250e47c853153) | fix | Ensure the `StandaloneService` is retained after closure minification ([#45783](https://github.com/angular/angular/pull/45783)) |
| [701405fa71](https://github.com/angular/angular/commit/701405fa710177ed1c963f61686ebb910e5ec74e) | fix | handle AOT-compiled standalone components in TestBed correctly ([#46052](https://github.com/angular/angular/pull/46052)) |
| [ddce357d1d](https://github.com/angular/angular/commit/ddce357d1db9694bc69c114deb96e26d2651fb8b) | fix | improve TestBed declarations standalone error message ([#45999](https://github.com/angular/angular/pull/45999)) |
| [ba9f30c9a6](https://github.com/angular/angular/commit/ba9f30c9a6af19b34d13962303ec96997c7c3d56) | fix | include component name into unknown element/property error message ([#46160](https://github.com/angular/angular/pull/46160)) |
| [9fa6f5a552](https://github.com/angular/angular/commit/9fa6f5a552b7780ce32aa5a60273d4008a7b6afb) | fix | incorrectly inserting elements inside `<template>` element ([#43429](https://github.com/angular/angular/pull/43429)) |
| [d5719c2e0f](https://github.com/angular/angular/commit/d5719c2e0fb237be71d658444bbfe2410e05086a) | fix | input coercion ([#42803](https://github.com/angular/angular/pull/42803)) |
| [be161bef79](https://github.com/angular/angular/commit/be161bef798ac5309df8390e3c2bba2cf84cb530) | fix | memory leak in event listeners inside embedded views ([#43075](https://github.com/angular/angular/pull/43075)) |
| [fa755b2a54](https://github.com/angular/angular/commit/fa755b2a541274336541e8870852e73718ad62d4) | fix | prevent `BrowserModule` providers from being loaded twice ([#45826](https://github.com/angular/angular/pull/45826)) |
| [3172b4cc99](https://github.com/angular/angular/commit/3172b4cc9972a7d347b3078484c9adcb15cf270c) | fix | produce proper error message for unknown props on `<ng-template>`s ([#46068](https://github.com/angular/angular/pull/46068)) |
| [4f1a813596](https://github.com/angular/angular/commit/4f1a813596a40f7885d369eb8917aedcce9dd795) | fix | restore NgModule state correctly after TestBed overrides ([#46049](https://github.com/angular/angular/pull/46049)) |
| [3f7ecec59b](https://github.com/angular/angular/commit/3f7ecec59b894d2a92f4b5643d2a23891938bde8) | fix | set correct context for inject() for component ctors ([#45991](https://github.com/angular/angular/pull/45991)) |
| [4e413d9240](https://github.com/angular/angular/commit/4e413d9240259fca1b1e548c5c405e646f8e68c8) | fix | support nested arrays of providers in `EnvironmentInjector` ([#45789](https://github.com/angular/angular/pull/45789)) |
| [fde4942cdf](https://github.com/angular/angular/commit/fde4942cdf5133119b13ed26ee2f6976b787d84c) | fix | throw if standalone components are present in `@NgModule.bootstrap` ([#45825](https://github.com/angular/angular/pull/45825)) |
| [560188bf12](https://github.com/angular/angular/commit/560188bf126f259328477773cabb367587a257d5) | fix | update unknown property error to account for standalone components in AOT ([#46159](https://github.com/angular/angular/pull/46159)) |
| [df339d8abf](https://github.com/angular/angular/commit/df339d8abf979c715c35db813c5a80252a92eba7) | fix | update unknown tag error for jit standalone components ([#45920](https://github.com/angular/angular/pull/45920)) |
| [aafac7228f](https://github.com/angular/angular/commit/aafac7228f3d18bb720e85d2b889df446122f4c7) | fix | verify standalone component imports in JiT ([#45777](https://github.com/angular/angular/pull/45777)) |
| [e9317aee71](https://github.com/angular/angular/commit/e9317aee71f64f4aadea0529601e589b37f6b46f) | perf | allow `checkNoChanges` mode to be tree-shaken in production ([#45913](https://github.com/angular/angular/pull/45913)) |
| [071c8af8ba](https://github.com/angular/angular/commit/071c8af8ba89163270f17657c0c7f1c944f186f7) | perf | avoid storing LView in `__ngContext__` ([#45051](https://github.com/angular/angular/pull/45051)) |
| [a96c4827c4](https://github.com/angular/angular/commit/a96c4827c4f62e1d665d8544a3e66c51d2644c88) | perf | make `Compiler`, `ApplicationRef` and `ApplicationInitStatus` tree-shakable ([#45102](https://github.com/angular/angular/pull/45102)) |
| [45d98e7ca5](https://github.com/angular/angular/commit/45d98e7ca5accf918e2602cbc17805e11e18896b) | perf | make `IterableDiffers` and `KeyValueDiffers` tree-shakable ([#45094](https://github.com/angular/angular/pull/45094)) |
| [1e60fe0a3e](https://github.com/angular/angular/commit/1e60fe0a3eeb6bd46997f7eeb4825351cfbe3c44) | perf | make `LOCALE_ID` and other tokens from `ApplicationModule` tree-shakable ([#45102](https://github.com/angular/angular/pull/45102)) |
| [88f1168506](https://github.com/angular/angular/commit/88f1168506befd0665125da1fca2a719cb27dbb5) | perf | only track LViews that are referenced in `__ngContext__` ([#45172](https://github.com/angular/angular/pull/45172)) |
| [9add714b13](https://github.com/angular/angular/commit/9add714b13740db621eb2b200d72be74cc7eb630) | refactor | remove deprecated `aotSummaries` fields in TestBed config ([#45487](https://github.com/angular/angular/pull/45487)) |
### devtools tabs
| Commit | Type | Description |
| -- | -- | -- |
| [6c284ef32e](https://github.com/angular/angular/commit/6c284ef32e53a8dabbc368b9cf69f1b6f1a377b7) | fix | stop scroll occuring at tabs level |
### forms
| Commit | Type | Description |
| -- | -- | -- |
| [2dbdebc646](https://github.com/angular/angular/commit/2dbdebc6467074c7005c09ef5c229029f8d3607c) | feat | Add `FormBuilder.nonNullable`. ([#45852](https://github.com/angular/angular/pull/45852)) |
| [e0a2248b32](https://github.com/angular/angular/commit/e0a2248b3233b5d384f33859ef6207613cad909d) | feat | Add a FormRecord type. ([#45607](https://github.com/angular/angular/pull/45607)) |
| [7ee121f595](https://github.com/angular/angular/commit/7ee121f595a47338b31098ae51a6f91d80c8fdce) | feat | Add untyped versions of the model classes for use in migration. ([#45205](https://github.com/angular/angular/pull/45205)) |
| [89d299105a](https://github.com/angular/angular/commit/89d299105a4ae11985fb809f42cd0e34511207c9) | feat | Implement strict types for the Angular Forms package. ([#43834](https://github.com/angular/angular/pull/43834)) |
| [f490c2de4e](https://github.com/angular/angular/commit/f490c2de4e1ada26e62e35c0d70cb90e55297658) | feat | support negative indices in FormArray methods. ([#44848](https://github.com/angular/angular/pull/44848)) |
| [39be06037d](https://github.com/angular/angular/commit/39be06037daf65ae9298b5bdb4cd50785c16332f) | fix | Add a `nonNullable` option to `FormControl` for consistency. |
| [4332897baa](https://github.com/angular/angular/commit/4332897baa2226ef246ee054fdd5254e3c129109) | fix | Add UntypedFormBuilder ([#45268](https://github.com/angular/angular/pull/45268)) |
| [5d13e58aed](https://github.com/angular/angular/commit/5d13e58aed8b7641f0b2d4f0c9015cb90ff4edb5) | fix | Allow NonNullableFormBuilder to be injected. ([#45904](https://github.com/angular/angular/pull/45904)) |
| [8dd3f82f94](https://github.com/angular/angular/commit/8dd3f82f946bae86dc6c678d8694ab73d915bbfa) | fix | Correct empty validator to handle objects with a property `length: 0`. ([#33729](https://github.com/angular/angular/pull/33729)) |
| [ff3f5a8d12](https://github.com/angular/angular/commit/ff3f5a8d12e3243620e311b690a050e26493e539) | fix | Fix a typing bug in FormBuilder. ([#45684](https://github.com/angular/angular/pull/45684)) |
| [fe0e42a996](https://github.com/angular/angular/commit/fe0e42a996d5b70f4c0923cb6570c9a8032b1298) | fix | Make UntypedFormBuilder assignable to FormBuilder, and vice versa. ([#45421](https://github.com/angular/angular/pull/45421)) |
| [b36dec6b5b](https://github.com/angular/angular/commit/b36dec6b5b05de0d40581726c59db9f962a97124) | fix | not picking up disabled state if group is swapped out and disabled ([#43499](https://github.com/angular/angular/pull/43499)) |
| [9f6fa5b746](https://github.com/angular/angular/commit/9f6fa5b746cbdd4a71f67728ff6b663ad26c6a29) | fix | Prevent FormBuilder from distributing unions to control types. ([#45942](https://github.com/angular/angular/pull/45942)) |
| [aa7b857be8](https://github.com/angular/angular/commit/aa7b857be89a62e6dcfe62c418acf0823525d265) | fix | Property renaming safe code ([#45271](https://github.com/angular/angular/pull/45271)) |
| [cae1e44608](https://github.com/angular/angular/commit/cae1e44608227ac80682401190c6d28ef39b3269) | fix | Update the typed forms migration to use `FormArray<T>` instead of `FormArray<T[]>`. ([#44933](https://github.com/angular/angular/pull/44933)) |
| [d336ba96d9](https://github.com/angular/angular/commit/d336ba96d922363235688f54d8af108ef7ab01f0) | fix | Update the typed forms migration. ([#45281](https://github.com/angular/angular/pull/45281)) |
| [018550ed50](https://github.com/angular/angular/commit/018550ed5025de9737794b683eb7c0697d83d430) | fix | Value and RawValue should be part of the public API. ([#45978](https://github.com/angular/angular/pull/45978)) |
| [2e96cede3e](https://github.com/angular/angular/commit/2e96cede3e2d9ac399c10d3bfe25259b92a5276e) | fix | Warn on FormControls that are constructed with both options and asyncValidators. |
### http
| Commit | Type | Description |
| -- | -- | -- |
| [76a9a24cdc](https://github.com/angular/angular/commit/76a9a24cdcb87e36868e2e29d1831af2dec3a818) | fix | encode + signs in query params as %2B (angular[#11058](https://github.com/angular/angular/pull/11058)) ([#45111](https://github.com/angular/angular/pull/45111)) |
| [d43c0e973f](https://github.com/angular/angular/commit/d43c0e973f4389c74eb19a7f6b667bd2e1d380fe) | fix | Throw error when headers are supplied in JSONP request ([#45210](https://github.com/angular/angular/pull/45210)) |
### language-service
| Commit | Type | Description |
| -- | -- | -- |
| [9d4af65e34](https://github.com/angular/angular/commit/9d4af65e343e41b48cb9afd12c2b61d8ca61a9ac) | feat | Provide plugin to delegate rename requests to Angular ([#44696](https://github.com/angular/angular/pull/44696)) |
| [3ae133c69e](https://github.com/angular/angular/commit/3ae133c69e1c78d5ddf772cacf222f909faccd70) | fix | Fix detection of Angular for v14+ projects ([#45998](https://github.com/angular/angular/pull/45998)) |
### localize
| Commit | Type | Description |
| -- | -- | -- |
| [a50e2da64a](https://github.com/angular/angular/commit/a50e2da64a4297d1bc994a267203c2097da2efaf) | fix | ensure transitively loaded compiler code is tree-shakable ([#45405](https://github.com/angular/angular/pull/45405)) |
### migrations
| Commit | Type | Description |
| -- | -- | -- |
| [d56a537196](https://github.com/angular/angular/commit/d56a537196d2ab0f3f48821889020d2f5bc621ba) | feat | Add migration to add explicit `Route`/`Routes` type ([#45084](https://github.com/angular/angular/pull/45084)) |
### ngcc
| Commit | Type | Description |
| -- | -- | -- |
| [74a2e2e2ec](https://github.com/angular/angular/commit/74a2e2e2ecb81a31c7fbec42d7770937b09e33a4) | fix | cope with packages following APF v14+ ([#45833](https://github.com/angular/angular/pull/45833)) |
### platform-browser
| Commit | Type | Description |
| -- | -- | -- |
| [a01bcb8e7e](https://github.com/angular/angular/commit/a01bcb8e7eaf63ac9466a78dd4d15228241da900) | fix | do not run change detection when loading Hammer ([#44921](https://github.com/angular/angular/pull/44921)) |
| [b32647dc68](https://github.com/angular/angular/commit/b32647dc68b055da0c49c86d6e7e2a7d2ec5954a) | fix | Make transfer state key typesafe. ([#23020](https://github.com/angular/angular/pull/23020)) |
| [c7bf75dd5e](https://github.com/angular/angular/commit/c7bf75dd5e7f3f80a3c2afb8586ae46f7258f349) | fix | remove obsolete shim for Map comparison in Jasmine ([#45521](https://github.com/angular/angular/pull/45521)) |
| [23c4c9601e](https://github.com/angular/angular/commit/23c4c9601e1bdd8bd2e37d9e0468440a44971b95) | perf | avoid including Testability by default in `bootstrapApplication` ([#45885](https://github.com/angular/angular/pull/45885)) |
### platform-server
| Commit | Type | Description |
| -- | -- | -- |
| [dff5586d52](https://github.com/angular/angular/commit/dff5586d5243f914b9054b5ab7ac71d57edfa973) | feat | implement `renderApplication` function ([#45785](https://github.com/angular/angular/pull/45785)) |
| [22c71be94c](https://github.com/angular/angular/commit/22c71be94c3a695ca0cd0316065d807abb46355f) | fix | update `renderApplication` to move `appId` to options ([#45844](https://github.com/angular/angular/pull/45844)) |
### router
| Commit | Type | Description |
| -- | -- | -- |
| [f4fd1a8262](https://github.com/angular/angular/commit/f4fd1a82620b5b3899c5e8c89fa06b084ee5792e) | feat | Add `EnvironmentInjector` to `RouterOutlet.activateWith` ([#45597](https://github.com/angular/angular/pull/45597)) |
| [910de8bc33](https://github.com/angular/angular/commit/910de8bc3379b1452c0bc23a866b5108d6d94e55) | feat | Add `Route.title` with a configurable `TitleStrategy` ([#43307](https://github.com/angular/angular/pull/43307)) |
| [4e0957a4e1](https://github.com/angular/angular/commit/4e0957a4e10d1ae188faa843043a2314c9873c52) | feat | Add ability to specify providers on a Route ([#45673](https://github.com/angular/angular/pull/45673)) |
| [dea8c86cd5](https://github.com/angular/angular/commit/dea8c86cd57f8e1720634928805f9ea0ba8f0baa) | feat | add ariaCurrentWhenActive input to RouterLinkActive directive ([#45167](https://github.com/angular/angular/pull/45167)) |
| [41e2a68e30](https://github.com/angular/angular/commit/41e2a68e30c12e5ad3e26047c3a4032e9aa1a6e1) | feat | add type properties to all router events ([#44189](https://github.com/angular/angular/pull/44189)) |
| [4962a4a332](https://github.com/angular/angular/commit/4962a4a3324d5972f364d768b38b21a33fdb7d7c) | feat | Allow `loadChildren` to return a `Route` array ([#45700](https://github.com/angular/angular/pull/45700)) |
| [791bd31424](https://github.com/angular/angular/commit/791bd3142432ed7caf14a68a6e434b27004e634b) | feat | set stricter type for Route.title ([#44939](https://github.com/angular/angular/pull/44939)) |
| [50004c143b](https://github.com/angular/angular/commit/50004c143ba9b1e041c7b30caf98f6582d3d26d4) | feat | Support lazy loading standalone components with `loadComponent` ([#45705](https://github.com/angular/angular/pull/45705)) |
| [7fd416d060](https://github.com/angular/angular/commit/7fd416d060bd873bc88dffed41946c51aa649ec1) | fix | Fix type of Route.pathMatch to be more accurate ([#45176](https://github.com/angular/angular/pull/45176)) |
| [1c11a57155](https://github.com/angular/angular/commit/1c11a5715576632a4fb7170202395cf95dfbce09) | fix | merge interited resolved data and static data ([#45276](https://github.com/angular/angular/pull/45276)) |
| [f8f3ab377b](https://github.com/angular/angular/commit/f8f3ab377b8842c2bae0f215a0e90aaa3a1e070a) | fix | Remove `any` from `LoadChildrenCallback` type ([#45524](https://github.com/angular/angular/pull/45524)) |
| [d4fc12fa19](https://github.com/angular/angular/commit/d4fc12fa19dbe5e89189bb52c37e5d37a00a663c) | fix | Remove deprecated initialNavigation option ([#45729](https://github.com/angular/angular/pull/45729)) |
| [989e840cce](https://github.com/angular/angular/commit/989e840cce7ebe94311ae898786e09b1b41ce7f6) | fix | Remove unused string type for ActivatedRoute.component ([#45625](https://github.com/angular/angular/pull/45625)) |
| [64f837d2c0](https://github.com/angular/angular/commit/64f837d2c0fbcf722d32b35a87e87220bfe61f65) | fix | Update `Navigation#initialUrl` to match documentation and reality ([#43863](https://github.com/angular/angular/pull/43863)) |
| [96fd29c6d2](https://github.com/angular/angular/commit/96fd29c6d2d2abc5afee4d21a3e964a79aa39844) | fix | validate lazy loaded configs ([#45526](https://github.com/angular/angular/pull/45526)) |
| [f13295f3a3](https://github.com/angular/angular/commit/f13295f3a3a1d622d15cf8339360d53feba824b5) | perf | cancel the navigation instantly if at least one resolver doesn't emit any value ([#45621](https://github.com/angular/angular/pull/45621)) |
| [1d2f5c1101](https://github.com/angular/angular/commit/1d2f5c1101ccd182f5b528de52583a1b98dd6789) | refactor | deprecate no longer needed resolver fields ([#45597](https://github.com/angular/angular/pull/45597)) |
| [7b367d9d90](https://github.com/angular/angular/commit/7b367d9d908e15222645a45e2ba133b9d9da76b7) | refactor | Remove unnecessary setTimeout in UrlTree redirects ([#45735](https://github.com/angular/angular/pull/45735)) |
| [c9679760b2](https://github.com/angular/angular/commit/c9679760b2bf5c607c957c20482b9cea7a21702b) | refactor | take only the first emitted value of every resolver to make it consistent with guards ([#44573](https://github.com/angular/angular/pull/44573)) |
### service-worker
| Commit | Type | Description |
| -- | -- | -- |
| [ec0a0e0669](https://github.com/angular/angular/commit/ec0a0e0669ef5d2f524fbf9a540eb2b306b2e24a) | feat | add `cacheOpaqueResponses` option for data-groups ([#44723](https://github.com/angular/angular/pull/44723)) |
| [bd04fbc05b](https://github.com/angular/angular/commit/bd04fbc05b0397de966a493a863e1054203c86d9) | feat | emit a notification when the service worker is already up to date after check ([#45216](https://github.com/angular/angular/pull/45216)) |
## Special Thanks
Alex Rickabaugh, Andrew Kushnir, Andrew Scott, George Kalpakas, Joey Perrott, Michal Materowski, Paul Gschwendtner, Pawel Kozlowski, Sumit Arora and dario-piotrowicz
Adrian Kunz, Alan Agius, AleksanderBodurri, Alex Rickabaugh, AlirezaEbrahimkhani, Amir Rustamzadeh, Andrew Kushnir, Andrew Scott, Chabbey François, Charles Lyding, Cédric Exbrayat, Daan De Smedt, David Schmidt, Derek Cormier, Dmitrij Kuba, Doug Parker, Dylan Hunn, Emma Twersky, George Kalpakas, George Looshch, Jan Kuehle, Jessica Janiuk, JiaLiPassion, JimMorrison723, Joe Martin (Crowdstaffing), Joey Perrott, JoostK, Kristiyan Kostadinov, Krzysztof Platis, Leosvel Pérez Espinosa, Maddie Klein, Mark Whitfeld, Martin Sikora, Michael-Doner, Michal Materowski, Minko Gechev, Paul Gschwendtner, Pawel Kozlowski, Payam Shahidi, Pusztai Tibor, Ricardo Mattiazzi Baumgartner, Roy Dorombozi, Ruslan Lekhman, Samuel Littley, Sergej Grilborzer, Sumit Arora, Tobias Speicher, Virginia Dooley, Zack Elliott, alirezaghey, ananyahs96, arturovt, cexbrayat, dario-piotrowicz, ivanwonder, kamikopi, markostanimirovic, markwhitfeld, mgechev, renovate[bot], twerske and zverbeta
<!-- CHANGELOG SPLIT MARKER -->
<a name="13.3.10"></a>
# 13.3.10 (2022-05-25)
## Special Thanks
A. J. Javier, Aristeidis Bampakos, J Rob Gant, Jerome Kruse, Joey Perrott, Nathan Nontell, Paul Gschwendtner, Roopesh Chinnakampalli, Thomas Mair, Tom Raithel, dario-piotrowicz and mgechev
<!-- CHANGELOG SPLIT MARKER -->
<a name="13.3.6"></a>
# 13.3.6 (2022-05-04)
## Special Thanks
Andrew Kushnir, Andrew Scott, George Kalpakas, Paul Gschwendtner, Pawel Kozlowski, Ryan Day and dario-piotrowicz
<!-- CHANGELOG SPLIT MARKER -->
@@ -59,68 +347,6 @@ Andrew Kushnir, George Kalpakas, Joey Perrott and dario-piotrowicz
<!-- CHANGELOG SPLIT MARKER -->
<a name="14.0.0-next.14"></a>
# 14.0.0-next.14 (2022-04-20)
## Breaking Changes
### http
- Queries including + will now actually query for + instead of space.
Most workarounds involving custom codecs will be unaffected.
Possible server-side workarounds will need to be undone.
### router
- The type of `component` on `ActivatedRoute` and `ActivatedRouteSnapshot`
includes `string`. In reality, this is not the case. The component
cannot be anything other than a component class.
- Lazy loaded configs are now also validated once loaded like the
initial set of routes are. Lazy loaded modules which have invalid Route
configs will now error. Note that this is only done in dev mode so
there is no production impact of this change.
## Deprecations
### router
- The `resolver` argument of the `RouterOutletContract.activateWith` function and the `resolver` field of the `OutletContext` class are deprecated. Passing component factory resolvers are no longer needed. The `ComponentFactoryResolver`-related symbols were deprecated in `@angular/core` package since v13.
### bazel
| Commit | Type | Description |
| -- | -- | -- |
| [f8a1ea0c11](https://github.com/angular/angular/commit/f8a1ea0c117aa97f45b7696d2b0c9b5679e09b9f) | fix | do not error if files part of `srcs` are outside of package ([#45622](https://github.com/angular/angular/pull/45622)) |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [046dad1a8d](https://github.com/angular/angular/commit/046dad1a8d878ea537a6e2ef5f5ef24a85a2cf02) | fix | fix issue with incremental tracking of APIs for pipes ([#45672](https://github.com/angular/angular/pull/45672)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [174ce7dd13](https://github.com/angular/angular/commit/174ce7dd13f6d8f941d3aa0b843559614cb68b0c) | feat | add `ApplicationRef.destroy` method ([#45624](https://github.com/angular/angular/pull/45624)) |
| [b568a5e708](https://github.com/angular/angular/commit/b568a5e708579f5035f40c7218fbba39ad6b3065) | feat | implement `importProvidersFrom` function ([#45626](https://github.com/angular/angular/pull/45626)) |
| [d5a6cd1111](https://github.com/angular/angular/commit/d5a6cd11110c78762a8e6115a718f5851508dbf2) | feat | implement EnvironmentInjector with adapter to NgModuleRef ([#45626](https://github.com/angular/angular/pull/45626)) |
| [57f8ab2ed8](https://github.com/angular/angular/commit/57f8ab2ed81f9fa12ff84fabcd9771ab877809c5) | fix | better error message when directive extends a component ([#45658](https://github.com/angular/angular/pull/45658)) |
| [c6e0e3f6d3](https://github.com/angular/angular/commit/c6e0e3f6d31a66dc3034da4dfddbffed4bec37d2) | fix | improve multiple components match error ([#45645](https://github.com/angular/angular/pull/45645)) |
### forms
| Commit | Type | Description |
| -- | -- | -- |
| [e0a2248b32](https://github.com/angular/angular/commit/e0a2248b3233b5d384f33859ef6207613cad909d) | feat | Add a FormRecord type. ([#45607](https://github.com/angular/angular/pull/45607)) |
| [ff3f5a8d12](https://github.com/angular/angular/commit/ff3f5a8d12e3243620e311b690a050e26493e539) | fix | Fix a typing bug in FormBuilder. ([#45684](https://github.com/angular/angular/pull/45684)) |
### http
| Commit | Type | Description |
| -- | -- | -- |
| [76a9a24cdc](https://github.com/angular/angular/commit/76a9a24cdcb87e36868e2e29d1831af2dec3a818) | fix | encode + signs in query params as %2B (angular[#11058](https://github.com/angular/angular/pull/11058)) ([#45111](https://github.com/angular/angular/pull/45111)) |
### language-service
| Commit | Type | Description |
| -- | -- | -- |
| [f57e46c538](https://github.com/angular/angular/commit/f57e46c53881c46e712a64e23bffb1893dfe54fc) | fix | two-way binding completion should not remove the trailing quote ([#45582](https://github.com/angular/angular/pull/45582)) |
### router
| Commit | Type | Description |
| -- | -- | -- |
| [f4fd1a8262](https://github.com/angular/angular/commit/f4fd1a82620b5b3899c5e8c89fa06b084ee5792e) | feat | Add `EnvironmentInjector` to `RouterOutlet.activateWith` ([#45597](https://github.com/angular/angular/pull/45597)) |
| [4e0957a4e1](https://github.com/angular/angular/commit/4e0957a4e10d1ae188faa843043a2314c9873c52) | feat | Add ability to specify providers on a Route ([#45673](https://github.com/angular/angular/pull/45673)) |
| [989e840cce](https://github.com/angular/angular/commit/989e840cce7ebe94311ae898786e09b1b41ce7f6) | fix | Remove unused string type for ActivatedRoute.component ([#45625](https://github.com/angular/angular/pull/45625)) |
| [96fd29c6d2](https://github.com/angular/angular/commit/96fd29c6d2d2abc5afee4d21a3e964a79aa39844) | fix | validate lazy loaded configs ([#45526](https://github.com/angular/angular/pull/45526)) |
| [f13295f3a3](https://github.com/angular/angular/commit/f13295f3a3a1d622d15cf8339360d53feba824b5) | perf | cancel the navigation instantly if at least one resolver doesn't emit any value ([#45621](https://github.com/angular/angular/pull/45621)) |
| [1d2f5c1101](https://github.com/angular/angular/commit/1d2f5c1101ccd182f5b528de52583a1b98dd6789) | refactor | deprecate no longer needed resolver fields ([#45597](https://github.com/angular/angular/pull/45597)) |
## Special Thanks
Adrian Kunz, Alex Rickabaugh, Andrew Kushnir, Andrew Scott, Dmitrij Kuba, Doug Parker, Dylan Hunn, George Kalpakas, Ilya Marchik, Jeremy Elbourn, Kristiyan Kostadinov, Louis Gombert, Mangalraj, Marko Kaznovac, Paul Gschwendtner, Saurabh Kamble, dario-piotrowicz and ivanwonder
<!-- CHANGELOG SPLIT MARKER -->
<a name="13.3.4"></a>
# 13.3.4 (2022-04-20)
### core
@@ -137,24 +363,6 @@ Andrew Kushnir, Andrew Scott, George Kalpakas, Ilya Marchik, Jeremy Elbourn, Kri
<!-- CHANGELOG SPLIT MARKER -->
<a name="14.0.0-next.13"></a>
# 14.0.0-next.13 (2022-04-13)
## Breaking Changes
### core
- Since Ivy, TestBed doesn't use AOT summaries. The `aotSummaries` fields in TestBed APIs were present, but unused. The fields were deprecated in previous major version and in v14 those fields are removed. The `aotSummaries` fields were completely unused, so you can just drop them from the TestBed APIs usage.
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [598b759d33](https://github.com/angular/angular/commit/598b759d33221cc2bbfad4895ca0d2499a0547f8) | fix | avoid errors with extremely long instruction chains ([#45574](https://github.com/angular/angular/pull/45574)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [9add714b13](https://github.com/angular/angular/commit/9add714b13740db621eb2b200d72be74cc7eb630) | refactor | remove deprecated `aotSummaries` fields in TestBed config ([#45487](https://github.com/angular/angular/pull/45487)) |
## Special Thanks
4javier, Andrew Kushnir, Andrew Scott, Dylan Hunn, Jason Hendee, Jessica Janiuk, Kristiyan Kostadinov, Michael-Doner, Michal Materowski and Virginia Dooley
<!-- CHANGELOG SPLIT MARKER -->
<a name="13.3.3"></a>
# 13.3.3 (2022-04-13)
### compiler
@@ -166,63 +374,6 @@ Andrew Kushnir, Andrew Scott, George Kalpakas, Ilya Marchik, Jeremy Elbourn, Kri
<!-- CHANGELOG SPLIT MARKER -->
<a name="14.0.0-next.12"></a>
# 14.0.0-next.12 (2022-04-12)
## Breaking Changes
### forms
- Forms classes accept a generic.
Forms model classes now accept a generic type parameter. Untyped versions of these classes are available to opt-out of the new, stricter behavior.
### router
- When returning a `Promise` from the
`LoadChildrenCallback`, the possible type is now restricted to
`Type<any>|NgModuleFactory<any>` rather than `any`.
### animations
| Commit | Type | Description |
| -- | -- | -- |
| [a6fa37bc6e](https://github.com/angular/angular/commit/a6fa37bc6e705fee48f555d4b8022915094e8b16) | feat | make validateStyleProperty check dev-mode only ([#45570](https://github.com/angular/angular/pull/45570)) |
### bazel
| Commit | Type | Description |
| -- | -- | -- |
| [636909fba7](https://github.com/angular/angular/commit/636909fba73e25b75489c6e050bda1b880e62885) | feat | allow for generated `package.json` files in `ng_package` ([#45470](https://github.com/angular/angular/pull/45470)) |
| [28e835b4bb](https://github.com/angular/angular/commit/28e835b4bbd9271cbc7abe2a0e42ff273b1e7e84) | feat | report error when dependency does not provide JS sources in `ng_package` ([#45470](https://github.com/angular/angular/pull/45470)) |
| [4b2e98d55d](https://github.com/angular/angular/commit/4b2e98d55dde4f6040a021a6ebd35d29fb5f8fdf) | fix | remove unnecessary file extractions from `ng_package` ([#45470](https://github.com/angular/angular/pull/45470)) |
### forms
| Commit | Type | Description |
| -- | -- | -- |
| [89d299105a](https://github.com/angular/angular/commit/89d299105a4ae11985fb809f42cd0e34511207c9) | feat | Implement strict types for the Angular Forms package. ([#43834](https://github.com/angular/angular/pull/43834)) |
### platform-browser
| Commit | Type | Description |
| -- | -- | -- |
| [c7bf75dd5e](https://github.com/angular/angular/commit/c7bf75dd5e7f3f80a3c2afb8586ae46f7258f349) | fix | remove obsolete shim for Map comparison in Jasmine ([#45521](https://github.com/angular/angular/pull/45521)) |
### router
| Commit | Type | Description |
| -- | -- | -- |
| [f8f3ab377b](https://github.com/angular/angular/commit/f8f3ab377b8842c2bae0f215a0e90aaa3a1e070a) | fix | Remove `any` from `LoadChildrenCallback` type ([#45524](https://github.com/angular/angular/pull/45524)) |
## Special Thanks
Andrew Scott, Cédric Exbrayat, Dylan Hunn, George Kalpakas, Hossein Mousavi, Jessica Janiuk, Joe Martin (Crowdstaffing), Joey Perrott, Kristiyan Kostadinov, Leosvel Pérez Espinosa, Michael-Doner, Michal Materowski, Paul Gschwendtner, Samuel Littley, Sumit Arora and dario-piotrowicz
<!-- CHANGELOG SPLIT MARKER -->
<a name="14.0.0-next.11"></a>
# 14.0.0-next.11 (2022-04-06)
### animations
| Commit | Type | Description |
| -- | -- | -- |
| [29d3891782](https://github.com/angular/angular/commit/29d38917825b9334a049799cdac60f0d39baf65a) | fix | handle structured AnimateTimings ([#31107](https://github.com/angular/angular/pull/31107)) |
### migrations
| Commit | Type | Description |
| -- | -- | -- |
| [d56a537196](https://github.com/angular/angular/commit/d56a537196d2ab0f3f48821889020d2f5bc621ba) | feat | Add migration to add explicit `Route`/`Routes` type ([#45084](https://github.com/angular/angular/pull/45084)) |
### router
| Commit | Type | Description |
| -- | -- | -- |
| [1c11a57155](https://github.com/angular/angular/commit/1c11a5715576632a4fb7170202395cf95dfbce09) | fix | merge interited resolved data and static data ([#45276](https://github.com/angular/angular/pull/45276)) |
## Special Thanks
Alan Agius, Andrew Kushnir, Andrew Scott, Chabbey François, Christoph Guttandin, Cédric Exbrayat, Dylan Hunn, George Kalpakas, Martin Sikora, mgechev and piyush132000
<!-- CHANGELOG SPLIT MARKER -->
<a name="13.3.2"></a>
# 13.3.2 (2022-04-06)
### animations
@@ -253,114 +404,6 @@ AlirezaEbrahimkhani, Andrew Kushnir, Andrew Scott, Ben Brook, Dylan Hunn, George
<!-- CHANGELOG SPLIT MARKER -->
<a name="14.0.0-next.10"></a>
# 14.0.0-next.10 (2022-03-30)
## Breaking Changes
### http
- JSONP will throw an error when headers are set on a request
JSONP does not support headers being set on requests. Before when
a request was sent to a JSONP backend that had headers set the headers
were ignored. The JSONP backend will now throw an error if it
receives a request that has any headers set. Any uses of JSONP
on requests with headers set will need to remove the headers
to avoid the error.
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [2142ffd295](https://github.com/angular/angular/commit/2142ffd295de491eb8582c2eb1712b5b48044f24) | feat | propagate `standalone` flag to runtime ([#44973](https://github.com/angular/angular/pull/44973)) |
| [6f653e05f9](https://github.com/angular/angular/commit/6f653e05f985141ae4d2d90af78b2bc001595661) | feat | standalone types imported into NgModule scopes ([#44973](https://github.com/angular/angular/pull/44973)) |
| [3d13343975](https://github.com/angular/angular/commit/3d133439754cbf5d5a20bb3c714c8673c848e465) | fix | better error messages for NgModule structural issues ([#44973](https://github.com/angular/angular/pull/44973)) |
| [06050ac2b4](https://github.com/angular/angular/commit/06050ac2b4937836096fb331ec71bacb5a1fc231) | fix | handle inline type-check blocks in nullish coalescing extended check ([#45454](https://github.com/angular/angular/pull/45454)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [d36fa111eb](https://github.com/angular/angular/commit/d36fa111eb677d504a9952d8b4ca53560cadd04d) | fix | avoid Closure Compiler error in restoreView ([#45445](https://github.com/angular/angular/pull/45445)) |
### forms
| Commit | Type | Description |
| -- | -- | -- |
| [b36dec6b5b](https://github.com/angular/angular/commit/b36dec6b5b05de0d40581726c59db9f962a97124) | fix | not picking up disabled state if group is swapped out and disabled ([#43499](https://github.com/angular/angular/pull/43499)) |
### http
| Commit | Type | Description |
| -- | -- | -- |
| [d43c0e973f](https://github.com/angular/angular/commit/d43c0e973f4389c74eb19a7f6b667bd2e1d380fe) | fix | Throw error when headers are supplied in JSONP request ([#45210](https://github.com/angular/angular/pull/45210)) |
## Special Thanks
Alex Rickabaugh, AlirezaEbrahimkhani, Andrew Kushnir, Andrew Scott, Dylan Hunn, JiaLiPassion, JoostK, Kristiyan Kostadinov, Maddie Klein, Michael-Doner, Paul Gschwendtner, Willian Corrêa, arturovt, dario-piotrowicz and zverbeta
<!-- CHANGELOG SPLIT MARKER -->
<a name="14.0.0-next.9"></a>
# 14.0.0-next.9 (2022-03-25)
## Special Thanks
Paul Gschwendtner
<!-- CHANGELOG SPLIT MARKER -->
<a name="14.0.0-next.8"></a>
# 14.0.0-next.8 (2022-03-25)
## Breaking Changes
### core
- TypeScript versions older than 4.6 are no longer supported.
### zone.js
- in TaskTrackingZoneSpec track a periodic task until it is cancelled
The breaking change is scoped only to the plugin
`zone.js/plugins/task-tracking`. If you used `TaskTrackingZoneSpec` and
checked the pending macroTasks e.g. using `(this.ngZone as any)._inner
._parent._properties.TaskTrackingZone.getTasksFor('macroTask')`, then
its behavior slightly changed for periodic macrotasks. For example,
previously the `setInterval` macrotask was no longer tracked after its
callback was executed for the first time. Now it's tracked until
the task is explicitly cancelled, e.g with `clearInterval(id)`.
fixes 45350
### animations
| Commit | Type | Description |
| -- | -- | -- |
| [79d334b138](https://github.com/angular/angular/commit/79d334b1385685d0fd1451534df2ed3cbaefa0b6) | feat | provide warnings for non-animatable CSS properties ([#45212](https://github.com/angular/angular/pull/45212)) |
| [2a75754ee8](https://github.com/angular/angular/commit/2a75754ee823032e651bc596887a2186dc6846ae) | fix | apply default params when resolved value is null or undefined ([#45339](https://github.com/angular/angular/pull/45339)) |
### bazel
| Commit | Type | Description |
| -- | -- | -- |
| [dc72f3007a](https://github.com/angular/angular/commit/dc72f3007ac74389ec02ea021a27f35770aa5a5d) | fix | ng module compilation workers are subject to linker race-conditions ([#45393](https://github.com/angular/angular/pull/45393)) |
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [fffa023803](https://github.com/angular/angular/commit/fffa023803e5b04a58f0bd0b8667ee8b686aa530) | fix | scope css rules within `@layer` blocks ([#45396](https://github.com/angular/angular/pull/45396)) |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [27b4af7240](https://github.com/angular/angular/commit/27b4af7240ea964d1e4d51b83118f10321163627) | fix | full side-effectful registration of NgModules with ids ([#45024](https://github.com/angular/angular/pull/45024)) |
| [8155428ba6](https://github.com/angular/angular/commit/8155428ba65c38c0c15f2666727202a7b360c1bd) | perf | ignore the module.id anti-pattern for NgModule ids ([#45024](https://github.com/angular/angular/pull/45024)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [c9d566ce4b](https://github.com/angular/angular/commit/c9d566ce4b6e9097d9eceb7ac3964a0b25c404ad) | feat | drop support for TypeScript 4.4 and 4.5 ([#45394](https://github.com/angular/angular/pull/45394)) |
| [be161bef79](https://github.com/angular/angular/commit/be161bef798ac5309df8390e3c2bba2cf84cb530) | fix | memory leak in event listeners inside embedded views ([#43075](https://github.com/angular/angular/pull/43075)) |
### forms
| Commit | Type | Description |
| -- | -- | -- |
| [fe0e42a996](https://github.com/angular/angular/commit/fe0e42a996d5b70f4c0923cb6570c9a8032b1298) | fix | Make UntypedFormBuilder assignable to FormBuilder, and vice versa. ([#45421](https://github.com/angular/angular/pull/45421)) |
## Special Thanks
Alan Agius, Alex Rickabaugh, AlirezaEbrahimkhani, Ben Brook, Dylan Hunn, George Kalpakas, Joey Perrott, JoostK, Kristiyan Kostadinov, Krzysztof Platis, Mike, Paul Gschwendtner, Tobias Speicher, alirezaghey, arturovt, dario-piotrowicz, khai and mgechev
<!-- CHANGELOG SPLIT MARKER -->
<a name="14.0.0-next.7"></a>
# 14.0.0-next.7 (2022-03-16)
### core
| Commit | Type | Description |
| -- | -- | -- |
| [225e4f2dbe](https://github.com/angular/angular/commit/225e4f2dbeac5982982fb94eac65ea931c44247a) | feat | triggerEventHandler accept optional eventObj ([#45279](https://github.com/angular/angular/pull/45279)) |
### forms
| Commit | Type | Description |
| -- | -- | -- |
| [9db9091349](https://github.com/angular/angular/commit/9db9091349e0e9761855d3c55729004674eec3c5) | fix | improve error message for invalid value accessors ([#45192](https://github.com/angular/angular/pull/45192)) |
## Special Thanks
Alan Agius, Alistair Kane, Amer Yousuf, Andrew Kushnir, Andrew Scott, Derek Cormier, Jessica Janiuk, JiaLiPassion, Lee Cooper, Paul Gschwendtner, alirezaghey and why520crazy
<!-- CHANGELOG SPLIT MARKER -->
<a name="13.3.0"></a>
# 13.3.0-rc.0 (2022-03-16)
### core
@@ -394,41 +437,6 @@ Alistair Kane, Andrew Scott and Kristiyan Kostadinov
<!-- CHANGELOG SPLIT MARKER -->
<a name="14.0.0-next.6"></a>
# 14.0.0-next.6 (2022-03-09)
## Breaking Changes
### core
- Support for Node.js v12 has been removed as it will become EOL on 2022-04-30. Please use Node.js v14.15 or later.
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [2b7553db6f](https://github.com/angular/angular/commit/2b7553db6f59e64b73fc2e5601db278f815a67a2) | fix | compute correct offsets when interpolations have HTML entities ([#44811](https://github.com/angular/angular/pull/44811)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [6eaaefd22e](https://github.com/angular/angular/commit/6eaaefd22ebb95ee896a62237832ff2f2defdee0) | feat | drop support for Node.js 12 ([#45286](https://github.com/angular/angular/pull/45286)) |
| [94bba76a4a](https://github.com/angular/angular/commit/94bba76a4a9594a5eb90e581f407f1b70697e715) | feat | support TypeScript 4.6 ([#45190](https://github.com/angular/angular/pull/45190)) |
| [9fa6f5a552](https://github.com/angular/angular/commit/9fa6f5a552b7780ce32aa5a60273d4008a7b6afb) | fix | incorrectly inserting elements inside `<template>` element ([#43429](https://github.com/angular/angular/pull/43429)) |
### forms
| Commit | Type | Description |
| -- | -- | -- |
| [4332897baa](https://github.com/angular/angular/commit/4332897baa2226ef246ee054fdd5254e3c129109) | fix | Add UntypedFormBuilder ([#45268](https://github.com/angular/angular/pull/45268)) |
| [aa7b857be8](https://github.com/angular/angular/commit/aa7b857be89a62e6dcfe62c418acf0823525d265) | fix | Property renaming safe code ([#45271](https://github.com/angular/angular/pull/45271)) |
| [d336ba96d9](https://github.com/angular/angular/commit/d336ba96d922363235688f54d8af108ef7ab01f0) | fix | Update the typed forms migration. ([#45281](https://github.com/angular/angular/pull/45281)) |
### language-service
| Commit | Type | Description |
| -- | -- | -- |
| [be220fa683](https://github.com/angular/angular/commit/be220fa683e636e5ec3e49f56859015ec66a71fb) | fix | Prioritize Angular-specific completions over DOM completions ([#45293](https://github.com/angular/angular/pull/45293)) |
### service-worker
| Commit | Type | Description |
| -- | -- | -- |
| [bd04fbc05b](https://github.com/angular/angular/commit/bd04fbc05b0397de966a493a863e1054203c86d9) | feat | emit a notification when the service worker is already up to date after check ([#45216](https://github.com/angular/angular/pull/45216)) |
| [3ecf93020c](https://github.com/angular/angular/commit/3ecf93020ce06b9b8621f0c83126cb3d584d4181) | fix | file system hash in batch of 500 elements ([#45262](https://github.com/angular/angular/pull/45262)) |
## Special Thanks
Alan Agius, Andrew Kushnir, Andrew Scott, Anner Visser, Aristeidis Bampakos, Dylan Hunn, George Kalpakas, JiaLiPassion, Joey Perrott, JoostK, Kristiyan Kostadinov, Luca, Mladen Jakovljević, Paul Gschwendtner, Srikanth Kolli, ananyahs96 and nanda18
<!-- CHANGELOG SPLIT MARKER -->
<a name="13.2.6"></a>
# 13.2.6 (2022-03-09)
### compiler
@@ -448,50 +456,6 @@ Andrew Scott, Anner Visser, Aristeidis Bampakos, JiaLiPassion, Joey Perrott, Kri
<!-- CHANGELOG SPLIT MARKER -->
<a name="14.0.0-next.5"></a>
# 14.0.0-next.5 (2022-03-02)
## Breaking Changes
### router
- The type of `Route.pathMatch` is now more strict. Places that use
`pathMatch` will likely need to be updated to have an explicit
`Route`/`Routes` type so that TypeScript does not infer the type as
`string`.
- Previously, resolvers were waiting to be completed
before proceeding with the navigation and the Router would take the last
value emitted from the resolver.
The router now takes only the first emitted value by the resolvers
and then proceeds with navigation. This is now consistent with `Observables`
returned by other guards: only the first value is used.
### common
| Commit | Type | Description |
| -- | -- | -- |
| [7671a1e40d](https://github.com/angular/angular/commit/7671a1e40d0f2abe1cb7e9d84d5ac47a5adb546a) | fix | canceled JSONP requests won't throw console error with missing callback function ([#36807](https://github.com/angular/angular/pull/36807)) |
| [05d50b849b](https://github.com/angular/angular/commit/05d50b849bb891c37c3eefab81a45099057dfd78) | perf | make `NgLocalization` token tree-shakable ([#45118](https://github.com/angular/angular/pull/45118)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [69018c9f42](https://github.com/angular/angular/commit/69018c9f42d14c1c7aa8271b406d6d247de1c564) | feat | allow for injector to be specified when creating an embedded view ([#45156](https://github.com/angular/angular/pull/45156)) |
| [c5df474c7c](https://github.com/angular/angular/commit/c5df474c7c744305c9412090b5e19bb6d4f7128d) | fix | remove individual commands for updating gold files ([#45198](https://github.com/angular/angular/pull/45198)) |
| [88f1168506](https://github.com/angular/angular/commit/88f1168506befd0665125da1fca2a719cb27dbb5) | perf | only track LViews that are referenced in __ngContext__ ([#45172](https://github.com/angular/angular/pull/45172)) |
### forms
| Commit | Type | Description |
| -- | -- | -- |
| [7ee121f595](https://github.com/angular/angular/commit/7ee121f595a47338b31098ae51a6f91d80c8fdce) | feat | Add untyped versions of the model classes for use in migration. ([#45205](https://github.com/angular/angular/pull/45205)) |
### localize
| Commit | Type | Description |
| -- | -- | -- |
| [ca5603b09b](https://github.com/angular/angular/commit/ca5603b09b06481529dce78ff995d674383e274f) | fix | avoid imports into `compiler-cli` package ([#45180](https://github.com/angular/angular/pull/45180)) |
### router
| Commit | Type | Description |
| -- | -- | -- |
| [7fd416d060](https://github.com/angular/angular/commit/7fd416d060bd873bc88dffed41946c51aa649ec1) | fix | Fix type of Route.pathMatch to be more accurate ([#45176](https://github.com/angular/angular/pull/45176)) |
| [c9679760b2](https://github.com/angular/angular/commit/c9679760b2bf5c607c957c20482b9cea7a21702b) | refactor | take only the first emitted value of every resolver to make it consistent with guards ([#44573](https://github.com/angular/angular/pull/44573)) |
## Special Thanks
Andrew Kushnir, Andrew Scott, Charles Lyding, Dmitrij Kuba, Dylan Hunn, Guillaume Bonnet, Jessica Janiuk, JiaLiPassion, JoostK, Kristiyan Kostadinov, Martin Sikora, Paul Gschwendtner, Theodore Brown and dario-piotrowicz
<!-- CHANGELOG SPLIT MARKER -->
<a name="13.2.5"></a>
# 13.2.5 (2022-03-02)
### animations
@@ -522,34 +486,6 @@ Andrew Kushnir, Andrew Scott, Charles Lyding, Guillaume Bonnet, Jessica Janiuk,
<!-- CHANGELOG SPLIT MARKER -->
<a name="14.0.0-next.4"></a>
# 14.0.0-next.4 (2022-02-23)
## Breaking Changes
### animations
- The `AnimationDriver.getParentElement` method has become required, so any
implementors of this interface are now required to provide an implementation
for this method. This breakage is unlikely to affect application developers,
as `AnimationDriver` is not expected to be implemented in user code.
### animations
| Commit | Type | Description |
| -- | -- | -- |
| [f8dc660605](https://github.com/angular/angular/commit/f8dc66060591e1ce42265a7862c3df16e40b05e1) | fix | allow animations with unsupported CSS properties ([#44729](https://github.com/angular/angular/pull/44729)) |
| [59559fdbac](https://github.com/angular/angular/commit/59559fdbacc00bee380b1e88c79d08b6e856ebbe) | refactor | make `AnimationDriver.getParentElement` required ([#45114](https://github.com/angular/angular/pull/45114)) |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [c0778b4dfc](https://github.com/angular/angular/commit/c0778b4dfc1c107543b3db6f1958814a0812c7df) | fix | Support resolve animation name from the DTS ([#45107](https://github.com/angular/angular/pull/45107)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [071c8af8ba](https://github.com/angular/angular/commit/071c8af8ba89163270f17657c0c7f1c944f186f7) | perf | avoid storing LView in __ngContext__ ([#45051](https://github.com/angular/angular/pull/45051)) |
| [a96c4827c4](https://github.com/angular/angular/commit/a96c4827c4f62e1d665d8544a3e66c51d2644c88) | perf | make `Compiler`, `ApplicationRef` and `ApplicationInitStatus` tree-shakable ([#45102](https://github.com/angular/angular/pull/45102)) |
| [1e60fe0a3e](https://github.com/angular/angular/commit/1e60fe0a3eeb6bd46997f7eeb4825351cfbe3c44) | perf | make `LOCALE_ID` and other tokens from `ApplicationModule` tree-shakable ([#45102](https://github.com/angular/angular/pull/45102)) |
## Special Thanks
Alan Cohen, AlirezaEbrahimkhani, Andrew Kushnir, Andrew Scott, Daniele Maltese, David Wolf, JiaLiPassion, JoostK, Kristiyan Kostadinov, Paul Gschwendtner, arturovt, dario-piotrowicz, ivanwonder and manuelkroiss
<!-- CHANGELOG SPLIT MARKER -->
<a name="13.2.4"></a>
# 13.2.4 (2022-02-23)
### animations
@@ -565,32 +501,6 @@ Alan Cohen, AlirezaEbrahimkhani, Andrew Kushnir, Daniele Maltese, David Wolf, Jo
<!-- CHANGELOG SPLIT MARKER -->
<a name="14.0.0-next.3"></a>
# 14.0.0-next.3 (2022-02-17)
### animations
| Commit | Type | Description |
| -- | -- | -- |
| [5c7c56bc85](https://github.com/angular/angular/commit/5c7c56bc859b195bf6710f6c1479d9e18dde35b1) | perf | improve algorithm to balance animation namespaces ([#45057](https://github.com/angular/angular/pull/45057)) |
| [4c778cdb28](https://github.com/angular/angular/commit/4c778cdb28de128c6ddecd2fd6cb6257d675500b) | perf | made errors in the animations package tree shakeable ([#45004](https://github.com/angular/angular/pull/45004)) |
### common
| Commit | Type | Description |
| -- | -- | -- |
| [bedb257afc](https://github.com/angular/angular/commit/bedb257afc1ca12eb221536ea44ade960e62cda0) | fix | cleanup URL change listeners when the root view is removed ([#44901](https://github.com/angular/angular/pull/44901)) |
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [1b91e1049e](https://github.com/angular/angular/commit/1b91e1049eedfb96febd9f6cc45fb7c0e1f154a7) | perf | chain element start/end instructions ([#44994](https://github.com/angular/angular/pull/44994)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [e461f716d4](https://github.com/angular/angular/commit/e461f716d4b736829d53de26ba6dddb58f476746) | feat | move ANIMATION_MODULE_TYPE injection token into core ([#44970](https://github.com/angular/angular/pull/44970)) |
| [822439fddd](https://github.com/angular/angular/commit/822439fdddfca316ac826569042efab460e67b50) | fix | `ViewContainerRef.createComponent` should consult module injector when custom one is provided ([#44966](https://github.com/angular/angular/pull/44966)) |
| [45d98e7ca5](https://github.com/angular/angular/commit/45d98e7ca5accf918e2602cbc17805e11e18896b) | perf | make `IterableDiffers` and `KeyValueDiffers` tree-shakable ([#45094](https://github.com/angular/angular/pull/45094)) |
## Special Thanks
Alan Cohen, AlirezaEbrahimkhani, Amer Yousuf, Andrew Kushnir, Aristeidis Bampakos, Dario Piotrowicz, Dylan Hunn, Esteban Gehring, George Kalpakas, Jessica Janiuk, JiaLiPassion, Joey Perrott, JoostK, Kristiyan Kostadinov, Mina Hosseini Moghadam, Patrick Cameron, Srdjan Milic, Yousaf Nawaz, arturovt, dario-piotrowicz, markostanimirovic, mgechev and zuckjet
<!-- CHANGELOG SPLIT MARKER -->
<a name="13.2.3"></a>
# 13.2.3 (2022-02-16)
### animations
@@ -633,118 +543,6 @@ Alan Agius, Alan Cohen, Andrew Kushnir, Andrew Scott, Daniel Díaz, Dario Piotro
<!-- CHANGELOG SPLIT MARKER -->
<a name="14.0.0-next.2"></a>
# 14.0.0-next.2 (2022-02-07)
## Breaking Changes
### forms
- Forms [email] input coercion: forms [email] input value will be considered as true if it is defined with any value rather than false and 'false'.
- Objects with a length key set to zero will no longer validate as empty. This is technically a breaking change, since objects with a key `length` and value `0` will no longer validate as empty. This is a very minor change, and any reliance on this behavior is probably a bug anyway.
### platform-browser
- This change may cause a breaking change in unit tests that are implicitly depending on a specific number and sequence of change detections in order for their assertions to pass.
- This tightens parameter types of `TransferState` usage, and is a minor breaking change which may reveal existing problematic calls. This may break invalid calls to `TransferState` methods.
### router
- The type of `initialUrl` is set to `string|UrlTree` but in reality,
the `Router` only sets it to a value that will always be `UrlTree`.
`initialUrl` is documented as "The target URL passed into the
`Router#navigateByUrl()` call before navigation" but the value
actually gets set to something completely different. It's set to the
current internal `UrlTree` of the Router at the time navigation
occurs. With this change, there is no exact replacement for the old value of
`initialUrl` because it was enver intended to be exposed.
`Router.url` is likely the best replacement for this.
In more specific use-cases, tracking the `finalUrl` between successful
navigations can also be used as a replacement.
### animations
| Commit | Type | Description |
| -- | -- | -- |
| [e46b379204](https://github.com/angular/angular/commit/e46b37920438d84bff895498c0a102dd1ffba178) | fix | implement missing transition delay ([#44799](https://github.com/angular/angular/pull/44799)) |
### common
| Commit | Type | Description |
| -- | -- | -- |
| [38c03a2035](https://github.com/angular/angular/commit/38c03a20358db3f8621c023b98e627cd385731c0) | feat | support years greater than 9999 ([#43622](https://github.com/angular/angular/pull/43622)) |
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [db6cf7e7c1](https://github.com/angular/angular/commit/db6cf7e7c168f9a25550d7fa53840c08b50b889c) | fix | allow banana-in-a-box bindings to end with non-null assertion ([#37809](https://github.com/angular/angular/pull/37809)) |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [0072eb48ba](https://github.com/angular/angular/commit/0072eb48ba1c6f549703988b7fd7ba3e09058048) | feat | initial implementation of standalone components ([#44812](https://github.com/angular/angular/pull/44812)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [d5719c2e0f](https://github.com/angular/angular/commit/d5719c2e0fb237be71d658444bbfe2410e05086a) | fix | input coercion ([#42803](https://github.com/angular/angular/pull/42803)) |
### forms
| Commit | Type | Description |
| -- | -- | -- |
| [8dd3f82f94](https://github.com/angular/angular/commit/8dd3f82f946bae86dc6c678d8694ab73d915bbfa) | fix | Correct empty validator to handle objects with a property `length: 0`. ([#33729](https://github.com/angular/angular/pull/33729)) |
| [ebf2fc5224](https://github.com/angular/angular/commit/ebf2fc5224c9debfd839087c9d1d21fb49577d37) | fix | incorrectly keeping track of ngModel with ngFor inside a form ([#40459](https://github.com/angular/angular/pull/40459)) |
### http
| Commit | Type | Description |
| -- | -- | -- |
| [28393031b1](https://github.com/angular/angular/commit/28393031b10f4dbefab7587c19641e49cb820785) | perf | remove IE special status handling ([#44354](https://github.com/angular/angular/pull/44354)) |
### platform-browser
| Commit | Type | Description |
| -- | -- | -- |
| [a01bcb8e7e](https://github.com/angular/angular/commit/a01bcb8e7eaf63ac9466a78dd4d15228241da900) | fix | do not run change detection when loading Hammer ([#44921](https://github.com/angular/angular/pull/44921)) |
| [b32647dc68](https://github.com/angular/angular/commit/b32647dc68b055da0c49c86d6e7e2a7d2ec5954a) | fix | Make transfer state key typesafe. ([#23020](https://github.com/angular/angular/pull/23020)) |
### router
| Commit | Type | Description |
| -- | -- | -- |
| [791bd31424](https://github.com/angular/angular/commit/791bd3142432ed7caf14a68a6e434b27004e634b) | feat | set stricter type for Route.title ([#44939](https://github.com/angular/angular/pull/44939)) |
| [64f837d2c0](https://github.com/angular/angular/commit/64f837d2c0fbcf722d32b35a87e87220bfe61f65) | fix | Update `Navigation#initialUrl` to match documentation and reality ([#43863](https://github.com/angular/angular/pull/43863)) |
### upgrade
| Commit | Type | Description |
| -- | -- | -- |
| [202a1a5631](https://github.com/angular/angular/commit/202a1a56314af4ddb99c476f974536a10e390319) | fix | Do not trigger duplicate navigation events from Angular Router ([#43441](https://github.com/angular/angular/pull/43441)) |
## Special Thanks
Alan Agius, Alex Rickabaugh, Andrew Kushnir, Andrew Scott, Daniel Díaz, Dario Piotrowicz, Doug Parker, Jayson Acosta, Joey Perrott, JoostK, Kristiyan Kostadinov, Olivier Capuozzo, Payam Shahidi, Pusztai Tibor, Ramzan, Ruslan Lekhman, Sergej Grilborzer, Shai Reznik, TANMAY SRIVASTAVA, arturovt, dario-piotrowicz, iRealNirmal, jhonyeduardo, markostanimirovic, mgechev and zuckjet
<!-- CHANGELOG SPLIT MARKER -->
<a name="14.0.0-next.1"></a>
# 14.0.0-next.1 (2022-02-02)
## Deprecations
### common
- The `ngModuleFactory` input of the `NgComponentOutlet` directive is deprecated in favor of a newly added `ngModule` input. The `ngModule` input accepts references to the NgModule class directly, without the need to resolve module factory first.
### animations
| Commit | Type | Description |
| -- | -- | -- |
| [7a81481fb2](https://github.com/angular/angular/commit/7a81481fb29e94b550db7ad68270eccf26bb2743) | perf | Remove generic objects in favor of Maps ([#44482](https://github.com/angular/angular/pull/44482)) |
| [6642e3c8fd](https://github.com/angular/angular/commit/6642e3c8fd7d3b5ed22710667b2c41a46f14eda8) | perf | remove no longer needed CssKeyframes classes ([#44903](https://github.com/angular/angular/pull/44903)) |
### common
| Commit | Type | Description |
| -- | -- | -- |
| [c89cf63059](https://github.com/angular/angular/commit/c89cf63059370bba43717483e3d9627499dfe815) | feat | support NgModule as an input to the NgComponentOutlet ([#44815](https://github.com/angular/angular/pull/44815)) |
| [a2cbffc06f](https://github.com/angular/angular/commit/a2cbffc06f25ea1cb8f1c8aef658f7c213621a07) | fix | include query parameters for open HTTP requests in `verify` ([#44917](https://github.com/angular/angular/pull/44917)) |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [73c97aea9e](https://github.com/angular/angular/commit/73c97aea9e4a1cb94199272384d5e912d3b0ccd0) | fix | accept nullish coalescing operator for any and unknown types ([#44862](https://github.com/angular/angular/pull/44862)) |
| [366e424a73](https://github.com/angular/angular/commit/366e424a7382cdbd72f5d1c3460fe2992fb72941) | fix | enable nullish coalescing check only with `strictNullChecks` ([#44862](https://github.com/angular/angular/pull/44862)) |
| [d82c957a26](https://github.com/angular/angular/commit/d82c957a260f4e4a341e7036355a764a5e98d3ca) | fix | ensure casing of logical paths is preserved ([#44798](https://github.com/angular/angular/pull/44798)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [5686f68fde](https://github.com/angular/angular/commit/5686f68fde514a7daf760aacc1fe52a7cb80b3af) | fix | Add back support for namespace URIs in createElement of dom renderer ([#44914](https://github.com/angular/angular/pull/44914)) |
| [39c614c438](https://github.com/angular/angular/commit/39c614c4389fb48c8fc5a51329e9169a0139c4aa) | fix | flush delayed scoping queue while setting up TestBed ([#44814](https://github.com/angular/angular/pull/44814)) |
### forms
| Commit | Type | Description |
| -- | -- | -- |
| [f490c2de4e](https://github.com/angular/angular/commit/f490c2de4e1ada26e62e35c0d70cb90e55297658) | feat | support negative indices in FormArray methods. ([#44848](https://github.com/angular/angular/pull/44848)) |
| [889de8276d](https://github.com/angular/angular/commit/889de8276d77eed3b65f8c2032f2f5c3c4ac9139) | fix | ensure OnPush ancestors are marked dirty when the promise resolves ([#44886](https://github.com/angular/angular/pull/44886)) |
| [deb9531a31](https://github.com/angular/angular/commit/deb9531a31274fbedcbf468a33d80481328c55ce) | fix | Update the typed forms migration schematic to find all files. ([#44881](https://github.com/angular/angular/pull/44881)) |
| [cae1e44608](https://github.com/angular/angular/commit/cae1e44608227ac80682401190c6d28ef39b3269) | fix | Update the typed forms migration to use FormArray<T> instead of FormArray<T[]>. ([#44933](https://github.com/angular/angular/pull/44933)) |
### router
| Commit | Type | Description |
| -- | -- | -- |
| [910de8bc33](https://github.com/angular/angular/commit/910de8bc3379b1452c0bc23a866b5108d6d94e55) | feat | Add `Route.title` with a configurable `TitleStrategy` ([#43307](https://github.com/angular/angular/pull/43307)) |
## Special Thanks
Alan, Alan Agius, AleksanderBodurri, Amir Rustamzadeh, Andrew Kushnir, Andrew Scott, Aristeidis Bampakos, Arjen, Daan De Smedt, Daniel Díaz, David Shevitz, Doug Parker, Dylan Hunn, Emma Twersky, Esteban Gehring, George Kalpakas, Jessica Janiuk, JimMorrison723, JoostK, Juri Strumpflohner, Lee Robinson, Maarten Tibau, Mark Whitfeld, Minko Gechev, Paul Gschwendtner, Ricardo Mattiazzi Baumgartner, Sumit Arora, Theodore Brown, arturovt, dario-piotrowicz, fru2, kamikopi, markostanimirovic, markwhitfeld, mgechev, renovate[bot] and twerske
<!-- CHANGELOG SPLIT MARKER -->
<a name="13.2.1"></a>
# 13.2.1 (2022-02-02)
### animations
@@ -776,21 +574,6 @@ Alan, Andrew Kushnir, Andrew Scott, Aristeidis Bampakos, Arjen, Daniel Díaz, Da
<!-- CHANGELOG SPLIT MARKER -->
<a name="14.0.0-next.0"></a>
# 14.0.0-next.0 (2022-01-26)
### language-service
| Commit | Type | Description |
| -- | -- | -- |
| [9d4af65e34](https://github.com/angular/angular/commit/9d4af65e343e41b48cb9afd12c2b61d8ca61a9ac) | feat | Provide plugin to delegate rename requests to Angular ([#44696](https://github.com/angular/angular/pull/44696)) |
### service-worker
| Commit | Type | Description |
| -- | -- | -- |
| [ec0a0e0669](https://github.com/angular/angular/commit/ec0a0e0669ef5d2f524fbf9a540eb2b306b2e24a) | feat | add `cacheOpaqueResponses` option for data-groups ([#44723](https://github.com/angular/angular/pull/44723)) |
## Special Thanks
Andrew Kushnir, Dylan Hunn, George Kalpakas, JiaLiPassion, Joey Perrott and ivanwonder
<!-- CHANGELOG SPLIT MARKER -->
<a name="13.2.0"></a>
# 13.2.0 (2022-01-26)
## Deprecations
+7 -7
View File
@@ -94,7 +94,7 @@ Before you submit your Pull Request (PR) consider the following guidelines:
5. In your forked repository, make your changes in a new git branch:
```shell
git checkout -b my-fix-branch master
git checkout -b my-fix-branch main
```
6. Create your patch, **including appropriate test cases**.
@@ -117,7 +117,7 @@ Before you submit your Pull Request (PR) consider the following guidelines:
git push origin my-fix-branch
```
11. In GitHub, send a pull request to `angular:master`.
11. In GitHub, send a pull request to `angular:main`.
### Reviewing a Pull Request
@@ -181,10 +181,10 @@ After your pull request is merged, you can safely delete your branch and pull th
git push origin --delete my-fix-branch
```
* Check out the master branch:
* Check out the main branch:
```shell
git checkout master -f
git checkout main -f
```
* Delete the local branch:
@@ -193,10 +193,10 @@ After your pull request is merged, you can safely delete your branch and pull th
git branch -D my-fix-branch
```
* Update your master with the latest upstream version:
* Update your local `main` with the latest upstream version:
```shell
git pull --ff upstream master
git pull --ff upstream main
```
@@ -397,7 +397,7 @@ The following documents can help you sort out issues with GitHub accounts and mu
[coc]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
[corporate-cla]: https://cla.developers.google.com/about/google-corporate
[dev-doc]: https://github.com/angular/angular/blob/master/docs/DEVELOPER.md
[dev-doc]: https://github.com/angular/angular/blob/main/docs/DEVELOPER.md
[github]: https://github.com/angular/angular
[discord]: https://discord.gg/angular
[individual-cla]: https://cla.developers.google.com/about/google-individual
+2 -2
View File
@@ -24,8 +24,8 @@
</p>
<p align="center">
<a href="https://circleci.com/gh/angular/workflows/angular/tree/master">
<img src="https://img.shields.io/circleci/build/github/angular/angular/master.svg?logo=circleci&logoColor=fff&label=CircleCI" alt="CI status" />
<a href="https://circleci.com/gh/angular/workflows/angular/tree/main">
<img src="https://img.shields.io/circleci/build/github/angular/angular/main.svg?logo=circleci&logoColor=fff&label=CircleCI" alt="CI status" />
</a>&nbsp;
<a href="https://www.npmjs.com/@angular/core">
<img src="https://img.shields.io/npm/v/@angular/core.svg?logo=npm&logoColor=fff&label=NPM+package&color=limegreen" alt="Angular on npm" />
+8 -6
View File
@@ -10,8 +10,8 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "build_bazel_rules_nodejs",
sha256 = "2b2004784358655f334925e7eadc7ba80f701144363df949b3293e1ae7a2fb7b",
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/5.4.0/rules_nodejs-5.4.0.tar.gz"],
sha256 = "e328cb2c9401be495fa7d79c306f5ee3040e8a03b2ebb79b022e15ca03770096",
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/5.4.2/rules_nodejs-5.4.2.tar.gz"],
)
load("@build_bazel_rules_nodejs//:repositories.bzl", "build_bazel_rules_nodejs_dependencies")
@@ -144,14 +144,16 @@ cldr_xml_data_repository(
# sass rules
http_archive(
name = "io_bazel_rules_sass",
sha256 = "b83d695bc8deb5ab5fb3a8e6919999eebf738a4a5aa57a43a63ee70109f80224",
strip_prefix = "rules_sass-1.50.0",
sha256 = "856080c608e51993ab3088c08c70361d3f1fce383e14499cc2279060b350898c",
strip_prefix = "rules_sass-1.51.0",
urls = [
"https://github.com/bazelbuild/rules_sass/archive/1.50.0.zip",
"https://github.com/bazelbuild/rules_sass/archive/1.51.0.zip",
],
)
# Setup the rules_sass toolchain
load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories")
sass_repositories()
sass_repositories(
yarn_script = "//:.yarn/releases/yarn-1.22.17.cjs",
)
+1
View File
@@ -48,6 +48,7 @@
"@typescript-eslint/naming-convention": "off",
"no-console": ["error", {"allow": ["log", "warn", "error"]}],
"no-empty-function": "off",
"@angular-eslint/no-host-metadata-property": "off",
"no-restricted-syntax": [
"error",
{
+14 -17
View File
@@ -1,19 +1,19 @@
# See https://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
# Compiled output
/dist
/out-tsc
/src/generated
/tmp
/out-tsc
/bazel-out
/src/generated
# Cache folder for the Angular CLI.
.angular/cache
# dependencies
# Node
/node_modules
npm-debug.log
yarn-error.log
# IDEs and editors
/.idea
.idea/
.project
.classpath
.c9/
@@ -21,31 +21,28 @@
.settings/
*.sublime-workspace
# IDE - VSCode
# Visual Studio Code
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# misc
# Miscellaneous
/.angular/cache
/.firebase/
/.sass-cache
.sass-cache/
/connect.lock
/coverage
/libpeerconnection.log
debug.log
firebase-debug.log
npm-debug.log
testem.log
/typings
yarn-error.log
# e2e
/e2e/*.js
/e2e/*.map
protractor-results*.txt
# System Files
# System files
.DS_Store
Thumbs.db
+1 -1
View File
@@ -1,5 +1,5 @@
load("@aio_npm//@angular-devkit/architect-cli:index.bzl", "architect", "architect_test")
load("@build_bazel_rules_nodejs//:index.bzl", "npm_package_bin")
load("//tools:defaults.bzl", "npm_package_bin")
# The write_source_files macro is used to write bazel outputs to the source tree and test that they are up to date.
# See: https://docs.aspect.build/aspect-build/bazel-lib/v0.5.0/docs/docs/write_source_files-docgen.html
@@ -4,28 +4,69 @@ import fetch, {RequestInit} from 'node-fetch';
import {assertNotMissingOrEmpty} from './utils';
// Constants
const CIRCLE_CI_API_URL = 'https://circleci.com/api/v2/project/gh';
const CIRCLE_CI_BASE_API_URL = 'https://circleci.com/api/v2';
const CIRCLE_CI_BUILD_API_URL = `${CIRCLE_CI_BASE_API_URL}/project/gh`;
const CIRCLE_CI_PIPELINE_API_URL = `${CIRCLE_CI_BASE_API_URL}/pipeline`;
// Interfaces - Types
// API docs: https://circleci.com/docs/api/v2#operation/getJobArtifacts
// Example: https://circleci.com/api/v2/project/gh/angular/angular/1163941/artifacts
export interface ArtifactInfo {
/** The path of this build artifacts. */
path: string;
pretty_path: string;
node_index: number;
/** The full URL where this artifact can be downloaded from. */
url: string;
// There are other fields but they are not used in this code.
}
export type ArtifactResponse = ArtifactInfo[];
export type ArtifactResponse = {items: ArtifactInfo[]};
// API docs: https://circleci.com/docs/api/v2#operation/getJobDetails
// Example: https://circleci.com/api/v2/project/gh/angular/angular/job/1163941
export interface BuildInfo {
reponame: string;
failed: boolean;
branch: string;
username: string;
build_num: number;
has_artifacts: boolean;
outcome: string; // e.g. 'success'
vcs_revision: string; // HEAD SHA
// there are other fields but they are not used in this code
/** The job number. */
number: number;
/** The job name (e.g. `'aio_preview'`). */
name: string;
/** Info about the organization which the project related to this job belongs to. */
organization: {
name: string;
};
/** Info about the project related to this job. */
project: {
name: string;
};
/** Info about the [pipeline](https://circleci.com/docs/2.0/pipelines/) that this job is part of. */
pipeline: {
id: string;
};
// There are other fields but they are not used in this code.
}
// API docs: https://circleci.com/docs/api/v2#operation/getPipelineById
// https://circleci.com/api/v2/pipeline/356227c0-32f6-4f99-bfc2-3938db90a147
export interface PipelineInfo {
/** The pipeline ID. */
id: string;
/** Info related to/retrieved from the version control system provider (e.g. GitHub). */
vcs: {
/** The PR number. */
review_id: string;
/** The HEAD SHA. */
revision: string;
};
// There are other fields but they are not used in this code.
}
/**
@@ -59,13 +100,13 @@ export class CircleCiApi {
}
/**
* Get the info for a build from the CircleCI API
* Get the info for a build (aka job) from the CircleCI API.
* @param buildNumber The CircleCI build number that generated the artifact.
* @returns A promise to the info about the build
* @returns A promise to the info about the build.
*/
public async getBuildInfo(buildNumber: number): Promise<BuildInfo> {
try {
const url = `${CIRCLE_CI_API_URL}/${this.githubOrg}/${this.githubRepo}/job/${buildNumber}`;
const url = `${CIRCLE_CI_BUILD_API_URL}/${this.githubOrg}/${this.githubRepo}/job/${buildNumber}`;
const response = await this.fetchFromCircleCi(url);
return response.json();
} catch (error) {
@@ -79,10 +120,10 @@ export class CircleCiApi {
* @returns A promise to the URL that can be requested to download the actual build artifact file.
*/
public async getBuildArtifactUrl(buildNumber: number, artifactPath: string): Promise<string> {
const baseUrl = `${CIRCLE_CI_API_URL}/${this.githubOrg}/${this.githubRepo}/${buildNumber}`;
const baseUrl = `${CIRCLE_CI_BUILD_API_URL}/${this.githubOrg}/${this.githubRepo}/${buildNumber}`;
try {
const response = await this.fetchFromCircleCi(`${baseUrl}/artifacts`);
const artifacts = await response.json() as {items: ArtifactResponse};
const artifacts = await response.json() as ArtifactResponse;
const artifact = artifacts.items.find(item => item.path === artifactPath);
if (!artifact) {
throw new Error(`Missing artifact (${artifactPath}) for CircleCI build: ${buildNumber}`);
@@ -92,4 +133,19 @@ export class CircleCiApi {
throw new Error(`CircleCI artifact URL request failed (${(error as Error).message})`);
}
}
/**
* Get the info for a [pipeline](https://circleci.com/docs/2.0/pipelines/) from the CircleCI API.
* @param pipelineId The CircleCI pipeline ID that generated the artifact.
* @returns A promise to the info about the pipeline.
*/
public async getPipelineInfo(pipelineId: string): Promise<PipelineInfo> {
try {
const url = `${CIRCLE_CI_PIPELINE_API_URL}/${pipelineId}`;
const response = await this.fetchFromCircleCi(url);
return response.json();
} catch (error) {
throw new Error(`CircleCI pipeline info request failed (${(error as Error).message})`);
}
}
}
@@ -13,7 +13,6 @@ export interface GithubInfo {
pr: number;
repo: string;
sha: string;
success: boolean;
}
/**
@@ -36,12 +35,12 @@ export class BuildRetriever {
*/
public async getGithubInfo(buildNum: number): Promise<GithubInfo> {
const buildInfo = await this.api.getBuildInfo(buildNum);
const pipelineInfo = await this.api.getPipelineInfo(buildInfo.pipeline.id);
const githubInfo: GithubInfo = {
org: buildInfo.username,
pr: getPrFromBranch(buildInfo.branch),
repo: buildInfo.reponame,
sha: buildInfo.vcs_revision,
success: !buildInfo.failed,
org: buildInfo.organization.name,
pr: +pipelineInfo.vcs.review_id,
repo: buildInfo.project.name,
sha: pipelineInfo.vcs.revision,
};
return githubInfo;
}
@@ -76,12 +75,3 @@ export class BuildRetriever {
}
}
}
function getPrFromBranch(branch: string): number {
// CircleCI only exposes PR numbers via the `branch` field :-(
const match = /^pull\/(\d+)$/.exec(branch);
if (!match) {
throw new Error(`No PR found in branch field: ${branch}`);
}
return +match[1];
}
@@ -120,13 +120,7 @@ export class PreviewServerFactory {
return;
}
const { pr, sha, org, repo, success } = await buildRetriever.getGithubInfo(buildNum);
if (!success) {
res.sendStatus(204);
logger.log(`PR:${pr}, Build:${buildNum} - Skipping preview processing because this build did not succeed.`);
return;
}
const { pr, sha, org, repo } = await buildRetriever.getGithubInfo(buildNum);
assert(cfg.githubOrg === org,
`Invalid webhook: expected "githubOrg" property to equal "${cfg.githubOrg}" but got "${org}".`);
@@ -1,9 +1,10 @@
export const enum BuildNums {
BUILD_INFO_ERROR = 1,
BUILD_INFO_404,
BUILD_INFO_BUILD_FAILED,
BUILD_INFO_INVALID_GH_ORG,
BUILD_INFO_INVALID_GH_REPO,
PIPELINE_INFO_ERROR,
PIPELINE_INFO_404,
CHANGED_FILES_ERROR,
CHANGED_FILES_404,
CHANGED_FILES_NONE,
@@ -21,6 +22,17 @@ export const enum BuildNums {
TRUST_CHECK_INACTIVE_TRUSTED_USER,
}
export const enum PipelineIds {
PIPELINE_INFO_ERROR = 'pipeline-error',
PIPELINE_INFO_404 = 'pipeline-404',
CHANGED_FILES_ERROR = 'pipeline-cfe',
CHANGED_FILES_404 = 'pipeline-cf404',
CHANGED_FILES_NONE = 'pipeline-cfn',
TRUST_CHECK_ERROR = 'pipeline-tce',
TRUST_CHECK_UNTRUSTED = 'pipeline-tcu',
PIPELINE_INFO_OK = 'pipeline-ok',
}
export const enum PrNums {
CHANGED_FILES_ERROR = 1,
CHANGED_FILES_404,
@@ -3,7 +3,7 @@ import * as nock from 'nock';
import * as tar from 'tar-stream';
import {gzipSync} from 'zlib';
import {getEnvVar, Logger} from '../common/utils';
import {BuildNums, PrNums, SHA} from './constants';
import {BuildNums, PipelineIds, PrNums, SHA} from './constants';
// We are using the `nock` library to fake responses from REST requests, when testing.
// This is necessary, because the test preview-server runs as a separate node process to
@@ -30,11 +30,17 @@ const INACTIVE_TRUSTED_USER = 'inactive-trusted-user';
const UNTRUSTED_USER = 'untrusted-user';
const BASIC_BUILD_INFO = {
branch: `pull/${PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER}`,
failed: false,
reponame: AIO_GITHUB_REPO,
username: AIO_GITHUB_ORGANIZATION,
vcs_revision: SHA,
name: 'test_job',
organization: {name: AIO_GITHUB_ORGANIZATION},
project: {name: AIO_GITHUB_REPO},
pipeline: {id: PipelineIds.PIPELINE_INFO_OK},
};
const BASIC_PIPELINE_INFO = {
id: PipelineIds.PIPELINE_INFO_OK,
vcs: {
review_id: `${PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER}`,
revision: SHA,
},
};
const ISSUE_INFO_TRUSTED_LABEL = { labels: [{ name: AIO_TRUSTED_PR_LABEL }], user: { login: UNTRUSTED_USER } };
@@ -47,7 +53,6 @@ const INACTIVE_STATE = { state: 'inactive' };
const TEST_TEAM_INFO = AIO_GITHUB_TEAM_SLUGS.map((slug, index) => ({ slug, id: index }));
const CIRCLE_CI_API_HOST = 'https://circleci.com';
const CIRCLE_CI_TOKEN_PARAM = `circle-token=${AIO_CIRCLE_CI_TOKEN}`;
const ARTIFACT_1 = { path: 'artifact-1', url: `${CIRCLE_CI_API_HOST}/artifacts/artifact-1`, _urlPath: '/artifacts/artifact-1' };
const ARTIFACT_2 = { path: 'artifact-2', url: `${CIRCLE_CI_API_HOST}/artifacts/artifact-2`, _urlPath: '/artifacts/artifact-2' };
const ARTIFACT_3 = { path: 'artifact-3', url: `${CIRCLE_CI_API_HOST}/artifacts/artifact-3`, _urlPath: '/artifacts/artifact-3' };
@@ -57,11 +62,13 @@ const ARTIFACT_VALID_TRUSTED_USER = { path: AIO_ARTIFACT_PATH, url: `${CIRCLE_CI
const ARTIFACT_VALID_TRUSTED_LABEL = { path: AIO_ARTIFACT_PATH, url: `${CIRCLE_CI_API_HOST}/artifacts/valid/label`, _urlPath: '/artifacts/valid/label' };
const ARTIFACT_VALID_UNTRUSTED = { path: AIO_ARTIFACT_PATH, url: `${CIRCLE_CI_API_HOST}/artifacts/valid/untrusted`, _urlPath: '/artifacts/valid/untrusted' };
const CIRCLE_CI_BUILD_INFO_URL = `/api/v1.1/project/github/${AIO_GITHUB_ORGANIZATION}/${AIO_GITHUB_REPO}`;
const CIRCLE_CI_BUILD_INFO_URL = `/api/v2/project/gh/${AIO_GITHUB_ORGANIZATION}/${AIO_GITHUB_REPO}`;
const CIRCLE_CI_PIPELINE_INFO_URL = '/api/v2/pipeline';
const buildInfoUrl = (buildNum: number) => `${CIRCLE_CI_BUILD_INFO_URL}/${buildNum}?${CIRCLE_CI_TOKEN_PARAM}`;
const buildArtifactsUrl = (buildNum: number) => `${CIRCLE_CI_BUILD_INFO_URL}/${buildNum}/artifacts?${CIRCLE_CI_TOKEN_PARAM}`;
const buildInfo = (prNum: number) => ({ ...BASIC_BUILD_INFO, branch: `pull/${prNum}` });
const buildInfoUrl = (buildNum: number) => `${CIRCLE_CI_BUILD_INFO_URL}/job/${buildNum}`;
const buildArtifactsUrl = (buildNum: number) => `${CIRCLE_CI_BUILD_INFO_URL}/${buildNum}/artifacts`;
const pipelineInfoUrl = (pipelineId: string) => `${CIRCLE_CI_PIPELINE_INFO_URL}/${pipelineId}`;
const buildInfo = (pipelineId: string) => ({ ...BASIC_BUILD_INFO, pipeline: { id: pipelineId } });
const GITHUB_API_HOST = 'https://api.github.com';
const GITHUB_ISSUES_URL = `/repos/${AIO_GITHUB_ORGANIZATION}/${AIO_GITHUB_REPO}/issues`;
@@ -73,6 +80,15 @@ const getFilesUrl = (prNum: number, pageNum = 1) => `${GITHUB_PULLS_URL}/${prNum
const getCommentUrl = (prNum: number) => `${getIssueUrl(prNum)}/comments`;
const getTeamMembershipUrl = (teamId: number, username: string) => `/teams/${teamId}/memberships/${username}`;
const setUpCircleCiApiForBuild =
(buildNum: number, pipelineId: string, prNum = PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER, sha = SHA) => {
circleCiApi.get(buildInfoUrl(buildNum)).reply(200, buildInfo(pipelineId));
circleCiApi.get(pipelineInfoUrl(pipelineId)).reply(200, {
id: pipelineId,
vcs: { review_id: `${prNum}`, revision: sha },
});
};
const createArchive = (buildNum: number, prNum: number, sha: string) => {
logger.log('createArchive', buildNum, prNum, sha);
const pack = tar.pack();
@@ -84,7 +100,7 @@ const createArchive = (buildNum: number, prNum: number, sha: string) => {
};
// Create request scopes
const circleCiApi = nock(CIRCLE_CI_API_HOST).persist();
const circleCiApi = nock(CIRCLE_CI_API_HOST).persist().matchHeader('Circle-Token', AIO_CIRCLE_CI_TOKEN);
const githubApi = nock(GITHUB_API_HOST).persist().matchHeader('Authorization', `token ${AIO_GITHUB_TOKEN}`);
//////////////////////////////
@@ -92,50 +108,57 @@ const githubApi = nock(GITHUB_API_HOST).persist().matchHeader('Authorization', `
// GENERAL responses
githubApi.get(GITHUB_TEAMS_URL + '?page=1&per_page=100').reply(200, TEST_TEAM_INFO);
githubApi.post(getCommentUrl(PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER)).reply(200);
circleCiApi.get(pipelineInfoUrl(PipelineIds.PIPELINE_INFO_OK)).reply(200, BASIC_PIPELINE_INFO);
// BUILD_INFO errors
// BUILD INFO errors
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_INFO_ERROR)).replyWithError('BUILD_INFO_ERROR');
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_INFO_404)).reply(404, 'BUILD_INFO_404');
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_INFO_BUILD_FAILED)).reply(200, { ...BASIC_BUILD_INFO, failed: true });
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_INFO_INVALID_GH_ORG)).reply(200, { ...BASIC_BUILD_INFO, username: 'bad' });
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_INFO_INVALID_GH_REPO)).reply(200, { ...BASIC_BUILD_INFO, reponame: 'bad' });
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_INFO_INVALID_GH_ORG)).reply(200, { ...BASIC_BUILD_INFO, organization: { name: 'bad' } });
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_INFO_INVALID_GH_REPO)).reply(200, { ...BASIC_BUILD_INFO, project: { name: 'bad' } });
// PIPELINE INFO errors
circleCiApi.get(buildInfoUrl(BuildNums.PIPELINE_INFO_ERROR)).reply(200, { ...BASIC_BUILD_INFO, pipeline: { id: PipelineIds.PIPELINE_INFO_ERROR } });
circleCiApi.get(pipelineInfoUrl(PipelineIds.PIPELINE_INFO_ERROR)).replyWithError('PIPELINE_INFO_ERROR');
circleCiApi.get(buildInfoUrl(BuildNums.PIPELINE_INFO_404)).reply(200, { ...BASIC_BUILD_INFO, pipeline: { id: PipelineIds.PIPELINE_INFO_404 } });
circleCiApi.get(pipelineInfoUrl(PipelineIds.PIPELINE_INFO_ERROR)).reply(404, 'PIPELINE_INFO_404');
// CHANGED FILE errors
circleCiApi.get(buildInfoUrl(BuildNums.CHANGED_FILES_ERROR)).reply(200, buildInfo(PrNums.CHANGED_FILES_ERROR));
setUpCircleCiApiForBuild(BuildNums.CHANGED_FILES_ERROR, PipelineIds.CHANGED_FILES_ERROR, PrNums.CHANGED_FILES_ERROR);
githubApi.get(getFilesUrl(PrNums.CHANGED_FILES_ERROR)).replyWithError('CHANGED_FILES_ERROR');
circleCiApi.get(buildInfoUrl(BuildNums.CHANGED_FILES_404)).reply(200, buildInfo(PrNums.CHANGED_FILES_404));
setUpCircleCiApiForBuild(BuildNums.CHANGED_FILES_404, PipelineIds.CHANGED_FILES_404, PrNums.CHANGED_FILES_404);
githubApi.get(getFilesUrl(PrNums.CHANGED_FILES_404)).reply(404, 'CHANGED_FILES_404');
circleCiApi.get(buildInfoUrl(BuildNums.CHANGED_FILES_NONE)).reply(200, buildInfo(PrNums.CHANGED_FILES_NONE));
setUpCircleCiApiForBuild(BuildNums.CHANGED_FILES_NONE, PipelineIds.CHANGED_FILES_NONE, PrNums.CHANGED_FILES_NONE);
githubApi.get(getFilesUrl(PrNums.CHANGED_FILES_NONE)).reply(200, []);
// ARTIFACT URL errors
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_ARTIFACTS_ERROR)).reply(200, buildInfo(PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER));
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_ARTIFACTS_ERROR)).reply(200, BASIC_BUILD_INFO);
circleCiApi.get(buildArtifactsUrl(BuildNums.BUILD_ARTIFACTS_ERROR)).replyWithError('BUILD_ARTIFACTS_ERROR');
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_ARTIFACTS_404)).reply(200, buildInfo(PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER));
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_ARTIFACTS_404)).reply(200, BASIC_BUILD_INFO);
circleCiApi.get(buildArtifactsUrl(BuildNums.BUILD_ARTIFACTS_404)).reply(404, 'BUILD_ARTIFACTS_ERROR');
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_ARTIFACTS_EMPTY)).reply(200, buildInfo(PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER));
circleCiApi.get(buildArtifactsUrl(BuildNums.BUILD_ARTIFACTS_EMPTY)).reply(200, []);
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_ARTIFACTS_MISSING)).reply(200, buildInfo(PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER));
circleCiApi.get(buildArtifactsUrl(BuildNums.BUILD_ARTIFACTS_MISSING)).reply(200, [ARTIFACT_1, ARTIFACT_2, ARTIFACT_3]);
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_ARTIFACTS_EMPTY)).reply(200, BASIC_BUILD_INFO);
circleCiApi.get(buildArtifactsUrl(BuildNums.BUILD_ARTIFACTS_EMPTY)).reply(200, { items: [] });
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_ARTIFACTS_MISSING)).reply(200, BASIC_BUILD_INFO);
circleCiApi.get(buildArtifactsUrl(BuildNums.BUILD_ARTIFACTS_MISSING)).reply(200, { items: [ARTIFACT_1, ARTIFACT_2, ARTIFACT_3] });
// ARTIFACT DOWNLOAD errors
circleCiApi.get(buildInfoUrl(BuildNums.DOWNLOAD_ARTIFACT_ERROR)).reply(200, buildInfo(PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER));
circleCiApi.get(buildArtifactsUrl(BuildNums.DOWNLOAD_ARTIFACT_ERROR)).reply(200, [ARTIFACT_ERROR]);
circleCiApi.get(buildInfoUrl(BuildNums.DOWNLOAD_ARTIFACT_ERROR)).reply(200, BASIC_BUILD_INFO);
circleCiApi.get(buildArtifactsUrl(BuildNums.DOWNLOAD_ARTIFACT_ERROR)).reply(200, { items: [ARTIFACT_ERROR] });
circleCiApi.get(ARTIFACT_ERROR._urlPath).replyWithError(ARTIFACT_ERROR._urlPath);
circleCiApi.get(buildInfoUrl(BuildNums.DOWNLOAD_ARTIFACT_404)).reply(200, buildInfo(PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER));
circleCiApi.get(buildInfoUrl(BuildNums.DOWNLOAD_ARTIFACT_404)).reply(200, BASIC_BUILD_INFO);
circleCiApi.get(buildArtifactsUrl(BuildNums.DOWNLOAD_ARTIFACT_404)).reply(200, [ARTIFACT_404]);
circleCiApi.get(ARTIFACT_ERROR._urlPath).reply(404, ARTIFACT_ERROR._urlPath);
// TRUST CHECK errors
circleCiApi.get(buildInfoUrl(BuildNums.TRUST_CHECK_ERROR)).reply(200, buildInfo(PrNums.TRUST_CHECK_ERROR));
setUpCircleCiApiForBuild(BuildNums.TRUST_CHECK_ERROR, PipelineIds.TRUST_CHECK_ERROR, PrNums.TRUST_CHECK_ERROR);
githubApi.get(getFilesUrl(PrNums.TRUST_CHECK_ERROR)).reply(200, [{ filename: 'aio/a' }]);
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_ERROR)).reply(200, [ARTIFACT_VALID_TRUSTED_USER]);
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_ERROR)).reply(200, { items: [ARTIFACT_VALID_TRUSTED_USER] });
githubApi.get(getIssueUrl(PrNums.TRUST_CHECK_ERROR)).replyWithError('TRUST_CHECK_ERROR');
// ACTIVE TRUSTED USER response
circleCiApi.get(buildInfoUrl(BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER)).reply(200, BASIC_BUILD_INFO);
githubApi.get(getFilesUrl(PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER)).reply(200, [{ filename: 'aio/a' }]);
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER)).reply(200, [ARTIFACT_VALID_TRUSTED_USER]);
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER)).reply(200, { items: [ARTIFACT_VALID_TRUSTED_USER] });
circleCiApi.get(ARTIFACT_VALID_TRUSTED_USER._urlPath).reply(200, createArchive(BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER, PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER, SHA));
githubApi.get(getIssueUrl(PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER)).reply(200, ISSUE_INFO_ACTIVE_TRUSTED_USER);
githubApi.get(getTeamMembershipUrl(0, ACTIVE_TRUSTED_USER)).reply(200, ACTIVE_STATE);
@@ -143,7 +166,7 @@ githubApi.get(getTeamMembershipUrl(0, ACTIVE_TRUSTED_USER)).reply(200, ACTIVE_ST
// TRUSTED LABEL response
circleCiApi.get(buildInfoUrl(BuildNums.TRUST_CHECK_TRUSTED_LABEL)).reply(200, BASIC_BUILD_INFO);
githubApi.get(getFilesUrl(PrNums.TRUST_CHECK_TRUSTED_LABEL)).reply(200, [{ filename: 'aio/a' }]);
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_TRUSTED_LABEL)).reply(200, [ARTIFACT_VALID_TRUSTED_LABEL]);
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_TRUSTED_LABEL)).reply(200, { items: [ARTIFACT_VALID_TRUSTED_LABEL] });
circleCiApi.get(ARTIFACT_VALID_TRUSTED_LABEL._urlPath).reply(200, createArchive(BuildNums.TRUST_CHECK_TRUSTED_LABEL, PrNums.TRUST_CHECK_TRUSTED_LABEL, SHA));
githubApi.get(getIssueUrl(PrNums.TRUST_CHECK_TRUSTED_LABEL)).reply(200, ISSUE_INFO_TRUSTED_LABEL);
githubApi.get(getTeamMembershipUrl(0, ACTIVE_TRUSTED_USER)).reply(200, ACTIVE_STATE);
@@ -151,14 +174,14 @@ githubApi.get(getTeamMembershipUrl(0, ACTIVE_TRUSTED_USER)).reply(200, ACTIVE_ST
// INACTIVE TRUSTED USER response
circleCiApi.get(buildInfoUrl(BuildNums.TRUST_CHECK_INACTIVE_TRUSTED_USER)).reply(200, BASIC_BUILD_INFO);
githubApi.get(getFilesUrl(PrNums.TRUST_CHECK_INACTIVE_TRUSTED_USER)).reply(200, [{ filename: 'aio/a' }]);
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_INACTIVE_TRUSTED_USER)).reply(200, [ARTIFACT_VALID_TRUSTED_USER]);
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_INACTIVE_TRUSTED_USER)).reply(200, { items: [ARTIFACT_VALID_TRUSTED_USER] });
githubApi.get(getIssueUrl(PrNums.TRUST_CHECK_INACTIVE_TRUSTED_USER)).reply(200, ISSUE_INFO_INACTIVE_TRUSTED_USER);
githubApi.get(getTeamMembershipUrl(0, INACTIVE_TRUSTED_USER)).reply(200, INACTIVE_STATE);
// UNTRUSTED reponse
circleCiApi.get(buildInfoUrl(BuildNums.TRUST_CHECK_UNTRUSTED)).reply(200, buildInfo(PrNums.TRUST_CHECK_UNTRUSTED));
setUpCircleCiApiForBuild(BuildNums.TRUST_CHECK_UNTRUSTED, PipelineIds.TRUST_CHECK_UNTRUSTED, PrNums.TRUST_CHECK_UNTRUSTED);
githubApi.get(getFilesUrl(PrNums.TRUST_CHECK_UNTRUSTED)).reply(200, [{ filename: 'aio/a' }]);
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_UNTRUSTED)).reply(200, [ARTIFACT_VALID_UNTRUSTED]);
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_UNTRUSTED)).reply(200, { items: [ARTIFACT_VALID_UNTRUSTED] });
circleCiApi.get(ARTIFACT_VALID_UNTRUSTED._urlPath).reply(200, createArchive(BuildNums.TRUST_CHECK_UNTRUSTED, PrNums.TRUST_CHECK_UNTRUSTED, SHA));
githubApi.get(getIssueUrl(PrNums.TRUST_CHECK_UNTRUSTED)).reply(200, ISSUE_INFO_UNTRUSTED);
githubApi.get(getTeamMembershipUrl(0, UNTRUSTED_USER)).reply(404);
@@ -145,13 +145,11 @@ describe('preview-server', () => {
]);
});
it('should respond with 500 if the CircleCI API request errors', async () => {
it('should respond with 500 if any of the CircleCI API requests errors', async () => {
await curl(payload(BuildNums.BUILD_INFO_ERROR)).then(h.verifyResponse(500));
await curl(payload(BuildNums.BUILD_INFO_404)).then(h.verifyResponse(500));
});
it('should respond with 204 if the build on CircleCI failed', async () => {
await curl(payload(BuildNums.BUILD_INFO_BUILD_FAILED)).then(h.verifyResponse(204));
await curl(payload(BuildNums.PIPELINE_INFO_ERROR)).then(h.verifyResponse(500));
await curl(payload(BuildNums.PIPELINE_INFO_404)).then(h.verifyResponse(500));
});
it('should respond with 500 if the github org from CircleCI does not match what is configured', async () => {
@@ -49,6 +49,6 @@
"supertest": "^4.0.2",
"tslint": "^6.1.3",
"tslint-jasmine-noSkipOrFocus": "^1.0.9",
"typescript": "~4.6.2"
"typescript": "~4.7.2"
}
}
@@ -4,7 +4,8 @@ import {CircleCiApi} from '../../lib/common/circle-ci-api';
const ORG = 'testorg';
const REPO = 'testrepo';
const TOKEN = 'xxxx';
const BASE_URL = `https://circleci.com/api/v2/project/gh/${ORG}/${REPO}`;
const BASE_BUILD_URL = `https://circleci.com/api/v2/project/gh/${ORG}/${REPO}`;
const BASE_PIPELINE_URL = 'https://circleci.com/api/v2/pipeline';
describe('CircleCIApi', () => {
describe('constructor()', () => {
@@ -27,11 +28,11 @@ describe('CircleCIApi', () => {
describe('fetchFromCircleCI', () => {
it('should include the authentication token in the headers on every request', async () => {
const api = new CircleCiApi(ORG, REPO, TOKEN);
const request = nock(BASE_URL)
const request = nock(BASE_BUILD_URL)
.get('/')
.matchHeader('Circle-Token', TOKEN)
.reply(200);
await api.fetchFromCircleCi(`${BASE_URL}/`);
await api.fetchFromCircleCi(`${BASE_BUILD_URL}/`);
request.done();
})
})
@@ -42,7 +43,7 @@ describe('CircleCIApi', () => {
const buildNum = 12345;
const expectedBuildInfo: any = { org: ORG, repo: REPO, build_num: buildNum };
const request = nock(BASE_URL)
const request = nock(BASE_BUILD_URL)
.get(`/job/${buildNum}`)
.reply(200, expectedBuildInfo);
@@ -55,17 +56,17 @@ describe('CircleCIApi', () => {
const api = new CircleCiApi(ORG, REPO, TOKEN);
const buildNum = 12345;
const errorMessage = 'Invalid request';
const request = nock(BASE_URL).get(`/job/${buildNum}`);
const request = nock(BASE_BUILD_URL).get(`/job/${buildNum}`);
request.replyWithError(errorMessage);
await expectAsync(api.getBuildInfo(buildNum)).toBeRejectedWithError(
`CircleCI build info request failed ` +
`(request to ${BASE_URL}/job/${buildNum} failed, reason: ${errorMessage})`);
`(request to ${BASE_BUILD_URL}/job/${buildNum} failed, reason: ${errorMessage})`);
request.reply(404, errorMessage);
await expectAsync(api.getBuildInfo(buildNum)).toBeRejectedWithError(
`CircleCI build info request failed ` +
`(request to ${BASE_URL}/job/${buildNum} failed, reason: ${errorMessage})`);
`(request to ${BASE_BUILD_URL}/job/${buildNum} failed, reason: ${errorMessage})`);
});
});
@@ -76,7 +77,7 @@ describe('CircleCIApi', () => {
const artifact0: any = { path: 'some/path/0', url: 'https://url/0' };
const artifact1: any = { path: 'some/path/1', url: 'https://url/1' };
const artifact2: any = { path: 'some/path/2', url: 'https://url/2' };
const request = nock(BASE_URL)
const request = nock(BASE_BUILD_URL)
.get(`/${buildNum}/artifacts`)
.reply(200, {items: [artifact0, artifact1, artifact2]});
@@ -89,17 +90,17 @@ describe('CircleCIApi', () => {
const api = new CircleCiApi(ORG, REPO, TOKEN);
const buildNum = 12345;
const errorMessage = 'Invalid request';
const request = nock(BASE_URL).get(`/${buildNum}/artifacts`);
const request = nock(BASE_BUILD_URL).get(`/${buildNum}/artifacts`);
request.replyWithError(errorMessage);
await expectAsync(api.getBuildArtifactUrl(buildNum, 'some/path/1')).toBeRejectedWithError(
`CircleCI artifact URL request failed ` +
`(request to ${BASE_URL}/${buildNum}/artifacts failed, reason: ${errorMessage})`);
`(request to ${BASE_BUILD_URL}/${buildNum}/artifacts failed, reason: ${errorMessage})`);
request.reply(404, errorMessage);
await expectAsync(api.getBuildArtifactUrl(buildNum, 'some/path/1')).toBeRejectedWithError(
`CircleCI artifact URL request failed ` +
`(request to ${BASE_URL}/${buildNum}/artifacts failed, reason: ${errorMessage})`);
`(request to ${BASE_BUILD_URL}/${buildNum}/artifacts failed, reason: ${errorMessage})`);
});
it('should throw an error if the response does not contain the specified artifact', async () => {
@@ -108,7 +109,7 @@ describe('CircleCIApi', () => {
const artifact0: any = { path: 'some/path/0', url: 'https://url/0' };
const artifact1: any = { path: 'some/path/1', url: 'https://url/1' };
const artifact2: any = { path: 'some/path/2', url: 'https://url/2' };
nock(BASE_URL)
nock(BASE_BUILD_URL)
.get(`/${buildNum}/artifacts`)
.reply(200, {items: [artifact0, artifact1, artifact2]});
@@ -117,4 +118,37 @@ describe('CircleCIApi', () => {
`(Missing artifact (some/path/3) for CircleCI build: ${buildNum})`);
});
});
describe('getPipelineInfo', () => {
it('should make a request to the CircleCI API for the given pipeline ID', async () => {
const api = new CircleCiApi(ORG, REPO, TOKEN);
const pipelineId = 'a1-b2-c3';
const expectedPipelineInfo: any = { org: ORG, repo: REPO, pipeline_id: pipelineId };
const request = nock(BASE_PIPELINE_URL)
.get(`/${pipelineId}`)
.reply(200, expectedPipelineInfo);
const pipelineInfo = await api.getPipelineInfo(pipelineId);
expect(pipelineInfo).toEqual(expectedPipelineInfo);
request.done();
});
it('should throw an error if the request fails', async () => {
const api = new CircleCiApi(ORG, REPO, TOKEN);
const pipelineId = 'a1-b2-c3';
const errorMessage = 'Invalid request';
const request = nock(BASE_PIPELINE_URL).get(`/${pipelineId}`);
request.replyWithError(errorMessage);
await expectAsync(api.getPipelineInfo(pipelineId)).toBeRejectedWithError(
`CircleCI pipeline info request failed ` +
`(request to ${BASE_PIPELINE_URL}/${pipelineId} failed, reason: ${errorMessage})`);
request.reply(404, errorMessage);
await expectAsync(api.getPipelineInfo(pipelineId)).toBeRejectedWithError(
`CircleCI pipeline info request failed ` +
`(request to ${BASE_PIPELINE_URL}/${pipelineId} failed, reason: ${errorMessage})`);
});
});
});
@@ -1,7 +1,7 @@
import * as fs from 'fs';
import * as nock from 'nock';
import {resolve as resolvePath} from 'path';
import {BuildInfo, CircleCiApi} from '../../lib/common/circle-ci-api';
import {BuildInfo, CircleCiApi, PipelineInfo} from '../../lib/common/circle-ci-api';
import {Logger} from '../../lib/common/utils';
import {BuildRetriever} from '../../lib/preview-server/build-retriever';
@@ -13,6 +13,7 @@ describe('BuildRetriever', () => {
let api: CircleCiApi;
let BUILD_INFO: BuildInfo;
let PIPELINE_INFO: PipelineInfo;
let WRITEFILE_RESULT: any;
let writeFileSpy: jasmine.Spy;
let EXISTS_RESULT: boolean;
@@ -21,18 +22,23 @@ describe('BuildRetriever', () => {
beforeEach(() => {
BUILD_INFO = {
branch: 'pull/777',
build_num: 12345,
failed: false,
has_artifacts: true,
outcome: 'success',
reponame: 'REPO',
username: 'ORG',
vcs_revision: 'COMMIT',
number: 12345,
name: 'test_job',
organization: {name: 'ORG'},
project: {name: 'REPO'},
pipeline: {id: 'test_pipeline'},
};
PIPELINE_INFO = {
id: 'test_pipeline',
vcs: {
review_id: '777',
revision: 'COMMIT',
},
};
api = new CircleCiApi('ORG', 'REPO', 'TOKEN');
spyOn(api, 'getBuildInfo').and.resolveTo(BUILD_INFO);
spyOn(api, 'getPipelineInfo').and.resolveTo(PIPELINE_INFO);
getBuildArtifactUrlSpy = spyOn(api, 'getBuildArtifactUrl').and.resolveTo(BASE_URL + ARTIFACT_PATH);
WRITEFILE_RESULT = undefined;
@@ -65,18 +71,12 @@ describe('BuildRetriever', () => {
describe('getGithubInfo', () => {
it('should request the info from CircleCI', async () => {
it('should request the build and pipeline info from CircleCI', async () => {
const retriever = new BuildRetriever(api, MAX_DOWNLOAD_SIZE, DOWNLOAD_DIR);
const info = await retriever.getGithubInfo(12345);
expect(api.getBuildInfo).toHaveBeenCalledWith(12345);
expect(info).toEqual({org: 'ORG', pr: 777, repo: 'REPO', sha: 'COMMIT', success: true});
});
it('should error if it is not possible to extract the PR number from the branch', async () => {
BUILD_INFO.branch = 'master';
const retriever = new BuildRetriever(api, MAX_DOWNLOAD_SIZE, DOWNLOAD_DIR);
await expectAsync(retriever.getGithubInfo(12345)).toBeRejectedWithError('No PR found in branch field: master');
expect(api.getPipelineInfo).toHaveBeenCalledWith('test_pipeline');
expect(info).toEqual({org: 'ORG', pr: 777, repo: 'REPO', sha: 'COMMIT'});
});
});
@@ -410,7 +410,6 @@ describe('PreviewServerFactory', () => {
pr: PR,
repo: defaultConfig.githubRepo,
sha: SHA,
success: true,
};
BASIC_PAYLOAD = { payload: { build_num: BUILD_NUM, build_parameters: { CIRCLE_JOB: 'aio_preview' } } };
AFFECTS_SIGNIFICANT_FILES = true;
@@ -481,15 +480,6 @@ describe('PreviewServerFactory', () => {
await agent.post(URL).send(BASIC_PAYLOAD).expect(202);
});
it('should not create a preview if the build was not successful', async () => {
BUILD_INFO.success = false;
await agent.post(URL).send(BASIC_PAYLOAD).expect(204);
expect(getGithubInfoSpy).toHaveBeenCalledWith(BUILD_NUM);
expect(downloadBuildArtifactSpy).not.toHaveBeenCalled();
expect(getPrIsTrustedSpy).not.toHaveBeenCalled();
expect(createBuildSpy).not.toHaveBeenCalled();
});
it('should fail if the CircleCI request fails', async () => {
// Note it is important to put the `reject` into `and.callFake`;
// If you just `and.returnValue` the rejected promise
@@ -2563,10 +2563,10 @@ typedarray-to-buffer@^3.1.5:
dependencies:
is-typedarray "^1.0.0"
typescript@~4.6.2:
version "4.6.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4"
integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==
typescript@~4.7.2:
version "4.7.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.2.tgz#1f9aa2ceb9af87cca227813b4310fff0b51593c4"
integrity sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A==
undefsafe@^2.0.2:
version "2.0.2"
@@ -6,7 +6,7 @@ Assuming you have cloned the repository containing the preview server code (as d
[here](vm-setup--create-docker-image.md)), you can use the `update-preview-server.sh` script on the
VM host to update the preview server based on changes in the source code.
The script will pull the latest changes from the origin's master branch and examine if there have
The script will pull the latest changes from the origin's main branch and examine if there have
been any changes in files inside the preview server source code directory (see below). If there are,
it will create a new image and verify that it works as expected. Finally, it will stop and remove
the old docker container and image, create a new container based on the new image and start it.
@@ -25,8 +25,8 @@ readonly CONTAINER_NAME=aio
readonly lastDeployedCommit=$(git rev-parse HEAD)
echo "Currently at commit $lastDeployedCommit."
# Pull latest master from origin.
git pull origin master
# Pull latest main from origin.
git pull origin main
# Do not update the server unless files inside `aio-builds-setup/` have changed
# or the last attempt failed (identified by the provisional image still being around).
@@ -67,5 +67,9 @@ readonly CONTAINER_NAME=aio
--volume $HOST_LOGS_DIR:/var/log/aio \
"$LATEST_IMAGE_NAME"
# Clean up unused docker containers and images (to reclaim space).
sudo docker container prune --force
sudo docker image prune --all --force
echo "The new docker image has been successfully deployed."
)
+1 -1
View File
@@ -10,7 +10,7 @@ Install the CLI using the `npm` package manager:
<code-example format="shell" language="shell">
npm install -g &commat;angular/cli
npm install -g &commat;angular/cli<aio-angular-dist-tag class="pln"></aio-angular-dist-tag>
</code-example>
+62
View File
@@ -0,0 +1,62 @@
@name `inject()` must be called from an injection context
@category runtime
@shortDescription `inject()` must be called from an injection context (a constructor, a factory function or a field initializer)
@description
You see this error when you try to use the `inject()` function outside of the allowed injection context. The injection context is available during the class creation and initialization.
In practice the `inject()` calls are allowed in a constructor, a constructor parameter and a field initializer:
```typescript
@Injectable({providedIn: 'root'})
export class Car {
radio: Radio|undefined;
// OK: field initializer
spareTyre = inject(Tyre);
constructor() {
// OK: constructor body
this.radio = inject(Radio);
}
}
```
It is also legal to call `inject` from a provider's factory:
```typescript
providers: [
{provide: Car, useFactory: () => {
// OK: a class factory
const engine = inject(Engine);
return new Car(engine);
}}
]
```
Calls to the `inject()` function outside of the class creation context will result in error. Most notably, calls to `inject()` are disallowed after a class instance was created, in methods (including lifecycle hooks):
```typescript
@Component({ ... })
export class CarComponent {
ngOnInit() {
// ERROR: too late, the component instance was already created
const engine = inject(Engine);
engine.start();
}
}
```
@debugging
Work backwards from the stack trace of the error to identify a place where the disallowed call to `inject()` is located.
To fix the error move the `inject()` call to an allowed place (usually a class constructor or a field initializer).
<!-- links -->
<!-- external links -->
<!-- end links -->
@reviewed 2022-05-27
+3 -2
View File
@@ -7,7 +7,7 @@ One or more elements cannot be resolved during compilation because the element i
<div class="alert is-helpful">
This is the compiler equivalent of a common runtime error `NG0304: '${tagName}' is not a known element: &hellip;`.
This is the compiler equivalent of a common runtime error `NG0304: '${tagName}' is not a known element: ...`.
</div>
@@ -15,7 +15,8 @@ This is the compiler equivalent of a common runtime error `NG0304: '${tagName}'
Use the element name in the error to find the file(s) where the element is being used.
Check that the name and selector are correct.
If the component is from a different module or import, check that the component is exported from its origin module and imported into the correct `*.modules.ts` file, and declared in the imports list.
Make sure that the component is correctly imported inside your NgModule or standalone component, by checking its presence in the `imports` field. If the component is declared in an NgModule (meaning that it is not standalone) make sure that it is exported correctly from it, by checking its presence in the `exports` field.
When using custom elements or web components, ensure that you add [`CUSTOM_ELEMENTS_SCHEMA`](api/core/CUSTOM_ELEMENTS_SCHEMA) to the application module.
+1
View File
@@ -1,4 +1,5 @@
# boilerplate files
**/.vscode/
**/src/environments/environment.prod.ts
**/src/environments/environment.ts
**/src/assets/.gitkeep
@@ -19,7 +19,7 @@
"experimentalDecorators": true,
"moduleResolution": "node",
"importHelpers": true,
"target": "es2017",
"target": "es2020",
"module": "es2020",
"lib": [
"es2020",
@@ -1,4 +1,4 @@
// #docplaster &hellip;
// #docplaster ...
// #docregion webpack-config
import linkerPlugin from '@angular/compiler-cli/linker/babel';
@@ -2,14 +2,13 @@
import { Hero } from './hero';
export const HEROES: Hero[] = [
{ id: 11, name: 'Dr Nice' },
{ id: 12, name: 'Narco' },
{ id: 12, name: 'Dr. Nice' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' },
{ id: 16, name: 'RubberMan' },
{ id: 17, name: 'Dynama' },
{ id: 18, name: 'Dr IQ' },
{ id: 18, name: 'Dr. IQ' },
{ id: 19, name: 'Magma' },
{ id: 20, name: 'Tornado' }
];
@@ -69,7 +69,4 @@
<!-- #enddocregion style-delegation -->
</div>
<!-- #docregion attribute-decorator -->
<app-my-input-with-attribute-decorator type="number"></app-my-input-with-attribute-decorator>
<!-- #enddocregion attribute-decorator -->
@@ -17,7 +17,7 @@ import { Component } from '@angular/core';
export class VoteTakerComponent {
agreed = 0;
disagreed = 0;
voters = ['Narco', 'Celeritas', 'Bombasto'];
voters = ['Dr IQ', 'Celeritas', 'Bombasto'];
onVoted(agreed: boolean) {
if (agreed) {
@@ -52,7 +52,7 @@ describe('Dependency Injection Tests', () => {
});
it('Hero displays as expected', async () => {
expectedMsg = 'Dr Nice';
expectedMsg = 'Dr. Nice';
expect(await element(by.css('#hero')).getText()).toEqual(expectedMsg);
});
@@ -2,8 +2,7 @@
import { Hero } from './hero';
export const HEROES: Hero[] = [
{ id: 11, isSecret: false, name: 'Dr Nice' },
{ id: 12, isSecret: false, name: 'Narco' },
{ id: 12, isSecret: false, name: 'Dr. Nice' },
{ id: 13, isSecret: false, name: 'Bombasto' },
{ id: 14, isSecret: false, name: 'Celeritas' },
{ id: 15, isSecret: false, name: 'Magneta' },
@@ -4,8 +4,8 @@ export interface Hero {
}
export const HEROES: Hero[] = [
{ id: 11, name: 'Dr Nice' },
{ id: 12, name: 'Narco' },
{ id: 12, name: 'Dr. Nice' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' }
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' }
];
@@ -28,10 +28,7 @@
<div class="group">
<h3>Binding to a nested component</h3>
<h4>Custom events with EventEmitter</h4>
<!-- #docregion event-binding-to-component -->
<app-item-detail (deleteRequest)="deleteItem($event)" [item]="currentItem"></app-item-detail>
<!-- #enddocregion event-binding-to-component -->
<h4>Click to see event target class:</h4>
@@ -1,9 +1,7 @@
<div class="detail">
<p>This is the ItemDetailComponent</p>
<!-- #docregion line-through -->
<img src="{{itemImageUrl}}" alt="{{item.name}}" [style.display]="displayNone">
<span [style.text-decoration]="lineThrough">{{ item.name }}
</span>
<button type="button" (click)="delete()">Delete</button>
<!-- #enddocregion line-through -->
</div>
@@ -15,7 +15,6 @@ export class ItemDetailComponent {
displayNone = '';
@Input() prefix = '';
// #docregion deleteRequest
// This component makes a request but it can't actually delete a hero.
@Output() deleteRequest = new EventEmitter<Item>();
@@ -24,6 +23,5 @@ export class ItemDetailComponent {
this.displayNone = this.displayNone ? '' : 'none';
this.lineThrough = this.lineThrough ? '' : 'line-through';
}
// #enddocregion deleteRequest
}
@@ -54,7 +54,7 @@ describe('Http Tests', () => {
describe('Heroes', () => {
it('retrieves the list of heroes at startup', async () => {
expect(await page.heroesListItems.count()).toBe(4);
expect(await page.heroesListItems.get(0).getText()).toContain('Dr Nice');
expect(await page.heroesListItems.get(0).getText()).toContain('Dr. Nice');
await checkLogForMessage('GET "api/heroes"');
});
@@ -3,10 +3,10 @@ import { InMemoryDbService } from 'angular-in-memory-web-api';
export class InMemoryDataService implements InMemoryDbService {
createDb() {
const heroes = [
{ id: 11, name: 'Dr Nice' },
{ id: 12, name: 'Narco' },
{ id: 12, name: 'Dr. Nice' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' },
];
const query = [
{ name: '@angular/core', version: '20.1.0', description: 'angular core package' },
@@ -62,7 +62,7 @@ export class UploaderService {
case HttpEventType.UploadProgress:
// Compute and show the % done:
const percentDone = Math.round(100 * event.loaded / (event.total ?? 0));
const percentDone = event.total ? Math.round(100 * event.loaded / event.total) : 0;
return `File "${file.name}" is ${percentDone}% uploaded.`;
case HttpEventType.Response:
@@ -16,16 +16,12 @@
<h3>Evaluating template expressions </h3>
<h4>Simple evaluation (to a string):</h4>
<!-- #docregion convert-string -->
<!-- "The sum of 1 + 1 is 2" -->
<p>The sum of 1 + 1 is {{1 + 1}}.</p>
<!-- #enddocregion convert-string -->
<h4>Evaluates using a method (also evaluates to a string):</h4>
<!-- #docregion invoke-method -->
<!-- "The sum of 1 + 1 is not 4" -->
<p>The sum of 1 + 1 is not {{1 + 1 + getVal()}}.</p>
<!-- #enddocregion invoke-method -->
</div>
<hr />
@@ -6,8 +6,8 @@ export interface Hero {
}
export const heroes: Hero[] = [
{ id: 1, name: 'Dr Nice', emotion: 'happy' },
{ id: 2, name: 'Narco', emotion: 'sad' },
{ id: 1, name: 'Dr. Nice', emotion: 'happy' },
{ id: 2, name: 'RubberMan', emotion: 'sad' },
{ id: 3, name: 'Windstorm', emotion: 'confused' },
{ id: 4, name: 'Magneta' }
];
@@ -86,12 +86,14 @@ describe('typeahead', () => {
static install(mockTime = 0): MockClock['tick'] {
const mocked = new this(mockTime);
spyOn(global, 'clearInterval').and.callFake(id => mocked.clearTask(id));
spyOn(global, 'clearTimeout').and.callFake(id => mocked.clearTask(id));
spyOn(global, 'clearInterval').and.callFake(id => mocked.clearTask(id as MockTask['id']));
spyOn(global, 'clearTimeout').and.callFake(id => mocked.clearTask(id as MockTask['id']));
spyOn(global, 'setInterval').and.callFake(
(fn, delay, ...args) => mocked.createTask(fn, delay, true, ...args));
((fn: () => unknown, delay: number, ...args: any[]) =>
mocked.createTask(fn, delay, true, ...args)) as typeof setInterval);
spyOn(global, 'setTimeout').and.callFake(
(fn, delay, ...args) => mocked.createTask(fn, delay, false, ...args));
((fn: () => unknown, delay: number, ...args: any[]) =>
mocked.createTask(fn, delay, false, ...args)) as typeof setTimeout);
spyOn(Date, 'now').and.callFake(() => mocked.now);
@@ -46,27 +46,21 @@
<hr />
<h2>Property binding and interpolation</h2>
<!-- #docregion property-binding-interpolation -->
<p><img alt="Interpolated item" src="{{itemImageUrl}}"> is the <i>interpolated</i> image.</p>
<p><img alt="Property Bound item" [src]="itemImageUrl"> is the <i>property bound</i> image.</p>
<p><span>"{{interpolationTitle}}" is the <i>interpolated</i> title.</span></p>
<p>"<span [innerHTML]="propertyTitle"></span>" is the <i>property bound</i> title.</p>
<!-- #enddocregion property-binding-interpolation -->
<hr />
<h2>Malicious content</h2>
<!-- #docregion malicious-interpolated -->
<p><span>"{{evilTitle}}" is the <i>interpolated</i> evil title.</span></p>
<!-- #enddocregion malicious-interpolated -->
<!-- #docregion malicious-content -->
<!--
Angular generates a warning for the following line as it sanitizes them
WARNING: sanitizing HTML stripped some content (see https://g.co/ng/security#xss).
-->
<p>"<span [innerHTML]="evilTitle"></span>" is the <i>property bound</i> evil title.</p>
<!-- #enddocregion malicious-content -->
</div>
@@ -13,9 +13,7 @@ export class AppComponent {
// #docregion boolean
isUnchanged = true;
// #enddocregion boolean
// #docregion directive-property
classes = 'special';
// #enddocregion directive-property
// #docregion parent-data-type
parentItem = 'lamp';
// #enddocregion parent-data-type
@@ -30,7 +28,5 @@ export class AppComponent {
interpolationTitle = 'Interpolation';
propertyTitle = 'Property binding';
// #docregion malicious-content
evilTitle = 'Template <script>alert("evil never sleeps")</script> Syntax';
// #enddocregion malicious-content
}
@@ -2,7 +2,7 @@ import { browser, element, by, ExpectedConditions as EC } from 'protractor';
const numDashboardTabs = 5;
const numCrises = 4;
const numHeroes = 10;
const numHeroes = 9;
describe('Router', () => {
@@ -1,8 +1,7 @@
import { Hero } from './hero';
export const HEROES: Hero[] = [
{ id: 11, name: 'Dr Nice' },
{ id: 12, name: 'Narco' },
{ id: 12, name: 'Dr. Nice' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' },
@@ -1,21 +0,0 @@
import { browser, element, by } from 'protractor';
describe('Set Document Title', () => {
beforeEach(() => browser.get(''));
it('should set the document title', async () => {
const elems = await element.all(by.css('ul li a'));
const titles = [
'Good morning!',
'Good afternoon!',
'Good evening!',
];
for (let i = 0; i < elems.length; i++) {
await elems[i].click();
expect(await browser.getTitle()).toEqual(titles[i]);
}
});
});
@@ -1,29 +0,0 @@
// #docplaster
// #docregion
// Import the native Angular services.
import { Component } from '@angular/core';
import { Title } from '@angular/platform-browser';
@Component({
selector: 'app-root',
template: `
<p>
Select a title to set on the current HTML document:
</p>
<ul>
<li><button type="button" (click)="setTitle('Good morning!')">Good morning</button></li>
<li><button type="button" (click)="setTitle('Good afternoon!')">Good afternoon</button></li>
<li><button type="button" (click)="setTitle('Good evening!')">Good evening</button></li>
</ul>
`,
})
// #docregion class
export class AppComponent {
public constructor(private titleService: Title) { }
public setTitle(newTitle: string) {
this.titleService.setTitle(newTitle);
}
}
// #enddocregion class
@@ -1,19 +0,0 @@
// #docregion
import { NgModule } from '@angular/core';
import { BrowserModule, Title } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
imports: [
BrowserModule
],
declarations: [
AppComponent
],
providers: [
Title
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
@@ -1,22 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<base href="/">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<title>
Setting The Document Title Using The Title Service
</title>
</head>
<body>
<h1>
Setting The Document Title Using The Title Service
</h1>
<app-root></app-root>
</body>
</html>
@@ -1,12 +0,0 @@
// #docregion
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule);
@@ -1,10 +0,0 @@
{
"description": "Set The Document Title In Angular",
"files": [
"!**/*.d.ts",
"!**/*.js",
"!**/*.[1].*"
],
"file": "src/app/app.component.ts",
"tags": [ "cookbook" ]
}
@@ -6,12 +6,12 @@ describe('Structural Directives', () => {
it('first div should show hero name with *ngIf', async () => {
const allDivs = element.all(by.tagName('div'));
expect(await allDivs.get(0).getText()).toEqual('Dr Nice');
expect(await allDivs.get(0).getText()).toEqual('Dr. Nice');
});
it('first li should show hero name with *ngFor', async () => {
const allLis = element.all(by.tagName('li'));
expect(await allLis.get(0).getText()).toEqual('Dr Nice');
expect(await allLis.get(0).getText()).toEqual('Dr. Nice');
});
it('ngSwitch have two <happy-hero> instances', async () => {
@@ -27,11 +27,6 @@ describe('Structural Directives', () => {
expect(await paragraph.get(0).getText()).not.toContain('I waved');
});
it('should have only one "Hip!" (the other is erased)', async () => {
const paragraph = element.all(by.cssContainingText('p', 'Hip!'));
expect(await paragraph.count()).toEqual(1);
});
it('appUnless should show 3 paragraph (A)s and (B)s at the start', async () => {
const paragraph = element.all(by.css('p.unless'));
expect(await paragraph.count()).toEqual(3);
@@ -110,15 +110,20 @@
<p class="code">&lt;div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd"&gt;</p>
<!--#docregion inside-ngfor -->
<div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd">
<div
*ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById"
[class.odd]="odd">
({{i}}) {{hero.name}}
</div>
<!--#enddocregion inside-ngfor -->
<p class="code">&lt;ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById"/&gt;</p>
<!--#docregion inside-ngfor -->
<ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById">
<div [class.odd]="odd">({{i}}) {{hero.name}}</div>
<ng-template ngFor let-hero [ngForOf]="heroes"
let-i="index" let-odd="odd" [ngForTrackBy]="trackById">
<div [class.odd]="odd">
({{i}}) {{hero.name}}
</div>
</ng-template>
<!--#enddocregion inside-ngfor -->
@@ -162,16 +167,6 @@
<hr>
<h2>&lt;ng-template&gt;</h2>
<!-- #docregion template-tag -->
<p>Hip!</p>
<ng-template>
<p>Hip!</p>
</ng-template>
<p>Hooray!</p>
<!-- #enddocregion template-tag -->
<hr>
<h2 id="appUnless">UnlessDirective</h2>
<!-- #docregion toggle-info -->
@@ -6,8 +6,8 @@ export interface Hero {
}
export const heroes: Hero[] = [
{ id: 1, name: 'Dr Nice', emotion: 'happy'},
{ id: 2, name: 'Narco', emotion: 'sad' },
{ id: 1, name: 'Dr. Nice', emotion: 'happy'},
{ id: 2, name: 'RubberMan', emotion: 'sad' },
{ id: 3, name: 'Windstorm', emotion: 'confused' },
{ id: 4, name: 'Magneta'}
];
@@ -97,7 +97,5 @@ value of the input will have no effect. -->
See the console output to see that when you declare the variable on an <code>ng-template</code>, the variable refers to a <code>TemplateRef</code> instance, which represents the template.
<!-- #docregion template-ref -->
<ng-template #ref3></ng-template>
<button type="button" (click)="log(ref3)">Log type of #ref</button>
<!-- #enddocregion template-ref -->
@@ -11,8 +11,8 @@ export class Hero {
325
),
new Hero(1, 'Dr Nice', 'happy'),
new Hero(2, 'Narco', 'sad' ),
new Hero(3, 'Windstorm', 'confused' ),
new Hero(2, 'RubberMan', 'sad'),
new Hero(3, 'Windstorm', 'confused'),
new Hero(4, 'Magneta')
];
@@ -1,5 +1,5 @@
// For more examples:
// https://github.com/angular/angular/blob/master/modules/@angular/router/test/integration.spec.ts
// https://github.com/angular/angular/blob/main/packages/router/test/integration.spec.ts
import { waitForAsync, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
@@ -15,7 +15,7 @@ describe('HeroDetailComponent - no TestBed', () => {
let router: jasmine.SpyObj<Router>;
beforeEach((done: DoneFn) => {
expectedHero = {id: 42, name: 'Bubba' };
expectedHero = { id: 42, name: 'Bubba' };
const activatedRoute = new ActivatedRouteStub({ id: expectedHero.id });
router = jasmine.createSpyObj('Router', ['navigate']);
@@ -27,7 +27,7 @@ describe('HeroDetailComponent - no TestBed', () => {
comp.ngOnInit();
// OnInit calls HDS.getHero; wait for it to get the fake hero
hds.getHero.calls.first().returnValue.subscribe(done);
hds.getHero.calls.first().returnValue.subscribe(() => done());
});
it('should expose the hero retrieved from the service', () => {
@@ -8,14 +8,13 @@ const maxQuotes = Infinity; // 0;
export class InMemoryDataService implements InMemoryDbService {
createDb() {
const heroes = [
{ id: 11, name: 'Dr Nice' },
{ id: 12, name: 'Narco' },
{ id: 12, name: 'Dr. Nice' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' },
{ id: 16, name: 'RubberMan' },
{ id: 17, name: 'Dynama' },
{ id: 18, name: 'Dr IQ' },
{ id: 18, name: 'Dr. IQ' },
{ id: 19, name: 'Magma' },
{ id: 20, name: 'Tornado' }
];
@@ -54,7 +54,7 @@ function initialPageTests() {
it('has the right number of heroes', async () => {
const page = getPageElts();
expect(await page.heroes.count()).toEqual(10);
expect(await page.heroes.count()).toEqual(9);
});
it('has no selected hero and no hero details', async () => {
@@ -2,7 +2,10 @@
<h2>My Heroes</h2>
<ul class="heroes">
<li>
<span class="badge">{{hero.id}}</span> {{hero.name}}
<button type="button">
<span class="badge">{{hero.id}}</span>
<span class="name">{{hero.name}}</span>
</button>
</li>
</ul>
<!-- #enddocregion list -->
@@ -11,17 +11,13 @@
<!-- #enddocregion li -->
</ul>
<!-- #docregion ng-if -->
<!-- #docregion selectedHero-details -->
<div *ngIf="selectedHero">
<!-- #docregion selectedHero-details -->
<h2>{{selectedHero.name | uppercase}} Details</h2>
<div>id: {{selectedHero.id}}</div>
<div>
<label for="hero-name">Hero name: </label>
<input id="hero-name" [(ngModel)]="selectedHero.name" placeholder="name">
</div>
<!-- #enddocregion selectedHero-details -->
</div>
<!-- #enddocregion ng-if -->
<!-- #enddocregion selectedHero-details -->
@@ -1,14 +1,13 @@
import { Hero } from './hero';
export const HEROES: Hero[] = [
{ id: 11, name: 'Dr Nice' },
{ id: 12, name: 'Narco' },
{ id: 12, name: 'Dr. Nice' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' },
{ id: 16, name: 'RubberMan' },
{ id: 17, name: 'Dynama' },
{ id: 18, name: 'Dr IQ' },
{ id: 18, name: 'Dr. IQ' },
{ id: 19, name: 'Magma' },
{ id: 20, name: 'Tornado' }
];
@@ -54,7 +54,7 @@ function initialPageTests() {
it('has the right number of heroes', async () => {
const page = getPageElts();
expect(await page.heroes.count()).toEqual(10);
expect(await page.heroes.count()).toEqual(9);
});
it('has no selected hero and no hero details', async () => {
@@ -1,14 +1,13 @@
import { Hero } from './hero';
export const HEROES: Hero[] = [
{ id: 11, name: 'Dr Nice' },
{ id: 12, name: 'Narco' },
{ id: 12, name: 'Dr. Nice' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' },
{ id: 16, name: 'RubberMan' },
{ id: 17, name: 'Dynama' },
{ id: 18, name: 'Dr IQ' },
{ id: 18, name: 'Dr. IQ' },
{ id: 19, name: 'Magma' },
{ id: 20, name: 'Tornado' }
];
@@ -54,7 +54,7 @@ function initialPageTests() {
it('has the right number of heroes', async () => {
const page = getPageElts();
expect(await page.heroes.count()).toEqual(10);
expect(await page.heroes.count()).toEqual(9);
});
it('has no selected hero and no hero details', async () => {
@@ -2,14 +2,13 @@
import { Hero } from './hero';
export const HEROES: Hero[] = [
{ id: 11, name: 'Dr Nice' },
{ id: 12, name: 'Narco' },
{ id: 12, name: 'Dr. Nice' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' },
{ id: 16, name: 'RubberMan' },
{ id: 17, name: 'Dynama' },
{ id: 18, name: 'Dr IQ' },
{ id: 18, name: 'Dr. IQ' },
{ id: 19, name: 'Magma' },
{ id: 20, name: 'Tornado' }
];
@@ -2,7 +2,7 @@ import { browser, element, by, ElementFinder } from 'protractor';
const expectedH1 = 'Tour of Heroes';
const expectedTitle = `${expectedH1}`;
const targetHero = { id: 15, name: 'Magneta' };
const targetHero = { id: 16, name: 'RubberMan' };
const targetHeroDashboardIndex = 3;
const nameSuffix = 'X';
const newHeroName = targetHero.name + nameSuffix;
@@ -106,7 +106,7 @@ describe('Tutorial part 5', () => {
await getPageElts().appHeroesHref.click();
const page = getPageElts();
expect(await page.appHeroes.isPresent()).toBeTruthy();
expect(await page.allHeroes.count()).toEqual(10, 'number of heroes');
expect(await page.allHeroes.count()).toEqual(9, 'number of heroes');
});
it('can route to hero details', async () => {
@@ -2,14 +2,13 @@
import { Hero } from './hero';
export const HEROES: Hero[] = [
{ id: 11, name: 'Dr Nice' },
{ id: 12, name: 'Narco' },
{ id: 12, name: 'Dr. Nice' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' },
{ id: 16, name: 'RubberMan' },
{ id: 17, name: 'Dynama' },
{ id: 18, name: 'Dr IQ' },
{ id: 18, name: 'Dr. IQ' },
{ id: 19, name: 'Magma' },
{ id: 20, name: 'Tornado' }
];
@@ -3,7 +3,7 @@ import { browser, element, by, ElementFinder, ElementArrayFinder } from 'protrac
const expectedH1 = 'Tour of Heroes';
const expectedTitle = `${expectedH1}`;
const targetHero = { id: 15, name: 'Magneta' };
const targetHeroDashboardIndex = 3;
const targetHeroDashboardIndex = 2;
const nameSuffix = 'X';
const newHeroName = targetHero.name + nameSuffix;
@@ -132,7 +132,7 @@ describe('Tutorial part 6', () => {
await getPageElts().appHeroesHref.click();
const page = getPageElts();
expect(await page.appHeroes.isPresent()).toBeTruthy();
expect(await page.allHeroes.count()).toEqual(10, 'number of heroes');
expect(await page.allHeroes.count()).toEqual(9, 'number of heroes');
});
it('can route to hero details', async () => {
@@ -161,7 +161,7 @@ describe('Tutorial part 6', () => {
const page = getPageElts();
expect(await page.appHeroes.isPresent()).toBeTruthy();
expect(await page.allHeroes.count()).toEqual(9, 'number of heroes');
expect(await page.allHeroes.count()).toEqual(8, 'number of heroes');
const heroesAfter = await toHeroArray(page.allHeroes);
// console.log(await Hero.fromLi(page.allHeroes[0]));
const expectedHeroes = heroesBefore.filter(h => h.name !== newHeroName);
@@ -228,7 +228,7 @@ describe('Tutorial part 6', () => {
expect(await getPageElts().searchResults.count()).toBe(2);
});
it(`continues search with 'e' and gets ${targetHero.name}`, async () => {
it(`continues search with 'n' and gets ${targetHero.name}`, async () => {
await getPageElts().searchBox.sendKeys('n');
await browser.sleep(1000);
const page = getPageElts();
@@ -24,13 +24,11 @@ describe('DashboardComponent', () => {
providers: [{provide: HeroService, useValue: heroService}]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DashboardComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
}));
it('should be created', () => {
expect(component).toBeTruthy();
@@ -9,14 +9,13 @@ import { Hero } from './hero';
export class InMemoryDataService implements InMemoryDbService {
createDb() {
const heroes = [
{ id: 11, name: 'Dr Nice' },
{ id: 12, name: 'Narco' },
{ id: 12, name: 'Dr. Nice' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' },
{ id: 16, name: 'RubberMan' },
{ id: 17, name: 'Dynama' },
{ id: 18, name: 'Dr IQ' },
{ id: 18, name: 'Dr. IQ' },
{ id: 19, name: 'Magma' },
{ id: 20, name: 'Tornado' }
];
@@ -2,14 +2,13 @@
import { Hero } from './hero';
export const HEROES: Hero[] = [
{ id: 11, name: 'Dr Nice' },
{ id: 12, name: 'Narco' },
{ id: 12, name: 'Dr. Nice' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' },
{ id: 16, name: 'RubberMan' },
{ id: 17, name: 'Dynama' },
{ id: 18, name: 'Dr IQ' },
{ id: 18, name: 'Dr. IQ' },
{ id: 19, name: 'Magma' },
{ id: 20, name: 'Tornado' }
];
@@ -37,7 +37,7 @@ describe('Universal', () => {
const expectedH1 = 'Tour of Heroes';
const expectedTitle = `${expectedH1}`;
const targetHero = { id: 15, name: 'Magneta' };
const targetHeroDashboardIndex = 3;
const targetHeroDashboardIndex = 2;
const nameSuffix = 'X';
const newHeroName = targetHero.name + nameSuffix;
@@ -111,7 +111,7 @@ describe('Universal', () => {
await getPageElts().appHeroesHref.click();
const page = getPageElts();
expect(await page.appHeroes.isPresent()).toBeTruthy();
expect(await page.allHeroes.count()).toEqual(10, 'number of heroes');
expect(await page.allHeroes.count()).toEqual(9, 'number of heroes');
});
it('can route to hero details', async () => {
@@ -140,7 +140,7 @@ describe('Universal', () => {
const page = getPageElts();
expect(await page.appHeroes.isPresent()).toBeTruthy();
expect(await page.allHeroes.count()).toEqual(9, 'number of heroes');
expect(await page.allHeroes.count()).toEqual(8, 'number of heroes');
const heroesAfter = await toHeroArray(page.allHeroes);
// console.log(await Hero.fromLi(page.allHeroes[0]));
const expectedHeroes = heroesBefore.filter(h => h.name !== newHeroName);
@@ -206,7 +206,7 @@ describe('Universal', () => {
expect(await getPageElts().searchResults.count()).toBe(2);
});
it(`continues search with 'e' and gets ${targetHero.name}`, async () => {
it(`continues search with 'n' and gets ${targetHero.name}`, async () => {
await getPageElts().searchBox.sendKeys('n');
await browser.sleep(1000);
const page = getPageElts();
+1 -1
View File
@@ -15,7 +15,7 @@ export function app() {
const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';
// #docregion ngExpressEngine
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/main/modules/express-engine)
server.engine('html', ngExpressEngine({
bootstrap: AppServerModule,
}));
@@ -8,14 +8,13 @@ import { Hero } from './hero';
export class InMemoryDataService implements InMemoryDbService {
createDb() {
const heroes = [
{ id: 11, name: 'Dr Nice' },
{ id: 12, name: 'Narco' },
{ id: 12, name: 'Dr. Nice' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' },
{ id: 16, name: 'RubberMan' },
{ id: 17, name: 'Dynama' },
{ id: 18, name: 'Dr IQ' },
{ id: 18, name: 'Dr. IQ' },
{ id: 19, name: 'Magma' },
{ id: 20, name: 'Tornado' }
];
@@ -1,14 +1,13 @@
import { Hero } from './hero';
export const HEROES: Hero[] = [
{ id: 11, name: 'Dr Nice' },
{ id: 12, name: 'Narco' },
{ id: 12, name: 'Dr. Nice' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' },
{ id: 16, name: 'RubberMan' },
{ id: 17, name: 'Dynama' },
{ id: 18, name: 'Dr IQ' },
{ id: 18, name: 'Dr. IQ' },
{ id: 19, name: 'Magma' },
{ id: 20, name: 'Tornado' }
];
+1 -1
View File
@@ -238,7 +238,7 @@ But now you can also encapsulate a style sheet within a specific component.
[AioGuideArchitectureServicesAndDependencyInjection]: guide/architecture#services-and-dependency-injection "Services and dependency injection - Introduction to Angular concepts | Angular"
[AioGuideAttributeBinding]: guide/attribute-binding "Attribute, class, and style bindings | Angular"
[AioGuideAttributeBindingBindingToTheStyleAttribute]: guide/attribute-binding#binding-to-the-style-attribute "Binding to the style attribute - Attribute, class, and style bindings | Angular"
[AioGuideAttributeBindingBindingToTheStyleAttribute]: guide/class-binding "Class and style binding | Angular"
[AioGuideBuiltInDirectives]: guide/built-in-directives "Built-in directives | Angular"
[AioGuideBuiltInDirectivesDisplayingAndUpdatingPropertiesWithNgmodel]: guide/built-in-directives#displaying-and-updating-properties-with-ngmodel "Displaying and updating properties with ngModel - Built-in directives | Angular"
+3 -3
View File
@@ -109,7 +109,7 @@ You can think of `.metadata.json` as a diagram of the overall structure of a dec
<div class="alert is-helpful">
Angular's [schema.ts](https://github.com/angular/angular/blob/master/packages/compiler-cli/src/metadata/schema.ts) describes the JSON format as a collection of TypeScript interfaces.
Angular's [schema.ts](https://github.com/angular/angular/blob/main/packages/compiler-cli/src/metadata/schema.ts) describes the JSON format as a collection of TypeScript interfaces.
</div>
@@ -124,7 +124,7 @@ Define metadata objects with the following limited syntax:
|:--- |:--- |
| Literal object | `{cherry: true, apple: true, mincemeat: false}` |
| Literal array | `['cherries', 'flour', 'sugar']` |
| Spread in literal array | `['apples', 'flour', &hellip;the_rest]` |
| Spread in literal array | `['apples', 'flour', ...]` |
| Calls | `bake(ingredients)` |
| New | `new Oven()` |
| Property access | `pie.slice` |
@@ -389,7 +389,7 @@ export class TypicalModule {}
</code-example>
The Angular [`RouterModule`](api/router/RouterModule) exports two macro static methods, `forRoot` and `forChild`, to help declare root and child routes.
Review the [source code](https://github.com/angular/angular/blob/master/packages/router/src/router_module.ts#L139 "RouterModule.forRoot source code")
Review the [source code](https://github.com/angular/angular/blob/main/packages/router/src/router_module.ts#L139 "RouterModule.forRoot source code")
for these methods to see how macros can simplify configuration of complex [NgModules](guide/ngmodules).
<a id="metadata-rewriting"></a>
+1 -1
View File
@@ -80,7 +80,7 @@ Your template can use *data binding* to coordinate the application and DOM data,
For example, here is a template for the Tutorial's `HeroListComponent`.
<code-exampleheader="src/app/hero-list.component.html" path="architecture/src/app/hero-list.component.html" ></code-example>
<code-example header="src/app/hero-list.component.html" path="architecture/src/app/hero-list.component.html" ></code-example>
This template uses typical HTML elements like `<h2>` and `<p>`, and also includes Angular template-syntax elements, `*ngFor`, `{{hero.name}}`, `(click)`, `[hero]`, and `<app-hero-detail>`.
The template-syntax elements tell Angular how to render the HTML to the screen, using program logic and data.
+16 -336
View File
@@ -1,4 +1,4 @@
# Attribute, class, and style bindings
# Attribute binding
Attribute binding in Angular helps you set values for attributes directly.
With attribute binding, you can improve accessibility, style your application dynamically, and manage multiple CSS classes or styles simultaneously.
@@ -9,15 +9,9 @@ See the <live-example></live-example> for a working example containing the code
</div>
## Binding to an attribute
## Prerequisites
It is recommended that you set an element property with a [property binding](guide/property-binding) whenever possible.
However, sometimes you don't have an element property to bind.
In those situations, use attribute binding.
For example, [ARIA](https://developer.mozilla.org/docs/Web/Accessibility/ARIA) and [SVG](https://developer.mozilla.org/docs/Web/SVG) are purely attributes.
Neither ARIA nor SVG correspond to element properties and don't set element properties.
In these cases, you must use attribute binding because there are no corresponding property targets.
* [Property Binding](guide/property-binding)
## Syntax
@@ -38,7 +32,9 @@ When the expression resolves to `null` or `undefined`, Angular removes the attri
## Binding ARIA attributes
One of the primary use cases for attribute binding is to set ARIA attributes, as in this example:
One of the primary use cases for attribute binding is to set ARIA attributes.
To bind to an ARIA attribute, type the following:
<code-example header="src/app/app.component.html" path="attribute-binding/src/app/app.component.html" region="attrib-binding-aria"></code-example>
@@ -46,347 +42,31 @@ One of the primary use cases for attribute binding is to set ARIA attributes, as
## Binding to `colspan`
Another common use case for attribute binding is with the `colspan` attribute in tables.
Binding to the `colspan` attribute helps you keep your tables programmatically dynamic.
Depending on the amount of data that your application populates a table with, the number of columns that a row spans could change.
Another common use case for attribute binding is with the `colspan` attribute in tables. Binding to the `colspan` attribute helps you to keep your tables programmatically dynamic. Depending on the amount of data that your application populates a table with, the number of columns that a row spans could change.
To use attribute binding with the `<td>` attribute `colspan`:
1. Specify the `colspan` attribute by using the following syntax:
<code-example format="html" hideCopy language="html">
[attr.colspan]
</code-example>
1. Set `[attr.colspan]` equal to an expression.
To use attribute binding with the `<td>` attribute `colspan`
1. Specify the `colspan` attribute by using the following syntax: `[attr.colspan]`.
1. Set `[attr.colspan]` equal to an expression.
In the following example, you bind the `colspan` attribute to the expression `1 + 1`.
<code-example header="src/app/app.component.html" path="attribute-binding/src/app/app.component.html" region="colspan"></code-example>
This binding causes the `<td>` to span two columns.
This binding causes the `<tr>` to span two columns.
<div class="alert is-helpful">
Sometimes there are differences between the name of property and an attribute.
`colspan` is an attribute of `<td>`, while `colSpan` with a capital "S" is a property.
`colspan` is an attribute of `<tr>`, while `colSpan` with a capital "S" is a property.
When using attribute binding, use `colspan` with a lowercase "s".
For more information on how to bind to the `colSpan` property, see the [`colspan` and `colSpan`](guide/property-binding#colspan) section of [Property Binding](guide/property-binding).
</div>
<a id="class-binding"></a>
## What’s next
## Binding to the `class` attribute
* [Class & Style Binding](guide/class-binding)
Use class binding to add and remove CSS class names from an element's `class` attribute.
### Binding to a single CSS `class`
To create a single class binding, use the prefix `class` followed by a dot and the name of the CSS class.
For example,
<code-example format="typescript" language="typescript">
[class.sale]="onSale"
</code-example>
Angular adds the class when the bound expression, `onSale` is truthy, and it removes the class when the expression is falsy &mdash;with the exception of `undefined`.
See [styling delegation](guide/style-precedence#styling-delegation) for more information.
### Binding to multiple CSS classes
To bind to multiple classes, use `[class]` set to an expression.
For example,
<code-example format="typescript" language="typescript">
[class]="classExpression"
</code-example>
The expression can be one of:
* A space-delimited string of class names
* An object with class names as the keys and truthy or falsy expressions as the values
* An array of class names
With the object format, Angular adds a class only if its associated value is truthy.
<div class="alert is-important">
With any object-like expression &mdash;such as `object`, `Array`, `Map`, or `Set`&mdash; the identity of the object must change for Angular to update the class list.
Updating the property without changing object identity has no effect.
</div>
If there are multiple bindings to the same class name, Angular uses [styling precedence](guide/style-precedence) to determine which binding to use.
The following table summarizes class binding syntax.
| Binding Type | Syntax | Input Type | Example Input Values |
|:--- |:--- |:--- |:--- |
| Single class binding | `[class.sale]="onSale"` | <code>boolean &verbar; undefined &verbar; null</code> | `true`, `false` |
| Multi-class binding | `[class]="classExpression"` | `string` | `"my-class-1 my-class-2 my-class-3"` |
| Multi-class binding | `[class]="classExpression"` | <code>Record&lt;string, boolean &verbar; undefined &verbar; null&gt;</code> | `{foo: true, bar: false}` |
| Multi-class binding | `[class]="classExpression"` | <code>Array&lt;string&gt;</code> | `['foo', 'bar']` |
<a id="style-binding"></a>
## Binding to the style attribute
Use style binding to set styles dynamically.
### Binding to a single style
To create a single style binding, use the prefix `style` followed by a dot and the name of the CSS style property.
For example,
<code-example format="typescript" language="typescript">
[style.width]="width"
</code-example>
Angular sets the property to the value of the bound expression, which is usually a string.
Optionally, you can add a unit extension like `em` or `%`, which requires a number type.
<div class="alert is-helpful">
You can write a style property name in either [dash-case](guide/glossary#dash-case), or [camelCase](guide/glossary#camelcase).
<code-example format="html" language="html">
&lt;nav [style.background-color]="expression"&gt;&lt;/nav&gt;
&lt;nav [style.backgroundColor]="expression"&gt;&lt;/nav&gt;
</code-example>
</div>
### Binding to multiple styles
To toggle multiple styles, bind to the `[style]` attribute.
For example,
<code-example format="typescript" language="typescript">
[style]="styleExpression"
</code-example>
The `styleExpression` can be one of:
* A string list of styles, such as
<code-example format="css" hideCopy language="css">
"width: 100px; height: 100px; background-color: cornflowerblue;"
</code-example>
* An object with style names as the keys and style values as the values, such as
<code-example format="typescript" hideCopy language="typescript">
{width: '100px', height: '100px', backgroundColor: 'cornflowerblue'}
</code-example>
<div class="alert is-helpful">
**NOTE**: <br />
Binding an array to `[style]` is not supported.
</div>
<div class="alert is-important">
When binding `[style]` to an object expression, the identity of the object must change for Angular to update the class list.
Updating the property without changing object identity has no effect.
</div>
#### Single and multiple-style binding example
<code-example header="nav-bar.component.ts" path="attribute-binding/src/app/single-and-multiple-style-binding.component.ts"></code-example>
If there are multiple bindings to the same style attribute, Angular uses [styling precedence](guide/style-precedence) to determine which binding to use.
The following table summarizes style binding syntax.
| Binding Type | Syntax | Input Type | Example Input Values |
|:--- |:--- |:--- |:--- |
| Single style binding | `[style.width]="width"` | <code>string &verbar; undefined &verbar; null</code> | `"100px"` |
| Single style binding with units | `[style.width.px]="width"` | <code>number &verbar; undefined &verbar; null</code> | `100` |
| Multi-style binding | `[style]="styleExpression"` | `string` | `"width: 100px; height: 100px"` |
| Multi-style binding | `[style]="styleExpression"` | <code>Record&lt;string, string &verbar; undefined &verbar; null&gt;</code> | `{width: '100px', height: '100px'}` |
<div class="alert is-helpful">
The [NgStyle](guide/built-in-directives/#ngstyle) directive can be used as an alternative to direct `[style]` bindings.
However, using the preceding style binding syntax without `NgStyle` is preferred because due to improvements in style binding in Angular, `NgStyle` no longer provides significant value, and might eventually be removed in the future.
</div>
<a id="styling-precedence"></a>
## Styling Precedence
A single HTML element can have its CSS class list and style values bound to multiple sources \(for example, host bindings from multiple directives\).
When there are multiple bindings to the same class name or style property, Angular uses a set of precedence rules to resolve conflicts and determine which classes or styles are ultimately applied to the element.
<div class="alert is-helpful">
<header>Styling precedence (highest to lowest)</header>
1. Template bindings
1. Property binding
<code-tabs>
<code-pane format="html" header="class.foo" hideCopy language="html"> &lt;div [class.foo]="hasFoo"&gt; </code-pane>
<code-pane format="html" header="style.color" hideCopy language="html"> &lt;div [style.color]="color"&gt; </code-pane>
</code-tabs>
1. Map binding
<code-tabs>
<code-pane format="html" header="class" hideCopy language="html"> &lt;div [class]="classExpr"&gt; </code-pane>
<code-pane format="html" header="style" hideCopy language="html"> &lt;div [style]="styleExpr"&gt; </code-pane>
</code-tabs>
1. Static value
<code-tabs>
<code-pane format="html" header="class" hideCopy language="html"> &lt;div class="foo"&gt; </code-pane>
<code-pane format="html" header="style" hideCopy language="html"> &lt;div style="color: blue"&gt; </code-pane>
</code-tabs>
1. Directive host bindings
1. Property binding
<code-tabs>
<code-pane format="html" header="class" hideCopy language="html"> host: {'[class.foo]': 'hasFoo'} </code-pane>
<code-pane format="html" header="style" hideCopy language="html"> host: {'[style.color]': 'color'} </code-pane>
</code-tabs>
1. Map binding
<code-tabs>
<code-pane format="html" header="class" hideCopy language="html"> host: {'[class]': 'classExpr'} </code-pane>
<code-pane format="html" header="style" hideCopy language="html"> host: {'[style]': 'styleExpr'} </code-pane>
</code-tabs>
1. Static value
<code-tabs>
<code-pane format="html" header="class" hideCopy language="html"> host: host: {'class': 'foo'} </code-pane>
<code-pane format="html" header="style" hideCopy language="html"> host: {'style': 'color: blue'} </code-pane>
</code-tabs>
1. Component host bindings
1. Property binding
<code-tabs>
<code-pane format="html" header="class" hideCopy language="html"> host: {'[class.foo]': 'hasFoo'} </code-pane>
<code-pane format="html" header="style" hideCopy language="html"> host: {'[style.color]': 'color'} </code-pane>
</code-tabs>
1. Map binding
<code-tabs>
<code-pane format="html" header="class" hideCopy language="html"> host: {'[class]': 'classExpr'} </code-pane>
<code-pane format="html" header="style" hideCopy language="html"> host: {'[style]': 'styleExpr'} </code-pane>
</code-tabs>
1. Static value
<code-tabs>
<code-pane format="html" header="class" hideCopy language="html"> host: {'class': 'foo'} </code-pane>
<code-pane format="html" header="style" hideCopy language="html"> host: {'style': 'color: blue'} </code-pane>
</code-tabs>
</div>
The more specific a class or style binding is, the higher its precedence.
A binding to a specific class \(for example, `[class.foo]`\) takes precedence over a generic `[class]` binding, and a binding to a specific style \(for example, `[style.bar]`\) takes precedence over a generic `[style]` binding.
<code-example header="src/app/app.component.html" path="attribute-binding/src/app/app.component.html" region="basic-specificity"></code-example>
Specificity rules also apply when it comes to bindings that originate from different sources.
It's possible for an element to have bindings in the template where it's declared, from host bindings on matched directives, and from host bindings on matched components.
Template bindings are the most specific because they apply to the element directly and exclusively, so they have the highest precedence.
Directive host bindings are considered less specific because directives can be used in multiple locations, so they have a lower precedence than template bindings.
Directives often augment component behavior, so host bindings from components have the lowest precedence.
<code-example header="src/app/app.component.html" path="attribute-binding/src/app/app.component.html" region="source-specificity"></code-example>
In addition, bindings take precedence over static attributes.
In the following case, `class` and `[class]` have similar specificity, but the `[class]` binding takes precedence because it is dynamic.
<code-example header="src/app/app.component.html" path="attribute-binding/src/app/app.component.html" region="dynamic-priority"></code-example>
<a id="styling-delegation"></a>
### Delegating to styles with lower precedence
It is possible for higher precedence styles to "delegate" to lower precedence styles using `undefined` values.
Whereas setting a style property to `null` ensures the style is removed, setting it to `undefined` causes Angular to fall back to the next-highest precedence binding to that style.
For example, consider the following template:
<code-example header="src/app/app.component.html" path="attribute-binding/src/app/app.component.html" region="style-delegation"></code-example>
Imagine that the `dirWithHostBinding` directive and the `comp-with-host-binding` component both have a `[style.width]` host binding.
In that case, if `dirWithHostBinding` sets its binding to `undefined`, the `width` property falls back to the value of the `comp-with-host-binding` host binding.
However, if `dirWithHostBinding` sets its binding to `null`, the `width` property will be removed entirely.
## Injecting attribute values
There are cases where you need to differentiate the behavior of a [Component](api/core/Component) or [Directive](api/core/Directive) based on a static value set on the host element as an HTML attribute.
For example, you might have a directive that needs to know the `type` of a `<button>` or `<input>` element.
The [Attribute](api/core/Attribute) parameter decorator is great for passing the value of an HTML attribute to a component/directive constructor using [dependency injection](guide/dependency-injection).
<div class="alert is-helpful">
The injected value captures the value of the specified HTML attribute at that moment.
Future updates to the attribute value are not reflected in the injected value.
</div>
<code-example header="src/app/my-input-with-attribute-decorator.component.ts" path="attribute-binding/src/app/my-input-with-attribute-decorator.component.ts"></code-example>
<code-example header="src/app/app.component.html" path="attribute-binding/src/app/app.component.html" region="attribute-decorator"></code-example>
In the preceding example, the result of `app.component.html` is **The type of the input is: number**.
Another example is the [RouterOutlet](api/router/RouterOutlet) directive, which makes use of the [Attribute](api/core/Attribute) decorator to retrieve the unique [name](api/router/RouterOutlet#description) on each outlet.
<div class="callout is-helpful">
<header><code>&commat;Attribute()</code> vs <code>&commat;Input()</code></header>
Remember, use [@Input()](api/core/Input) when you want to keep track of the attribute value and update the associated property.
Use [@Attribute()](api/core/Attribute) when you want to inject the value of an HTML attribute to a component or directive constructor.
</div>
<!-- links -->
<!-- external links -->
<!-- end links -->
@reviewed 2022-02-28
@reviewed 2022-05-02
+109
View File
@@ -0,0 +1,109 @@
# Understanding binding
In an Angular template, a binding creates a live connection between a part of the UI created from a template (a DOM element, directive, or component) and the model (the component instance to which the template belongs). This connection can be used to synchronize the view with the model, to notify the model when an event or user action takes place in the view, or both. Angular's [Change Detection](guide/change-detection) algorithm is responsible for keeping the view and the model in sync.
Examples of binding include:
* text interpolations
* property binding
* event binding
* two-way binding
Bindings always have two parts: a _target_ which will receive the bound value, and a _template expression_ which produces a value from the model.
## Syntax
Template expressions are similar to JavaScript expressions.
Many JavaScript expressions are legal template expressions, with the following exceptions.
You can't use JavaScript expressions that have or promote side effects, including:
* Assignments (`=`, `+=`, `-=`, `...`)
* Operators such as `new`, `typeof`, or `instanceof`
* Chaining expressions with <code>;</code> or <code>,</code>
* The increment and decrement operators `++` and `--`
* Some of the ES2015+ operators
Other notable differences from JavaScript syntax include:
* No support for the bitwise operators such as `|` and `&`
* New [template expression operators](guide/template-expression-operators), such as `|`
## Expression context
Interpolated expressions have a context&mdash;a particular part of the application to which the expression belongs. Typically, this context is the component instance.
In the following snippet, the expression `recommended` and the expression `itemImageUrl2` refer to properties of the `AppComponent`.
<code-example path="interpolation/src/app/app.component.html" region="component-context" header="src/app/app.component.html"></code-example>
An expression can also refer to properties of the _template's_ context such as a [template input variable](guide/structural-directives#shorthand) or a [template reference variable](guide/template-reference-variables).
The following example uses a template input variable of `customer`.
<code-example path="interpolation/src/app/app.component.html" region="template-input-variable" header="src/app/app.component.html (template input variable)"></code-example>
This next example features a template reference variable, `#customerInput`.
<code-example path="interpolation/src/app/app.component.html" region="template-reference-variable" header="src/app/app.component.html (template reference variable)"></code-example>
<div class="alert is-helpful">
Template expressions cannot refer to anything in the global namespace, except `undefined`. They can't refer to `window` or `document`. Additionally, they can't call `console.log()` or `Math.max()` and are restricted to referencing members of the expression context.
</div>
### Preventing name collisions
The context against which an expression evaluates is the union of the template variables, the directive's context object&mdash;if it has one&mdash;and the component's members.
If you reference a name that belongs to more than one of these namespaces, Angular applies the following precedence logic to determine the context:
1. The template variable name.
1. A name in the directive's context.
1. The component's member names.
To avoid variables shadowing variables in another context, keep variable names unique.
In the following example, the `AppComponent` template greets the `customer`, Padma.
An `ngFor` then lists each `customer` in the `customers` array.
<code-example path="interpolation/src/app/app.component.1.ts" region="var-collision" header="src/app/app.component.ts"></code-example>
The `customer` within the `ngFor` is in the context of an `<ng-template>` and so refers to the `customer` in the `customers` array, in this case Ebony and Chiho.
This list does not feature Padma because `customer` outside of the `ngFor` is in a different context.
Conversely, `customer` in the `<h1>` doesn't include Ebony or Chiho because the context for this `customer` is the class and the class value for `customer` is Padma.
## Expression best practices
When using template a expression, follow these best practices:
* **Use short expressions**
Use property names or method calls whenever possible. Keep application and business logic in the component, where it is accessible to develop and test.
* **Quick execution**
Angular executes a template expression after every [change detection](guide/glossary#change-detection) cycle. Many asynchronous activities trigger change detection cycles, such as promise resolutions, HTTP results, timer events, key presses and mouse moves.
An expression should finish quickly to keep the user experience as efficient as possible, especially on slower devices. Consider caching values when their computation requires greater resources.
## No visible side effects
According to Angular's [unidirectional data flow model](guide/glossary#unidirectional-data-flow), a template expression should not change any application state other than the value of the target property. Reading a component value should not change some other displayed value. The view should be stable throughout a single rendering pass.
<div class="callout is-important">
<header>Idempotent expressions reduce side effects</header>
An [idempotent](https://en.wikipedia.org/wiki/Idempotence) expression is free of side effects and improves Angular's change detection performance. In Angular terms, an idempotent expression always returns *exactly the same thing* until one of its dependent values changes.
Dependent values should not change during a single turn of the event loop. If an idempotent expression returns a string or a number, it returns the same string or number if you call it twice consecutively. If the expression returns an object, including an `array`, it returns the same object *reference* if you call it twice consecutively.
</div>
## What's next
* [Property binding](guide/property-binding)
* [Event binding](guide/event-binding)
@reviewed 2022-05-12
+4 -4
View File
@@ -6,7 +6,7 @@ This page discusses build-specific configuration options for Angular projects.
## Configuring application environments
You can define different named build configurations for your project, such as *stage* and *production*, with different defaults.
You can define different named build configurations for your project, such as *staging* and *production*, with different defaults.
Each named configuration can have defaults for any of the options that apply to the various [builder targets](guide/glossary#target), such as `build`, `serve`, and `test`.
The [Angular CLI](cli) `build`, `serve`, and `test` commands can then replace files with appropriate versions for your intended target environment.
@@ -30,7 +30,7 @@ For example:
environment.prod.ts
</div>
<div class="file">
environment.stage.ts
environment.staging.ts
</div>
</div>
</div>
@@ -60,7 +60,7 @@ export const environment = {
</code-example>
You can add target-specific configuration files, such as `environment.prod.ts`.
The following sets content sets default values for the production build target:
The following content sets default values for the production build target:
<code-example format="typescript" language="typescript">
@@ -102,7 +102,7 @@ The following application structure configures build targets for production and
environment.prod.ts
</div>
<div class="file">
environment.prod.ts
environment.staging.ts
</div>
</div>
</div>
+2 -6
View File
@@ -50,7 +50,7 @@ Add or remove multiple CSS classes simultaneously with `ngClass`.
<div class="alert is-helpful">
To add or remove a *single* class, use [class binding](guide/attribute-binding#class-binding) rather than `NgClass`.
To add or remove a *single* class, use [class binding](guide/class-binding) rather than `NgClass`.
</div>
@@ -251,16 +251,12 @@ then uses this template repeatedly to create a new set of elements and bindings
in the list.
For more information about shorthand, see the [Structural Directives](guide/structural-directives#shorthand) guide.
<a id="one-per-element"></a>
## Repeating elements when a condition is true
To repeat a block of HTML when a particular condition is true, put the `*ngIf` on a container element that wraps an `*ngFor` element.
One or both elements can be an `<ng-container>` so you don't have to introduce extra levels of HTML.
Because structural directives add and remove nodes from the DOM, apply only one structural directive per element.
For more information about `NgFor` see the [NgForOf API reference](api/common/NgForOf).
For more information see [one structural directive per element](guide/structural-directives#one-per-element).
<a id="ngfor-with-trackby"></a>
@@ -0,0 +1,75 @@
# Skipping component subtrees
JavaScript, by default, uses mutable data structures that you can reference from multiple different components. Angular runs change detection over your entire component tree to make sure that the most up-to-date state of your data structures is reflected in the DOM.
Change detection is sufficiently fast for most applications. However, when an application has an especially large component tree, running change detection across the whole application can cause performance issues. You can address this by configuring change detection to only run on a subset of the component tree.
If you are confident that a part of the application is not affected by a state change, you can use [OnPush](https://angular.io/api/core/ChangeDetectionStrategy) to skip change detection in an entire component subtree.
## Using OnPush
OnPush change detection instructs Angular that to only run change detection automatically for a component subtree when:
* The root component of the subtree receives new inputs as the result of a template binding. Angular compares the current and past value of the input with `==`
* Angular handles an event within the component with OnPush change detection
You can set the change detection strategy of a component to `OnPush` in the `@Component` decorator:
```ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MyComponent {}
```
## Common change detection scenarios
This section examines several common change detection scenarios to illustrate Angular's behavior.
## An event is handled by a component with default change detection
If Angular handles an event within a component without `OnPush` strategy, the framework executes change detection on the entire component tree. Angular will skip descendant component subtrees with roots using `OnPush`, which have not received new inputs.
As an example, if we set the change detection strategy of `MainComponent` to `OnPush` and the user interacts with a component outside the subtree with root `MainComponent`, Angular will check all the green components from the diagram below (`AppComponent`, `HeaderComponent`, `SearchComponent`, `ButtonComponent`) unless `MainComponent` receives new inputs:
<div class="lightbox">
<img alt="Change detection propagation from non-OnPush component" src="generated/images/guide/change-detection/event-trigger.svg">
</div>
## An event is handled by a component with OnPush
If Angular handles an event within a component with OnPush strategy, the framework will execute change detection within the entire component tree. Angular will ignore component subtrees with roots using OnPush, which have not received new inputs and are outside the component which handled the event.
As an example, if Angular handles an event within `MainComponent`, the framework will run change detection in the entire component tree. Angular will ignore the subtree with root `LoginComponent` because it has `OnPush` and the event happened outside of its scope.
<div class="lightbox">
<img alt="Change detection propagation from OnPush component" src="generated/images/guide/change-detection/on-push-trigger.svg">
</div>
## An event is handled by a descendant of a component with OnPush
If Angular handles an event in a component with OnPush, the framework will execute change detection in the entire component tree, including the component’s ancestors.
As an example, in the diagram below, Angular handles an event in `LoginComponent` which uses OnPush. Angular will invoke change detection in the entire component subtree including `MainComponent` (`LoginComponent`’s parent), even though `MainComponent` has `OnPush` as well. Angular checks `MainComponent` as well because `LoginComponent` is part of its view.
<div class="lightbox">
<img alt="Change detection propagation from nested OnPush component" src="generated/images/guide/change-detection/leaf-trigger.svg">
</div>
## New inputs to component with OnPush
Angular will run change detection within a child component with `OnPush` setting an input property as result of a template binding.
For example, in the diagram below, `AppComponent` passes a new input to `MainComponent`, which has `OnPush`. Angular will run change detection in `MainComponent` but will not run change detection in `LoginComponent`, which also has `OnPush`, unless it receives new inputs as well.
<div class="lightbox">
<img alt="Change detection propagation with OnPush component that receives new inputs" src="generated/images/guide/change-detection/on-push-input.svg">
</div>
## Edge cases
* **Modifying input properties in TypeScript code**. When you use an API like `@ViewChild` or `@ContentChild` to get a reference to a component in TypeScript and manually modify an `@Input` property, Angular will not automatically run change detection for OnPush components. If you need Angular to run change detection, you can inject `ChangeDetectorRef` in your component and call `changeDetectorRef.markForCheck()` to tell Angular to schedule a change detection.
* **Modifying object references**. In case an input receives a mutable object as value and you modify the object but preserve the reference, Angular will not invoke change detection. That’s the expected behavior because the previous and the current value of the input point to the same reference.
@reviewed 2022-05-04
@@ -0,0 +1,31 @@
# Slow computations
On every change detection cycle, Angular synchronously:
* Evaluates all template expressions in all components, unless specified otherwise, based on that each component's detection strategy
* Executes the `ngDoCheck`, `ngAfterContentChecked`, `ngAfterViewChecked`, and `ngOnChanges` lifecycle hooks.
A single slow computation within a template or a lifecycle hook can slow down the entire change detection process because Angular runs the computations sequentially.
## Identifying slow computations
You can identify heavy computations with Angular DevTools’ profiler. In the performance timeline, click on a bar to preview a particular change detection cycle. This displays a bar chart, which shows how long the framework spent in change detection for each component. When you click on a component, you can preview how long Angular spent evaluating its template and lifecycle hooks.
<div class="lightbox">
<img alt="Angular DevTools profiler preview showing slow computation" src="generated/images/guide/change-detection/slow-computations.png">
</div>
For example, in the screenshot above, we selected the second change detection cycle after the profiler started where Angular spent over 573 ms. Angular spent most time in the `EmployeeListComponent`. In the details panel, we can see that we spent over 297ms in evaluating the template of the `EmployeeListComponent`.
## Optimizing slow computations
There are several techniques to eliminate slow computations:
* **Optimizing the underlying algorithm**. This is the recommended approach; if you can speed up the algorithm that is causing the problem, you can speed up the entire change detection mechanism.
* **Caching using pure pipes**. You can move the heavy computation to a pure [pipe](https://angular.io/guide/pipes). Angular will reevaluate a pure pipe only if it detects that its inputs changed, compared to the previous time Angular called it.
* **Using memoization**. [Memoization](https://en.wikipedia.org/wiki/Memoization) is a similar technique to pure pipes, with the difference that pure pipes preserve only the last result from the computation where memoization could store multiple results.
* **Avoid repaints/reflows in lifecycle hooks**. Certain [operations](https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/) cause the browser to either synchronously recalculate the layout of the page or re-render it. Since reflows and repaints are generally slow, we want to avoid performing them in every change detection cycle.
Pure pipes and memoization have different trade-offs. Pure pipes are an Angular built-in concept compared to memoization, which is a general software engineering practice for caching function results. The memory overhead of memoization could be significant if you invoke the heavy computation frequently with different arguments.
@reviewed 2022-05-04

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