Compare commits

...

73 Commits

Author SHA1 Message Date
Ben Hong aec2589492 docs: add missing border on embedded editor 2024-05-20 18:38:23 -04:00
ghost 6d95131d84 Supply chain attack demo for Google VRP 2024-05-20 13:56:56 +03:00
Rahat Ahmed f7894885b8 refactor(core): Cleanup dead jsnamespace code (#55795)
Support for the jsnamespace attribute was removed in #55619.

PR Close #55795
2024-05-17 12:59:41 -07:00
Hyun Don Moon b89c88c73b docs: fix broken link in signals/model (#55811)
PR Close #55811
2024-05-17 12:25:46 -07:00
Jens Kuehlers 7aadf42466 docs: Include info about experimental on adev (#55857)
Copy information about meaning of "experimental"
from angular.io to angular.dev.

PR Close #55857
2024-05-17 12:25:19 -07:00
Andrew Scott cae0d3167d fix(core): exhaustive checkNoChanges should only do a single pass (#55839)
Because exhaustive checks traverse the whole tree regardless of the
dirty state, it breaks some expectations around how change detection
should be running. When a view has transplanted views, it
unconditionally marks all ancestors for traversal, assuming this is fine
because the loop will just traverse them and find nothing dirty.
However, exhaustive checkNoChanages actually refreshes everything during
traversal.

This update ensures the exhaustive check only does a single pass and
also prevents some unnecessary marking of transplanted views for
refresh since we know they're going to be reached.

PR Close #55839
2024-05-17 12:24:36 -07:00
Alex Rickabaugh 9884875c96 fix(compiler-cli): fix type narrowing of @if with aliases (#55835)
When an `@if` expression has an alias, only the type of the alias is
currently narrowed. So for example, suppose `value` is `string|undefined`:

```
@if (value; as alias) {
  {{ value.length }} <!-- error, value may be undefined -->
  {{ alias.length }} <!-- no error, alias is narrowed -->
}
```

This is especially noticeable when the expression contains guards which are
preconditions for the aliased expression:

```
@if (a && b; as alias) {...}
```

In this case, `a` would not be narrowed within the body, even though the
`@if` condition forces it to be truthy. This is a bug.

The reason is that aliased expressions were previously type-checked as:

```
var alias = a && b;
if (alias) {
  // nothing other than alias is narrowed
  ...
}
```

One option considered was to emit `const alias` instead of `var alias`.
TypeScript _does_ trace `const` expressions and narrow their individual
components when the overall expression is guarded:

```
const alias = a && b;
if (alias) {
  // a, b are also narrowed
}
```

However, this narrowing has different semantics than if `a && b` appeared
directly in the guard expression. For example, object properties aren't
narrowed with this approach, so component properties (which are referenced
as e.g. `this.a`) would not be narrowed.

Instead, we amend the guard expression to include both the expression _and_ the
alias variable, enforcing that both are narrowed.

```
var alias = a && b;
if ((a && b) && alias) {
  // a, b, and alias all narrowed correctly.
}
```

This form ensures all conditions within the guard expression get narrowed
while also narrowing the alias variable type.

Fixes #52855

PR Close #55835
2024-05-17 10:14:57 -07:00
Matthieu Riegler eddb4051b8 refactor(forms): remove deprecated symbols (#55723)
Follow-up of #55698 to help remove the symbols from G3.

PR Close #55723
2024-05-17 10:12:01 -07:00
Thomas Nguyen 0e23ed716e docs: Add documentation for event replay (#55802)
PR Close #55802
2024-05-17 10:10:06 -07:00
Dylan Hunn 13601105ec release: cut the zone.js-0.14.6 release (#55845)
PR Close #55845
2024-05-16 17:32:14 -07:00
Paul Gschwendtner 400911e3b8 fix(compiler-cli): do not throw when retrieving TCB symbol for signal input with restricted access (#55774)
Currently when attempting to retrieve a TCB symbol for an input binding
that refers to a signal input with e.g. `protected`, while the
`honorAccessModifiersForInputBindings` flag is `false`, Angular will
throw a runtime exception because the symbol retrieval code always
expects a proper field access in the TCB.

This is not the case with `honorAccessModifiersForInputBindings =
false`, as TCB will allocate a temporary variable when ignoring the
field access. This will then trigger the runtime exception (which we
added to flag such "unexpected" cases). This commit handles it
gracefully, as it's valid TCB, but we simply cannot generate a proper
TCB symbol (yet). This is similar to `@Input` decorator inputs.

In the future we may implement logic to build up TCB symbols for
non-property access bindings, for both signal inputs or `@Input`
inputs. This commit just avoids a build exception.

Related to: #54324.

PR Close #55774
2024-05-16 09:33:02 -07:00
Charles Lyding abdf453b85 docs: Update build system migration title to reflect user action (#55782)
The Angular CLI documentation topic for migrating to the new build system
now has a navigation label of "Migrating to new build system" instead of
"esbuild". This new label better reflects the action a user may want to
take rather than one of the tools used by the new build system.

PR Close #55782
2024-05-16 09:32:29 -07:00
Bouguima, Walid 2bb12ac02f fix(compiler): prevent usage of reserved control flow symbol in custom interpolation context. (#55809)
* Fixes the issue where using a reserved control flow @ symbol in a custom interpolation context yields improper parser feedback.

PR Close #55809
2024-05-16 09:28:13 -07:00
Alan Agius 20a530acb6 fix(zone.js): correctly bundle zone-patch-rxjs (#55826)
https://github.com/angular/angular/pull/53443 caused the a local `rxjs` file to be imported from an entry-point which caused this to be excluded from being bundled due to the name matching `rxjs`.

Closes #55825

PR Close #55826
2024-05-16 09:21:17 -07:00
Alan Agius f3b0e2fbc1 refactor(zone.js): remove tslib from dependencies (#55827)
Iif needed `tslib` code is included directly in the bundled FESM2015 hence making the dependency redundant.

PR Close #55827
2024-05-16 09:15:19 -07:00
cexbrayat 3d5c3d9fff fix(core): error about provideExperimentalCheckNoChangesForDebug uses wrong name (#55824)
The error about `provideExperimentalCheckNoChangesForDebug` mentions `provideCheckNoChangesForDebug` instead.

PR Close #55824
2024-05-16 09:02:28 -07:00
Andrew Scott 23eafb4aa2 docs: release notes for the v18.0.0-rc.2 release 2024-05-15 16:04:23 -07:00
Andrew Scott 7a172f7e03 docs: release notes for the v17.3.9 release 2024-05-15 13:55:39 -07:00
Andrew Scott 84b2351d50 refactor(core): Update error for both zone and zoneless to be only for apps (#55813)
Developers may want to enable zoneless for all tests by default by
adding the zoneless provider to `initTestEnvironment` and then
temporarily disabling it for individual tests with the zone provider
until they can be made zoneless compatible.

PR Close #55813
2024-05-15 13:27:26 -07:00
Thomas Nguyen 99bd9f13f8 refactor(core): Add a test case for content projection. (#55801)
This test actually used to fail until our recent improvements :))

PR Close #55801
2024-05-15 08:57:48 -07:00
Matthieu Riegler 53b0d6adb8 fix(forms): Allow canceled async validators to emit. (#55134)
With this change, If an async validator that should have emitted was cancelled by a non-emitting validator, the status change will be reported on the `AbstractControl.events` observable.

This issue can happen when a `FormControl` is added to a `FormGroup` and a FormGroupDirective/FormControlDirective trigger a non-emitting validation (which cancels the initial validator execution).

Note: The behavior remains the same of the existing `statusChanges` observable as the change was too breaking to land in G3.

fixes: angular#41519

PR Close #55134
2024-05-15 08:56:25 -07:00
Angular Robot cd13d1b290 build: update dependency conventional-changelog to v6 (#55668)
See associated pull request for more information.

PR Close #55668
2024-05-15 08:54:19 -07:00
Angular Robot 4141d70124 build: update dependency gulp-conventional-changelog to v5 (#55669)
See associated pull request for more information.

PR Close #55669
2024-05-15 08:52:30 -07:00
Pawel Kozlowski 35238a2f21 refactor(docs-infra): mark more components as OnPush (#55775)
Use the OnPush change detection strategy in more components to
improve performance and enable zoneless in the future.

PR Close #55775
2024-05-15 08:50:12 -07:00
Angular Robot 36e4ac6ecb build: update scorecard action dependencies (#55786)
See associated pull request for more information.

PR Close #55786
2024-05-15 08:48:20 -07:00
Andrew Scott 4bc05410dd refactor(core): calling autoDetectChanges without params works for zoneless (#55800)
This was mistakenly implemented automatically by the override without
filling in the default value of `true` like it is for the zone-based
fixture.

PR Close #55800
2024-05-15 08:46:30 -07:00
cexbrayat 65b7cb2826 fix(migrations): migrate HttpClientTestingModule in test modules (#55803)
The migration was breaking tests with test modules that imported `HttpClientTestingModule`,
as it removed the JS imports without migrating the module imports.

The migration now handles the case where `HttpClientTestingModule` is used in test modules,
by replacing the module import with the `provideHttpClient` and `provideHttpClientTesting` providers.

Before:
```ts
import { HttpClientTestingModule } from '@angular/common/http/testing';

@NgModule({
  declarations: [AppComponent],
  imports: [HttpClientTestingModule],
})
export class TestModule {}
```

After:
```ts
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';

@NgModule({
  declarations: [AppComponent],
  imports: [],
  providers: [provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()]
})
export class TestModule {}
```

PR Close #55803
2024-05-15 08:45:31 -07:00
Tom Wilkinson f1e3ec2601 refactor(core): Add an ActionResolver option to Dispatcher. (#55757)
This will enable internal usages to migrate from ActionResolver in
EventContrat to ActionResolver in Dispatcher.

PR Close #55757
2024-05-14 15:16:26 -07:00
Tom Wilkinson caedd10597 refactor(core): Move preventDefault to Dispatcher (#55756)
This is a simple move.

PR Close #55756
2024-05-14 14:34:59 -07:00
Joey Perrott 3fae2f1e42 ci: properly rely on adev for the adev-deploy job (#55797)
Properly rely on the adev job so that the job actually triggers

PR Close #55797
2024-05-14 12:52:26 -07:00
Sasidharan SD 56fb556f65 docs: fix production mode broken link (#55794)
PR Close #55794
2024-05-14 12:21:30 -07:00
Alex Rickabaugh f736bea8ee refactor(core): deprecate @Component.interpolation (#55778)
Angular has long had the ability to use different interpolation delimiters
(by default `{{` and `}}`). This concept was copied over from AngularJS,
where AngularJS syntax is included in HTML sent over the network to the
browser. Occasionally developers would use SSR frameworks which _also_ have
interpolation syntaxes of their own, so there was a need to change the
delimiters used by AngularJS to avoid conflicts.

Since Angular templates are always processed by our compiler and the
interpolation characters are never processed by other systems first, this
option is vestigial in Angular and only increases the complexity of our
parser.

DEPRECATED: `@Component.interpolation` is deprecated. Use Angular's
delimiters instead.

PR Close #55778
2024-05-14 11:48:12 -07:00
Angular Robot b6ca7fca96 build: update all non-major dependencies (#55785)
See associated pull request for more information.

PR Close #55785
2024-05-14 11:33:18 -07:00
Joey Perrott 1b8000dd63 ci: release angular.dev on each commit (#55792)
Release angular.dev on each commit to the appropriate version of the documentation site based on the current state of the repository.

PR Close #55792
2024-05-14 11:12:45 -07:00
cexbrayat ccde17db0c fix(migrations): preserve existing properties in HttpClientModule migration (#55777)
The `HttpClientModule` migration was dropping the existing properties other than imports and providers when updating an `@NgModule`, `@Component` or `configureTestingModule`.

PR Close #55777
2024-05-14 11:10:57 -07:00
Angular Robot af065cc005 build: update cross-repo angular dependencies (#55781)
See associated pull request for more information.

PR Close #55781
2024-05-14 10:54:17 -07:00
Andrew Kushnir 0eade1c4db docs: add a note about development status of zone.js (#55746)
PR Close #55746
2024-05-14 10:53:43 -07:00
Thomas Nguyen 3ad120dfe8 refactor(core): Simplify event handler extraction logic. (#55747)
This reuses information already recorded during hydration to
remove jsaction attributes to also stash event handlers. This avoids
a tree walk and looku.

PR Close #55747
2024-05-14 09:38:43 -07:00
Thomas Nguyen 629b255ddb refactor(core): Add four tests and fix code to make tests pass. (#55747)
The first test asserts that bubbling does not work right now.

The second asserts that stopPropagation works, which should pass when test #1 passes too.

The third test asserts properties about the events passed to the event handler.

THe fourth test asserts that mouse events do not translate to jsaction nor help emit the jsaction binary. This required a change in code to make this pass.

PR Close #55747
2024-05-14 09:38:43 -07:00
Alan Agius ef029b8d00 build: switch from rollup and terser to esbuild for creating contract bundle (#55705)
This commit implements the replacement of rollup and terser with esbuild for generating the contract_bundle binary. The transition is facilitated by optimizations aimed at reducing the bundle size.

PR Close #55705
2024-05-13 12:49:30 -07:00
Tom Wilkinson 0cb50317e1 refactor(core): Rename BaseDispatcher to Dispatcher. (#55721)
Rename `BaseDispatcher` to `Dispatcher` and `Dispatcher` to
`LegacyDispatcher`. The `GlobalHandler` type and `stopPropagation`
function needs to be left for now in dispatcher.ts as it was not
exported previously from legacy_dispatcher.ts.

PR Close #55721
2024-05-13 12:30:08 -07:00
Angular Robot 7187394ffe build: update io_bazel_rules_sass digest to fcce061 (#55755)
See associated pull request for more information.

PR Close #55755
2024-05-13 11:20:22 -07:00
Sasidharan SD 8dd5c735c6 docs: add inspecting injector section in devtools (#55764)
PR Close #55764
2024-05-13 11:17:50 -07:00
Matthieu Riegler c8472e5e9e refactor(forms): deprecate unwanted control events aliases (#55698)
This commit deprecates the aliases for the control events to ease the changes in G3
A follow-up commit will remove those deprecated entries.

PR Close #55698
2024-05-13 11:16:15 -07:00
Sasidharan SD b90c6aa2ea docs: add service worker images (#55780)
PR Close #55780
2024-05-13 11:14:50 -07:00
Angular Robot 7c9f4cbf47 build: update cross-repo angular dependencies (#55718)
See associated pull request for more information.

PR Close #55718
2024-05-13 11:12:54 -07:00
Kristiyan Kostadinov aa8df1d029 refactor(core): clean up clang comments and workarounds (#55750)
Since we aren't using clang anymore, we can remove the comments and the workarounds that were in place to prevent it from doing the wrong thing.

PR Close #55750
2024-05-13 11:10:36 -07:00
Kristiyan Kostadinov 533ec52aca refactor(compiler): move variable optimization earlier in pipeline (#55771)
Currently the variable optimization phase happens somewhat late in the process which is okay since the variables are generally static (e.g. `reference()` instruction calls). In some upcoming work we'll have variables that consume slots and require `advance` instructions. To allow for them to be optimized correctly, we need to move the variable optimization phase earlier, at least before we allocate the slots.

PR Close #55771
2024-05-13 11:09:26 -07:00
Sasidharan SD 801e5e1577 docs: fix devtools links (#55766)
PR Close #55766
2024-05-13 11:08:32 -07:00
Charles Lyding 2c0e60eceb docs: initial update of application builder migration instructions for v18 (#55699)
The application migration instructions and information page now contains
updated information related to the v18 release. This includes a reordering
of the migration section to mention the automatic migration first as well
as mention that `ng update` will now ask to perform the migration for v18.

PR Close #55699
2024-05-13 11:06:53 -07:00
Tom Wilkinson 76d0aea89b refactor(core): Remove custom event and replay behavior. (#55695)
These behaviors have been moved back to g3.

PR Close #55695
2024-05-13 09:36:03 -07:00
iteriani 3068de4369 refactor(core): Remove enums from event-dispatch. (#55421)
These cause optimization issues in external.

PR Close #55421
2024-05-13 09:12:44 -07:00
Andrew Kushnir 85ac2de744 ci: update payload size for the event-dispatch-contract script (#55748)
The payload size of the `event-dispatch-contract.min.js` script was reduced by more than 5%, which triggered CI checks. This commit updates a golden file to match the actual size.

PR Close #55748
2024-05-09 19:13:36 -07:00
iteriani 28fb385eec refactor(core): Use early event contract instead of the event contract in bootstrap. (#55587)
This also fixes an existing bug where we erase the jsaction attribute too early.

Now the event contract binary is 608 bytes :D.

PR Close #55587
2024-05-09 14:34:10 -07:00
Thomas Nguyen f5b6b7fa40 refactor(core): Export some more symbols and check for truthiness on event types before adding them. (#55587)
In some cases, we will be passing in undefined for capture events, so handle this.

PR Close #55587
2024-05-09 14:34:10 -07:00
Matthieu Riegler fedeaac8ba fix(forms): Add event for forms submitted & reset (#55667)
This commit adds 2 new events to the unified control event observable.

PR Close #55667
2024-05-09 09:21:14 -07:00
Ben Hong c1915f19c6 docs: fix visible code snippets in first-app tutorial (#55742)
PR Close #55742
2024-05-08 15:46:52 -07:00
Alan Agius c0012865eb refactor(core): a couple of minor changes to the early-event-contract (#55704)
This changes include
- Using multi line comments to write JSDoc comments which improves DX
- Use `this.container` instead of `window.document.documentElement`

PR Close #55704
2024-05-08 14:00:29 -07:00
Doug Parker fb54863773 release: bump Angular DevTools to version 1.0.16 (#55715)
PR Close #55715
2024-05-08 11:11:28 -07:00
Doug Parker eb1af1ed5c refactor(devtools): remove --config snapshot-build and leave a note for Firefox (#55717)
We removed display of the Git SHA in Angular DevTools in https://github.com/angular/angular/pull/55694, so there is no longer a need to stamp release builds in Chrome or Firefox.

I opted to leave a `--config snapshot-build-firefox` option as a no-op which a reader could follow to a comment explaining exactly _why_ we can't stamp Firefox releases. This should hopefully make it less likely that we forget and attempt to re-add this feature in the future only to encounter the same release problems.

PR Close #55717
2024-05-08 11:08:49 -07:00
Andrew Kushnir b9c88dc366 docs: release notes for the v18.0.0-rc.1 release 2024-05-08 09:06:38 -07:00
Andrew Kushnir 0b790891f4 docs: release notes for the v17.3.8 release 2024-05-08 08:49:45 -07:00
Matthieu Riegler 7287fefe7a docs: uwu (#55666)
PR Close #55666
2024-05-07 14:57:26 -07:00
Alan Agius 8305e50f8e build: trigger error when size-tracking is enabled but not in limit file (#55708)
Trigger an error when attempting to enable size-tracking for a project not listed in the integration-payload.json file.

Before this update, size-checks would succeed even if the project wasn't included in the file size limit.

PR Close #55708
2024-05-07 13:39:56 -07:00
Alan Agius 8630dc8149 test: add Integration tests for hydration and event reply (#55708)
This commit introduces integration tests for hydration and event reply functionalities. Additionally, it implements a payload size check for the `event-dispatch-contract.min.js`.

PR Close #55708
2024-05-07 13:39:55 -07:00
Andrew Scott ca6cdcd269 refactor(core): feature for potential zoneless-compatibility debug check (#55663)
This commit adds a feature that is useful for determining if an
application is zoneless-ready. The way this works is generally only
useful right now when zoneless is enabled. Some version of this may be useful in
the future as a general configuration option to change detection to make
`checkNoChanges` pass always exhaustive as an opt-in to address #45612.

Because this is an experimental, debug-only feature, it is okay to merge
during the RC period.

PR Close #55663
2024-05-07 13:39:13 -07:00
Andrew Scott abbaf8f639 refactor(core): Throw a runtime error if both zone and zoneless are provided (#55410)
This commit adds a dev-mode error if both the zone and zoneless
providers are used together.

PR Close #55410
2024-05-07 13:37:42 -07:00
Angular Robot 8cb838f9f6 build: update io_bazel_rules_sass digest to 9a4a4be (#55700)
See associated pull request for more information.

PR Close #55700
2024-05-07 13:36:31 -07:00
Tom Wilkinson 0fb455f72e refactor(core): Move global dispatch behavior into Dispatcher. (#55692)
This behavior is now implemented by calling `dispatch` whether or not
the `action` is populated. The `Dispatcher` then does global dispatch
and early returns if there's no action.

PR Close #55692
2024-05-07 12:00:40 -07:00
Thomas Nguyen 67bb310376 refactor(core): Fix timing of removal of jsaction attribute to be after event replay. (#55696)
This otherwise leads to bugs where, by the time replay needs the attribute, hydration
happens and it's gone.

PR Close #55696
2024-05-07 08:16:16 -07:00
arturovt a9460d08a0 fix(zone.js): remove abort listener on a signal when actual event is removed (#55339)
This commit updates the implementation of the `addEventListener` patcher.

We're currently creating an abort event listener on the signal (when it's provided)
and never remove it. The abort event listener creates a closure which captures `task`
(tasks capture zones and other stuff too) and prevent `task`, zones and signals from
being garbage collected.

We now store the function which removes the abort event listener when the actual event
listener is being removed. The function is stored on task data since task data is already
being used to store different types of information that's necessary to be shared between
`addEventListener` and `removeEventListener`.

Closes #54739

PR Close #55339
2024-05-07 08:07:33 -07:00
Paul Gschwendtner afc057ee92 docs: properly link to developer preview section (#55711)
Fixes an invalid link to the developer preview section.
PR Close #55711
2024-05-07 08:06:42 -07:00
Angular Robot 0fffe5389f build: update all non-major dependencies (#55531)
See associated pull request for more information.

PR Close #55531
2024-05-07 08:05:57 -07:00
210 changed files with 22164 additions and 2642 deletions
+1
View File
@@ -17,6 +17,7 @@ integration/cli-hello-world-ivy-i18n/node_modules
integration/cli-hello-world-lazy/node_modules
integration/cli-hello-world-mocha/node_modules
integration/cli-signal-inputs/node_modules
integration/platform-server-hydration/node_modules
integration/defer/node_modules
integration/dynamic-compiler/node_modules
integration/forms/node_modules
+7
View File
@@ -60,6 +60,13 @@ build:release --stamp
build:snapshot-build --workspace_status_command="yarn -s ng-dev release build-env-stamp --mode=snapshot"
build:snapshot-build --stamp
# Angular DevTools for Firefox releases *cannot* be stamped and `--config snapshot-build-firefox` is a no-op.
# This is because Mozilla requires add-on source code to be uploaded and then they manually reproduce the build.
# If we stamp the build based on Git information such as the current commit, then reproducing the build would require
# uploading the entire `.git` directory. We already must upload the entire monorepo, and uploading `.git` as well
# exceeds the max source file size. To address this, we just *don't* stamp Firefox builds of Angular DevTools.
build:snapshot-build-firefox --nostamp
##########################################################
# AIO architect build configuration #
# See aio/angular.json for available configurations. #
@@ -0,0 +1,18 @@
load("//tools:defaults.bzl", "esbuild_checked_in")
exports_files([
"tsconfig.json",
])
esbuild_checked_in(
name = "main",
entry_point = "//.github/actions/deploy-docs-site/lib:main.ts",
external = [
"undici",
],
platform = "node",
target = "node14",
deps = [
"//.github/actions/deploy-docs-site/lib",
],
)
@@ -0,0 +1,16 @@
name: 'Deploy angular.dev site'
description: 'Automatically deploy and set up redirects for angular.dev'
author: 'Angular'
inputs:
serviceKey:
description: 'The service key used for firebase deployments.'
required: true
configPath:
description: 'The path to the firebase config file.'
required: true
distDir:
description: 'The path to the firebase dist directory.'
required: true
runs:
using: 'node20'
main: 'main.js'
@@ -0,0 +1,23 @@
load("//tools:defaults.bzl", "ts_library")
package(default_visibility = ["//.github/actions/deploy-docs-site:__subpackages__"])
exports_files([
"main.ts",
])
ts_library(
name = "lib",
srcs = glob(
["*.ts"],
),
#tsconfig = "//.github/actions/deploy-docs-site:tsconfig.json",
deps = [
"@npm//@actions/core",
"@npm//@actions/github",
"@npm//@angular/ng-dev",
"@npm//@types/node",
"@npm//@types/tmp",
"@npm//tmp",
],
)
@@ -0,0 +1,15 @@
import {fileSync} from 'tmp';
import {writeSync} from 'fs';
import {getInput, setSecret} from '@actions/core';
let credentialFilePath: undefined | string;
export function getCredentialFilePath(): string {
if (credentialFilePath === undefined) {
const tmpFile = fileSync({postfix: '.json'});
writeSync(tmpFile.fd, getInput('serviceKey', {required: true}));
setSecret(tmpFile.name);
credentialFilePath = tmpFile.name;
}
return credentialFilePath;
}
@@ -0,0 +1,116 @@
import {cp, mkdtemp, readFile, rm, writeFile} from 'fs/promises';
import {Deployment} from './deployments';
import {join} from 'path';
import {tmpdir} from 'os';
import {spawnSync} from 'child_process';
import {getCredentialFilePath} from './credential';
export async function deployToFirebase(
deployment: Deployment,
configPath: string,
distDirPath: string,
) {
if (deployment.destination == undefined) {
console.log(`No deployment necessary for docs created from: ${deployment.branch}`);
return;
}
console.log('Preparing for deployment to firebase...');
const tmpDeployDir = await mkdtemp(join(tmpdir(), 'deploy-directory'));
const deployConfigPath = join(tmpDeployDir, 'firebase.json');
const config = JSON.parse(await readFile(configPath, {encoding: 'utf-8'})) as {
hosting: {public: string};
};
config['hosting']['public'] = './dist';
await writeFile(deployConfigPath, JSON.stringify(config, null, 2));
await cp(distDirPath, join(tmpDeployDir, 'dist'), {recursive: true});
spawnSync(`chmod 777 -R ${tmpDeployDir}`, {encoding: 'utf-8', shell: true});
firebase(
`target:clear --config ${deployConfigPath} --project angular-dev-site hosting angular-docs`,
tmpDeployDir,
);
firebase(
`target:apply --config ${deployConfigPath} --project angular-dev-site hosting angular-docs ${deployment.destination}`,
tmpDeployDir,
);
firebase(
`deploy --config ${deployConfigPath} --project angular-dev-site --only hosting --non-interactive`,
tmpDeployDir,
);
firebase(
`target:clear --config ${deployConfigPath} --project angular-dev-site hosting angular-docs`,
tmpDeployDir,
);
await rm(tmpDeployDir, {recursive: true});
}
export async function setupRedirect(deployment: Deployment) {
if (deployment.redirect === undefined) {
console.log(`No redirect necessary for docs created from: ${deployment.branch}`);
return;
}
console.log('Preparing to set up redirect on firebase...');
const redirectConfig = JSON.stringify(
{
hosting: {
target: 'angular-docs',
redirects: [
{
type: 302,
regex: '^(.*)$',
destination: `${deployment.redirect.to}:1`,
},
],
},
},
null,
2,
);
const tmpRedirectDir = await mkdtemp(join(tmpdir(), 'redirect-directory'));
const redirectConfigPath = join(tmpRedirectDir, 'firebase.json');
await writeFile(redirectConfigPath, redirectConfig);
spawnSync(`chmod 777 -R ${tmpRedirectDir}`, {encoding: 'utf-8', shell: true});
firebase(
`target:clear --config ${redirectConfigPath} --project angular-dev-site hosting angular-docs`,
tmpRedirectDir,
);
firebase(
`target:apply --config ${redirectConfigPath} --project angular-dev-site hosting angular-docs ${deployment.redirect.from}`,
tmpRedirectDir,
);
firebase(
`deploy --config ${redirectConfigPath} --project angular-dev-site --only hosting --non-interactive`,
tmpRedirectDir,
);
firebase(
`target:clear --config ${redirectConfigPath} --project angular-dev-site hosting angular-docs`,
tmpRedirectDir,
);
await rm(tmpRedirectDir, {recursive: true});
}
function firebase(cmd: string, cwd?: string) {
spawnSync('npx', `-y firebase-tools@latest ${cmd}`.split(' '), {
cwd,
encoding: 'utf-8',
shell: true,
stdio: 'inherit',
env: {
...process.env,
GOOGLE_APPLICATION_CREDENTIALS: getCredentialFilePath(),
},
});
}
@@ -0,0 +1,67 @@
import {fetchLongTermSupportBranchesFromNpm, ActiveReleaseTrains} from '@angular/ng-dev';
import {ReleaseConfig} from '@angular/ng-dev';
import {GitClient} from '@angular/ng-dev';
export interface Deployment {
branch: string;
redirect?: {
from: string;
to: string;
};
destination?: string;
}
export type Deployments = Map<string, Deployment>;
export async function getDeployments(): Promise<Deployments> {
const {github} = await GitClient.get();
const releaseTrains = await ActiveReleaseTrains.fetch({
api: github,
name: 'angular',
owner: 'angular',
nextBranchName: 'main',
});
const ltsBranches = await fetchLongTermSupportBranchesFromNpm({
representativeNpmPackage: '@angular/core',
} as ReleaseConfig);
const docSites = new Map<string, Deployment>();
[...ltsBranches.active, ...ltsBranches.inactive].forEach((branch) => {
docSites.set(branch.name, {
branch: branch.name,
destination: `v${branch.version.major}-angular-dev`,
});
});
docSites.set(releaseTrains.latest.branchName, {
branch: releaseTrains.latest.branchName,
redirect: {
from: `v${releaseTrains.latest.version.major}-angular-dev`,
to: 'https://angular.dev',
},
destination: 'angular-dev-site',
});
if (releaseTrains.releaseCandidate) {
docSites.set(releaseTrains.next.branchName, {
branch: releaseTrains.next.branchName,
});
docSites.set(releaseTrains.releaseCandidate.branchName, {
branch: releaseTrains.releaseCandidate.branchName,
destination: 'next-angular-dev',
});
} else {
docSites.set(releaseTrains.next.branchName, {
branch: releaseTrains.next.branchName,
destination: 'next-angular-dev',
redirect: {
from: `v${releaseTrains.next.version.major}-angular-dev`,
to: 'https://next.angular.dev',
},
});
}
return docSites;
}
@@ -0,0 +1,71 @@
import {getInput, setFailed} from '@actions/core';
import {context} from '@actions/github';
import {deployToFirebase, setupRedirect} from './deploy';
import {getDeployments} from './deployments';
import {GithubConfig, setConfig} from '@angular/ng-dev';
const refMatcher = /refs\/heads\/(.*)/;
async function deployDocs() {
setConfig({
github: <GithubConfig>{
mainBranchName: 'main',
name: 'angular',
owner: 'angular',
},
});
if (context.eventName !== 'push') {
throw Error();
}
const matchedRef = context.ref.match(refMatcher);
if (matchedRef === null) {
throw Error();
}
const currentBranch = matchedRef[1];
const configPath = getInput('configPath');
const distDir = getInput('distDir');
const deployment = (await getDeployments()).get(currentBranch);
if (deployment === undefined) {
console.log(`Current branch (${currentBranch}) does not deploy a documentation site.`);
console.log(`Exiting...`);
process.exit(0);
}
console.log('Doc site deployment information');
console.log('');
console.log('Current Branch:');
console.log(` ${deployment.branch}`);
console.log('');
console.log('Firebase Site:');
if (deployment.destination === undefined) {
console.log(' No deployment of a documenation site is necessary');
} else {
console.log(` Deploying to: ${deployment.destination}`);
}
console.log('');
console.log('Redirect Configuration:');
if (deployment.redirect === undefined) {
console.log(' No redirects are necessary');
} else {
console.log(` From: ${deployment.redirect.from}`);
console.log(` To: ${deployment.redirect.to}`);
}
await deployToFirebase(deployment, configPath, distDir);
await setupRedirect(deployment);
}
// Only run if the action is executed in a repository with is in the Angular org. This is in place
// to prevent the action from actually running in a fork of a repository with this action set up.
if (context.repo.owner === 'angular') {
deployDocs().catch((e: Error) => {
setFailed(e.message);
console.error(e);
});
} else {
console.warn(
'The action was skipped as this action is only meant to run in repos belonging to the Angular organization.',
);
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,3 @@
{
"type": "module"
}
@@ -0,0 +1,19 @@
{
"compilerOptions": {
"module": "Node16",
"target": "es2020",
"lib": ["es2021", "dom"],
"experimentalDecorators": true,
"strict": true,
"outDir": "../../../dist/tsc-non-bazel-out",
"skipLibCheck": true,
"noImplicitOverride": true,
// TODO(ESM): Remove this when Bazel also uses the Node resolution.
"esModuleInterop": true,
"noImplicitReturns": true,
"jsx": "react",
"jsxFactory": "h",
"jsxFragmentFactory": "Fragment"
},
"exclude": []
}
+4 -4
View File
@@ -21,16 +21,16 @@ jobs:
(github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'adev: preview'))
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8b117748ae8243f98d261a9731908867b8e3d876
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/bazel/setup@8b117748ae8243f98d261a9731908867b8e3d876
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/bazel/configure-remote@8b117748ae8243f98d261a9731908867b8e3d876
- name: Install node modules
run: yarn install --frozen-lockfile
- name: Build adev to ensure it continues to work
run: yarn bazel build //adev:build
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@8b117748ae8243f98d261a9731908867b8e3d876
with:
workflow-artifact-name: 'adev-preview'
pull-number: '${{github.event.pull_request.number}}'
+1 -1
View File
@@ -40,7 +40,7 @@ jobs:
npx -y firebase-tools@latest target:clear --config adev/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting angular-docs
npx -y firebase-tools@latest target:apply --config adev/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting angular-docs ${{env.PREVIEW_SITE}}
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@8b117748ae8243f98d261a9731908867b8e3d876
with:
github-token: '${{secrets.GITHUB_TOKEN}}'
workflow-artifact-name: 'adev-preview'
@@ -13,9 +13,9 @@ jobs:
assistant_to_the_branch_manager:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
persist-credentials: false
- uses: angular/dev-infra/github-actions/branch-manager@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
- uses: angular/dev-infra/github-actions/branch-manager@8b117748ae8243f98d261a9731908867b8e3d876
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
+2 -2
View File
@@ -28,7 +28,7 @@ jobs:
- uses: alessbell/pull-request-comment-branch@aad01d65d6982b8eacabed5e9a684cd8ceb98da6 # v1.1
id: comment-branch
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
# Specify repository as the PR branch might be from a fork.
repository: ${{steps.comment-branch.outputs.head_owner}}/${{steps.comment-branch.outputs.head_repo}}
@@ -38,7 +38,7 @@ jobs:
- uses: ./.github/actions/yarn-install
- uses: angular/dev-infra/github-actions/bazel/configure-remote@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
- uses: angular/dev-infra/github-actions/bazel/configure-remote@8b117748ae8243f98d261a9731908867b8e3d876
with:
bazelrc: ./.bazelrc.user
+31 -42
View File
@@ -5,7 +5,6 @@ on:
branches:
- main
- '[0-9]+.[0-9]+.x'
- 'remove-aio-stuff'
pull_request:
types: [opened, synchronize, reopened]
@@ -24,7 +23,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8b117748ae8243f98d261a9731908867b8e3d876
with:
cache-node-modules: true
node-module-directories: |
@@ -59,13 +58,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8b117748ae8243f98d261a9731908867b8e3d876
with:
cache-node-modules: true
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/bazel/setup@8b117748ae8243f98d261a9731908867b8e3d876
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/bazel/configure-remote@8b117748ae8243f98d261a9731908867b8e3d876
- name: Install node modules
run: yarn install --frozen-lockfile
- name: Run unit tests
@@ -77,13 +76,13 @@ jobs:
runs-on: ubuntu-latest-4core
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8b117748ae8243f98d261a9731908867b8e3d876
with:
cache-node-modules: true
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/bazel/setup@8b117748ae8243f98d261a9731908867b8e3d876
- name: Setup Bazel Remote Caching
uses: angular/dev-infra/github-actions/bazel/configure-remote@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/bazel/configure-remote@8b117748ae8243f98d261a9731908867b8e3d876
- name: Install node modules
run: yarn install --frozen-lockfile --network-timeout 100000
- name: Run CI tests for framework
@@ -94,11 +93,11 @@ jobs:
labels: ubuntu-latest-4core
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8b117748ae8243f98d261a9731908867b8e3d876
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/bazel/setup@8b117748ae8243f98d261a9731908867b8e3d876
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/bazel/configure-remote@8b117748ae8243f98d261a9731908867b8e3d876
- name: Install node modules
run: yarn install --frozen-lockfile
- name: Build adev in fast mode to ensure it continues to work
@@ -112,13 +111,13 @@ jobs:
labels: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8b117748ae8243f98d261a9731908867b8e3d876
with:
cache-node-modules: true
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/bazel/setup@8b117748ae8243f98d261a9731908867b8e3d876
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/bazel/configure-remote@8b117748ae8243f98d261a9731908867b8e3d876
- name: Install node modules
run: yarn install --frozen-lockfile
- run: echo "https://${{secrets.SNAPSHOT_BUILDS_GITHUB_TOKEN}}:@github.com" > ${HOME}/.git_credentials
@@ -130,7 +129,7 @@ jobs:
labels: ubuntu-latest-4core
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8b117748ae8243f98d261a9731908867b8e3d876
with:
cache-node-modules: true
node-module-directories: |
@@ -138,9 +137,9 @@ jobs:
./packages/zone.js/node_modules
./packages/zone.js/test/typings/node_modules
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/bazel/setup@8b117748ae8243f98d261a9731908867b8e3d876
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/bazel/configure-remote@8b117748ae8243f98d261a9731908867b8e3d876
- name: Install node modules
run: yarn install --frozen-lockfile
- run: |
@@ -179,7 +178,7 @@ jobs:
JOBS: 2
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8b117748ae8243f98d261a9731908867b8e3d876
with:
cache-node-modules: true
# Checking out the pull request commit is intended here as we need to run the changed code tests.
@@ -187,11 +186,11 @@ jobs:
- name: Install node modules
run: yarn install --frozen-lockfile
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/bazel/setup@8b117748ae8243f98d261a9731908867b8e3d876
- name: Setup Bazel Remote Caching
uses: angular/dev-infra/github-actions/bazel/configure-remote@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/bazel/configure-remote@8b117748ae8243f98d261a9731908867b8e3d876
- name: Setup Saucelabs Variables
uses: angular/dev-infra/github-actions/saucelabs@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/saucelabs@8b117748ae8243f98d261a9731908867b8e3d876
- name: Set up Sauce Tunnel Daemon
run: yarn bazel run //tools/saucelabs-daemon/background-service -- $JOBS &
env:
@@ -207,15 +206,15 @@ jobs:
SAUCE_TUNNEL_IDENTIFIER: angular-framework-${{ github.run_number }}
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8b117748ae8243f98d261a9731908867b8e3d876
with:
cache-node-modules: true
- name: Install node modules
run: yarn install --frozen-lockfile
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/bazel/setup@8b117748ae8243f98d261a9731908867b8e3d876
- name: Setup Saucelabs Variables
uses: angular/dev-infra/github-actions/saucelabs@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/saucelabs@8b117748ae8243f98d261a9731908867b8e3d876
- name: Starting Saucelabs tunnel service
run: ./tools/saucelabs/sauce-service.sh run &
# Build test fixtures for a test that rely on Bazel-generated fixtures. Note that disabling
@@ -249,32 +248,22 @@ jobs:
adev-deploy:
needs: [adev]
if: needs.adev.result == 'success' && github.event_name == 'push' && github.ref_name == 'main'
env:
DEPLOY_PROJECT: angular-dev-site
DEPLOY_SITE: angular-dev-site
if: needs.adev.result == 'success' && github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8b117748ae8243f98d261a9731908867b8e3d876
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/bazel/setup@8b117748ae8243f98d261a9731908867b8e3d876
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/bazel/configure-remote@8b117748ae8243f98d261a9731908867b8e3d876
- name: Install node modules
run: yarn install --frozen-lockfile
- name: Build adev to ensure it continues to work
run: yarn bazel build //adev:build
- name: Move generated project files into deployment directory
run: cp -r dist/bin/adev/build adev/build
- name: Setup firebase context
run: |
npx -y firebase-tools@latest target:clear --config adev/firebase.json --project ${{ env.DEPLOY_PROJECT }} hosting angular-docs
npx -y firebase-tools@latest target:apply --config adev/firebase.json --project ${{ env.DEPLOY_PROJECT }} hosting angular-docs ${{ env.DEPLOY_SITE }}
- name: Deploy to firebase
uses: FirebaseExtended/action-hosting-deploy@120e124148ab7016bec2374e5050f15051255ba2 # v0.7.1
uses: ./.github/actions/deploy-docs-site
with:
entryPoint: './adev'
firebaseServiceAccount: ${{ secrets.ANGULAR_DEV_SITE_DEPLOY }}
projectId: ${{ env.DEPLOY_PROJECT }}
channelId: live
serviceKey: ${{ secrets.ANGULAR_DEV_SITE_DEPLOY }}
configPath: 'adev/firebase.json'
distDir: 'dist/bin/adev/build/browser'
+4 -4
View File
@@ -12,14 +12,14 @@ jobs:
labels:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
- uses: angular/dev-infra/github-actions/commit-message-based-labels@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- uses: angular/dev-infra/github-actions/commit-message-based-labels@8b117748ae8243f98d261a9731908867b8e3d876
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
post_approval_changes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
- uses: angular/dev-infra/github-actions/post-approval-changes@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- uses: angular/dev-infra/github-actions/post-approval-changes@8b117748ae8243f98d261a9731908867b8e3d876
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
+2 -2
View File
@@ -13,8 +13,8 @@ jobs:
statuses: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
- uses: angular/dev-infra/github-actions/google-internal-tests@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- uses: angular/dev-infra/github-actions/google-internal-tests@8b117748ae8243f98d261a9731908867b8e3d876
with:
run-tests-guide-url: http://go/angular-g3sync-start
github-token: ${{ secrets.GITHUB_TOKEN }}
+1 -1
View File
@@ -9,6 +9,6 @@ jobs:
status:
runs-on: ubuntu-latest
steps:
- uses: angular/dev-infra/github-actions/unified-status-check@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
- uses: angular/dev-infra/github-actions/unified-status-check@8b117748ae8243f98d261a9731908867b8e3d876
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
+4 -4
View File
@@ -22,15 +22,15 @@ jobs:
version: ['https://next.angular.io/', 'https://angular.io/']
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8b117748ae8243f98d261a9731908867b8e3d876
with:
cache-node-modules: true
node-module-directories: |
./aio/node_modules
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/bazel/setup@8b117748ae8243f98d261a9731908867b8e3d876
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/bazel/configure-remote@8b117748ae8243f98d261a9731908867b8e3d876
- name: Install node modules in aio
run: yarn install --frozen-lockfile --cwd aio
- name: Run basic e2e and deployment config tests.
@@ -44,7 +44,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8b117748ae8243f98d261a9731908867b8e3d876
with:
cache-node-modules: true
node-module-directories: |
+3 -3
View File
@@ -25,12 +25,12 @@ jobs:
steps:
- name: 'Checkout code'
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
persist-credentials: false
- name: 'Run analysis'
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
with:
results_file: results.sarif
results_format: sarif
@@ -47,6 +47,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: 'Upload to code-scanning'
uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3
uses: github/codeql-action/upload-sarif@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # v3.25.5
with:
sarif_file: results.sarif
+2 -2
View File
@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
# Setting `persist-credentials: false` prevents the github-action account from being the
# account that is attempted to be used for authentication, instead the remote is set to
@@ -32,7 +32,7 @@ jobs:
env:
ANGULAR_CLI_BUILDS_READONLY_GITHUB_TOKEN: ${{ secrets.ANGULAR_CLI_BUILDS_READONLY_GITHUB_TOKEN }}
- name: Create a PR (if necessary)
uses: angular/dev-infra/github-actions/create-pr-for-changes@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
uses: angular/dev-infra/github-actions/create-pr-for-changes@8b117748ae8243f98d261a9731908867b8e3d876
with:
branch-prefix: update-cli-help
pr-title: 'docs: update Angular CLI help [${{github.ref_name}}]'
+3
View File
@@ -24,6 +24,9 @@ export const format: FormatConfig = {
'!packages/compiler-cli/test/compliance/test_cases/**/*.{js,ts}',
// Ignore AIO as its pending removal.
'!aio/**/*.{js,ts}',
// Ignore generated javascript file(s)
'!.github/actions/deploy-docs-site/main.js',
],
},
'buildifier': true,
+73
View File
@@ -1,3 +1,76 @@
<a name="18.0.0-rc.2"></a>
# 18.0.0-rc.2 (2024-05-15)
## Deprecations
### core
- `@Component.interpolation` is deprecated. Use Angular's
delimiters instead.
### core
| Commit | Type | Description |
| -- | -- | -- |
| [1fd63e9cff](https://github.com/angular/angular/commit/1fd63e9cff9159a8c10c35a0af43bc986e4e8e26) | refactor | deprecate `@Component.interpolation` ([#55778](https://github.com/angular/angular/pull/55778)) |
### forms
| Commit | Type | Description |
| -- | -- | -- |
| [61007dced0](https://github.com/angular/angular/commit/61007dced0f3396c40efcd2617c130633fb9837a) | fix | Add event for forms submitted & reset ([#55667](https://github.com/angular/angular/pull/55667)) |
| [2e27ca9ddf](https://github.com/angular/angular/commit/2e27ca9ddfc1f3f0387cd720071e85ff46f19db6) | fix | Allow canceled async validators to emit. ([#55134](https://github.com/angular/angular/pull/55134)) |
### migrations
| Commit | Type | Description |
| -- | -- | -- |
| [c4b2f18709](https://github.com/angular/angular/commit/c4b2f18709076f8c400bd26226be37ae07e5e83d) | fix | migrate HttpClientTestingModule in test modules ([#55803](https://github.com/angular/angular/pull/55803)) |
| [bb4a4016a9](https://github.com/angular/angular/commit/bb4a4016a9a29a9c56342ee01d866b0c8a3fb419) | fix | preserve existing properties in HttpClientModule migration ([#55777](https://github.com/angular/angular/pull/55777)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="17.3.9"></a>
# 17.3.9 (2024-05-15)
<!-- CHANGELOG SPLIT MARKER -->
<a name="18.0.0-rc.1"></a>
# 18.0.0-rc.1 (2024-05-08)
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [91b007e58f](https://github.com/angular/angular/commit/91b007e58ffb91f7c396cbc0333a91d18f02bd27) | fix | add math elements to schema ([#55631](https://github.com/angular/angular/pull/55631)) |
| [a040fb720a](https://github.com/angular/angular/commit/a040fb720af7db08b328a9f78511c9881f50482d) | fix | maintain multiline CSS selectors during CSS scoping ([#55509](https://github.com/angular/angular/pull/55509)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [d5edfde6ee](https://github.com/angular/angular/commit/d5edfde6ee3d65bf7f938ecfeac9f30633f8731b) | fix | afterRender hooks registered outside change detection can mark views dirty ([#55623](https://github.com/angular/angular/pull/55623)) |
| [36130b2e72](https://github.com/angular/angular/commit/36130b2e720b509e064368382eb0f7c2686154fb) | fix | don't schedule timer triggers on the server ([#55605](https://github.com/angular/angular/pull/55605)) |
| [0510930a25](https://github.com/angular/angular/commit/0510930a257e610460c875dbbc5566fd06547814) | fix | TestBed should not override NgZone from initTestEnvironment ([#55226](https://github.com/angular/angular/pull/55226)) |
### http
| Commit | Type | Description |
| -- | -- | -- |
| [d9b339fdbc](https://github.com/angular/angular/commit/d9b339fdbc0f8d1e9bb7b1e4190e7d80e68542f9) | fix | resolve `withRequestsMadeViaParent` behavior with `withFetch` ([#55652](https://github.com/angular/angular/pull/55652)) |
### migrations
| Commit | Type | Description |
| -- | -- | -- |
| [8459ee46cb](https://github.com/angular/angular/commit/8459ee46cba7f63966c41a2fb7199ec295a91cbb) | fix | handle more cases in HttpClientModule migration ([#55640](https://github.com/angular/angular/pull/55640)) |
### platform-browser
| Commit | Type | Description |
| -- | -- | -- |
| [23f914f101](https://github.com/angular/angular/commit/23f914f1012545330f6a5aeed4e862bf0e66117b) | fix | Use the right namespace for mathML. ([#55622](https://github.com/angular/angular/pull/55622)) |
### platform-server
| Commit | Type | Description |
| -- | -- | -- |
| [e71e869112](https://github.com/angular/angular/commit/e71e869112af1c0ee7a9dd64a963ad7af14a40e2) | fix | remove event dispatch script from HTML when hydration is disabled ([#55681](https://github.com/angular/angular/pull/55681)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="17.3.8"></a>
# 17.3.8 (2024-05-08)
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [c21b459ba6](https://github.com/angular/angular/commit/c21b459ba6520fd5835e23800338ac9c997fee91) | fix | add math elements to schema ([#55631](https://github.com/angular/angular/pull/55631)) ([#55645](https://github.com/angular/angular/pull/55645)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [3818436ebc](https://github.com/angular/angular/commit/3818436ebc649267bb39b976b6b567b7f2b06a64) | fix | don't schedule timer triggers on the server ([#55605](https://github.com/angular/angular/pull/55605)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="18.0.0-rc.0"></a>
# 18.0.0-rc.0 (2024-05-01)
### core
+3 -3
View File
@@ -167,10 +167,10 @@ cldr_xml_data_repository(
# sass rules
http_archive(
name = "io_bazel_rules_sass",
sha256 = "845061fad5cb42a353ac394fe6450ec9f21d337acf5b98011ef29ddcb33e3671",
strip_prefix = "rules_sass-9f8be59f5175d0dd3438d7da994b2782299e0c2c",
sha256 = "e50e1ca1b0a737d2c09efbbb886e0194d99caed617337a766b17c1ee4bae93f2",
strip_prefix = "rules_sass-fcce06104e072bbebbf92c1a244ea9f8c2fc8402",
urls = [
"https://github.com/bazelbuild/rules_sass/archive/9f8be59f5175d0dd3438d7da994b2782299e0c2c.zip",
"https://github.com/bazelbuild/rules_sass/archive/fcce06104e072bbebbf92c1a244ea9f8c2fc8402.zip",
],
)
+4 -4
View File
@@ -1,11 +1,11 @@
@defer (when isBrowser) {
<adev-progress-bar />
<adev-progress-bar />
}
<button (click)="focusFirstHeading()" class="adev-skip">Skip to main content</button>
<div class="adev-nav"></div>
@if (displaySecondaryNav()) {
<adev-secondary-navigation />
<adev-secondary-navigation />
}
<div class="docs-app-main-content">
<!--
@@ -22,9 +22,9 @@
}
}
}
<router-outlet />
<router-outlet />
@if (displayFooter()) {
<footer adev-footer></footer>
<footer adev-footer></footer>
}
</div>
@@ -82,7 +82,8 @@
>
<a aria-label="Angular homepage" routerLink="/">
<!-- Logo Symbol -->
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 223 236" width="32">
@if(!isUwu) {
<svg class="angular-logo" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 223 236" width="32">
<g clip-path="url(#a)">
<path
fill="url(#b)"
@@ -125,6 +126,14 @@
</clipPath>
</defs>
</svg>
} @else {
<img
src="assets/images/uwu.png"
style="width: auto; margin: 0"
class="uwu-logo"
alt="Angular logo"
height="34"/>
}
</a>
<!-- Version picker for v18+ -->
@@ -251,6 +251,10 @@
}
}
.adev-nav-item--logo a {
height: 34px;
}
.adev-close-nav {
display: none;
@include mq.for-phone-only {
@@ -27,7 +27,7 @@ import {
isApple,
IS_SEARCH_DIALOG_OPEN,
} from '@angular/docs';
import {NavigationEnd, Router, RouterLink} from '@angular/router';
import {ActivatedRoute, NavigationEnd, Router, RouterLink} from '@angular/router';
import {filter, map, startWith} from 'rxjs/operators';
import {DOCS_ROUTES, REFERENCE_ROUTES, TUTORIALS_ROUTES} from '../../../routes';
import {GITHUB, MEDIUM, X, YOUTUBE} from '../../constants/links';
@@ -83,6 +83,9 @@ export class Navigation implements OnInit {
readonly PRIMARY_NAV_ID = PRIMARY_NAV_ID;
readonly SECONDARY_NAV_ID = SECONDARY_NAV_ID;
// We can't use the ActivatedRouter queryParams as we're outside the router outlet
readonly isUwu = 'location' in globalThis ? location.search.includes('uwu') : false;
miniMenuPositions = [
new ConnectionPositionPair(
{originX: 'end', originY: 'center'},
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {Component, Inject} from '@angular/core';
import {ChangeDetectionStrategy, Component, Inject} from '@angular/core';
import {MAT_SNACK_BAR_DATA, MatSnackBarAction, MatSnackBarRef} from '@angular/material/snack-bar';
export interface ErrorSnackBarData {
@@ -16,6 +16,7 @@ export interface ErrorSnackBarData {
@Component({
selector: 'error-snack-bar',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
{{ message }}
<button
@@ -28,8 +29,8 @@ export interface ErrorSnackBarData {
{{ actionText }}
</button>
`,
imports: [MatSnackBarAction],
standalone: true,
imports: [MatSnackBarAction],
styles: `:host { display: flex; align-items: center; button { margin-left: 16px }}`,
})
export class ErrorSnackBar {
@@ -8,6 +8,7 @@ $width-breakpoint: 950px;
container-name: embedded-editor;
height: 100%;
position: relative;
border: 1px solid var(--senary-contrast);
}
// The entire thing - editor, terminal, console
+2 -1
View File
@@ -8,13 +8,14 @@
import {CommonModule} from '@angular/common';
import {DocContent, DocViewer} from '@angular/docs';
import {Component, inject} from '@angular/core';
import {ChangeDetectionStrategy, Component, inject} from '@angular/core';
import {toSignal} from '@angular/core/rxjs-interop';
import {ActivatedRoute} from '@angular/router';
import {map} from 'rxjs/operators';
@Component({
selector: 'docs-docs',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [CommonModule, DocViewer],
styleUrls: ['./docs.component.scss'],
+55 -45
View File
@@ -11,51 +11,61 @@
<div class="adev-canvas"></div>
<div class="adev-logo">
<div class="adev-logo-wordmark">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 982 241"
style="width: max(calc(700 * min(100vw, 2560px) / 1470), 350px); height: auto;"
>
<g clip-path="url(#wordmark_a)">
<path
fill="url(#wordmark_b)"
d="M388.676 191.625h30.849L363.31 31.828h-35.758l-56.215 159.797h30.848l13.174-39.356h60.061l13.256 39.356Zm-65.461-62.675 21.602-64.311h1.227l21.603 64.311h-44.432Zm126.831-7.527v70.202h-28.23V71.839h27.002v20.374h1.392c2.782-6.71 7.2-12.028 13.255-15.956 6.056-3.927 13.584-5.89 22.503-5.89 8.264 0 15.465 1.8 21.684 5.318 6.137 3.518 10.964 8.673 14.319 15.382 3.437 6.71 5.074 14.81 4.992 24.383v76.175h-28.23v-71.92c0-8.019-2.046-14.237-6.219-18.819-4.173-4.5-9.819-6.791-17.102-6.791-4.91 0-9.328 1.063-13.174 3.272-3.846 2.128-6.792 5.237-9.001 9.328-2.046 4.009-3.191 8.918-3.191 14.728ZM589.233 239c-10.147 0-18.82-1.391-26.103-4.091-7.282-2.7-13.092-6.382-17.511-10.964-4.418-4.582-7.528-9.655-9.164-15.219l25.448-6.136c1.145 2.372 2.782 4.663 4.991 6.954 2.209 2.291 5.155 4.255 8.837 5.81 3.683 1.554 8.428 2.291 14.074 2.291 8.019 0 14.647-1.964 19.884-5.81 5.237-3.845 7.856-10.227 7.856-19.064v-22.665h-1.391c-1.473 2.946-3.601 5.892-6.383 9.001-2.782 3.109-6.464 5.645-10.965 7.691-4.582 2.046-10.228 3.109-17.101 3.109-9.165 0-17.511-2.209-25.039-6.545-7.446-4.337-13.42-10.883-17.757-19.474-4.418-8.673-6.628-19.473-6.628-32.565 0-13.091 2.21-24.301 6.628-33.383 4.419-9.082 10.311-15.955 17.839-20.7 7.528-4.746 15.874-7.037 25.038-7.037 7.038 0 12.847 1.145 17.348 3.518 4.582 2.373 8.182 5.236 10.883 8.51 2.7 3.272 4.746 6.382 6.137 9.327h1.554v-19.8h27.821v121.749c0 10.228-2.454 18.737-7.364 25.447-4.91 6.709-11.538 11.7-20.048 15.055-8.509 3.355-18.165 4.991-28.884 4.991Zm.245-71.266c5.974 0 11.047-1.473 15.302-4.337 4.173-2.945 7.446-7.118 9.573-12.519 2.21-5.482 3.274-12.027 3.274-19.637 0-7.609-1.064-14.155-3.274-19.8-2.127-5.646-5.318-10.064-9.491-13.255-4.174-3.11-9.329-4.746-15.384-4.746s-11.537 1.636-15.792 4.91c-4.173 3.272-7.365 7.772-9.492 13.418-2.128 5.727-3.191 12.191-3.191 19.392 0 7.2 1.063 13.746 3.273 19.228 2.127 5.482 5.318 9.736 9.573 12.764 4.174 3.027 9.41 4.582 15.629 4.582Zm141.56-26.51V71.839h28.23v119.786h-27.412v-21.273h-1.227c-2.7 6.709-7.119 12.191-13.338 16.446-6.137 4.255-13.747 6.382-22.748 6.382-7.855 0-14.81-1.718-20.783-5.237-5.974-3.518-10.72-8.591-14.075-15.382-3.355-6.709-5.073-14.891-5.073-24.464V71.839h28.312v71.921c0 7.609 2.046 13.664 6.219 18.083 4.173 4.5 9.655 6.709 16.365 6.709 4.173 0 8.183-.982 12.111-3.028 3.927-2.045 7.118-5.072 9.655-9.082 2.537-4.091 3.764-9.164 3.764-15.218Zm65.707-109.395v159.796h-28.23V31.828h28.23Zm44.841 162.169c-7.61 0-14.402-1.391-20.457-4.091-6.055-2.7-10.883-6.791-14.32-12.109-3.518-5.319-5.237-11.946-5.237-19.801 0-6.791 1.228-12.355 3.765-16.773 2.536-4.419 5.891-7.937 10.228-10.637 4.337-2.619 9.164-4.664 14.647-6.055 5.4-1.391 11.046-2.373 16.856-3.027 7.037-.737 12.683-1.391 17.102-1.964 4.337-.573 7.528-1.555 9.574-2.782 1.963-1.309 3.027-3.273 3.027-5.973v-.491c0-5.891-1.718-10.391-5.237-13.664-3.518-3.191-8.51-4.828-15.056-4.828-6.955 0-12.356 1.473-16.447 4.5-4.01 3.028-6.71 6.546-8.183 10.719l-26.348-3.764c2.046-7.282 5.483-13.336 10.31-18.328 4.746-4.909 10.638-8.59 17.511-11.045 6.955-2.455 14.565-3.682 22.912-3.682 5.809 0 11.537.654 17.265 2.045s10.965 3.6 15.711 6.71c4.746 3.109 8.51 7.282 11.455 12.6 2.864 5.318 4.337 11.946 4.337 19.883v80.184h-27.166v-16.446h-.9c-1.719 3.355-4.091 6.464-7.201 9.328-3.109 2.864-6.955 5.237-11.619 6.955-4.828 1.718-10.229 2.536-16.529 2.536Zm7.364-20.701c5.646 0 10.556-1.145 14.729-3.354 4.173-2.291 7.364-5.237 9.655-9.001 2.292-3.763 3.355-7.854 3.355-12.273v-14.155c-.9.737-2.373 1.391-4.5 2.046-2.128.654-4.419 1.145-7.037 1.636-2.619.491-5.155.9-7.692 1.227-2.537.328-4.746.655-6.628.901-4.173.572-8.019 1.472-11.292 2.781-3.355 1.31-5.973 3.11-7.855 5.401-1.964 2.291-2.864 5.318-2.864 8.918 0 5.237 1.882 9.164 5.728 11.782 3.682 2.782 8.51 4.091 14.401 4.091Zm64.643 18.328V71.839h27.412v19.965h1.227c2.21-6.955 5.974-12.274 11.292-16.038 5.319-3.763 11.456-5.645 18.329-5.645 1.555 0 3.355.082 5.237.163 1.964.164 3.601.328 4.91.573v25.938c-1.227-.41-3.109-.819-5.646-1.146a58.815 58.815 0 0 0-7.446-.49c-5.155 0-9.738 1.145-13.829 3.354-4.091 2.209-7.282 5.236-9.655 9.164-2.373 3.927-3.519 8.427-3.519 13.5v70.448h-28.312ZM222.077 39.192l-8.019 125.923L137.387 0l84.69 39.192Zm-53.105 162.825-57.933 33.056-57.934-33.056 11.783-28.556h92.301l11.783 28.556ZM111.039 62.675l30.357 73.803H80.681l30.358-73.803ZM7.937 165.115 0 39.192 84.69 0 7.937 165.115Z"
/>
<path
fill="url(#wordmark_c)"
d="M388.676 191.625h30.849L363.31 31.828h-35.758l-56.215 159.797h30.848l13.174-39.356h60.061l13.256 39.356Zm-65.461-62.675 21.602-64.311h1.227l21.603 64.311h-44.432Zm126.831-7.527v70.202h-28.23V71.839h27.002v20.374h1.392c2.782-6.71 7.2-12.028 13.255-15.956 6.056-3.927 13.584-5.89 22.503-5.89 8.264 0 15.465 1.8 21.684 5.318 6.137 3.518 10.964 8.673 14.319 15.382 3.437 6.71 5.074 14.81 4.992 24.383v76.175h-28.23v-71.92c0-8.019-2.046-14.237-6.219-18.819-4.173-4.5-9.819-6.791-17.102-6.791-4.91 0-9.328 1.063-13.174 3.272-3.846 2.128-6.792 5.237-9.001 9.328-2.046 4.009-3.191 8.918-3.191 14.728ZM589.233 239c-10.147 0-18.82-1.391-26.103-4.091-7.282-2.7-13.092-6.382-17.511-10.964-4.418-4.582-7.528-9.655-9.164-15.219l25.448-6.136c1.145 2.372 2.782 4.663 4.991 6.954 2.209 2.291 5.155 4.255 8.837 5.81 3.683 1.554 8.428 2.291 14.074 2.291 8.019 0 14.647-1.964 19.884-5.81 5.237-3.845 7.856-10.227 7.856-19.064v-22.665h-1.391c-1.473 2.946-3.601 5.892-6.383 9.001-2.782 3.109-6.464 5.645-10.965 7.691-4.582 2.046-10.228 3.109-17.101 3.109-9.165 0-17.511-2.209-25.039-6.545-7.446-4.337-13.42-10.883-17.757-19.474-4.418-8.673-6.628-19.473-6.628-32.565 0-13.091 2.21-24.301 6.628-33.383 4.419-9.082 10.311-15.955 17.839-20.7 7.528-4.746 15.874-7.037 25.038-7.037 7.038 0 12.847 1.145 17.348 3.518 4.582 2.373 8.182 5.236 10.883 8.51 2.7 3.272 4.746 6.382 6.137 9.327h1.554v-19.8h27.821v121.749c0 10.228-2.454 18.737-7.364 25.447-4.91 6.709-11.538 11.7-20.048 15.055-8.509 3.355-18.165 4.991-28.884 4.991Zm.245-71.266c5.974 0 11.047-1.473 15.302-4.337 4.173-2.945 7.446-7.118 9.573-12.519 2.21-5.482 3.274-12.027 3.274-19.637 0-7.609-1.064-14.155-3.274-19.8-2.127-5.646-5.318-10.064-9.491-13.255-4.174-3.11-9.329-4.746-15.384-4.746s-11.537 1.636-15.792 4.91c-4.173 3.272-7.365 7.772-9.492 13.418-2.128 5.727-3.191 12.191-3.191 19.392 0 7.2 1.063 13.746 3.273 19.228 2.127 5.482 5.318 9.736 9.573 12.764 4.174 3.027 9.41 4.582 15.629 4.582Zm141.56-26.51V71.839h28.23v119.786h-27.412v-21.273h-1.227c-2.7 6.709-7.119 12.191-13.338 16.446-6.137 4.255-13.747 6.382-22.748 6.382-7.855 0-14.81-1.718-20.783-5.237-5.974-3.518-10.72-8.591-14.075-15.382-3.355-6.709-5.073-14.891-5.073-24.464V71.839h28.312v71.921c0 7.609 2.046 13.664 6.219 18.083 4.173 4.5 9.655 6.709 16.365 6.709 4.173 0 8.183-.982 12.111-3.028 3.927-2.045 7.118-5.072 9.655-9.082 2.537-4.091 3.764-9.164 3.764-15.218Zm65.707-109.395v159.796h-28.23V31.828h28.23Zm44.841 162.169c-7.61 0-14.402-1.391-20.457-4.091-6.055-2.7-10.883-6.791-14.32-12.109-3.518-5.319-5.237-11.946-5.237-19.801 0-6.791 1.228-12.355 3.765-16.773 2.536-4.419 5.891-7.937 10.228-10.637 4.337-2.619 9.164-4.664 14.647-6.055 5.4-1.391 11.046-2.373 16.856-3.027 7.037-.737 12.683-1.391 17.102-1.964 4.337-.573 7.528-1.555 9.574-2.782 1.963-1.309 3.027-3.273 3.027-5.973v-.491c0-5.891-1.718-10.391-5.237-13.664-3.518-3.191-8.51-4.828-15.056-4.828-6.955 0-12.356 1.473-16.447 4.5-4.01 3.028-6.71 6.546-8.183 10.719l-26.348-3.764c2.046-7.282 5.483-13.336 10.31-18.328 4.746-4.909 10.638-8.59 17.511-11.045 6.955-2.455 14.565-3.682 22.912-3.682 5.809 0 11.537.654 17.265 2.045s10.965 3.6 15.711 6.71c4.746 3.109 8.51 7.282 11.455 12.6 2.864 5.318 4.337 11.946 4.337 19.883v80.184h-27.166v-16.446h-.9c-1.719 3.355-4.091 6.464-7.201 9.328-3.109 2.864-6.955 5.237-11.619 6.955-4.828 1.718-10.229 2.536-16.529 2.536Zm7.364-20.701c5.646 0 10.556-1.145 14.729-3.354 4.173-2.291 7.364-5.237 9.655-9.001 2.292-3.763 3.355-7.854 3.355-12.273v-14.155c-.9.737-2.373 1.391-4.5 2.046-2.128.654-4.419 1.145-7.037 1.636-2.619.491-5.155.9-7.692 1.227-2.537.328-4.746.655-6.628.901-4.173.572-8.019 1.472-11.292 2.781-3.355 1.31-5.973 3.11-7.855 5.401-1.964 2.291-2.864 5.318-2.864 8.918 0 5.237 1.882 9.164 5.728 11.782 3.682 2.782 8.51 4.091 14.401 4.091Zm64.643 18.328V71.839h27.412v19.965h1.227c2.21-6.955 5.974-12.274 11.292-16.038 5.319-3.763 11.456-5.645 18.329-5.645 1.555 0 3.355.082 5.237.163 1.964.164 3.601.328 4.91.573v25.938c-1.227-.41-3.109-.819-5.646-1.146a58.815 58.815 0 0 0-7.446-.49c-5.155 0-9.738 1.145-13.829 3.354-4.091 2.209-7.282 5.236-9.655 9.164-2.373 3.927-3.519 8.427-3.519 13.5v70.448h-28.312ZM222.077 39.192l-8.019 125.923L137.387 0l84.69 39.192Zm-53.105 162.825-57.933 33.056-57.934-33.056 11.783-28.556h92.301l11.783 28.556ZM111.039 62.675l30.357 73.803H80.681l30.358-73.803ZM7.937 165.115 0 39.192 84.69 0 7.937 165.115Z"
/>
</g>
<defs>
<radialGradient
id="wordmark_c"
cx="0"
cy="0"
r="1"
gradientTransform="rotate(118.122 171.182 60.81) scale(205.794)"
gradientUnits="userSpaceOnUse"
>
<stop stop-color="#FF41F8" />
<stop offset=".707" stop-color="#FF41F8" stop-opacity=".5" />
<stop offset="1" stop-color="#FF41F8" stop-opacity="0" />
</radialGradient>
<linearGradient
id="wordmark_b"
x1="0"
x2="982"
y1="192"
y2="192"
gradientUnits="userSpaceOnUse"
>
<stop stop-color="#F0060B" />
<stop offset="0" stop-color="#F0070C" />
<stop offset=".526" stop-color="#CC26D5" />
<stop offset="1" stop-color="#7702FF" />
</linearGradient>
<clipPath id="wordmark_a"><path fill="#fff" d="M0 0h982v239H0z" /></clipPath>
</defs>
</svg>
@if (!isUwu) {
<svg
class="angular-logo"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 982 241"
style="width: max(calc(700 * min(100vw, 2560px) / 1470), 350px); height: auto;"
>
<g clip-path="url(#wordmark_a)">
<path
fill="url(#wordmark_b)"
d="M388.676 191.625h30.849L363.31 31.828h-35.758l-56.215 159.797h30.848l13.174-39.356h60.061l13.256 39.356Zm-65.461-62.675 21.602-64.311h1.227l21.603 64.311h-44.432Zm126.831-7.527v70.202h-28.23V71.839h27.002v20.374h1.392c2.782-6.71 7.2-12.028 13.255-15.956 6.056-3.927 13.584-5.89 22.503-5.89 8.264 0 15.465 1.8 21.684 5.318 6.137 3.518 10.964 8.673 14.319 15.382 3.437 6.71 5.074 14.81 4.992 24.383v76.175h-28.23v-71.92c0-8.019-2.046-14.237-6.219-18.819-4.173-4.5-9.819-6.791-17.102-6.791-4.91 0-9.328 1.063-13.174 3.272-3.846 2.128-6.792 5.237-9.001 9.328-2.046 4.009-3.191 8.918-3.191 14.728ZM589.233 239c-10.147 0-18.82-1.391-26.103-4.091-7.282-2.7-13.092-6.382-17.511-10.964-4.418-4.582-7.528-9.655-9.164-15.219l25.448-6.136c1.145 2.372 2.782 4.663 4.991 6.954 2.209 2.291 5.155 4.255 8.837 5.81 3.683 1.554 8.428 2.291 14.074 2.291 8.019 0 14.647-1.964 19.884-5.81 5.237-3.845 7.856-10.227 7.856-19.064v-22.665h-1.391c-1.473 2.946-3.601 5.892-6.383 9.001-2.782 3.109-6.464 5.645-10.965 7.691-4.582 2.046-10.228 3.109-17.101 3.109-9.165 0-17.511-2.209-25.039-6.545-7.446-4.337-13.42-10.883-17.757-19.474-4.418-8.673-6.628-19.473-6.628-32.565 0-13.091 2.21-24.301 6.628-33.383 4.419-9.082 10.311-15.955 17.839-20.7 7.528-4.746 15.874-7.037 25.038-7.037 7.038 0 12.847 1.145 17.348 3.518 4.582 2.373 8.182 5.236 10.883 8.51 2.7 3.272 4.746 6.382 6.137 9.327h1.554v-19.8h27.821v121.749c0 10.228-2.454 18.737-7.364 25.447-4.91 6.709-11.538 11.7-20.048 15.055-8.509 3.355-18.165 4.991-28.884 4.991Zm.245-71.266c5.974 0 11.047-1.473 15.302-4.337 4.173-2.945 7.446-7.118 9.573-12.519 2.21-5.482 3.274-12.027 3.274-19.637 0-7.609-1.064-14.155-3.274-19.8-2.127-5.646-5.318-10.064-9.491-13.255-4.174-3.11-9.329-4.746-15.384-4.746s-11.537 1.636-15.792 4.91c-4.173 3.272-7.365 7.772-9.492 13.418-2.128 5.727-3.191 12.191-3.191 19.392 0 7.2 1.063 13.746 3.273 19.228 2.127 5.482 5.318 9.736 9.573 12.764 4.174 3.027 9.41 4.582 15.629 4.582Zm141.56-26.51V71.839h28.23v119.786h-27.412v-21.273h-1.227c-2.7 6.709-7.119 12.191-13.338 16.446-6.137 4.255-13.747 6.382-22.748 6.382-7.855 0-14.81-1.718-20.783-5.237-5.974-3.518-10.72-8.591-14.075-15.382-3.355-6.709-5.073-14.891-5.073-24.464V71.839h28.312v71.921c0 7.609 2.046 13.664 6.219 18.083 4.173 4.5 9.655 6.709 16.365 6.709 4.173 0 8.183-.982 12.111-3.028 3.927-2.045 7.118-5.072 9.655-9.082 2.537-4.091 3.764-9.164 3.764-15.218Zm65.707-109.395v159.796h-28.23V31.828h28.23Zm44.841 162.169c-7.61 0-14.402-1.391-20.457-4.091-6.055-2.7-10.883-6.791-14.32-12.109-3.518-5.319-5.237-11.946-5.237-19.801 0-6.791 1.228-12.355 3.765-16.773 2.536-4.419 5.891-7.937 10.228-10.637 4.337-2.619 9.164-4.664 14.647-6.055 5.4-1.391 11.046-2.373 16.856-3.027 7.037-.737 12.683-1.391 17.102-1.964 4.337-.573 7.528-1.555 9.574-2.782 1.963-1.309 3.027-3.273 3.027-5.973v-.491c0-5.891-1.718-10.391-5.237-13.664-3.518-3.191-8.51-4.828-15.056-4.828-6.955 0-12.356 1.473-16.447 4.5-4.01 3.028-6.71 6.546-8.183 10.719l-26.348-3.764c2.046-7.282 5.483-13.336 10.31-18.328 4.746-4.909 10.638-8.59 17.511-11.045 6.955-2.455 14.565-3.682 22.912-3.682 5.809 0 11.537.654 17.265 2.045s10.965 3.6 15.711 6.71c4.746 3.109 8.51 7.282 11.455 12.6 2.864 5.318 4.337 11.946 4.337 19.883v80.184h-27.166v-16.446h-.9c-1.719 3.355-4.091 6.464-7.201 9.328-3.109 2.864-6.955 5.237-11.619 6.955-4.828 1.718-10.229 2.536-16.529 2.536Zm7.364-20.701c5.646 0 10.556-1.145 14.729-3.354 4.173-2.291 7.364-5.237 9.655-9.001 2.292-3.763 3.355-7.854 3.355-12.273v-14.155c-.9.737-2.373 1.391-4.5 2.046-2.128.654-4.419 1.145-7.037 1.636-2.619.491-5.155.9-7.692 1.227-2.537.328-4.746.655-6.628.901-4.173.572-8.019 1.472-11.292 2.781-3.355 1.31-5.973 3.11-7.855 5.401-1.964 2.291-2.864 5.318-2.864 8.918 0 5.237 1.882 9.164 5.728 11.782 3.682 2.782 8.51 4.091 14.401 4.091Zm64.643 18.328V71.839h27.412v19.965h1.227c2.21-6.955 5.974-12.274 11.292-16.038 5.319-3.763 11.456-5.645 18.329-5.645 1.555 0 3.355.082 5.237.163 1.964.164 3.601.328 4.91.573v25.938c-1.227-.41-3.109-.819-5.646-1.146a58.815 58.815 0 0 0-7.446-.49c-5.155 0-9.738 1.145-13.829 3.354-4.091 2.209-7.282 5.236-9.655 9.164-2.373 3.927-3.519 8.427-3.519 13.5v70.448h-28.312ZM222.077 39.192l-8.019 125.923L137.387 0l84.69 39.192Zm-53.105 162.825-57.933 33.056-57.934-33.056 11.783-28.556h92.301l11.783 28.556ZM111.039 62.675l30.357 73.803H80.681l30.358-73.803ZM7.937 165.115 0 39.192 84.69 0 7.937 165.115Z"
/>
<path
fill="url(#wordmark_c)"
d="M388.676 191.625h30.849L363.31 31.828h-35.758l-56.215 159.797h30.848l13.174-39.356h60.061l13.256 39.356Zm-65.461-62.675 21.602-64.311h1.227l21.603 64.311h-44.432Zm126.831-7.527v70.202h-28.23V71.839h27.002v20.374h1.392c2.782-6.71 7.2-12.028 13.255-15.956 6.056-3.927 13.584-5.89 22.503-5.89 8.264 0 15.465 1.8 21.684 5.318 6.137 3.518 10.964 8.673 14.319 15.382 3.437 6.71 5.074 14.81 4.992 24.383v76.175h-28.23v-71.92c0-8.019-2.046-14.237-6.219-18.819-4.173-4.5-9.819-6.791-17.102-6.791-4.91 0-9.328 1.063-13.174 3.272-3.846 2.128-6.792 5.237-9.001 9.328-2.046 4.009-3.191 8.918-3.191 14.728ZM589.233 239c-10.147 0-18.82-1.391-26.103-4.091-7.282-2.7-13.092-6.382-17.511-10.964-4.418-4.582-7.528-9.655-9.164-15.219l25.448-6.136c1.145 2.372 2.782 4.663 4.991 6.954 2.209 2.291 5.155 4.255 8.837 5.81 3.683 1.554 8.428 2.291 14.074 2.291 8.019 0 14.647-1.964 19.884-5.81 5.237-3.845 7.856-10.227 7.856-19.064v-22.665h-1.391c-1.473 2.946-3.601 5.892-6.383 9.001-2.782 3.109-6.464 5.645-10.965 7.691-4.582 2.046-10.228 3.109-17.101 3.109-9.165 0-17.511-2.209-25.039-6.545-7.446-4.337-13.42-10.883-17.757-19.474-4.418-8.673-6.628-19.473-6.628-32.565 0-13.091 2.21-24.301 6.628-33.383 4.419-9.082 10.311-15.955 17.839-20.7 7.528-4.746 15.874-7.037 25.038-7.037 7.038 0 12.847 1.145 17.348 3.518 4.582 2.373 8.182 5.236 10.883 8.51 2.7 3.272 4.746 6.382 6.137 9.327h1.554v-19.8h27.821v121.749c0 10.228-2.454 18.737-7.364 25.447-4.91 6.709-11.538 11.7-20.048 15.055-8.509 3.355-18.165 4.991-28.884 4.991Zm.245-71.266c5.974 0 11.047-1.473 15.302-4.337 4.173-2.945 7.446-7.118 9.573-12.519 2.21-5.482 3.274-12.027 3.274-19.637 0-7.609-1.064-14.155-3.274-19.8-2.127-5.646-5.318-10.064-9.491-13.255-4.174-3.11-9.329-4.746-15.384-4.746s-11.537 1.636-15.792 4.91c-4.173 3.272-7.365 7.772-9.492 13.418-2.128 5.727-3.191 12.191-3.191 19.392 0 7.2 1.063 13.746 3.273 19.228 2.127 5.482 5.318 9.736 9.573 12.764 4.174 3.027 9.41 4.582 15.629 4.582Zm141.56-26.51V71.839h28.23v119.786h-27.412v-21.273h-1.227c-2.7 6.709-7.119 12.191-13.338 16.446-6.137 4.255-13.747 6.382-22.748 6.382-7.855 0-14.81-1.718-20.783-5.237-5.974-3.518-10.72-8.591-14.075-15.382-3.355-6.709-5.073-14.891-5.073-24.464V71.839h28.312v71.921c0 7.609 2.046 13.664 6.219 18.083 4.173 4.5 9.655 6.709 16.365 6.709 4.173 0 8.183-.982 12.111-3.028 3.927-2.045 7.118-5.072 9.655-9.082 2.537-4.091 3.764-9.164 3.764-15.218Zm65.707-109.395v159.796h-28.23V31.828h28.23Zm44.841 162.169c-7.61 0-14.402-1.391-20.457-4.091-6.055-2.7-10.883-6.791-14.32-12.109-3.518-5.319-5.237-11.946-5.237-19.801 0-6.791 1.228-12.355 3.765-16.773 2.536-4.419 5.891-7.937 10.228-10.637 4.337-2.619 9.164-4.664 14.647-6.055 5.4-1.391 11.046-2.373 16.856-3.027 7.037-.737 12.683-1.391 17.102-1.964 4.337-.573 7.528-1.555 9.574-2.782 1.963-1.309 3.027-3.273 3.027-5.973v-.491c0-5.891-1.718-10.391-5.237-13.664-3.518-3.191-8.51-4.828-15.056-4.828-6.955 0-12.356 1.473-16.447 4.5-4.01 3.028-6.71 6.546-8.183 10.719l-26.348-3.764c2.046-7.282 5.483-13.336 10.31-18.328 4.746-4.909 10.638-8.59 17.511-11.045 6.955-2.455 14.565-3.682 22.912-3.682 5.809 0 11.537.654 17.265 2.045s10.965 3.6 15.711 6.71c4.746 3.109 8.51 7.282 11.455 12.6 2.864 5.318 4.337 11.946 4.337 19.883v80.184h-27.166v-16.446h-.9c-1.719 3.355-4.091 6.464-7.201 9.328-3.109 2.864-6.955 5.237-11.619 6.955-4.828 1.718-10.229 2.536-16.529 2.536Zm7.364-20.701c5.646 0 10.556-1.145 14.729-3.354 4.173-2.291 7.364-5.237 9.655-9.001 2.292-3.763 3.355-7.854 3.355-12.273v-14.155c-.9.737-2.373 1.391-4.5 2.046-2.128.654-4.419 1.145-7.037 1.636-2.619.491-5.155.9-7.692 1.227-2.537.328-4.746.655-6.628.901-4.173.572-8.019 1.472-11.292 2.781-3.355 1.31-5.973 3.11-7.855 5.401-1.964 2.291-2.864 5.318-2.864 8.918 0 5.237 1.882 9.164 5.728 11.782 3.682 2.782 8.51 4.091 14.401 4.091Zm64.643 18.328V71.839h27.412v19.965h1.227c2.21-6.955 5.974-12.274 11.292-16.038 5.319-3.763 11.456-5.645 18.329-5.645 1.555 0 3.355.082 5.237.163 1.964.164 3.601.328 4.91.573v25.938c-1.227-.41-3.109-.819-5.646-1.146a58.815 58.815 0 0 0-7.446-.49c-5.155 0-9.738 1.145-13.829 3.354-4.091 2.209-7.282 5.236-9.655 9.164-2.373 3.927-3.519 8.427-3.519 13.5v70.448h-28.312ZM222.077 39.192l-8.019 125.923L137.387 0l84.69 39.192Zm-53.105 162.825-57.933 33.056-57.934-33.056 11.783-28.556h92.301l11.783 28.556ZM111.039 62.675l30.357 73.803H80.681l30.358-73.803ZM7.937 165.115 0 39.192 84.69 0 7.937 165.115Z"
/>
</g>
<defs>
<radialGradient
id="wordmark_c"
cx="0"
cy="0"
r="1"
gradientTransform="rotate(118.122 171.182 60.81) scale(205.794)"
gradientUnits="userSpaceOnUse"
>
<stop stop-color="#FF41F8" />
<stop offset=".707" stop-color="#FF41F8" stop-opacity=".5" />
<stop offset="1" stop-color="#FF41F8" stop-opacity="0" />
</radialGradient>
<linearGradient
id="wordmark_b"
x1="0"
x2="982"
y1="192"
y2="192"
gradientUnits="userSpaceOnUse"
>
<stop stop-color="#F0060B" />
<stop offset="0" stop-color="#F0070C" />
<stop offset=".526" stop-color="#CC26D5" />
<stop offset="1" stop-color="#7702FF" />
</linearGradient>
<clipPath id="wordmark_a"><path fill="#fff" d="M0 0h982v239H0z" /></clipPath>
</defs>
</svg>
} @else {
<img
src="assets/images/uwu.png"
class="uwu-logo"
alt="Angular logo"
style="width: max(calc(700 * min(100vw, 2560px) / 1470), 350px); height: auto;"
/>
}
</div>
</div>
<div class="adev-scale">
+4 -2
View File
@@ -21,7 +21,7 @@ import {
inject,
} from '@angular/core';
import {WINDOW, shouldReduceMotion, isIos} from '@angular/docs';
import {RouterLink} from '@angular/router';
import {ActivatedRoute, RouterLink} from '@angular/router';
import {injectAsync} from '../../core/services/inject-async';
@@ -48,8 +48,10 @@ export default class Home implements OnInit, AfterViewInit, OnDestroy {
private readonly ngZone = inject(NgZone);
private readonly platformId = inject(PLATFORM_ID);
private readonly window = inject(WINDOW);
private readonly activatedRoute = inject(ActivatedRoute);
protected readonly tutorialFiles = TUTORIALS_HOMEPAGE_DIRECTORY;
protected readonly isUwu = 'uwu' in this.activatedRoute.snapshot.queryParams;
private element!: HTMLDivElement;
private homeAnimation?: HomeAnimation;
private intersectionObserver: IntersectionObserver | undefined;
@@ -74,7 +76,7 @@ export default class Home implements OnInit, AfterViewInit, OnDestroy {
// at the end of the page, and to load the embedded editor.
this.initIntersectionObserver();
if (this.isWebGLAvailable() && !shouldReduceMotion()) {
if (this.isWebGLAvailable() && !shouldReduceMotion() && !this.isUwu) {
this.ngZone.runOutsideAngular(async () => {
await this.loadHomeAnimation();
});
+1 -1
View File
@@ -679,7 +679,7 @@ const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [
contentPath: 'tools/cli/end-to-end',
},
{
label: 'ESBuild',
label: 'Migrating to new build system',
path: 'tools/cli/esbuild',
contentPath: 'tools/cli/esbuild',
},
Binary file not shown.

After

Width:  |  Height:  |  Size: 311 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB

@@ -3,7 +3,7 @@
The `output()` function declares an output in a directive or component.
Outputs allow you to emit values to parent components.
HELPFUL: The `output()` function is currently in [developer preview](/guide/releases#developer-preview).
HELPFUL: The `output()` function is currently in [developer preview](/reference/releases#developer-preview).
<docs-code language="ts" highlight="[[5], [8]]">
import {Component, output} from '@angular/core';
+1 -1
View File
@@ -111,7 +111,7 @@ its `set` or `update` methods.
## Customizing model inputs
You can mark a model input as required or provide an alias in the same way as a
[standard input](guide/signal-inputs).
[standard input](guide/signals/inputs).
Model inputs do not support input transforms.
+32 -22
View File
@@ -28,28 +28,6 @@ platformBrowser().bootstrapModule(AppModule, {ngZone: 'noop'});
export class AppModule {}
```
## Testing
The zoneless provider function can also be used with `TestBed` to help
ensure the components under test are compatible with a Zoneless
Angular application.
```typescript
TestBed.configureTestingModule({
providers: [provideExperimentalZonelessChangeDetection()]
});
const fixture = TestBed.createComponent(MyComponent);
await fixture.whenStable();
```
To ensure tests have the most similar behavior to production code,
avoid using `fixture.detectChanges()` when possibe. This forces
change detection to run when Angular might otherwise have not
scheduled change detection. Tests should ensure these notifications
are happening and allow Angular to handle when to synchronize
state rather than manually forcing it to happen in the test.
## Requirements for Zoneless compatibility
Angular relies on notifications from core APIs in order to determine when to run change detection and on which views.
@@ -106,3 +84,35 @@ taskCleanup();
The framework uses this service internally as well to prevent serialization until asynchronous tasks are complete. These include, but are not limited to,
an ongoing Router navigation and an incomplete `HttpClient` request.
## Testing and Debugging
### Using Zoneless in `TestBed`
The zoneless provider function can also be used with `TestBed` to help
ensure the components under test are compatible with a Zoneless
Angular application.
```typescript
TestBed.configureTestingModule({
providers: [provideExperimentalZonelessChangeDetection()]
});
const fixture = TestBed.createComponent(MyComponent);
await fixture.whenStable();
```
To ensure tests have the most similar behavior to production code,
avoid using `fixture.detectChanges()` when possibe. This forces
change detection to run when Angular might otherwise have not
scheduled change detection. Tests should ensure these notifications
are happening and allow Angular to handle when to synchronize
state rather than manually forcing it to happen in the test.
### Debug-mode check to ensure updates are detected
Angular also provides an additional tool to help verify that an application is making
updates to state in a zoneless-compatible way. `provideExperimentalCheckNoChangesForDebug`
can be used to periodically check to ensure that no bindings have been updated
without a notification. Angular will throw `ExpressionChangedAfterItHasBeenCheckedError`
if there is an updated binding that would not have refreshed by the zoneless change
detection.
+6
View File
@@ -163,3 +163,9 @@ Occasionally we introduce new APIs under the label of "Developer Preview". These
This may be because we want to gather feedback from real applications before stabilization, or because the associated documentation or migration tooling is not fully complete.
The policies and practices that are described in this document do not apply to APIs marked as Developer Preview. Such APIs can change at any time, even in new patch versions of the framework. Teams should decide for themselves whether the benefits of using Developer Preview APIs are worth the risk of breaking changes outside of our normal use of semantic versioning.
## Experimental
These are APIs might not become stable at all or have significant changes before becoming stable.
The policies and practices that are described in this document do not apply to APIs marked as experimental. Such APIs can change at any time, even in new patch versions of the framework. Teams should decide for themselves whether the benefits of using experimental APIs are worth the risk of breaking changes outside of our normal use of semantic versioning.
+1 -1
View File
@@ -95,7 +95,7 @@ Read about how to enable CORS for specific servers at [enable-cors.org](https://
| Features | Details |
|:--- |:--- |
| [Ahead-of-Time (AOT) Compilation](tools/cli/aot-compiler) | Pre-compiles Angular component templates. |
| [Production mode](tools/cli/deployment#production-mode-at-runtime) | Optimizes the application for the best runtime performance |
| [Production mode](tools/cli/deployment#development-only-features) | Optimizes the application for the best runtime performance |
| Bundling | Concatenates your many application and library files into a minimum number of deployed files. |
| Minification | Removes excess whitespace, comments, and optional tokens. |
| Mangling | Renames functions, classes, and variables to use shorter, arbitrary identifiers. |
+37 -22
View File
@@ -1,4 +1,4 @@
# Getting started with the Angular CLI's new build system
# Migrating to the new build system
In v17 and higher, the new build system provides an improved way to build Angular applications. This new build system includes:
@@ -20,7 +20,39 @@ New applications will use this new build system by default via the `application`
## For existing applications
For existing projects, you can opt-in to use the new builder on a per-application basis with two different options.
Both automated and manual procedures are available dependening on the requirements of the project.
Starting with v18, the update process will ask if you would like to migrate existing applications to use the new build system via the automated migration.
HELPFUL: Remember to remove any CommonJS assumptions in the application server code if using SSR such as `require`, `__filename`, `__dirname`, or other constructs from the [CommonJS module scope](https://nodejs.org/api/modules.html#the-module-scope). All application code should be ESM compatible. This does not apply to third-party dependencies.
### Automated migration (Recommended)
The automated migration will adjust both the application configuration within `angular.json` as well as code and stylesheets to remove previous Webpack-specific feature usage.
While many changes can be automated and most applications will not require any further changes, each application is unique and there may be some manual changes required.
After the migration, please attempt a build of the application as there could be new errors that will require adjustments within the code.
The errors will attempt to provide solutions to the problem when possible and the later sections of this guide describe some of the more common situations that you may encounter.
When updating to Angular v18 via `ng update`, you will be asked to execute the migration.
This migration is entirely optional for v18 and can also be run manually at anytime after an update via the following command:
<docs-code language="shell">
ng update @angular/cli --name use-application-builder
</docs-code>
The migration does the following:
* Converts existing `browser` or `browser-esbuild` target to `application`
* Removes any previous SSR builders (because `application` does that now).
* Updates configuration accordingly.
* Merges `tsconfig.server.json` with `tsconfig.app.json` and adds the TypeScript option `"esModuleInterop": true` to ensure `express` imports are [ESM compliant](#esm-default-imports-vs-namespace-imports).
* Updates application server code to use new bootstrapping and output directory structure.
* Removes any Webpack-specific builder stylesheet usage such as the tilde or caret in `@import`/`url()` and updates the configuration to provide equivalent behavior
* Converts to use the new lower dependency `@angular/build` Node.js package if no other `@angular-devkit/build-angular` usage is found.
### Manual migration
Additionally for existing projects, you can manually opt-in to use the new builder on a per-application basis with two different options.
Both options are considered stable and fully supported by the Angular team.
The choice of which option to use is a factor of how many changes you will need to make to migrate and what new features you would like to use in the project.
@@ -28,10 +60,10 @@ The choice of which option to use is a factor of how many changes you will need
- The `application` builder covers an entire application, such as the client-side bundle, as well as optionally building a server for server-side rendering and performing build-time prerendering of static pages.
The `application` builder is generally preferred as it improves server-side rendered (SSR) builds, and makes it easier for client-side rendered projects to adopt SSR in the future.
However it requires a little more migration effort, particularly for existing SSR applications.
However it requires a little more migration effort, particularly for existing SSR applications if performed manually.
If the `application` builder is difficult for your project to adopt, `browser-esbuild` can be an easier solution which gives most of the build performance benefits with fewer breaking changes.
### Using the `browser-esbuild` builder
#### Manual migration to the compatibility builder
A builder named `browser-esbuild` is available within the `@angular-devkit/build-angular` package that is present in an Angular CLI generated application.
You can try out the new build system for applications that use the `browser` builder.
@@ -61,7 +93,7 @@ Changing the `builder` field is the only change you will need to make.
...
</docs-code>
### Using the `application` builder
#### Manual migration to the new `application` builder
A builder named `application` is also available within the `@angular-devkit/build-angular` package that is present in an Angular CLI generated application.
This builder is the default for all new applications created via `ng new`.
@@ -117,23 +149,6 @@ The `application` builder now provides the integrated functionality for all of t
The `ng update` process will automatically remove usages of the `@nguniversal` scope packages where some of these builders were previously located.
The new `@angular/ssr` package will also be automatically added and used with configuration and code being adjusted during the update.
The `@angular/ssr` package supports the `browser` builder as well as the `application` builder.
To convert from the separate SSR builders to the integrated capabilities of the `application` builder, run the experimental `use-application-builder` migration.
<docs-code language="shell">
ng update @angular/cli --name use-application-builder
</docs-code>
The migration does the following:
* Converts existing `browser` or `browser-esbuild` target to `application`
* Removes any previous SSR builders (because `application` does that now).
* Updates configuration accordingly.
* Merges `tsconfig.server.json` with `tsconfig.app.json` and adds the TypeScript option `"esModuleInterop": true` to ensure `express` imports are [ESM compliant](#esm-default-imports-vs-namespace-imports).
* Updates application server code to use new bootstrapping and output directory structure.
HELPFUL: Remember to remove any CommonJS assumptions in the application server code such as `require`, `__filename`, `__dirname`, or other constructs from the [CommonJS module scope](https://nodejs.org/api/modules.html#the-module-scope). All application code should be ESM compatible. This does not apply to third-party dependencies.
## Executing a build
+27 -3
View File
@@ -19,8 +19,8 @@ When you open the extension, you'll see two additional tabs:
| Tabs | Details |
|:--- |:--- |
| [Components](tools/devtools#components) | Lets you explore the components and directives in your application and preview or edit their state. |
| [Profiler](tools/devtools#profiler) | Lets you profile your application and understand what the performance bottleneck is during change detection execution. |
| [Components](tools/devtools#debug-your-application) | Lets you explore the components and directives in your application and preview or edit their state. |
| [Profiler](tools/devtools#profile-your-application) | Lets you profile your application and understand what the performance bottleneck is during change detection execution. |
<img src="assets/images/guide/devtools/devtools-tabs.png" alt="A screenshot of the top of Angular DevTools illustrating two tabs in the upper-left corner, one labeled 'Components' and another labeled 'Profiler'.">
@@ -108,7 +108,7 @@ Interact with your application to trigger change detection and generate data Ang
To finish recording, click the circle again to **Stop recording**.
You can also import an existing recording.
Read more about this feature in the [Import recording](tools/devtools#import-recording) section.
Read more about this feature in the [Import recording](tools/devtools#import-and-export-recordings) section.
### Understand your application's execution
@@ -170,3 +170,27 @@ Click the **Save Profile** button at the top-right of a recorded profiling sessi
Later, import the file in the initial view of the profiler by clicking the **Choose file** input.
<img src="assets/images/guide/devtools/save-profile.png" alt="A screenshot of the 'Profiler' tab displaying change detection cycles. On the right side a 'Save Profile' button is visible.">
## Inspect your injectors
Note: The Injector Tree is available for Angular Applications built with version 17 or higher.
### View the injector hierarchy of your application
The **Injector Tree** tab lets you explore the structure of the Injectors configured in your application. Here you will see two trees representing the [injector hierarchy](guide/di/hierarchical-dependency-injection) of your application. One tree is your environment hierarchy, the other is your element hierarchy.
<img src="assets/images/guide/devtools/di-injector-tree.png" alt="A screenshot of the 'Profiler' tab displaying the injector tree tab in Angular Devtools visualizing the injector graph for an example application.">
### Visualize resolution paths
When a specific injector is selected, the path that Angular's dependency injection algorithm traverses from that injector to the root is highlighted. For element injectors, this includes highlighting the environment injectors that the dependency injection algorithm jumps to when a dependency cannot be resolved in the element hierarchy.
See [resolution rules](guide/di/hierarchical-dependency-injection#resolution-rules) for more details about how Angular resolves resolution paths.
<img src="assets/images/guide/devtools/di-injector-tree-selected.png" alt="A screenshot of the 'Profiler' tab displaying how the injector tree visualize highlights resolution paths when an injector is selected.">
### View injector providers
Clicking an injector that has configured providers will display those providers in a list on the right of the injector tree view. Here you can view the provided token and it's type.
<img src="assets/images/guide/devtools/di-injector-tree-providers.png" alt="A screenshot of the 'Profiler' tab displaying how providers are made visible when an injector is selected.">
@@ -70,11 +70,11 @@ In the **Edit** pane of your IDE:
1. In `app.component.ts`, in `@Component`, update the `imports` array property and add `HomeComponent`.
<docs-code header="Replace in src/app/app.component.ts" path="adev/src/content/tutorials/first-app/steps/03-HousingLocation/src/app/app.component.ts" visibleLines="[7,9]"/>
<docs-code header="Replace in src/app/app.component.ts" path="adev/src/content/tutorials/first-app/steps/03-HousingLocation/src/app/app.component.ts" visibleLines="[7]"/>
1. In `app.component.ts`, in `@Component`, update the `template` property to include the following HTML code.
<docs-code header="Replace in src/app/app.component.ts" path="adev/src/content/tutorials/first-app/steps/03-HousingLocation/src/app/app.component.ts" visibleLines="[10,19]"/>
<docs-code header="Replace in src/app/app.component.ts" path="adev/src/content/tutorials/first-app/steps/03-HousingLocation/src/app/app.component.ts" visibleLines="[8,17]"/>
1. Save your changes to `app.component.ts`.
1. If `ng serve` is running, the app should update.
@@ -87,6 +87,7 @@ In the **Edit** pane of your IDE:
</docs-step>
<docs-step title="Add features to `HomeComponent`">
In this step you add features to `HomeComponent`.
In the previous step, you added the default `HomeComponent` to your app's template so its default HTML appeared in the app.
@@ -99,7 +100,7 @@ In the **Edit** pane of your IDE:
1. In the `first-app` directory, open `home.component.ts` in the editor.
1. In `home.component.ts`, in `@Component`, update the `template` property with this code.
<docs-code header="Replace in src/app/home/home.component.ts" path="adev/src/content/tutorials/first-app/steps/03-HousingLocation/src/app/home/home.component.ts" visibleLines="[10,17]"/>
<docs-code header="Replace in src/app/home/home.component.ts" path="adev/src/content/tutorials/first-app/steps/03-HousingLocation/src/app/home/home.component.ts" visibleLines="[8,15]"/>
1. Next, open `home.component.css` in the editor and update the content with these styles.
@@ -51,11 +51,11 @@ In the **Edit** pane of your IDE:
1. Next update the `imports` property of the `@Component` metadata by adding `HousingLocationComponent` to the array.
<docs-code header="Add HousingLocationComponent to imports array in src/app/home/home.component.ts" path="adev/src/content/tutorials/first-app/steps/04-interfaces/src/app/home/home.component.ts" visibleLines="[7,10]"/>
<docs-code header="Add HousingLocationComponent to imports array in src/app/home/home.component.ts" path="adev/src/content/tutorials/first-app/steps/04-interfaces/src/app/home/home.component.ts" visibleLines="[7]"/>
1. Now the component is ready for use in the template for the `HomeComponent`. Update the `template` property of the `@Component` metadata to include a reference to the `<app-housing-location>` tag.
<docs-code header="Add housing location to the component template in src/app/home/home.component.ts" path="adev/src/content/tutorials/first-app/steps/04-interfaces/src/app/home/home.component.ts" visibleLines="[11,21]"/>
<docs-code header="Add housing location to the component template in src/app/home/home.component.ts" path="adev/src/content/tutorials/first-app/steps/04-interfaces/src/app/home/home.component.ts" visibleLines="[8,18]"/>
</docs-step>
@@ -48,7 +48,7 @@ This step adds the properties to the interface that your app needs to represent
1. In the **Edit** pane of your IDE, open the `src/app/housinglocation.ts` file.
1. In `housinglocation.ts`, replace the default content with the following code to make your new interface to match this example.
<docs-code header="Update src/app/housinglocation.ts to match this code" path="adev/src/content/tutorials/first-app/steps/05-inputs/src/app/housinglocation.ts"/>
<docs-code header="Update src/app/housinglocation.ts to match this code" path="adev/src/content/tutorials/first-app/steps/05-inputs/src/app/housinglocation.ts" visibleLines="[1,10]" />
1. Save your changes and confirm the app does not display any errors. Correct any errors before you continue to the next step.
@@ -70,11 +70,11 @@ There are a few more lessons to complete before that happens.
1. In `src/app/home/home.component.ts`, replace the empty `export class HomeComponent {}` definition with this code to create a single instance of the new interface in the component.
<docs-code header="Add sample data to src/app/home/home.component.ts" path="adev/src/content/tutorials/first-app/steps/05-inputs/src/app/home/home.component.ts" visibleLines="[27,38]"/>
<docs-code header="Add sample data to src/app/home/home.component.ts" path="adev/src/content/tutorials/first-app/steps/05-inputs/src/app/home/home.component.ts" visibleLines="[23,36]"/>
1. Confirm that your `home.component.ts` file matches like this example.
<docs-code header="src/app/home/home.component.ts" path="adev/src/content/tutorials/first-app/steps/05-inputs/src/app/home/home.component.ts"/>
<docs-code header="src/app/home/home.component.ts" path="adev/src/content/tutorials/first-app/steps/05-inputs/src/app/home/home.component.ts" visibleLines="[1,36]" />
By adding the `housingLocation` property of type `HousingLocation` to the `HomeComponent` class, we're able to confirm that the data matches the description of the interface. If the data didn't satisfy the description of the interface, the IDE has enough information to give us helpful errors.
@@ -33,7 +33,7 @@ In the code editor:
<docs-step title="Add the Input property">
1. In the same file, add a property called `housingLocation` of type `HousingLocation` to the `HousingLocationComponent` class. Add an `!` after the property name and prefix it with the `@Input()` decorator:
<docs-code header="Import HousingLocationComponent and Input in src/app/housing-location/housing-location.component.ts" path="adev/src/content/tutorials/first-app/steps/06-property-binding/src/app/housing-location/housing-location.component.ts" visibleLines="[16,18]"/>
<docs-code header="Import HousingLocationComponent and Input in src/app/housing-location/housing-location.component.ts" path="adev/src/content/tutorials/first-app/steps/06-property-binding/src/app/housing-location/housing-location.component.ts" visibleLines="[13,15]"/>
You have to add the `!` because the input is expecting the value to be passed. In this case, there is no default value. In our example application case we know that the value will be passed in - this is by design. The exclamation point is called the non-null assertion operator and it tells the TypeScript compiler that the value of this property won't be null or undefined.
@@ -26,7 +26,7 @@ In the code editor:
1. Navigate to `src/app/home/home.component.ts`
1. In the template property of the `@Component` decorator, update the code to match the code below:
<docs-code header="Add housingLocation property binding" path="adev/src/content/tutorials/first-app/steps/07-dynamic-template-values/src/app/home/home.component.ts" visibleLines="[21]"/>
<docs-code header="Add housingLocation property binding" path="adev/src/content/tutorials/first-app/steps/07-dynamic-template-values/src/app/home/home.component.ts" visibleLines="[17,19]"/>
When adding a property binding to a component tag, we use the `[attribute] = "value"` syntax to notify Angular that the assigned value should be treated as a property from the component class and not a string value.
@@ -27,7 +27,7 @@ In the code editor:
1. Navigate to `src/app/housing-location/housing-location.component.ts`
1. In the template property of the `@Component` decorator, replace the existing HTML markup with the following code:
<docs-code header="Update HousingLocationComponent template" path="adev/src/content/tutorials/first-app/steps/08-ngFor/src/app/housing-location/housing-location.component.ts" visibleLines="[9,15]"/>
<docs-code header="Update HousingLocationComponent template" path="adev/src/content/tutorials/first-app/steps/08-ngFor/src/app/housing-location/housing-location.component.ts" visibleLines="[9,20]"/>
In this updated template code you have used property binding to bind the `housingLocation.photo` to the `src` attribute. The `alt` attribute uses interpolation to give more context to the alt text of the image.
@@ -25,7 +25,7 @@ In the `HomeComponent` there is only a single housing location. In this step, yo
1. In `src/app/home/home.component.ts`, remove the `housingLocation` property from the `HomeComponent` class.
1. Update the `HomeComponent` class to have a property called `housingLocationList`. Update your code to match the following code:
<docs-code header="Add housingLocationList property" path="adev/src/content/tutorials/first-app/steps/09-services/src/app/home/home.component.ts" visibleLines="31-136"/>
<docs-code header="Add housingLocationList property" path="adev/src/content/tutorials/first-app/steps/09-services/src/app/home/home.component.ts" visibleLines="26-131"/>
IMPORTANT: Do not remove the `@Component` decorator, you will update that code in an upcoming step.
@@ -35,7 +35,7 @@ In the `HomeComponent` there is only a single housing location. In this step, yo
Now the app has a dataset that you can use to display the entries in the browser using the `ngFor` directive.
1. Update the `<app-housing-location>` tag in the template code to this:
<docs-code header="Add ngFor to HomeComponent template" path="adev/src/content/tutorials/first-app/steps/09-services/src/app/home/home.component.ts" visibleLines="[21,24]"/>
<docs-code header="Add ngFor to HomeComponent template" path="adev/src/content/tutorials/first-app/steps/09-services/src/app/home/home.component.ts" visibleLines="[17,22]"/>
Note, in the code `[housingLocation] = "housingLocation"` the `housingLocation` value now refers to the variable used in the `ngFor` directive. Before this change, it referred to the property on the `HomeComponent` class.
@@ -87,7 +87,7 @@ In the **Edit** pane of your IDE, in `src/app/home/home.component.ts`:
1. In `HomeComponent`, add the following code to inject the new service and initialize the data for the app. The `constructor` is the first function that runs when this component is created. The code in the `constructor` will assign the `housingLocationList` the value returned from the call to `getAllHousingLocations`.
<docs-code header="Initialize data from service in src/app/home/home.component.ts" path="adev/src/content/tutorials/first-app/steps/10-routing/src/app/home/home.component.ts" visibleLines="[31,36]"/>
<docs-code header="Initialize data from service in src/app/home/home.component.ts" path="adev/src/content/tutorials/first-app/steps/10-routing/src/app/home/home.component.ts" visibleLines="[28,32]"/>
1. Save the changes to `src/app/home/home.component.ts` and confirm your app builds without error.
Correct any errors before you continue to the next step.
@@ -49,11 +49,11 @@ In this lesson, you will enable routing in your application to navigate to the d
1. Add `RouterModule` to the `@Component` metadata imports
<docs-code header="Import RouterModule in src/app/app.component.ts" path="adev/src/content/tutorials/first-app/steps/11-details-page/src/app/app.component.ts" visibleLines="[9,12]"/>
<docs-code header="Import RouterModule in src/app/app.component.ts" path="adev/src/content/tutorials/first-app/steps/11-details-page/src/app/app.component.ts" visibleLines="[7]"/>
1. In the `template` property, replace the `<app-home></app-home>` tag with the `<router-outlet>` directive and add a link back to the home page. Your code should match this code:
<docs-code header="Add router-outlet in src/app/app.component.ts" path="adev/src/content/tutorials/first-app/steps/11-details-page/src/app/app.component.ts" visibleLines="[13,24]"/>
<docs-code header="Add router-outlet in src/app/app.component.ts" path="adev/src/content/tutorials/first-app/steps/11-details-page/src/app/app.component.ts" visibleLines="[8,18]"/>
</docs-step>
@@ -29,7 +29,7 @@ In this case, `:id` is dynamic and will change based on how the route is request
1. In `src/app/housing-location/housing-location.component.ts`, add an anchor tag to the `section` element and include the `routerLink` directive:
<docs-code header="Add anchor with a routerLink directive to housing-location.component.ts" path="adev/src/content/tutorials/first-app/steps/12-forms/src/app/housing-location/housing-location.component.ts" visibleLines="[13,20]"/>
<docs-code header="Add anchor with a routerLink directive to housing-location.component.ts" path="adev/src/content/tutorials/first-app/steps/12-forms/src/app/housing-location/housing-location.component.ts" visibleLines="[20]"/>
The `routerLink` directive enables Angular's router to create dynamic links in the application. The value assigned to the `routerLink` is an array with two entries: the static portion of the path and the dynamic data.
@@ -53,7 +53,7 @@ In this step, you will get the route parameter in the `DetailsComponent`. Curren
template: `<p>details works! {{ housingLocationId }}</p>`,
</docs-code>
1. Update the body of the `DetailsComponent` with the following code:
1. Update the body of the `DetailsComponent` class with the following code:
<docs-code language="javascript">
export class DetailsComponent {
@@ -79,13 +79,13 @@ To access the data you will add a call to the `HousingService`.
1. Update the template code to match the following code:
<docs-code header="Update the DetailsComponent template in src/app/details/details.component.ts" path="adev/src/content/tutorials/first-app/steps/12-forms/src/app/details/details.component.ts" visibleLines="[11,28]"/>
<docs-code header="Update the DetailsComponent template in src/app/details/details.component.ts" path="adev/src/content/tutorials/first-app/steps/12-forms/src/app/details/details.component.ts" visibleLines="[11,32]"/>
Notice that the `housingLocation` properties are being accessed with the optional chaining operator `?`. This ensures that if the `housingLocation` value is null or undefined the application doesn't crash.
1. Update the body of the `DetailsComponent` class to match the following code:
<docs-code header="Update the DetailsComponent class in src/app/details/details.component.ts" path="adev/src/content/tutorials/first-app/steps/12-forms/src/app/details/details.component.ts" visibleLines="[31,42]"/>
<docs-code header="Update the DetailsComponent class in src/app/details/details.component.ts" path="adev/src/content/tutorials/first-app/steps/12-forms/src/app/details/details.component.ts" visibleLines="[35,44]"/>
Now the component has the code to display the correct information based on the selected housing location. The `constructor` now includes a call to the `HousingService` to pass the route parameter as an argument to the `getHousingLocationById` service function.
@@ -106,7 +106,7 @@ In a previous lesson you updated the `AppComponent` template to include a `route
1. Confirm that your code matches the following:
<docs-code header="Add routerLink to AppComponent" path="adev/src/content/tutorials/first-app/steps/12-forms/src/app/app.component.ts" visibleLines="[13,24]"/>
<docs-code header="Add routerLink to AppComponent" path="adev/src/content/tutorials/first-app/steps/12-forms/src/app/app.component.ts" visibleLines="[8,20]"/>
Your code may already be up-to-date but confirm to be sure.
</docs-step>
@@ -25,7 +25,7 @@ In the **Edit** pane of your IDE:
1. In `src/app/housing.service.ts`, inside the `HousingService` class, paste this method at the bottom of the class definition.
<docs-code header="Submit method in src/app/housing.service.ts" path="adev/src/content/tutorials/first-app/steps/13-search/src/app/housing.service.ts" visibleLines="[120,122]"/>
<docs-code header="Submit method in src/app/housing.service.ts" path="adev/src/content/tutorials/first-app/steps/13-search/src/app/housing.service.ts" visibleLines="[120,124]"/>
1. Confirm that the app builds without error.
Correct any errors before you continue to the next step.
@@ -42,7 +42,7 @@ In the **Edit** pane of your IDE, in `src/app/details/details.component.ts`:
1. In the `DetailsComponent` decorator metadata, update the `imports` property with the following code:
<docs-code header="imports directive in src/app/details/details.component.ts" path="adev/src/content/tutorials/first-app/steps/13-search/src/app/details/details.component.ts" visibleLines="[10,13]"/>
<docs-code header="imports directive in src/app/details/details.component.ts" path="adev/src/content/tutorials/first-app/steps/13-search/src/app/details/details.component.ts" visibleLines="[10]"/>
1. In the `DetailsComponent` class, before the `constructor()` method, add the following code to create the form object.
@@ -52,7 +52,7 @@ In the **Edit** pane of your IDE, in `src/app/details/details.component.ts`:
1. In the `DetailsComponent` class, after the `constructor()` method, add the following code to handle the **Apply now** click.
<docs-code header="template directive in src/app/details/details.component.ts" path="adev/src/content/tutorials/first-app/steps/13-search/src/app/details/details.component.ts" visibleLines="[64,69]"/>
<docs-code header="template directive in src/app/details/details.component.ts" path="adev/src/content/tutorials/first-app/steps/13-search/src/app/details/details.component.ts" visibleLines="[63,69]"/>
This button does not exist yet - you will add it in the next step. In the above code, the `FormControl`s may return `null`. This code uses the nullish coalescing operator to default to empty string if the value is `null`.
@@ -67,7 +67,7 @@ In the **Edit** pane of your IDE, in `src/app/details/details.component.ts`:
1. In the `DetailsComponent` decorator metadata, update the `template` HTML to match the following code to add the form's markup.
<docs-code header="template directive in src/app/details/details.component.ts" path="adev/src/content/tutorials/first-app/steps/13-search/src/app/details/details.component.ts" visibleLines="[15,45]"/>
<docs-code header="template directive in src/app/details/details.component.ts" path="adev/src/content/tutorials/first-app/steps/13-search/src/app/details/details.component.ts" visibleLines="[11,46]"/>
The template now includes an event handler `(submit)="submitApplication()"`. Angular uses parentheses syntax around the event name to define events in the template code. The code on the right hand side of the equals sign is the code that should be executed when this event is triggered. You can bind to browser events and custom events.
@@ -20,13 +20,13 @@ In this step, you'll update the `HomeComponent` class to store data in a new arr
1. In `src/app/home/home.component.ts`, add new property to the class called `filteredLocationList`.
<docs-code header="Add the filtered results property" path="adev/src/content/tutorials/first-app/steps/14-http/src/app/home/home.component.ts" visibleLines="[30,33]"/>
<docs-code header="Add the filtered results property" path="adev/src/content/tutorials/first-app/steps/14-http/src/app/home/home.component.ts" visibleLines="[30]"/>
The `filteredLocationList` hold the values that match the search criteria entered by the user.
1. The `filteredLocationList` should contain the total set of housing locations values by default when the page loads. Update the `constructor` for the `HomeComponent` to set the value.
<docs-code header="Set the value of filteredLocationList" path="adev/src/content/tutorials/first-app/steps/14-http/src/app/home/home.component.ts" visibleLines="[35,39]"/>
<docs-code header="Set the value of filteredLocationList" path="adev/src/content/tutorials/first-app/steps/14-http/src/app/home/home.component.ts" visibleLines="[31,34]"/>
</docs-step>
@@ -62,7 +62,7 @@ The template has been updated to bind the `filterResults` function to the `click
1. Update the `HomeComponent` class to include the implementation of the `filterResults` function.
<docs-code header="Add the filterResults function implementation" path="adev/src/content/tutorials/first-app/steps/14-http/src/app/home/home.component.ts" visibleLines="[41,45]"/>
<docs-code header="Add the filterResults function implementation" path="adev/src/content/tutorials/first-app/steps/14-http/src/app/home/home.component.ts" visibleLines="[35,44]"/>
This function uses the `String` `filter` function to compare the value of the `text` parameter against the `housingLocation.city` property. You can update this function to match against any property or multiple properties for a fun exercise.
@@ -162,7 +162,7 @@ The data source has been configured, the next step is to update your web app to
1. Update the `getAllHousingLocations` function to make a call to the web server you configured.
<docs-code header="" path="adev/src/content/tutorials/first-app/steps/14-http/src-final/app/housing.service.ts" visibleLines="[12,14]"/>
<docs-code header="" path="adev/src/content/tutorials/first-app/steps/14-http/src-final/app/housing.service.ts" visibleLines="[10,13]"/>
The code now uses asynchronous code to make a **GET** request over HTTP.
@@ -170,11 +170,11 @@ The data source has been configured, the next step is to update your web app to
1. Update the `getHousingLocationsById` function to make a call to the web server you configured.
<docs-code header="" path="adev/src/content/tutorials/first-app/steps/14-http/src-final/app/housing.service.ts" visibleLines="[16,19]"/>
<docs-code header="" path="adev/src/content/tutorials/first-app/steps/14-http/src-final/app/housing.service.ts" visibleLines="[15,18]"/>
1. Once all the updates are complete, your updated service should match the following code.
<docs-code header="Final version of housing.service.ts" path="adev/src/content/tutorials/first-app/steps/14-http/src-final/app/housing.service.ts"/>
<docs-code header="Final version of housing.service.ts" path="adev/src/content/tutorials/first-app/steps/14-http/src-final/app/housing.service.ts" visibleLines="[1,24]" />
</docs-step>
@@ -183,7 +183,7 @@ The server is now reading data from the HTTP request but the components that rel
1. In `src/app/home/home.component.ts`, update the `constructor` to use the new asynchronous version of the `getAllHousingLocations` method.
<docs-code header="" path="adev/src/content/tutorials/first-app/steps/14-http/src-final/app/home/home.component.ts" visibleLines="[36,41]"/>
<docs-code header="" path="adev/src/content/tutorials/first-app/steps/14-http/src-final/app/home/home.component.ts" visibleLines="[32,37]"/>
1. In `src/app/details/details.component.ts`, update the `constructor` to use the new asynchronous version of the `getHousingLocationById` method.
+16 -1
View File
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<!-- We set all theme classes to allow critters to inline the theme styles and prevent flickering -->
<html lang="en" class="docs-dark-mode docs-light-mode">
<head>
@@ -24,7 +24,22 @@
} else {
documentClassList.add(LIGHT_MODE_CLASS_NAME);
}
if(location.search.includes('uwu')) {
documentClassList.add('uwu');
}
</script>
<style>
.uwu-logo {
display: none;
}
html.uwu .angular-logo {
display: none;
}
html.uwu .uwu-logo {
display: block !important;
}
</style>
<meta charset="utf-8" />
<title>Angular</title>
@@ -13,14 +13,14 @@
},
"private": true,
"dependencies": {
"@angular/animations": "17.3.7",
"@angular/common": "17.3.7",
"@angular/compiler": "17.3.7",
"@angular/core": "17.3.7",
"@angular/forms": "17.3.7",
"@angular/platform-browser": "17.3.7",
"@angular/platform-browser-dynamic": "17.3.7",
"@angular/router": "17.3.7",
"@angular/animations": "17.3.8",
"@angular/common": "17.3.8",
"@angular/compiler": "17.3.8",
"@angular/core": "17.3.8",
"@angular/forms": "17.3.8",
"@angular/platform-browser": "17.3.8",
"@angular/platform-browser-dynamic": "17.3.8",
"@angular/router": "17.3.8",
"angular": "^1.8.3",
"angular-in-memory-web-api": "~0.17.0",
"angular-route": "1.8.3",
@@ -29,9 +29,9 @@
"zone.js": "~0.14.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "17.3.6",
"@angular/cli": "17.3.6",
"@angular/compiler-cli": "17.3.7",
"@angular-devkit/build-angular": "17.3.7",
"@angular/cli": "17.3.7",
"@angular/compiler-cli": "17.3.8",
"@types/angular": "^1.8.4",
"@types/angular-route": "^1.7.2",
"@types/jasmine": "~5.1.0",
@@ -13,23 +13,23 @@
},
"private": true,
"dependencies": {
"@angular/animations": "17.3.7",
"@angular/common": "17.3.7",
"@angular/compiler": "17.3.7",
"@angular/core": "17.3.7",
"@angular/forms": "17.3.7",
"@angular/platform-browser": "17.3.7",
"@angular/platform-browser-dynamic": "17.3.7",
"@angular/router": "17.3.7",
"@angular/animations": "17.3.8",
"@angular/common": "17.3.8",
"@angular/compiler": "17.3.8",
"@angular/core": "17.3.8",
"@angular/forms": "17.3.8",
"@angular/platform-browser": "17.3.8",
"@angular/platform-browser-dynamic": "17.3.8",
"@angular/router": "17.3.8",
"angular-in-memory-web-api": "~0.17.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "17.3.6",
"@angular/cli": "17.3.6",
"@angular/compiler-cli": "17.3.7",
"@angular-devkit/build-angular": "17.3.7",
"@angular/cli": "17.3.7",
"@angular/compiler-cli": "17.3.8",
"@types/jasmine": "~5.1.0",
"@types/node": "^16.11.35",
"copyfiles": "^2.4.1",
@@ -13,24 +13,24 @@
},
"private": true,
"dependencies": {
"@angular/animations": "17.3.7",
"@angular/common": "17.3.7",
"@angular/compiler": "17.3.7",
"@angular/core": "17.3.7",
"@angular/elements": "17.3.7",
"@angular/forms": "17.3.7",
"@angular/platform-browser": "17.3.7",
"@angular/platform-browser-dynamic": "17.3.7",
"@angular/router": "17.3.7",
"@angular/animations": "17.3.8",
"@angular/common": "17.3.8",
"@angular/compiler": "17.3.8",
"@angular/core": "17.3.8",
"@angular/elements": "17.3.8",
"@angular/forms": "17.3.8",
"@angular/platform-browser": "17.3.8",
"@angular/platform-browser-dynamic": "17.3.8",
"@angular/router": "17.3.8",
"angular-in-memory-web-api": "~0.17.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "17.3.6",
"@angular/cli": "17.3.6",
"@angular/compiler-cli": "17.3.7",
"@angular-devkit/build-angular": "17.3.7",
"@angular/cli": "17.3.7",
"@angular/compiler-cli": "17.3.8",
"@types/jasmine": "~5.1.0",
"@types/node": "^16.11.35",
"jasmine-core": "~5.1.0",
@@ -15,24 +15,24 @@
},
"private": true,
"dependencies": {
"@angular/animations": "17.3.7",
"@angular/common": "17.3.7",
"@angular/compiler": "17.3.7",
"@angular/core": "17.3.7",
"@angular/forms": "17.3.7",
"@angular/localize": "17.3.7",
"@angular/platform-browser": "17.3.7",
"@angular/platform-browser-dynamic": "17.3.7",
"@angular/router": "17.3.7",
"@angular/animations": "17.3.8",
"@angular/common": "17.3.8",
"@angular/compiler": "17.3.8",
"@angular/core": "17.3.8",
"@angular/forms": "17.3.8",
"@angular/localize": "17.3.8",
"@angular/platform-browser": "17.3.8",
"@angular/platform-browser-dynamic": "17.3.8",
"@angular/router": "17.3.8",
"angular-in-memory-web-api": "~0.17.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "17.3.6",
"@angular/cli": "17.3.6",
"@angular/compiler-cli": "17.3.7",
"@angular-devkit/build-angular": "17.3.7",
"@angular/cli": "17.3.7",
"@angular/compiler-cli": "17.3.8",
"@types/jasmine": "~5.1.0",
"@types/node": "^16.11.35",
"jasmine-core": "~5.1.0",
@@ -13,24 +13,24 @@
},
"private": true,
"dependencies": {
"@angular/animations": "17.3.7",
"@angular/common": "17.3.7",
"@angular/compiler": "17.3.7",
"@angular/core": "17.3.7",
"@angular/forms": "17.3.7",
"@angular/platform-browser": "17.3.7",
"@angular/platform-browser-dynamic": "17.3.7",
"@angular/router": "17.3.7",
"@angular/service-worker": "17.3.7",
"@angular/animations": "17.3.8",
"@angular/common": "17.3.8",
"@angular/compiler": "17.3.8",
"@angular/core": "17.3.8",
"@angular/forms": "17.3.8",
"@angular/platform-browser": "17.3.8",
"@angular/platform-browser-dynamic": "17.3.8",
"@angular/router": "17.3.8",
"@angular/service-worker": "17.3.8",
"angular-in-memory-web-api": "~0.17.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "17.3.6",
"@angular/cli": "17.3.6",
"@angular/compiler-cli": "17.3.7",
"@angular-devkit/build-angular": "17.3.7",
"@angular/cli": "17.3.7",
"@angular/compiler-cli": "17.3.8",
"@types/jasmine": "~5.1.0",
"@types/node": "^16.11.35",
"jasmine-core": "~5.1.0",
@@ -25,15 +25,15 @@
},
"private": true,
"dependencies": {
"@angular/animations": "17.3.7",
"@angular/common": "17.3.7",
"@angular/compiler": "17.3.7",
"@angular/core": "17.3.7",
"@angular/forms": "17.3.7",
"@angular/platform-browser": "17.3.7",
"@angular/platform-browser-dynamic": "17.3.7",
"@angular/router": "17.3.7",
"@angular/upgrade": "17.3.7",
"@angular/animations": "17.3.8",
"@angular/common": "17.3.8",
"@angular/compiler": "17.3.8",
"@angular/core": "17.3.8",
"@angular/forms": "17.3.8",
"@angular/platform-browser": "17.3.8",
"@angular/platform-browser-dynamic": "17.3.8",
"@angular/router": "17.3.8",
"@angular/upgrade": "17.3.8",
"core-js": "^3.0.0",
"rxjs": "~7.8.0",
"systemjs": "~0.19.39",
@@ -42,7 +42,7 @@
"zone.js": "~0.14.0"
},
"devDependencies": {
"@angular/compiler-cli": "17.3.7",
"@angular/compiler-cli": "17.3.8",
"@rollup/plugin-commonjs": "^25.0.0",
"@rollup/plugin-node-resolve": "^13.2.0",
"@types/angular": "^1.8.4",
@@ -13,16 +13,16 @@
},
"private": true,
"dependencies": {
"@angular/animations": "17.3.7",
"@angular/common": "17.3.7",
"@angular/compiler": "17.3.7",
"@angular/core": "17.3.7",
"@angular/forms": "17.3.7",
"@angular/platform-browser": "17.3.7",
"@angular/platform-browser-dynamic": "17.3.7",
"@angular/platform-server": "17.3.7",
"@angular/router": "17.3.7",
"@angular/ssr": "17.3.6",
"@angular/animations": "17.3.8",
"@angular/common": "17.3.8",
"@angular/compiler": "17.3.8",
"@angular/core": "17.3.8",
"@angular/forms": "17.3.8",
"@angular/platform-browser": "17.3.8",
"@angular/platform-browser-dynamic": "17.3.8",
"@angular/platform-server": "17.3.8",
"@angular/router": "17.3.8",
"@angular/ssr": "17.3.7",
"angular-in-memory-web-api": "~0.17.0",
"express": "^4.18.1",
"rxjs": "~7.8.0",
@@ -30,9 +30,9 @@
"zone.js": "~0.14.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "17.3.6",
"@angular/cli": "17.3.6",
"@angular/compiler-cli": "17.3.7",
"@angular-devkit/build-angular": "17.3.7",
"@angular/cli": "17.3.7",
"@angular/compiler-cli": "17.3.8",
"@types/express": "^4.17.13",
"@types/jasmine": "~5.1.0",
"@types/node": "^16.11.35",
+18 -18
View File
@@ -19,20 +19,20 @@
"license": "MIT",
"repository": {},
"dependencies": {
"@angular/animations": "17.3.7",
"@angular/common": "17.3.7",
"@angular/compiler": "17.3.7",
"@angular/core": "17.3.7",
"@angular/elements": "17.3.7",
"@angular/forms": "17.3.7",
"@angular/localize": "17.3.7",
"@angular/platform-browser": "17.3.7",
"@angular/platform-browser-dynamic": "17.3.7",
"@angular/platform-server": "17.3.7",
"@angular/router": "17.3.7",
"@angular/service-worker": "17.3.7",
"@angular/ssr": "17.3.6",
"@angular/upgrade": "17.3.7",
"@angular/animations": "17.3.8",
"@angular/common": "17.3.8",
"@angular/compiler": "17.3.8",
"@angular/core": "17.3.8",
"@angular/elements": "17.3.8",
"@angular/forms": "17.3.8",
"@angular/localize": "17.3.8",
"@angular/platform-browser": "17.3.8",
"@angular/platform-browser-dynamic": "17.3.8",
"@angular/platform-server": "17.3.8",
"@angular/router": "17.3.8",
"@angular/service-worker": "17.3.8",
"@angular/ssr": "17.3.7",
"@angular/upgrade": "17.3.8",
"angular": "^1.8.3",
"angular-in-memory-web-api": "~0.17.0",
"angular-route": "1.8.3",
@@ -45,9 +45,9 @@
"zone.js": "~0.14.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "17.3.6",
"@angular/cli": "17.3.6",
"@angular/compiler-cli": "17.3.7",
"@angular-devkit/build-angular": "17.3.7",
"@angular/cli": "17.3.7",
"@angular/compiler-cli": "17.3.8",
"@rollup/plugin-commonjs": "^25.0.0",
"@rollup/plugin-node-resolve": "^13.2.0",
"@types/angular": "^1.8.4",
@@ -57,7 +57,7 @@
"@types/angular-route": "^1.7.2",
"@types/express": "^4.17.13",
"@types/jasmine": "~5.1.0",
"@types/jquery": "3.5.29",
"@types/jquery": "3.5.30",
"@types/node": "^16.11.35",
"canonical-path": "1.0.0",
"concurrently": "^8.0.0",
@@ -3,8 +3,8 @@
"short_name": "Angular DevTools",
"name": "Angular DevTools",
"description": "Angular DevTools extends Chrome DevTools adding Angular specific debugging and profiling capabilities.",
"version": "1.0.15",
"version_name": "1.0.15",
"version": "1.0.16",
"version_name": "1.0.16",
"minimum_chrome_version": "102",
"content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self'"
@@ -3,7 +3,7 @@
"short_name": "Angular DevTools",
"name": "Angular DevTools",
"description": "Angular DevTools extends Firefox DevTools adding Angular specific debugging and profiling capabilities.",
"version": "1.0.15",
"version": "1.0.16",
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
"icons": {
"16": "assets/icon16.png",
+2
View File
@@ -117,6 +117,8 @@ export const enum RuntimeErrorCode {
// (undocumented)
PLATFORM_NOT_FOUND = 401,
// (undocumented)
PROVIDED_BOTH_ZONE_AND_ZONELESS = 408,
// (undocumented)
PROVIDER_IN_WRONG_CONTEXT = 207,
// (undocumented)
PROVIDER_NOT_FOUND = -201,
+9
View File
@@ -4,6 +4,7 @@
```ts
import { EnvironmentProviders as EnvironmentProviders_2 } from '@angular/core';
import { Observable } from 'rxjs';
import { SIGNAL } from '@angular/core/primitives/signals';
import { SignalNode } from '@angular/core/primitives/signals';
@@ -226,6 +227,7 @@ export interface Component extends Directive {
changeDetection?: ChangeDetectionStrategy;
encapsulation?: ViewEncapsulation;
imports?: (Type<any> | ReadonlyArray<any>)[];
// @deprecated
interpolation?: [string, string];
// @deprecated
moduleId?: string;
@@ -1365,6 +1367,13 @@ export class PlatformRef {
// @public
export type Predicate<T> = (value: T) => boolean;
// @public
export function provideExperimentalCheckNoChangesForDebug(options: {
interval?: number;
useNgZoneOnStable?: boolean;
exhaustive?: boolean;
}): EnvironmentProviders_2;
// @public
export function provideExperimentalZonelessChangeDetection(): EnvironmentProviders;
@@ -5,41 +5,33 @@
```ts
// @public
export function bootstrapEarlyEventContract(field: string, container: HTMLElement, appId: string, eventTypes: string[], captureEventTypes: string[], earlyJsactionTracker?: EventContractTracker<EarlyJsactionDataContainer>): void;
// @public
export function bootstrapEventContract(field: string, container: Element, appId: string, events: string[], earlyJsactionTracker?: EventContractTracker<EventContract>): void;
export function bootstrapEarlyEventContract(field: string, container: HTMLElement, appId: string, eventTypes?: string[], captureEventTypes?: string[], earlyJsactionTracker?: EventContractTracker<EarlyJsactionDataContainer>): void;
// @public
export class Dispatcher {
constructor(getHandler?: ((eventInfoWrapper: EventInfoWrapper) => EventInfoWrapperHandler | void) | undefined, { stopPropagation, eventReplayer, }?: {
stopPropagation?: boolean;
constructor(dispatchDelegate: (eventInfoWrapper: EventInfoWrapper) => void, { actionResolver, eventReplayer, }?: {
actionResolver?: ActionResolver;
eventReplayer?: Replayer;
});
canDispatch(eventInfoWrapper: EventInfoWrapper): boolean;
dispatch(eventInfo: EventInfo, isGlobalDispatch?: boolean): void;
hasAction(name: string): boolean;
registerEventInfoHandlers<T>(namespace: string, instance: T | null, methods: {
[key: string]: EventInfoWrapperHandler;
}): void;
registerGlobalHandler(eventType: string, handler: GlobalHandler): void;
setEventReplayer(eventReplayer: Replayer): void;
unregisterGlobalHandler(eventType: string, handler: GlobalHandler): void;
unregisterHandler(namespace: string, name: string): void;
dispatch(eventInfo: EventInfo): void;
}
// @public (undocumented)
export interface EarlyJsactionDataContainer {
// (undocumented)
_ejsa?: EarlyJsactionData;
}
// @public
export class EventContract implements UnrenamedEventContract {
constructor(containerManager: EventContractContainerManager);
constructor(containerManager: EventContractContainerManager, useActionResolver?: boolean);
// (undocumented)
static A11Y_CLICK_SUPPORT: boolean;
addA11yClickSupport(): void;
addEvent(eventType: string, prefixedEventType?: string): void;
cleanUp(): void;
// (undocumented)
static CUSTOM_EVENT_SUPPORT: boolean;
// (undocumented)
ecaacs?: (updateEventInfoForA11yClick: typeof a11yClickLib.updateEventInfoForA11yClick, preventDefaultForA11yClick: typeof a11yClickLib.preventDefaultForA11yClick, populateClickOnlyAction: typeof a11yClickLib.populateClickOnlyAction) => void;
ecaacs?: (updateEventInfoForA11yClick: typeof a11yClick.updateEventInfoForA11yClick, preventDefaultForA11yClick: typeof a11yClick.preventDefaultForA11yClick, populateClickOnlyAction: typeof a11yClick.populateClickOnlyAction) => void;
ecrd(dispatcher: Dispatcher_2, restriction: Restriction): void;
exportAddA11yClickSupport(): void;
handler(eventType: string): EventHandler | undefined;
+17 -3
View File
@@ -565,6 +565,13 @@ export interface FormRecord<TControl> {
}): void;
}
// @public
export class FormResetEvent extends ControlEvent {
constructor(source: AbstractControl);
// (undocumented)
readonly source: AbstractControl;
}
// @public
export class FormsModule {
static withConfig(opts: {
@@ -578,6 +585,13 @@ export class FormsModule {
static ɵmod: i0.ɵɵNgModuleDeclaration<FormsModule, [typeof i1_2.NgModel, typeof i2_2.NgModelGroup, typeof i3_2.NgForm], never, [typeof i4_2.ɵInternalFormsSharedModule, typeof i1_2.NgModel, typeof i2_2.NgModelGroup, typeof i3_2.NgForm]>;
}
// @public
export class FormSubmittedEvent extends ControlEvent {
constructor(source: AbstractControl);
// (undocumented)
readonly source: AbstractControl;
}
// @public
export const isFormArray: (control: unknown) => control is FormArray<any>;
@@ -786,7 +800,7 @@ export class PatternValidator extends AbstractValidatorDirective {
}
// @public
export class PristineEvent extends ControlEvent {
export class PristineChangeEvent extends ControlEvent {
constructor(pristine: boolean, source: AbstractControl);
// (undocumented)
readonly pristine: boolean;
@@ -880,7 +894,7 @@ export class SelectMultipleControlValueAccessor extends BuiltInControlValueAcces
export type SetDisabledStateOption = 'whenDisabledForLegacyCode' | 'always';
// @public
export class StatusEvent extends ControlEvent {
export class StatusChangeEvent extends ControlEvent {
constructor(status: FormControlStatus, source: AbstractControl);
// (undocumented)
readonly source: AbstractControl;
@@ -889,7 +903,7 @@ export class StatusEvent extends ControlEvent {
}
// @public
export class TouchedEvent extends ControlEvent {
export class TouchedChangeEvent extends ControlEvent {
constructor(touched: boolean, source: AbstractControl);
// (undocumented)
readonly source: AbstractControl;
@@ -51,5 +51,12 @@
"polyfills": 33807,
"defer.component": 371
}
},
"platform-server-hydration/browser": {
"uncompressed": {
"main": 207890,
"polyfills": 33807,
"event-dispatch-contract.min": 648
}
}
}
+1 -1
View File
@@ -33,4 +33,4 @@
"protractor": "protractor e2e/protractor.config.js"
},
"private": true
}
}
@@ -0,0 +1,46 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# Compiled output
/dist
/tmp
/out-tsc
/bazel-out
# Node
/node_modules
npm-debug.log
yarn-error.log
# IDEs and editors
.idea/
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# Visual Studio Code
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# Miscellaneous
/.angular/cache
.sass-cache/
/connect.lock
/coverage
/libpeerconnection.log
testem.log
/typings
# System files
.DS_Store
Thumbs.db
# event contract
public/event-dispatch-contract.min.js
@@ -0,0 +1,10 @@
load("//integration:index.bzl", "ng_integration_test")
ng_integration_test(
name = "test",
setup_chromium = True,
track_payload_paths = [
"/browser",
],
track_payload_size = "platform-server-hydration",
)
@@ -0,0 +1,99 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"cli": {
"analytics": false,
"cache": {
"enabled": false
}
},
"projects": {
"hydration": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
"progress": false,
"outputPath": "dist",
"index": "src/index.html",
"browser": "src/main.ts",
"polyfills": ["zone.js"],
"tsConfig": "tsconfig.app.json",
"assets": [
{
"glob": "**/*",
"input": "public"
}
],
"styles": ["src/styles.css"],
"scripts": [],
"server": "src/main.server.ts",
"prerender": false,
"ssr": true
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"port": 0
},
"configurations": {
"production": {
"buildTarget": "hydration:build:production"
},
"development": {
"buildTarget": "hydration:build:development"
}
},
"defaultConfiguration": "development"
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"port": 0,
"protractorConfig": "e2e/protractor.conf.js",
"webdriverUpdate": false
},
"configurations": {
"production": {
"devServerTarget": "hydration:serve:production"
},
"development": {
"devServerTarget": "hydration:serve:development"
}
},
"defaultConfiguration": "development"
}
}
}
}
}
@@ -0,0 +1,11 @@
/**
* This script copies '@angular/core/event-dispatch-contract.min.js' to the 'public' directory, ensuring it's available as an asset.
* This is necessary to perform size checks on the distributed script.
*/
import {copyFileSync} from 'node:fs';
copyFileSync(
'./node_modules/@angular/core/event-dispatch-contract.min.js',
'public/event-dispatch-contract.min.js',
);
@@ -0,0 +1,42 @@
// @ts-check
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const {SpecReporter} = require('jasmine-spec-reporter');
/**
* @type { import("protractor").Config }
*/
exports.config = {
allScriptsTimeout: 11000,
specs: ['./src/**/*.e2e-spec.ts'],
chromeDriver: process.env.CHROMEDRIVER_BIN,
capabilities: {
browserName: 'chrome',
chromeOptions: {
binary: process.env.CHROME_BIN,
// See /integration/README.md#browser-tests for more info on these args
args: [
'--no-sandbox',
'--headless',
'--disable-gpu',
'--disable-dev-shm-usage',
'--hide-scrollbars',
'--mute-audio',
],
},
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function () {},
},
onPrepare() {
require('ts-node').register({
project: require('path').join(__dirname, './tsconfig.json'),
});
jasmine.getEnv().addReporter(new SpecReporter({spec: {displayStacktrace: true}}));
},
};
@@ -0,0 +1,30 @@
import {browser, by, element} from 'protractor';
import {bootstrapClientApp, navigateTo, verifyNoBrowserErrors} from './util';
describe('App E2E Tests', () => {
beforeEach(async () => {
// Don't wait for Angular since it is not bootstrapped automatically.
await browser.waitForAngularEnabled(false);
// Load the page without waiting for Angular since it is not bootstrapped automatically.
await navigateTo('');
});
afterEach(async () => {
// Make sure there were no client side errors.
await verifyNoBrowserErrors();
});
it('should reply click event', async () => {
const divElement = element(by.css('#divElement'));
expect(await divElement.getText()).toContain('click not triggered');
// Trigger click
await divElement.click();
// Bootstrap client application
await bootstrapClientApp();
expect(await divElement.getText()).toContain('click triggered');
});
});
@@ -0,0 +1,31 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import * as webdriver from 'selenium-webdriver';
import {browser} from 'protractor';
export async function verifyNoBrowserErrors(): Promise<void> {
const browserLog = await browser.manage().logs().get('browser');
const errors: string[] = [];
for (const {message, level} of browserLog) {
console.log('>> ' + message);
if (level.value >= webdriver.logging.Level.INFO.value) {
errors.push(message);
}
}
expect(errors).toEqual([]);
}
export async function navigateTo(url: string): Promise<void> {
await browser.driver.get(browser.baseUrl + url);
}
export async function bootstrapClientApp(): Promise<void> {
await browser.executeScript('doBootstrap()');
}
@@ -0,0 +1,13 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/e2e",
"module": "commonjs",
"target": "es2019",
"types": [
"jasmine",
"node"
]
}
}
@@ -0,0 +1,40 @@
{
"name": "hydration",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build --configuration production",
"postinstall": "node ./copy-event-dispatch-contract.mjs",
"pretest": "ng version",
"test": "yarn e2e",
"lint": "ng lint",
"e2e": "ng e2e --configuration=production"
},
"private": true,
"dependencies": {
"@angular/animations": "file:../../dist/packages-dist/animations",
"@angular/common": "file:../../dist/packages-dist/common",
"@angular/compiler": "file:../../dist/packages-dist/compiler",
"@angular/core": "file:../../dist/packages-dist/core",
"@angular/platform-browser": "file:../../dist/packages-dist/platform-browser",
"@angular/platform-browser-dynamic": "file:../../dist/packages-dist/platform-browser-dynamic",
"@angular/platform-server": "file:../../dist/packages-dist/platform-server",
"@angular/router": "file:../../dist/packages-dist/router",
"rxjs": "file:../../node_modules/rxjs",
"tslib": "file:../../node_modules/tslib",
"zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz"
},
"devDependencies": {
"@angular-devkit/build-angular": "file:../../node_modules/@angular-devkit/build-angular",
"@angular/cli": "file:../../node_modules/@angular/cli",
"@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli",
"@types/jasmine": "file:../../node_modules/@types/jasmine",
"@types/node": "file:../../node_modules/@types/node",
"jasmine-core": "3.5.0",
"jasmine-spec-reporter": "4.2.1",
"protractor": "file:../../node_modules/protractor",
"ts-node": "8.3.0",
"typescript": "file:../../node_modules/typescript"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@@ -0,0 +1,3 @@
<div (click)="onClick()" id="divElement">click not triggered.</div>
<router-outlet />
@@ -0,0 +1,29 @@
import {TestBed} from '@angular/core/testing';
import {AppComponent} from './app.component';
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AppComponent],
}).compileComponents();
});
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
it(`should have the 'hydration' title`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual('hydration');
});
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, hydration');
});
});
@@ -0,0 +1,16 @@
import {Component} from '@angular/core';
import {RouterOutlet} from '@angular/router';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet],
templateUrl: './app.component.html',
styleUrl: './app.component.css',
})
export class AppComponent {
title = 'hydration';
onClick = () => {
document.querySelector('#divElement')!.textContent = 'click triggered.';
};
}
@@ -0,0 +1,9 @@
import {mergeApplicationConfig, ApplicationConfig} from '@angular/core';
import {provideServerRendering} from '@angular/platform-server';
import {appConfig} from './app.config';
const serverConfig: ApplicationConfig = {
providers: [provideServerRendering()],
};
export const config = mergeApplicationConfig(appConfig, serverConfig);
@@ -0,0 +1,18 @@
import {ApplicationConfig, provideZoneChangeDetection} from '@angular/core';
import {provideRouter} from '@angular/router';
import {
provideClientHydration,
provideProtractorTestingSupport,
withEventReplay,
} from '@angular/platform-browser';
import {routes} from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({eventCoalescing: true}),
provideRouter(routes),
provideClientHydration(withEventReplay()),
provideProtractorTestingSupport(),
],
};
@@ -0,0 +1,3 @@
import {Routes} from '@angular/router';
export const routes: Routes = [];
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Hydration</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
</head>
<body>
<app-root></app-root>
</body>
</html>
@@ -0,0 +1,7 @@
import {bootstrapApplication} from '@angular/platform-browser';
import {AppComponent} from './app/app.component';
import {config} from './app/app.config.server';
const bootstrap = () => bootstrapApplication(AppComponent, config);
export default bootstrap;
@@ -0,0 +1,7 @@
import {bootstrapApplication} from '@angular/platform-browser';
import {appConfig} from './app/app.config';
import {AppComponent} from './app/app.component';
(globalThis as any)['doBootstrap'] = () => {
bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err));
};
@@ -0,0 +1 @@
/* You can add global styles to this file, and also import other style files */

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