diff --git a/.node-version b/.node-version index d135defb28..19464bf8db 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -22.12.0 \ No newline at end of file +22.22.2 \ No newline at end of file diff --git a/adev-ja/src/app/core/services/a-dev-title-strategy.en.ts b/adev-ja/src/app/core/services/a-dev-title-strategy.en.ts index d023d95b94..60662a00dd 100644 --- a/adev-ja/src/app/core/services/a-dev-title-strategy.en.ts +++ b/adev-ja/src/app/core/services/a-dev-title-strategy.en.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ -import {Injectable, inject} from '@angular/core'; +import {inject, Service} from '@angular/core'; import {NavigationItem} from '@angular/docs'; import {Meta, Title} from '@angular/platform-browser'; import {ActivatedRouteSnapshot, RouterStateSnapshot, TitleStrategy} from '@angular/router'; @@ -22,7 +22,7 @@ export const TITLE_TWITTER_META_TAG = 'twitter:title'; export const ALL_TITLE_META_TAGS = [TITLE_OG_META_TAG, TITLE_TWITTER_META_TAG]; -@Injectable({providedIn: 'root'}) +@Service() export class ADevTitleStrategy extends TitleStrategy { private readonly title = inject(Title); private readonly meta = inject(Meta); diff --git a/adev-ja/src/app/core/services/a-dev-title-strategy.ts b/adev-ja/src/app/core/services/a-dev-title-strategy.ts index 31d1549da8..0ebdf56b4c 100644 --- a/adev-ja/src/app/core/services/a-dev-title-strategy.ts +++ b/adev-ja/src/app/core/services/a-dev-title-strategy.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ -import {Injectable, inject} from '@angular/core'; +import {inject, Service} from '@angular/core'; import {NavigationItem} from '@angular/docs'; import {Meta, Title} from '@angular/platform-browser'; import {ActivatedRouteSnapshot, RouterStateSnapshot, TitleStrategy} from '@angular/router'; @@ -22,7 +22,7 @@ export const TITLE_TWITTER_META_TAG = 'twitter:title'; export const ALL_TITLE_META_TAGS = [TITLE_OG_META_TAG, TITLE_TWITTER_META_TAG]; -@Injectable({providedIn: 'root'}) +@Service() export class ADevTitleStrategy extends TitleStrategy { private readonly title = inject(Title); private readonly meta = inject(Meta); diff --git a/adev-ja/src/app/features/home/home.component.en.html b/adev-ja/src/app/features/home/home.component.en.html index 8a7a65c1db..0af7560ddf 100644 --- a/adev-ja/src/app/features/home/home.component.en.html +++ b/adev-ja/src/app/features/home/home.component.en.html @@ -3,9 +3,9 @@
- -

Angular v21 is here!

-

🕹 Start your adventure

+
+

Angular v22 is here!

+

⚡ Explore what's new

@@ -36,49 +36,49 @@

The framework for building scalable web apps with confidence

-
+

Features that actually
help you solve problems

-
+
-
Signals
-
Control Flow
-
Deferrable Views
-
Hydration
+
Signals
+
Control Flow
+
Deferrable Views
+
Hydration
-
- - @defer (on idle) { +
+ @defer (on idle) { + - } - + + }
-
- - @defer (on idle) { +
+ @defer (on idle) { + - } - + + }
-
- - @defer { +
+ @defer (on idle) { + - } - + + }
-
- - @defer { +
+ @defer (on idle) { + - } - + + }
diff --git a/adev-ja/src/app/features/home/home.component.html b/adev-ja/src/app/features/home/home.component.html index 5f39e07600..8899e45a43 100644 --- a/adev-ja/src/app/features/home/home.component.html +++ b/adev-ja/src/app/features/home/home.component.html @@ -3,9 +3,9 @@
-
+

あなたの問題解決を助ける
倚くの機胜

-
+
-
シグナル
-
制埡フロヌ
-
遅延可胜ビュヌ
-
ハむドレヌション
+
シグナル
+
制埡フロヌ
+
遅延可胜ビュヌ
+
ハむドレヌション
-
- - @defer (on idle) { +
+ @defer (on idle) { + - } - + + }
-
- - @defer (on idle) { +
+ @defer (on idle) { + - } - + + }
-
- - @defer { +
+ @defer (on idle) { + - } - + + }
-
- - @defer { +
+ @defer (on idle) { + - } - + + }
diff --git a/adev-ja/src/app/features/update/recommendations.en.ts b/adev-ja/src/app/features/update/recommendations.en.ts index f0c49b2079..df358a32c2 100644 --- a/adev-ja/src/app/features/update/recommendations.en.ts +++ b/adev-ja/src/app/features/update/recommendations.en.ts @@ -2933,4 +2933,285 @@ export const RECOMMENDATIONS: Step[] = [ action: "Starting `@angular/ssr` 21.1.5, if your application uses SSR with `CommonEngine`, set the `allowedHosts` option in your `server.ts` (for example, `new CommonEngine({allowedHosts: ['localhost', '*.yourdomain.com']})`). Without it, SSR silently falls back to client-side rendering. This requirement comes from security advisory [GHSA-x288-3778-4hhx](https://github.com/angular/angular-cli/security/advisories/GHSA-x288-3778-4hhx) (also backported to 20.3.17 and 19.2.21).", }, + { + action: + "In the application's project directory, run `ng update @angular/core@22 @angular/cli@22` to update your application to Angular v22.", + level: ApplicationComplexity.Basic, + necessaryAsOf: 2200, + possibleIn: 2200, + step: '22.0.0_ng_update', + }, + + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Basic, + material: true, + step: 'update @angular/material', + action: 'Run `ng update @angular/material@22`.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Basic, + step: '22.0.0-update-nodejs-version', + action: + 'Angular v22 requires Node.js v22.22.3 or v24.15.0 and later. Update your Node.js version to meet this minimum requirement. You can check your current version with `node --version`.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Basic, + step: '22.0.0-update-typescript-version', + action: + 'Update your project to use TypeScript 6.0 or later. Versions older than 6.0 are no longer supported. Use `ng update` which will handle this automatically.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-data-attributes-input-output-binding', + action: + 'Data-prefixed attributes (e.g., `data-*`) no longer bind to inputs or outputs. If you were relying on this behavior, use explicit property bindings instead (e.g., `[attr.data-value]="value"` or `[dataValue]="value"` for a component input).', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-duplicate-input-output-bindings', + action: + 'The compiler now throws an error when inputs, outputs, or model are binding to the same property/output. Review your component decorators and ensure no duplicate bindings exist.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-safe-navigation-nullability-narrowing', + action: + 'Safe navigation (`?.`) and nullish coalescing (`??`) now correctly narrow down nullable types in templates. This may trigger `nullishCoalescingNotNullable` and `optionalChainNotNullable` diagnostics on existing projects. Either fix the diagnostics by updating your templates, or temporarily disable them in your `tsconfig.json` under `angularCompilerOptions`.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-safe-navigation-returns-undefined', + action: + 'Angular expressions with optional chaining (`?.`) now return `undefined` instead of `null`. You can use the `$safeNavigationMigration()` magic function to revert to the previous behavior.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-remove-in-expressions', + action: + '`in` variables in template expressions now throw an error as it does in native JavaScript. If you have variables named `in` in your component or template, update your template expressions to use `this.in` or rename your variable.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-animation-callback-event-signature-change', + action: + 'The `AnimationCallbackEvent.animationComplete` signature has changed. Update any code that depends on the old signature of this event. Review your animation event handlers and tests.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-http-xhr-backend-explicit-opt-in', + action: + 'If your application uses upload progress reporting through `HttpXhrBackend`, explicitly opt-in by using `provideHttpClient(withXhr())`. The default HTTP client no longer includes XHR support by default.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-deprecate-report-progress-option', + action: + 'The `reportProgress` option in HTTP requests is deprecated. Use `reportUploadProgress` or `reportDownloadProgress` instead for more explicit control over progress reporting.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-provide-routes-removed', + action: + '`provideRoutes()` has been removed. Use `provideRouter()` instead, or configure routes as a multi token using `ROUTES` if necessary. Update your application bootstrap configuration.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-upgrade-angular-js-global-migration', + action: + 'If using AngularJS interoperability, replace deprecated `getAngularLib()` and `setAngularLib()` with `getAngularJSGlobal()` and `setAngularJSGlobal()` respectively.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-remove-component-factory-resolver', + action: + '`ComponentFactoryResolver` and `ComponentFactory` are no longer available. Pass the component class directly to APIs like `ViewContainerRef.createComponent()` or use the standalone `createComponent()` function instead.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-remove-create-ng-module-ref', + action: + '`createNgModuleRef` has been removed. Use `createNgModule()` instead for dynamic module creation scenarios.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-compile-time-duplicate-selectors', + action: + 'Elements with multiple matching selectors now throw a compile-time error. Ensure your components use unique selectors and review any directives that might have conflicting selectors.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-component-onpush-default', + action: + 'Components with no `changeDetection` property defined are now `OnPush` by default. To maintain `Eager` (the previous default) change detection, explicitly set `changeDetection: ChangeDetectionStrategy.Eager` in your component decorator.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-remove-check-no-changes', + action: + '`ChangeDetectorRef.checkNoChanges()` has been removed. In tests, use `fixture.detectChanges()` instead or verify your component state through other means.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-leave-animations-scope-change', + action: + 'Leave animations are no longer limited to the element being removed. They now support nested animations scoped to component boundaries. Review your animation configurations if you relied on the previous scoping behavior.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-params-inheritance-strategy-default', + action: + '`paramsInheritanceStrategy` now defaults to `"always"` instead of `"emptyOnly"`. This means route parameters are inherited from all parent routes. To restore the previous behavior, explicitly set `paramsInheritanceStrategy: "emptyOnly"` in your router configuration.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-can-match-current-snapshot-required', + action: + 'The `currentSnapshot` parameter in `CanMatchFn` and the `canMatch` method of the `CanMatch` interface is now required. Update any class implementations of `CanMatch` to include this required third argument.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-hammer-js-removed', + action: + 'Hammer.js integration has been removed from Angular platform-browser. If you need touch gesture support, implement your own gesture detection or use an alternative library.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-app-ref-bootstrap-typing', + action: + 'The second argument of `appRef.bootstrap()` no longer accepts `any` type. Ensure the element you pass is not nullable and matches the expected type.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-platform-browser-styles-removal', + action: + 'Unused styles are now automatically removed when their associated `host` is dropped. Be aware that other DOM on the page may be affected if those styles are used by elements outside of Angular or if not using `ViewEncapsulation.Emulated`.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-title-strategy-return-type', + action: + 'The return type for `TitleStrategy.getResolvedTitleForRoute` has changed from `any` to a stricter type (e.g., `string | undefined`). Update your custom `TitleStrategy` implementations to match the new signature.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Basic, + step: '22.0.0-incremental-hydration-default', + action: + 'Incremental hydration is now the default behavior for applications using Server-Side Rendering (SSR). Review your application if you relied on the previous non-incremental hydration behavior. You can use `withNoIncrementalHydration()` to restore the previous behavior if needed.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-full-template-type-check-removed', + action: + 'The `fullTemplateTypeCheck` compiler option has been removed. Use `strictTemplates` instead to enable strict template type checking in your `tsconfig.json`.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Basic, + step: '22.0.0-strict-templates-default', + action: + 'The `strictTemplates` compiler option now defaults to `true`. If your project was not using strict template type checking, you may see new compilation errors. Resolve these errors or explicitly set `strictTemplates: false` in your `tsconfig.json` to opt out.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-webpack-builders-deprecated', + action: + 'Webpack builders (`@angular-devkit/build-angular` and `@angular-devkit/build-webpack`) are now deprecated. Migrate to the `@angular/build` builders (esbuild/application) for your application builds.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-ssr-commonengine-deprecated', + action: + '`CommonEngine` APIs from `@angular/ssr` are deprecated. Migrate to `AngularNodeAppEngine` or `AngularAppEngine` instead.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-istanbul-lib-instrument-optional', + action: + '`istanbul-lib-instrument` is now an optional peer dependency. If your project uses Karma with code coverage enabled, ensure `istanbul-lib-instrument` is explicitly installed.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Basic, + step: '22.0.0-dev-server-port-env-priority', + action: + '`ng serve` now gives the highest priority to the `PORT` environment variable. This value overrides any port configured in `angular.json` or provided via the `--port` flag.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-architect-cli-removed', + action: + 'The `@angular-devkit/architect-cli` package is no longer available. Use the `architect` CLI tool from the `@angular-devkit/architect` package instead.', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-experimental-test-builders-removed', + action: + 'The experimental `@angular-devkit/build-angular:jest` and `@angular-devkit/build-angular:web-test-runner` test builders have been removed.', + }, ]; diff --git a/adev-ja/src/app/features/update/recommendations.ts b/adev-ja/src/app/features/update/recommendations.ts index 911cf26691..66574888d0 100644 --- a/adev-ja/src/app/features/update/recommendations.ts +++ b/adev-ja/src/app/features/update/recommendations.ts @@ -2933,4 +2933,285 @@ export const RECOMMENDATIONS: Step[] = [ action: "`@angular/ssr` 21.1.5以降、アプリケヌションがSSRで`CommonEngine`を䜿甚しおいる堎合は、`server.ts`で`allowedHosts`オプションを蚭定しおください䟋: `new CommonEngine({allowedHosts: ['localhost', '*.yourdomain.com']})`。蚭定しない堎合、SSRはサむレントにクラむアントサむドレンダリングにフォヌルバックしたす。この芁件はセキュリティアドバむザリ [GHSA-x288-3778-4hhx](https://github.com/angular/angular-cli/security/advisories/GHSA-x288-3778-4hhx) に基づくものです20.3.17および19.2.21にもバックポヌトされおいたす。", }, + { + action: + "アプリケヌションのプロゞェクトディレクトリで、`ng update @angular/core@22 @angular/cli@22` を実行しお、アプリケヌションを Angular v22 に曎新したす。", + level: ApplicationComplexity.Basic, + necessaryAsOf: 2200, + possibleIn: 2200, + step: '22.0.0_ng_update', + }, + + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Basic, + material: true, + step: 'update @angular/material', + action: '`ng update @angular/material@22` を実行したす。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Basic, + step: '22.0.0-update-nodejs-version', + action: + 'Angular v22 には Node.js v22.22.3 たたは v24.15.0 以降が必芁です。この最小芁件を満たすように Node.js のバヌゞョンを曎新しおください。`node --version` で珟圚のバヌゞョンを確認できたす。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Basic, + step: '22.0.0-update-typescript-version', + action: + 'プロゞェクトを TypeScript 6.0 以降を䜿甚するように曎新しおください。6.0 より叀いバヌゞョンはサポヌトされなくなりたした。`ng update` を䜿甚すれば自動的に凊理されたす。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-data-attributes-input-output-binding', + action: + 'data プレフィックス付き属性 (䟋: `data-*`) は入力や出力にバむンドされなくなりたした。この動䜜に䟝存しおいた堎合は、明瀺的なプロパティバむンディングを䜿甚しおください (䟋: `[attr.data-value]="value"` や、コンポヌネント入力に察する `[dataValue]="value"`)。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-duplicate-input-output-bindings', + action: + '入力、出力、たたは model が同じプロパティ/出力にバむンドされおいる堎合、コンパむラヌが゚ラヌをスロヌするようになりたした。コンポヌネントデコレヌタヌを確認し、重耇したバむンディングが存圚しないようにしおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-safe-navigation-nullability-narrowing', + action: + 'セヌフナビゲヌション (`?.`) ず nullish 合䜓 (`??`) がテンプレヌト内で nullable 型を正しく絞り蟌むようになりたした。既存プロゞェクトでは `nullishCoalescingNotNullable` ず `optionalChainNotNullable` の蚺断が発生する可胜性がありたす。テンプレヌトを曎新しお蚺断を修正するか、`tsconfig.json` の `angularCompilerOptions` でこれらを䞀時的に無効化しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-safe-navigation-returns-undefined', + action: + 'オプショナルチェむニング (`?.`) を䜿甚した Angular の匏は、`null` の代わりに `undefined` を返すようになりたした。以前の動䜜に戻すには `$safeNavigationMigration()` マゞック関数を䜿甚できたす。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-remove-in-expressions', + action: + 'テンプレヌト匏䞭の `in` 倉数は、ネむティブ JavaScript ず同様に゚ラヌをスロヌするようになりたした。コンポヌネントやテンプレヌトに `in` ずいう名前の倉数がある堎合は、テンプレヌト匏を `this.in` に曎新するか、倉数の名前を倉曎しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-animation-callback-event-signature-change', + action: + '`AnimationCallbackEvent.animationComplete` のシグネチャが倉曎されたした。このむベントの叀いシグネチャに䟝存しおいるコヌドを曎新しおください。アニメヌションむベントハンドラヌずテストを確認しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-http-xhr-backend-explicit-opt-in', + action: + 'アプリケヌションが `HttpXhrBackend` 経由でアップロヌドの進捗レポヌトを䜿甚しおいる堎合は、`provideHttpClient(withXhr())` を䜿甚しお明瀺的にオプトむンしおください。デフォルトの HTTP クラむアントは、XHR サポヌトをデフォルトで含たなくなりたした。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-deprecate-report-progress-option', + action: + 'HTTP リク゚ストの `reportProgress` オプションは非掚奚になりたした。進捗レポヌトをより明瀺的に制埡するには、代わりに `reportUploadProgress` たたは `reportDownloadProgress` を䜿甚しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-provide-routes-removed', + action: + '`provideRoutes()` は削陀されたした。代わりに `provideRouter()` を䜿甚するか、必芁に応じお `ROUTES` を䜿甚しおマルチトヌクンずしおルヌトを蚭定しおください。アプリケヌションのブヌトストラップ蚭定を曎新しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-upgrade-angular-js-global-migration', + action: + 'AngularJS ずの盞互運甚を䜿甚しおいる堎合は、非掚奚の `getAngularLib()` および `setAngularLib()` をそれぞれ `getAngularJSGlobal()` および `setAngularJSGlobal()` に眮き換えおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-remove-component-factory-resolver', + action: + '`ComponentFactoryResolver` ず `ComponentFactory` は䜿甚できなくなりたした。`ViewContainerRef.createComponent()` のような API にコンポヌネントクラスを盎接枡すか、代わりにスタンドアロンの `createComponent()` 関数を䜿甚しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-remove-create-ng-module-ref', + action: + '`createNgModuleRef` は削陀されたした。動的なモゞュヌル䜜成シナリオでは、代わりに `createNgModule()` を䜿甚しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-compile-time-duplicate-selectors', + action: + '耇数の䞀臎するセレクタヌを持぀芁玠は、コンパむル時゚ラヌをスロヌするようになりたした。コンポヌネントが䞀意のセレクタヌを䜿甚しおいるこずを確認し、競合するセレクタヌを持぀ディレクティブを確認しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-component-onpush-default', + action: + '`changeDetection` プロパティが定矩されおいないコンポヌネントは、デフォルトで `OnPush` になりたした。`Eager` (以前のデフォルト) の倉曎怜知を維持するには、コンポヌネントデコレヌタヌで `changeDetection: ChangeDetectionStrategy.Eager` を明瀺的に蚭定しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-remove-check-no-changes', + action: + '`ChangeDetectorRef.checkNoChanges()` は削陀されたした。テストでは、代わりに `fixture.detectChanges()` を䜿甚するか、他の手段でコンポヌネントの状態を怜蚌しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-leave-animations-scope-change', + action: + 'leave アニメヌションは、削陀される芁玠のみに限定されなくなりたした。コンポヌネント境界にスコヌプされたネストされたアニメヌションをサポヌトするようになりたした。以前のスコヌプ動䜜に䟝存しおいた堎合は、アニメヌション蚭定を確認しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-params-inheritance-strategy-default', + action: + '`paramsInheritanceStrategy` のデフォルトが `"emptyOnly"` から `"always"` に倉曎されたした。これにより、ルヌトパラメヌタヌがすべおの芪ルヌトから継承されるようになりたす。以前の動䜜に戻すには、ルヌタヌ蚭定で `paramsInheritanceStrategy: "emptyOnly"` を明瀺的に蚭定しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-can-match-current-snapshot-required', + action: + '`CanMatchFn` および `CanMatch` むンタヌフェヌスの `canMatch` メ゜ッドの `currentSnapshot` パラメヌタヌが必須になりたした。`CanMatch` のクラス実装を曎新しお、必須の第3匕数を含めるようにしおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-hammer-js-removed', + action: + 'Hammer.js 統合は Angular の platform-browser から削陀されたした。タッチゞェスチャヌのサポヌトが必芁な堎合は、独自のゞェスチャヌ怜出を実装するか、代替ラむブラリを䜿甚しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-app-ref-bootstrap-typing', + action: + '`appRef.bootstrap()` の第2匕数は `any` 型を受け付けなくなりたした。枡す芁玠が nullable でなく、期埅される型ず䞀臎しおいるこずを確認しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-platform-browser-styles-removal', + action: + '関連付けられた `host` が削陀されるず、未䜿甚のスタむルが自動的に削陀されるようになりたした。これらのスタむルが Angular の倖郚の芁玠で䜿甚されおいる堎合や `ViewEncapsulation.Emulated` を䜿甚しおいない堎合、ペヌゞ䞊の他の DOM に圱響する可胜性があるこずに泚意しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-title-strategy-return-type', + action: + '`TitleStrategy.getResolvedTitleForRoute` の戻り型が `any` からより厳密な型 (䟋: `string | undefined`) に倉曎されたした。新しいシグネチャに合わせお、カスタム `TitleStrategy` の実装を曎新しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Basic, + step: '22.0.0-incremental-hydration-default', + action: + 'サヌバヌサむドレンダリング (SSR) を䜿甚するアプリケヌションのデフォルト動䜜ずしお、むンクリメンタルハむドレヌションが採甚されたした。以前の非むンクリメンタルハむドレヌションの動䜜に䟝存しおいた堎合は、アプリケヌションを確認しおください。必芁に応じお `withNoIncrementalHydration()` を䜿甚すれば以前の動䜜に戻せたす。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-full-template-type-check-removed', + action: + '`fullTemplateTypeCheck` コンパむラヌオプションは削陀されたした。`tsconfig.json` で厳密なテンプレヌト型チェックを有効にするには、代わりに `strictTemplates` を䜿甚しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Basic, + step: '22.0.0-strict-templates-default', + action: + '`strictTemplates` コンパむラヌオプションがデフォルトで `true` になりたした。プロゞェクトで厳密なテンプレヌト型チェックを䜿甚しおいなかった堎合、新しいコンパむル゚ラヌが衚瀺される可胜性がありたす。これらの゚ラヌを解決するか、`tsconfig.json` で `strictTemplates: false` を明瀺的に蚭定しおオプトアりトしおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-webpack-builders-deprecated', + action: + 'Webpack ビルダヌ (`@angular-devkit/build-angular` ず `@angular-devkit/build-webpack`) は非掚奚になりたした。アプリケヌションのビルドには `@angular/build` ビルダヌ (esbuild/application) に移行しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-ssr-commonengine-deprecated', + action: + '`@angular/ssr` の `CommonEngine` API は非掚奚になりたした。代わりに `AngularNodeAppEngine` たたは `AngularAppEngine` に移行しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-istanbul-lib-instrument-optional', + action: + '`istanbul-lib-instrument` はオプションのピア䟝存関係になりたした。プロゞェクトでコヌドカバレッゞを有効にした Karma を䜿甚しおいる堎合は、`istanbul-lib-instrument` を明瀺的にむンストヌルしおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Basic, + step: '22.0.0-dev-server-port-env-priority', + action: + '`ng serve` は `PORT` 環境倉数に最も高い優先床を䞎えるようになりたした。この倀は `angular.json` で蚭定されたポヌトや `--port` フラグで枡されたポヌトを䞊曞きしたす。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Advanced, + step: '22.0.0-architect-cli-removed', + action: + '`@angular-devkit/architect-cli` パッケヌゞは䜿甚できなくなりたした。代わりに `@angular-devkit/architect` パッケヌゞの `architect` CLI ツヌルを䜿甚しおください。', + }, + { + possibleIn: 2200, + necessaryAsOf: 2200, + level: ApplicationComplexity.Medium, + step: '22.0.0-experimental-test-builders-removed', + action: + '実隓的な `@angular-devkit/build-angular:jest` および `@angular-devkit/build-angular:web-test-runner` テストビルダヌは削陀されたした。', + }, ]; diff --git a/adev-ja/src/app/features/update/update.component.en.ts b/adev-ja/src/app/features/update/update.component.en.ts index 79745cf952..6445d9188c 100644 --- a/adev-ja/src/app/features/update/update.component.en.ts +++ b/adev-ja/src/app/features/update/update.component.en.ts @@ -6,16 +6,16 @@ * found in the LICENSE file at https://angular.dev/license */ -import {ChangeDetectionStrategy, Component, inject, signal} from '@angular/core'; -import {Step, RECOMMENDATIONS, ApplicationComplexity} from './recommendations'; import {Clipboard} from '@angular/cdk/clipboard'; import {CdkMenu, CdkMenuItem, CdkMenuTrigger} from '@angular/cdk/menu'; -import {MatCheckbox} from '@angular/material/checkbox'; -import {MatButtonToggleGroup, MatButtonToggle} from '@angular/material/button-toggle'; +import {Component, inject, signal} from '@angular/core'; import {IconComponent} from '@angular/docs'; +import {MatButtonToggle, MatButtonToggleGroup} from '@angular/material/button-toggle'; +import {MatCheckbox} from '@angular/material/checkbox'; +import {MatSnackBar} from '@angular/material/snack-bar'; import {ActivatedRoute, Router} from '@angular/router'; import {marked} from 'marked'; -import {MatSnackBar} from '@angular/material/snack-bar'; +import {ApplicationComplexity, RECOMMENDATIONS, Step} from './recommendations'; /** * Configure marked with a custom link renderer so external links in the @@ -52,7 +52,6 @@ const isWindows = typeof window !== 'undefined' && window.navigator.userAgent.in CdkMenuItem, IconComponent, ], - changeDetection: ChangeDetectionStrategy.OnPush, host: { '(click)': 'copyCode($event)', }, @@ -82,6 +81,7 @@ export default class UpdateComponent { protected afterRecommendations: Step[] = []; protected readonly versions = [ + {name: '22.0', number: 2200}, {name: '21.0', number: 2100}, {name: '20.0', number: 2000}, {name: '19.0', number: 1900}, @@ -120,9 +120,9 @@ export default class UpdateComponent { {name: '2.1', number: 201}, {name: '2.0', number: 200}, ]; - protected from = this.versions.find((version) => version.name === '20.0')!; - protected to = this.versions.find((version) => version.name === '21.0')!; - protected futureVersion = 2200; + protected from = this.versions.find((version) => version.name === '21.0')!; + protected to = this.versions.find((version) => version.name === '22.0')!; + protected futureVersion = 2300; protected readonly steps: Step[] = RECOMMENDATIONS; diff --git a/adev-ja/src/app/features/update/update.component.ts b/adev-ja/src/app/features/update/update.component.ts index 2e753be1cd..9e8f471bb6 100644 --- a/adev-ja/src/app/features/update/update.component.ts +++ b/adev-ja/src/app/features/update/update.component.ts @@ -6,16 +6,16 @@ * found in the LICENSE file at https://angular.dev/license */ -import {ChangeDetectionStrategy, Component, inject, signal} from '@angular/core'; -import {Step, RECOMMENDATIONS, ApplicationComplexity} from './recommendations'; import {Clipboard} from '@angular/cdk/clipboard'; import {CdkMenu, CdkMenuItem, CdkMenuTrigger} from '@angular/cdk/menu'; -import {MatCheckbox} from '@angular/material/checkbox'; -import {MatButtonToggleGroup, MatButtonToggle} from '@angular/material/button-toggle'; +import {Component, inject, signal} from '@angular/core'; import {IconComponent} from '@angular/docs'; +import {MatButtonToggle, MatButtonToggleGroup} from '@angular/material/button-toggle'; +import {MatCheckbox} from '@angular/material/checkbox'; +import {MatSnackBar} from '@angular/material/snack-bar'; import {ActivatedRoute, Router} from '@angular/router'; import {marked} from 'marked'; -import {MatSnackBar} from '@angular/material/snack-bar'; +import {ApplicationComplexity, RECOMMENDATIONS, Step} from './recommendations'; /** * Configure marked with a custom link renderer so external links in the @@ -52,7 +52,6 @@ const isWindows = typeof window !== 'undefined' && window.navigator.userAgent.in CdkMenuItem, IconComponent, ], - changeDetection: ChangeDetectionStrategy.OnPush, host: { '(click)': 'copyCode($event)', }, @@ -82,6 +81,7 @@ export default class UpdateComponent { protected afterRecommendations: Step[] = []; protected readonly versions = [ + {name: '22.0', number: 2200}, {name: '21.0', number: 2100}, {name: '20.0', number: 2000}, {name: '19.0', number: 1900}, @@ -120,9 +120,9 @@ export default class UpdateComponent { {name: '2.1', number: 201}, {name: '2.0', number: 200}, ]; - protected from = this.versions.find((version) => version.name === '20.0')!; - protected to = this.versions.find((version) => version.name === '21.0')!; - protected futureVersion = 2200; + protected from = this.versions.find((version) => version.name === '21.0')!; + protected to = this.versions.find((version) => version.name === '22.0')!; + protected futureVersion = 2300; protected readonly steps: Step[] = RECOMMENDATIONS; diff --git a/adev-ja/src/app/routing/navigation-entries/index.en.ts b/adev-ja/src/app/routing/navigation-entries/index.en.ts index 02adf87b29..c021ea7f27 100644 --- a/adev-ja/src/app/routing/navigation-entries/index.en.ts +++ b/adev-ja/src/app/routing/navigation-entries/index.en.ts @@ -116,6 +116,12 @@ export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ path: 'guide/signals/resource', contentPath: 'guide/signals/resource', }, + { + label: 'Debounced signals', + path: 'guide/signals/debounced', + contentPath: 'guide/signals/debounced', + status: 'new', + }, { label: 'Side effects for non-reactives APIs', path: 'guide/signals/effect', @@ -315,6 +321,12 @@ export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ contentPath: 'guide/di/creating-and-using-services', status: 'updated', }, + { + label: 'Lazy loading services', + path: 'guide/di/lazy-loading-services', + contentPath: 'guide/di/lazy-loading-services', + status: 'new', + }, { label: 'Defining dependency providers', path: 'guide/di/defining-dependency-providers', @@ -937,6 +949,12 @@ export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ path: 'ai/design-patterns', contentPath: 'ai/design-patterns', }, + { + label: 'WebMCP', + path: 'ai/webmcp', + contentPath: 'ai/webmcp', + status: 'new', + }, ], }, { @@ -1137,6 +1155,12 @@ export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ contentPath: 'guide/templates/defer', category: 'Loading Performance', }, + { + label: 'Lazy loading services', + path: 'best-practices/performance/lazy-loading-services', + contentPath: 'guide/di/lazy-loading-services', + category: 'Loading Performance', + }, { label: 'Image optimization', path: 'best-practices/performance/image-optimization', @@ -1200,11 +1224,16 @@ export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ { label: 'Developer Events', children: [ + { + label: 'Angular v22 Release', + path: 'events/v22', + contentPath: 'events/v22', + status: 'new', + }, { label: 'Angular v21 Release', path: 'events/v21', contentPath: 'events/v21', - status: 'new', }, ], }, diff --git a/adev-ja/src/app/routing/navigation-entries/index.ts b/adev-ja/src/app/routing/navigation-entries/index.ts index b4431358fc..c83e0c99ca 100644 --- a/adev-ja/src/app/routing/navigation-entries/index.ts +++ b/adev-ja/src/app/routing/navigation-entries/index.ts @@ -116,6 +116,12 @@ export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ path: 'guide/signals/resource', contentPath: 'guide/signals/resource', }, + { + label: 'シグナルのデバりンス', + path: 'guide/signals/debounced', + contentPath: 'guide/signals/debounced', + status: 'new', + }, { label: '非リアクティブAPIのための副䜜甚', path: 'guide/signals/effect', @@ -315,6 +321,12 @@ export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ contentPath: 'guide/di/creating-and-using-services', status: 'updated', }, + { + label: 'サヌビスの遅延読み蟌み', + path: 'guide/di/lazy-loading-services', + contentPath: 'guide/di/lazy-loading-services', + status: 'new', + }, { label: '䟝存性プロバむダヌの定矩', path: 'guide/di/defining-dependency-providers', @@ -937,6 +949,12 @@ export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ path: 'ai/design-patterns', contentPath: 'ai/design-patterns', }, + { + label: 'WebMCP', + path: 'ai/webmcp', + contentPath: 'ai/webmcp', + status: 'new', + }, ], }, { @@ -1137,6 +1155,12 @@ export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ contentPath: 'guide/templates/defer', category: 'Loading Performance', }, + { + label: 'サヌビスの遅延読み蟌み', + path: 'best-practices/performance/lazy-loading-services', + contentPath: 'guide/di/lazy-loading-services', + category: 'Loading Performance', + }, { label: '画像の最適化', path: 'best-practices/performance/image-optimization', @@ -1200,11 +1224,16 @@ export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ { label: '開発者向けむベント', children: [ + { + label: 'Angular v22 Release', + path: 'events/v22', + contentPath: 'events/v22', + status: 'new', + }, { label: 'Angular v21 Release', path: 'events/v21', contentPath: 'events/v21', - status: 'new', }, ], }, diff --git a/adev-ja/src/content/ai/ai-tutor.en.md b/adev-ja/src/content/ai/ai-tutor.en.md index 7c922be054..e5a6144966 100644 --- a/adev-ja/src/content/ai/ai-tutor.en.md +++ b/adev-ja/src/content/ai/ai-tutor.en.md @@ -141,9 +141,7 @@ You will build your application over a five-phase journey. You can follow this p - **Module 16:** Introduction to Forms - **Module 17:** Intro to Angular Material -### **Phase 5: Experimental Signal Forms (⚠ WARNING: Subject to Change)** - -**CRITICAL NOTE FOR THIS PHASE:** Signal Forms are currently an [**EXPERIMENTAL** feature](/reference/releases#experimental). The API may change significantly in future Angular releases. Please proceed with the understanding that this section demonstrates a cutting-edge feature. +### **Phase 5: Signal Forms** - **Module 18**: **Introduction to Signal Forms** - **Module 19**: **Submitting & Resetting** diff --git a/adev-ja/src/content/ai/ai-tutor.md b/adev-ja/src/content/ai/ai-tutor.md index 7ff8f7d375..1e35df924a 100644 --- a/adev-ja/src/content/ai/ai-tutor.md +++ b/adev-ja/src/content/ai/ai-tutor.md @@ -141,9 +141,7 @@ Angular AIチュヌタヌは、完党でモダンなAngularアプリケヌショ - **モゞュヌル16** フォヌム入門 - **モゞュヌル17** Angular Material入門 -### **フェヌズ5実隓的なシグナルフォヌム⚠ 譊告倉曎の可胜性あり** {#phase-5-experimental-signal-forms-warning-subject-to-change} - -**このフェヌズに関する重芁な泚意** シグナルフォヌムは珟圚[**実隓的な**機胜](/reference/releases#experimental)です。APIは将来のAngularリリヌスで倧幅に倉曎される可胜性がありたす。このセクションは最先端の機胜を瀺すものであるこずをご理解の䞊、お進みください。 +### **フェヌズ5シグナルフォヌム** {#phase-5-signal-forms} - **モゞュヌル18** **シグナルフォヌム入門** - **モゞュヌル19** **送信ずリセット** diff --git a/adev-ja/src/content/ai/webmcp.en.md b/adev-ja/src/content/ai/webmcp.en.md new file mode 100644 index 0000000000..b175a4dc85 --- /dev/null +++ b/adev-ja/src/content/ai/webmcp.en.md @@ -0,0 +1,259 @@ +# WebMCP + +Web Model Context Protocol (WebMCP) is an [emerging web standard](https://github.com/webmachinelearning/webmcp/) that allows web applications to expose structured tools directly to AI agents running natively in the browser. Tools defined by an application allow AI assistants to interact with it directly, providing additional capabilities to the agent and reducing the need for DOM interactions. + +For example, an application to register a new user might provide a WebMCP tool for a browser's AI agent to create the user directly rather than requiring the agent to go through a complex wizard UI via DOM interactions. + +Angular provides experimental support for WebMCP, allowing you to easily register tools tied to your application's dependency injection lifecycle and automatically turn your Signal Forms into AI-ready tools. + +IMPORTANT: The WebMCP spec is very early in its lifecycle and is undergoing frequent changes. As such, WebMCP support in Angular is currently [**experimental**](reference/releases#experimental). APIs are subject to change even outside of major versions. + +## Provide tools for the application + +Use [`provideExperimentalWebMcpTools`](api/core/provideExperimentalWebMcpTools) in your application config to register tools for the entire lifecycle of the application. Tools provided this way are automatically registered when the application initializes and unregistered when the application is destroyed. + +The `execute` callback is invoked in the injection context of the associated `Injector`, meaning you can [`inject`](api/core/inject) services directly. + +```ts {header:"main.ts"} +import {Service, inject, provideExperimentalWebMcpTools} from '@angular/core'; +import {bootstrapApplication} from '@angular/platform-browser'; +import {AppRoot} from './app-root'; + +@Service() +class Greeter { + sayHello(): string { + return 'Hello agent!'; + } +} + +bootstrapApplication(AppRoot, { + providers: [ + provideExperimentalWebMcpTools([ + { + name: 'greet', + description: 'Greets the agent.', + inputSchema: {type: 'object', properties: {}}, + execute: () => { + const greeter = inject(Greeter); + + return {content: [{type: 'text', text: greeter.sayHello()}]}; + }, + }, + ]), + ], +}); +``` + +### Define tool parameters + +When a tool requires input from the AI assistant, define the expected arguments inside `inputSchema` using [JSON Schema](https://json-schema.org/) syntax. Angular automatically infers the parameter types passed into your `execute` callback based on the schema definition. + +```ts {header:"main.ts"} +import {provideExperimentalWebMcpTools} from '@angular/core'; +import {bootstrapApplication} from '@angular/platform-browser'; +import {AppRoot} from './app-root'; + +bootstrapApplication(AppRoot, { + providers: [ + provideExperimentalWebMcpTools([ + { + name: 'searchCatalog', + description: 'Searches the store catalog for products matching a query.', + inputSchema: { + type: 'object', + properties: { + query: { + type: 'string', + description: 'The search keywords.', + }, + maxResults: { + type: 'number', + description: 'Maximum number of results to return.', + }, + }, + required: ['query'], + additionalProperties: false, + }, + execute: ({query, maxResults}) => { + // Type of `query` is inferred as `string`. + // Type of `maxResults` is inferred as `number | undefined`. + + // Consider validating this at runtime, since inputs may not be validated to match the schema. + if (typeof query !== 'string') throw new Error(`Bad query: ${query}`); + if (typeof maxResults !== 'number' && maxResults !== undefined) + throw new Error(`Bad maxResults: ${maxResults}`); + + const limit = maxResults ?? 5; + return { + content: [{type: 'text', text: `Returning up to ${limit} results for "${query}".`}], + }; + }, + }, + ]), + ], +}); +``` + +TIP: Use `required: ['param1', 'param2', ...]` to remove `undefined` from the types of those parameters and use `additionalProperties: false` to restrict the argument object's type to only these parameters. + +## Provide tools for a route + +When building complex applications, you may only want certain tools available when the user is viewing specific routes. You can achieve this by providing tools directly in route definitions. + +```ts {header:"routes.ts"} +import {provideExperimentalWebMcpTools} from '@angular/core'; +import {Routes} from '@angular/router'; + +export const routes: Routes = [ + { + path: 'dashboard', + loadComponent: () => import('./dashboard').then((m) => m.Dashboard), + providers: [ + provideExperimentalWebMcpTools([ + { + name: 'exportDashboardReports', + description: 'Exports the current dashboard analytics.', + inputSchema: {type: 'object', properties: {}}, + execute: () => ({ + content: [{type: 'text', text: 'Dashboard export successfully triggered.'}], + }), + }, + ]), + ], + }, +]; +``` + +NOTE: When registering tools to a particular route, consider configuring the router to use [`withExperimentalAutoCleanupInjectors`](api/router/withExperimentalAutoCleanupInjectors) to ensure tools are automatically _unregistered_ when the user navigates away from the route. Without this option, WebMCP tools declared on routes will remain accessible to AI agents even after the user has navigated to a different route. + +```ts {header:"app.config.ts"} +import {ApplicationConfig} from '@angular/core'; +import {provideRouter, withExperimentalAutoCleanupInjectors} from '@angular/router'; +import {routes} from './routes'; + +export const appConfig: ApplicationConfig = { + providers: [provideRouter(routes, withExperimentalAutoCleanupInjectors())], +}; +``` + +## Provide tools within services + +For dynamic use cases, the [`declareExperimentalWebMcpTool`](api/core/declareExperimentalWebMcpTool) function registers a tool directly within an injection context and automatically unregisters it when that context is destroyed. + +```ts {header:"counter.ts"} +import {Service, declareExperimentalWebMcpTool, signal, inject} from '@angular/core'; + +@Service() +export class Counter { + readonly count = signal(0); + + constructor() { + declareExperimentalWebMcpTool({ + name: 'getCounter', + description: 'Reads the global counter.', + inputSchema: {type: 'object', properties: {}}, + execute: () => ({ + content: [{type: 'text', text: `The count is: ${this.count()}.`}], + }), + }); + } +} +``` + +While `declareExperimentalWebMcpTool` works in any injection context, watch out for [name collisions](#name-collisions) and prefer using it in root services. + +## Implicit tools in Signal Forms + +You can create a WebMCP tool implicitly from an existing Angular [Signal Form](essentials/signal-forms) with minimal configuration. Angular converts your form models into rich WebMCP tools, effectively supporting highly dynamic forms without requiring you to manually write JSON schemas or event handlers. + +### Enable the WebMCP forms feature + +First, add [`provideExperimentalWebMcpForms`](api/forms/signals/provideExperimentalWebMcpForms) to your root application providers: + +```ts {header:"main.ts"} +import {bootstrapApplication} from '@angular/platform-browser'; +import {provideExperimentalWebMcpForms} from '@angular/forms/signals'; +import {AppRoot} from './app-root'; + +bootstrapApplication(AppRoot, { + providers: [provideExperimentalWebMcpForms()], +}); +``` + +### Opt in a Signal Form + +Second, when defining a Signal Form using [`form`](api/forms/signals/form), pass the `experimentalWebMcpTool` configuration option to opt-in to an implicit WebMCP tool. Angular will inspect your form's data model and automatically generate a JSON schema for connected AI agents. + +```ts {header:"user-registration.ts"} +import {Component, signal} from '@angular/core'; +import {form, required, minLength} from '@angular/forms/signals'; + +@Component({ + selector: 'app-user-registration', + templateUrl: './user-registration.html', +}) +export class UserRegistration { + private readonly model = signal({ + firstName: '', + lastName: '', + age: 0, + hobbies: ['Web Development'], + }); + + readonly userForm = form( + this.model, + (f) => { + required(f.firstName, {message: 'First name is mandatory.'}); + required(f.lastName, {message: 'Last name is mandatory.'}); + }, + { + // Implicitly registers a WebMCP tool named `registerUser` with parameters derived from `model`. + experimentalWebMcpTool: { + name: 'registerUser', + description: 'Registers a new user.', + }, + submission: { + action: async (formValue) => { + console.log('Submitting user:', formValue); + // ... + }, + }, + }, + ); +} +``` + +In this example, Angular generates a WebMCP tool with a JSON schema which: + +1. includes `firstName`, `lastName`, `age`, and `hobbies` as parameters inferred from the initial value of the `model` signal. +2. defines `firstName` and `lastName` as _required_ fields as inferred from the [`required`](api/forms/signals/required) validator. +3. defines `hobbies` as an array of strings, allowing the agent to provide an arbitrary amount of hobbies. + +Beyond inferring the input schema, Angular also connects the WebMCP tool to the form's validation logic and submission handler. This means the agent will observe any validation errors triggered by its inputs or any failures which happen during submission, allowing it to self-correct and potentially retry. + +NOTE: Async validators are _not_ triggered and should be handled by the submission action. + +#### Constraints + +Angular infers the WebMCP schema from the initial value of your form model. This requires: + +- Concrete initial values (`''`, `0`, `false`): Angular cannot infer data types from `null` or `undefined`. +- Non-empty arrays (`['Hello!']`): Angular cannot infer data types from an empty array and requires at least one initial value. + +## Best practices + +Keep the following best practices in mind: + +### Name collisions + +WebMCP requires each tool to have a unique name and will throw an error if the same tool name is registered multiple times. This means calling `declareExperimentalWebMcpTool` or `provideExperimentalWebMcpTools` in a context where they might be registered multiple times (such as a component constructor) may lead to errors at runtime. + +Prefer placing tools on application providers, route providers, or root services where possible. When putting tools on a component, including [implicit tools in Signal Forms](#implicit-tools-in-signal-forms), ensure that component is only ever rendered on the page at most _once_ at any given time. + +### Validate tool inputs + +Angular does not provide any implicit validation that the inputs provided by an agent actually match the defined JSON schema. Consider explicitly validating arguments to the `execute` function before using them to ensure reliability. + +### Testing + +Consider using a mock WebMCP implementation like [`@mcp-b/webmcp-polyfill`](https://www.npmjs.com/package/@mcp-b/webmcp-polyfill) to effectively unit test your tools. diff --git a/adev-ja/src/content/ai/webmcp.md b/adev-ja/src/content/ai/webmcp.md new file mode 100644 index 0000000000..a0dfe26049 --- /dev/null +++ b/adev-ja/src/content/ai/webmcp.md @@ -0,0 +1,259 @@ +# WebMCP + +Web Model Context Protocol (WebMCP)は、Webアプリケヌションがブラりザ内でネむティブに実行されるAI゚ヌゞェントに構造化されたツヌルを盎接公開できるようにする[新興のWeb暙準](https://github.com/webmachinelearning/webmcp/)です。アプリケヌションによっお定矩されたツヌルにより、AIアシスタントはアプリケヌションず盎接察話できるようになり、゚ヌゞェントに远加の機胜を提䟛し、DOM操䜜の必芁性を枛らしたす。 + +䟋えば、新芏ナヌザヌを登録するアプリケヌションは、゚ヌゞェントがDOM操䜜を通じお耇雑なりィザヌドUIを操䜜するこずを芁求する代わりに、ブラりザのAI゚ヌゞェントがナヌザヌを盎接䜜成するためのWebMCPツヌルを提䟛する堎合がありたす。 + +AngularはWebMCPの実隓的サポヌトを提䟛しおおり、アプリケヌションの䟝存性の泚入ラむフサむクルに結び぀いたツヌルを簡単に登録し、シグナルフォヌムを自動的にAI察応ツヌルに倉換できたす。 + +IMPORTANT: WebMCP仕様はラむフサむクルの非垞に初期の段階にあり、頻繁に倉曎されおいたす。そのため、AngularにおけるWebMCPサポヌトは珟圚[**実隓的**](reference/releases#experimental)です。APIはメゞャヌバヌゞョン以倖でも倉曎される可胜性がありたす。 + +## アプリケヌションにツヌルを提䟛する {#provide-tools-for-the-application} + +アプリケヌション蚭定で[`provideExperimentalWebMcpTools`](api/core/provideExperimentalWebMcpTools)を䜿甚しお、アプリケヌションのラむフサむクル党䜓にわたっおツヌルを登録したす。この方法で提䟛されたツヌルは、アプリケヌションの初期化時に自動的に登録され、アプリケヌションの砎棄時に登録解陀されたす。 + +`execute`コヌルバックは関連付けられた`Injector`の泚入コンテキストで呌び出されるため、サヌビスを盎接[`inject`](api/core/inject)できたす。 + +```ts {header:"main.ts"} +import {Service, inject, provideExperimentalWebMcpTools} from '@angular/core'; +import {bootstrapApplication} from '@angular/platform-browser'; +import {AppRoot} from './app-root'; + +@Service() +class Greeter { + sayHello(): string { + return 'Hello agent!'; + } +} + +bootstrapApplication(AppRoot, { + providers: [ + provideExperimentalWebMcpTools([ + { + name: 'greet', + description: 'Greets the agent.', + inputSchema: {type: 'object', properties: {}}, + execute: () => { + const greeter = inject(Greeter); + + return {content: [{type: 'text', text: greeter.sayHello()}]}; + }, + }, + ]), + ], +}); +``` + +### ツヌルパラメヌタを定矩する {#define-tool-parameters} + +ツヌルがAIアシスタントからの入力を必芁ずする堎合、[JSON Schema](https://json-schema.org/)構文を䜿甚しお`inputSchema`内に期埅される匕数を定矩したす。Angularはスキヌマ定矩に基づいお、`execute`コヌルバックに枡されるパラメヌタの型を自動的に掚論したす。 + +```ts {header:"main.ts"} +import {provideExperimentalWebMcpTools} from '@angular/core'; +import {bootstrapApplication} from '@angular/platform-browser'; +import {AppRoot} from './app-root'; + +bootstrapApplication(AppRoot, { + providers: [ + provideExperimentalWebMcpTools([ + { + name: 'searchCatalog', + description: 'Searches the store catalog for products matching a query.', + inputSchema: { + type: 'object', + properties: { + query: { + type: 'string', + description: 'The search keywords.', + }, + maxResults: { + type: 'number', + description: 'Maximum number of results to return.', + }, + }, + required: ['query'], + additionalProperties: false, + }, + execute: ({query, maxResults}) => { + // Type of `query` is inferred as `string`. + // Type of `maxResults` is inferred as `number | undefined`. + + // Consider validating this at runtime, since inputs may not be validated to match the schema. + if (typeof query !== 'string') throw new Error(`Bad query: ${query}`); + if (typeof maxResults !== 'number' && maxResults !== undefined) + throw new Error(`Bad maxResults: ${maxResults}`); + + const limit = maxResults ?? 5; + return { + content: [{type: 'text', text: `Returning up to ${limit} results for "${query}".`}], + }; + }, + }, + ]), + ], +}); +``` + +TIP: `required: ['param1', 'param2', ...]`を䜿甚しおそれらのパラメヌタの型から`undefined`を削陀し、`additionalProperties: false`を䜿甚しお匕数オブゞェクトの型をこれらのパラメヌタのみに制限したす。 + +## ルヌトにツヌルを提䟛する {#provide-tools-for-a-route} + +耇雑なアプリケヌションを構築する堎合、ナヌザヌが特定のルヌトを衚瀺しおいるずきにのみ特定のツヌルを利甚できるようにしたい堎合がありたす。これは、ルヌト定矩で盎接ツヌルを提䟛するこずで実珟できたす。 + +```ts {header:"routes.ts"} +import {provideExperimentalWebMcpTools} from '@angular/core'; +import {Routes} from '@angular/router'; + +export const routes: Routes = [ + { + path: 'dashboard', + loadComponent: () => import('./dashboard').then((m) => m.Dashboard), + providers: [ + provideExperimentalWebMcpTools([ + { + name: 'exportDashboardReports', + description: 'Exports the current dashboard analytics.', + inputSchema: {type: 'object', properties: {}}, + execute: () => ({ + content: [{type: 'text', text: 'Dashboard export successfully triggered.'}], + }), + }, + ]), + ], + }, +]; +``` + +NOTE: 特定のルヌトにツヌルを登録する堎合、ナヌザヌがルヌトから移動したずきにツヌルが自動的に_登録解陀_されるように、ルヌタヌを構成しお[`withExperimentalAutoCleanupInjectors`](api/router/withExperimentalAutoCleanupInjectors)を䜿甚するこずを怜蚎しおください。このオプションがない堎合、ルヌトで宣蚀されたWebMCPツヌルは、ナヌザヌが別のルヌトに移動した埌でもAI゚ヌゞェントからアクセス可胜なたたになりたす。 + +```ts {header:"app.config.ts"} +import {ApplicationConfig} from '@angular/core'; +import {provideRouter, withExperimentalAutoCleanupInjectors} from '@angular/router'; +import {routes} from './routes'; + +export const appConfig: ApplicationConfig = { + providers: [provideRouter(routes, withExperimentalAutoCleanupInjectors())], +}; +``` + +## サヌビス内でのツヌルの提䟛 {#provide-tools-within-services} + +動的なナヌスケヌスの堎合、[`declareExperimentalWebMcpTool`](api/core/declareExperimentalWebMcpTool)関数は泚入コンテキスト内にツヌルを盎接登録し、そのコンテキストが砎棄されたずきに自動的に登録を解陀したす。 + +```ts {header:"counter.ts"} +import {Service, declareExperimentalWebMcpTool, signal, inject} from '@angular/core'; + +@Service() +export class Counter { + readonly count = signal(0); + + constructor() { + declareExperimentalWebMcpTool({ + name: 'getCounter', + description: 'Reads the global counter.', + inputSchema: {type: 'object', properties: {}}, + execute: () => ({ + content: [{type: 'text', text: `The count is: ${this.count()}.`}], + }), + }); + } +} +``` + +`declareExperimentalWebMcpTool`は任意の泚入コンテキストで機胜したすが、[名前の衝突](#name-collisions)に泚意し、ルヌトサヌビスで䜿甚するこずを掚奚したす。 + +## シグナルフォヌムの暗黙的ツヌル {#implicit-tools-in-signal-forms} + +最小限の蚭定で、既存のAngularの[Signal Form](essentials/signal-forms)から暗黙的にWebMCPツヌルを䜜成できたす。AngularはフォヌムモデルをリッチなWebMCPツヌルに倉換し、JSONスキヌマやむベントハンドラヌを手動で蚘述するこずなく、高床に動的なフォヌムを効果的にサポヌトしたす。 + +### WebMCPフォヌム機胜の有効化 {#enable-the-webmcp-forms-feature} + +たず、ルヌトアプリケヌションのプロバむダヌに[`provideExperimentalWebMcpForms`](api/forms/signals/provideExperimentalWebMcpForms)を远加したす: + +```ts {header:"main.ts"} +import {bootstrapApplication} from '@angular/platform-browser'; +import {provideExperimentalWebMcpForms} from '@angular/forms/signals'; +import {AppRoot} from './app-root'; + +bootstrapApplication(AppRoot, { + providers: [provideExperimentalWebMcpForms()], +}); +``` + +### Signal Formのオプトむン {#opt-in-a-signal-form} + +次に、[`form`](api/forms/signals/form)を䜿甚しおSignal Formを定矩する際、`experimentalWebMcpTool`蚭定オプションを枡しお暗黙的なWebMCPツヌルにオプトむンしたす。Angularはフォヌムのデヌタモデルを怜査し、接続されたAI゚ヌゞェント甚のJSONスキヌマを自動的に生成したす。 + +```ts {header:"user-registration.ts"} +import {Component, signal} from '@angular/core'; +import {form, required, minLength} from '@angular/forms/signals'; + +@Component({ + selector: 'app-user-registration', + templateUrl: './user-registration.html', +}) +export class UserRegistration { + private readonly model = signal({ + firstName: '', + lastName: '', + age: 0, + hobbies: ['Web Development'], + }); + + readonly userForm = form( + this.model, + (f) => { + required(f.firstName, {message: 'First name is mandatory.'}); + required(f.lastName, {message: 'Last name is mandatory.'}); + }, + { + // Implicitly registers a WebMCP tool named `registerUser` with parameters derived from `model`. + experimentalWebMcpTool: { + name: 'registerUser', + description: 'Registers a new user.', + }, + submission: { + action: async (formValue) => { + console.log('Submitting user:', formValue); + // ... + }, + }, + }, + ); +} +``` + +この䟋では、Angularは以䞋のJSONスキヌマを持぀WebMCPツヌルを生成したす: + +1. `model`シグナルの初期倀から掚論されたパラメヌタヌずしお、`firstName`、`lastName`、`age`、および`hobbies`を含みたす。 +2. [`required`](api/forms/signals/required)バリデヌタヌから掚論された_必須_フィヌルドずしお、`firstName`ず`lastName`を定矩したす。 +3. `hobbies`を文字列の配列ずしお定矩し、゚ヌゞェントが任意の数の趣味を提䟛できるようにしたす。 + +入力スキヌマの掚論にずどたらず、AngularはWebMCPツヌルをフォヌムの怜蚌ロゞックず送信ハンドラヌにも接続したす。これにより、゚ヌゞェントは自身の入力によっおトリガヌされた怜蚌゚ラヌや送信䞭に発生した倱敗を監芖し、自己修正しお再詊行できるようになりたす。 + +NOTE: 非同期バリデヌタヌはトリガヌされ_ない_ため、送信アクションで凊理する必芁がありたす。 + +#### 制玄事項 {#constraints} + +Angularはフォヌムモデルの初期倀からWebMCPスキヌマを掚論したす。これには以䞋が必芁です: + +- 具䜓的な初期倀(`''`、`0`、`false`): Angularは`null`や`undefined`からデヌタ型を掚論できたせん。 +- 空ではない配列(`['Hello!']`): Angularは空の配列からデヌタ型を掚論できず、少なくずも1぀の初期倀を必芁ずしたす。 + +## ベストプラクティス {#best-practices} + +以䞋のベストプラクティスを念頭に眮いおください: + +### 名前の衝突 {#name-collisions} + +WebMCPは各ツヌルが䞀意の名前を持぀こずを芁求し、同じツヌル名が耇数回登録された堎合ぱラヌをスロヌしたす。これは、耇数回登録される可胜性のあるコンテキスト(コンポヌネントのコンストラクタヌなど)で`declareExperimentalWebMcpTool`や`provideExperimentalWebMcpTools`を呌び出すず、実行時に゚ラヌが発生する可胜性があるこずを意味したす。 + +可胜な限り、ツヌルはアプリケヌションプロバむダヌ、ルヌトプロバむダヌ、たたはルヌトサヌビスに配眮するこずを掚奚したす。[Signal Formsの暗黙的ツヌル](#implicit-tools-in-signal-forms)を含め、コンポヌネントにツヌルを配眮する堎合は、そのコンポヌネントが垞にペヌゞ䞊で最倧_1回_しかレンダリングされないこずを確認しおください。 + +### ツヌル入力の怜蚌 {#validate-tool-inputs} + +Angularは、゚ヌゞェントによっお提䟛された入力が定矩されたJSONスキヌマず実際に䞀臎するかどうかの暗黙的な怜蚌を提䟛したせん。信頌性を確保するために、䜿甚する前に`execute`関数ぞの匕数を明瀺的に怜蚌するこずを怜蚎しおください。 + +### テスト {#testing} + +ツヌルを効果的にナニットテストするために、[`@mcp-b/webmcp-polyfill`](https://www.npmjs.com/package/@mcp-b/webmcp-polyfill)のようなモックWebMCP実装を䜿甚するこずを怜蚎しおください。 diff --git a/adev-ja/src/content/best-practices/a11y.en.md b/adev-ja/src/content/best-practices/a11y.en.md index 54994a5c19..2531454d88 100644 --- a/adev-ja/src/content/best-practices/a11y.en.md +++ b/adev-ja/src/content/best-practices/a11y.en.md @@ -63,6 +63,9 @@ For example: For full details of these and other tools, see the [Angular CDK accessibility overview](https://material.angular.dev/cdk/a11y/overview). +For custom-styled components that need reusable WAI-ARIA interaction patterns, [Angular Aria](guide/aria/overview) provides headless directives for patterns such as accordion, combobox, listbox, menu, tabs, and toolbar. +These directives handle keyboard interaction, ARIA attributes, focus management, and screen reader support while letting you provide the HTML structure and styling for your application. + ### Augmenting native elements Native HTML elements capture several standard interaction patterns that are important to accessibility. diff --git a/adev-ja/src/content/best-practices/a11y.md b/adev-ja/src/content/best-practices/a11y.md index 7c94114817..643bccea2c 100644 --- a/adev-ja/src/content/best-practices/a11y.md +++ b/adev-ja/src/content/best-practices/a11y.md @@ -63,6 +63,9 @@ Angularチヌムが保守しおいる[Angular Material](https://material.angular これらのツヌルやその他のツヌルの詳现に぀いおは、[Angular CDKアクセシビリティの抂芁](https://material.angular.dev/cdk/a11y/overview)を参照しおください。 +再利甚可胜なWAI-ARIAむンタラクションパタヌンを必芁ずするカスタムスタむルのコンポヌネントには、[Angular Aria](guide/aria/overview)がアコヌディオン、コンボボックス、リストボックス、メニュヌ、タブ、ツヌルバヌなどのパタヌン向けのヘッドレスディレクティブを提䟛したす。 +これらのディレクティブは、キヌボヌド操䜜、ARIA属性、フォヌカス管理、スクリヌンリヌダヌサポヌトを凊理する䞀方で、アプリケヌションのHTML構造ずスタむリングは開発者が提䟛できるようにしたす。 + ### ネむティブ芁玠の拡匵 {#augmenting-native-elements} ネむティブHTML芁玠は、アクセシビリティにずっお重芁な、いく぀かの暙準的な盞互䜜甚パタヌンを捉えおいたす。 diff --git a/adev-ja/src/content/best-practices/performance/overview.md b/adev-ja/src/content/best-practices/performance/overview.md index 0280057f3f..0754c74c34 100644 --- a/adev-ja/src/content/best-practices/performance/overview.md +++ b/adev-ja/src/content/best-practices/performance/overview.md @@ -10,6 +10,7 @@ Loading performance determines how quickly your application becomes visible and | :------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------- | | [Lazy-loaded routes](best-practices/performance/lazy-loaded-routes#lazily-loaded-components-and-routes) | Defers loading route components until navigation, reducing the initial bundle size | Applications with multiple routes where not all are needed on initial load | | [Deferred loading with `@defer`](best-practices/performance/defer) | Splits components into separate bundles that load on demand | Components not visible on initial render, heavy third-party libraries, below-the-fold content | +| [Lazy loading services with `injectAsync`](guide/di/lazy-loading-services) | Splits rarely used services into separate chunks and loads them on demand | Services backed by large libraries or infrequently used features | | [Image optimization](best-practices/performance/image-optimization) | Prioritizes LCP images, lazy loads others, generates responsive `srcset` attributes | Any application that displays images | | [Server-side rendering](best-practices/performance/ssr) | Renders pages on the server for faster first paint and better SEO, with [hydration](guide/hydration) to restore interactivity and [incremental hydration](guide/incremental-hydration) to defer hydrating sections until needed | Content-heavy applications, pages that need search engine indexing | diff --git a/adev-ja/src/content/best-practices/runtime-performance/skipping-subtrees.en.md b/adev-ja/src/content/best-practices/runtime-performance/skipping-subtrees.en.md index 02304d483b..405836da6e 100644 --- a/adev-ja/src/content/best-practices/runtime-performance/skipping-subtrees.en.md +++ b/adev-ja/src/content/best-practices/runtime-performance/skipping-subtrees.en.md @@ -4,33 +4,20 @@ JavaScript, by default, uses mutable data structures that you can reference from Change detection is sufficiently fast for most applications. However, when an application has an especially large component tree, running change detection across the whole application can cause performance issues. You can address this by configuring change detection to only run on a subset of the component tree. -If you are confident that a part of the application is not affected by a state change, you can use [OnPush](/api/core/ChangeDetectionStrategy) to skip change detection in an entire component subtree. - ## Using `OnPush` -OnPush change detection instructs Angular to run change detection for a component subtree **only** when: +OnPush is the default change detection strategy in Angular (since v22). It instructs Angular to run change detection for a component subtree **only** when: - The root component of the subtree receives new inputs as the result of a template binding. Angular compares the current and past value of the input with `==`. - Angular handles an event _(for example using event binding, output binding, or `@HostListener` )_ in the subtree's root component or any of its children whether they are using OnPush change detection or not. -You can set the change detection strategy of a component to `OnPush` in the `@Component` decorator: - -```ts -import {ChangeDetectionStrategy, Component} from '@angular/core'; - -@Component({ - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class MyComponent {} -``` - ## Common change detection scenarios This section examines several common change detection scenarios to illustrate Angular's behavior. -### An event is handled by a component with default change detection +### An event is handled by a component with `Eager` change detection -If Angular handles an event within a component without `OnPush` strategy, the framework executes change detection on the entire component tree. Angular will skip descendant component subtrees with roots using `OnPush`, which have not received new inputs. +If Angular handles an event within a component with the `Eager` strategy, the framework executes change detection on the entire component tree. Angular will skip descendant component subtrees with roots using `OnPush`, which have not received new inputs. As an example, if we set the change detection strategy of `MainComponent` to `OnPush` and the user interacts with a component outside the subtree with root `MainComponent`, Angular will check all the pink components from the diagram below (`AppComponent`, `HeaderComponent`, `SearchComponent`, `ButtonComponent`) unless `MainComponent` receives new inputs: diff --git a/adev-ja/src/content/best-practices/runtime-performance/skipping-subtrees.md b/adev-ja/src/content/best-practices/runtime-performance/skipping-subtrees.md index 2f549e4185..bbd639bdf4 100644 --- a/adev-ja/src/content/best-practices/runtime-performance/skipping-subtrees.md +++ b/adev-ja/src/content/best-practices/runtime-performance/skipping-subtrees.md @@ -4,33 +4,20 @@ JavaScriptは、デフォルトでは、耇数の異なるコンポヌネント 倉曎怜知は、ほずんどのアプリケヌションにずっお十分に高速です。ただし、アプリケヌションが特に倧きなコンポヌネントツリヌを持っおいる堎合、アプリケヌション党䜓で倉曎怜知を実行するず、パフォヌマンスの問題が発生する可胜性がありたす。これは、コンポヌネントツリヌのサブセットでのみ倉曎怜知が実行されるように構成するこずで察凊できたす。 -アプリケヌションの䞀郚が状態倉化の圱響を受けないず確信できる堎合は、[OnPush](/api/core/ChangeDetectionStrategy)を䜿甚しお、コンポヌネントのサブツリヌ党䜓の倉曎怜知をスキップできたす。 - ## `OnPush`の䜿甚 {#using-onpush} -OnPush倉曎怜知は、Angularにコンポヌネントのサブツリヌの倉曎怜知を次の堎合**のみ**実行するように指瀺したす。 +OnPushはAngularのデフォルトの倉曎怜知戊略ですv22以降。Angularにコンポヌネントのサブツリヌの倉曎怜知を次の堎合**のみ**実行するように指瀺したす。 - サブツリヌのルヌトコンポヌネントが、テンプレヌトバむンディングの結果ずしお新しいむンプットを受け取った堎合。Angularは、むンプットの珟圚ず過去の倀を`==`で比范したす。 - Angularが、OnPush倉曎怜知を䜿甚しおいるかどうかに関係なく、サブツリヌのルヌトコンポヌネント、たたは、その子でむベント *(䟋えば、むベントバむンディング、アりトプットバむンディング、たたは`@HostListener`を䜿甚)* を凊理する堎合。 -コンポヌネントの倉曎怜知戊略を`@Component`デコレヌタヌで`OnPush`に蚭定できたす。 - -```ts -import {ChangeDetectionStrategy, Component} from '@angular/core'; - -@Component({ - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class MyComponent {} -``` - ## 䞀般的な倉曎怜知のシナリオ このセクションでは、Angularの動䜜を説明するために、いく぀かの䞀般的な倉曎怜知のシナリオを怜蚌したす。 -### デフォルトの倉曎怜知を持぀コンポヌネントによっおむベントが凊理される堎合 +### `Eager`な倉曎怜知を持぀コンポヌネントによっおむベントが凊理される堎合 -Angularが`OnPush`戊略なしでコンポヌネント内でむベントを凊理する堎合、フレヌムワヌクはコンポヌネントツリヌ党䜓で倉曎怜知を実行したす。Angularは、新しいむンプットを受け取っおいない、`OnPush`を䜿甚しおいるルヌトを持぀子孫コンポヌネントのサブツリヌをスキップしたす。 +Angularが`Eager`戊略を持぀コンポヌネント内でむベントを凊理する堎合、フレヌムワヌクはコンポヌネントツリヌ党䜓で倉曎怜知を実行したす。Angularは、新しいむンプットを受け取っおいない、`OnPush`を䜿甚しおいるルヌトを持぀子孫コンポヌネントのサブツリヌをスキップしたす。 䟋ずしお、`MainComponent`の倉曎怜知戊略を`OnPush`に蚭定し、ナヌザヌが`MainComponent`をルヌトずするサブツリヌの倖郚のコンポヌネントずやり取りする堎合、`MainComponent`が新しいむンプットを受け取らない限り、Angularは䞋の図のすべおのピンク色のコンポヌネント`AppComponent`、`HeaderComponent`、`SearchComponent`、`ButtonComponent`をチェックしたす: diff --git a/adev-ja/src/content/cli/index.md b/adev-ja/src/content/cli/index.md deleted file mode 100644 index d6c5d06146..0000000000 --- a/adev-ja/src/content/cli/index.md +++ /dev/null @@ -1,136 +0,0 @@ -# CLI Overview and Command Reference - -The Angular CLI is a command-line interface tool that you use to initialize, develop, scaffold, and maintain Angular applications directly from a command shell. - -## Installing Angular CLI - -Major versions of Angular CLI follow the supported major version of Angular, but minor versions can be released separately. - -Install the CLI using the `npm` package manager: - - - -npm install -g @angular/cli - - - -For details about changes between versions, and information about updating from previous releases, see the Releases tab on GitHub: https://github.com/angular/angular-cli/releases - -## Basic workflow - -Invoke the tool on the command line through the `ng` executable. -Online help is available on the command line. -Enter the following to list commands or options for a given command \(such as [new](cli/new)\) with a short description. - - - -ng --help -ng new --help - - - -To create, build, and serve a new, basic Angular project on a development server, go to the parent directory of your new workspace use the following commands: - - - -ng new my-first-project -cd my-first-project -ng serve - - - -In your browser, open http://localhost:4200/ to see the new application run. -When you use the [ng serve](cli/serve) command to build an application and serve it locally, the server automatically rebuilds the application and reloads the page when you change any of the source files. - -
- -When you run `ng new my-first-project` a new folder, named `my-first-project`, will be created in the current working directory. -Since you want to be able to create files inside that folder, make sure you have sufficient rights in the current working directory before running the command. - -If the current working directory is not the right place for your project, you can change to a more appropriate directory by running `cd `. - -
- -## Workspaces and project files - -The [ng new](cli/new) command creates an _Angular workspace_ folder and generates a new application skeleton. -A workspace can contain multiple applications and libraries. -The initial application created by the [ng new](cli/new) command is at the top level of the workspace. -When you generate an additional application or library in a workspace, it goes into a `projects/` subfolder. - -A newly generated application contains the source files for a root module, with a root component and template. -Each application has a `src` folder that contains the logic, data, and assets. - -You can edit the generated files directly, or add to and modify them using CLI commands. -Use the [ng generate](cli/generate) command to add new files for additional components and services, and code for new pipes, directives, and so on. -Commands such as [add](cli/add) and [generate](cli/generate), which create or operate on applications and libraries, must be executed from within a workspace or project folder. - -- See more about the [Workspace file structure](guide/file-structure). - -### Workspace and project configuration - -A single workspace configuration file, `angular.json`, is created at the top level of the workspace. -This is where you can set per-project defaults for CLI command options, and specify configurations to use when the CLI builds a project for different targets. - -The [ng config](cli/config) command lets you set and retrieve configuration values from the command line, or you can edit the `angular.json` file directly. - -
- -**NOTE**:
-Option names in the configuration file must use [camelCase](guide/glossary#case-types), while option names supplied to commands must be dash-case. - -
- -- See more about [Workspace Configuration](guide/workspace-config). - -## CLI command-language syntax - -Command syntax is shown as follows: - -`ng` __ __ [*optional-arg*] `[options]` - -- Most commands, and some options, have aliases. - Aliases are shown in the syntax statement for each command. - -- Option names are prefixed with a double dash \(`--`\) characters. - Option aliases are prefixed with a single dash \(`-`\) character. - Arguments are not prefixed. - For example: - - - - ng build my-app -c production - - - -- Typically, the name of a generated artifact can be given as an argument to the command or specified with the `--name` option. - -- Arguments and option names must be given in [dash-case](guide/glossary#case-types). - For example: `--my-option-name` - -### Boolean options - -Boolean options have two forms: `--this-option` sets the flag to `true`, `--no-this-option` sets it to `false`. -If neither option is supplied, the flag remains in its default state, as listed in the reference documentation. - -### Array options - -Array options can be provided in two forms: `--option value1 value2` or `--option value1 --option value2`. - -### Relative paths - -Options that specify files can be given as absolute paths, or as paths relative to the current working directory, which is generally either the workspace or project root. - -### Schematics - -The [ng generate](cli/generate) and [ng add](cli/add) commands take, as an argument, the artifact or library to be generated or added to the current project. -In addition to any general options, each artifact or library defines its own options in a _schematic_. -Schematic options are supplied to the command in the same format as immediate command options. - - - - - - - -@reviewed 2022-02-28 diff --git a/adev-ja/src/content/ecosystem/rxjs-interop/signals-interop.md b/adev-ja/src/content/ecosystem/rxjs-interop/signals-interop.md index 9b28a809a4..3e8fd13c9c 100644 --- a/adev-ja/src/content/ecosystem/rxjs-interop/signals-interop.md +++ b/adev-ja/src/content/ecosystem/rxjs-interop/signals-interop.md @@ -128,8 +128,6 @@ Here, only the last value (3) will be logged. ## Using `rxResource` for async data -IMPORTANT: `rxResource` is [experimental](reference/releases#experimental). It's ready for you to try, but it might change before it is stable. - Angular's [`resource` function](/guide/signals/resource) gives you a way to incorporate async data into your application's signal-based code. Building on top of this pattern, `rxResource` lets you define a resource where the source of your data is defined in terms of an RxJS `Observable`. Instead of accepting a `loader` function, `rxResource` accepts a `stream` function that accepts an RxJS `Observable`. ```typescript diff --git a/adev-ja/src/content/events/v22.en.md b/adev-ja/src/content/events/v22.en.md new file mode 100644 index 0000000000..18ec2ae2aa --- /dev/null +++ b/adev-ja/src/content/events/v22.en.md @@ -0,0 +1,32 @@ +# Angular v22: Rock solid foundation for building what's next for the web + +![A digital illustration styled like a vintage postcard with a thin white border. The top left features the words "Welcome to" written in a cursive, yellow script font. The main focus is a large, brown rocky mountain in the center. Imposed on the mountain face is a 3D white text block reading "Angular V22" along with the Angular logo icon. Dense pine trees in shades of green, yellow, and grey line the foreground at the base of the mountain. A winding path trails up the right side of the mountain, and a few birds fly in the sunset-colored purple and orange sky.](assets/images/v22-event/angular-v22-hero.png {loading: 'eager', fetchpriority: 'high'} 'Angular v22 Hero Image') + +Angular v22 is ready for you to build modern, high-performance web applications. This release introduces key stabilization updates, template enhancements, and API improvements: + +- **Stabilized APIs**: Signal Forms, Asynchronous Signals, and Angular Aria are now stable, offering a production-ready reactive foundation. +- **Template enhancements**: New template features streamline development, improve ergonomics, and enhance code clarity. +- **API improvements**: Core APIs have been updated for better performance, simpler syntax, and more robust typing. +- **Angular AI integration**: Streamlined support and updates for AI-driven development workflows. + +## Key resources + + + + Discover all the major features, community updates, and design decisions behind Angular v22. + + + Review the detailed, commit-by-commit list of new features, bug fixes, and breaking changes. + + + Get instructions on how to update your project to Angular v22. + + + +## Developer event + +The v22 release video will be launching soon, [so tune in to the Angular YouTube Channel Friday, June 5 @ 9 AM Pacific](https://goo.gle/angular-v22-yt). + +In the meantime, you can watch the Angular v21 Developer Event: + + diff --git a/adev-ja/src/content/events/v22.md b/adev-ja/src/content/events/v22.md new file mode 100644 index 0000000000..d72b32722c --- /dev/null +++ b/adev-ja/src/content/events/v22.md @@ -0,0 +1,32 @@ +# Angular v22: 次䞖代Webを構築するための盀石な基盀 + +![癜いふち取りのあるビンテヌゞ颚絵葉曞のようなデゞタルむラスト。巊䞊には筆蚘䜓の黄色いスクリプトフォントで「Welcome to」ず曞かれおいる。䞭倮には倧きな茶色い岩山が描かれ、山肌にはAngularのロゎアむコンずずもに「Angular V22」ず読める3D癜文字のブロックが重ねられおいる。手前には緑・黄・灰色の束の朚が山の麓に密集しお䞊び、右偎には山頂ぞず続く曲がりくねった道がある。倕暮れの玫ず橙の空には数矜の鳥が飛んでいる。](assets/images/v22-event/angular-v22-hero.png {loading: 'eager', fetchpriority: 'high'} 'Angular v22 Hero Image') + +Angular v22は、モダンで高性胜なWebアプリケヌションを構築するための準備を敎えたした。このリリヌスでは、䞻芁な安定化のアップデヌト、テンプレヌトの拡匵、APIの改善が導入されおいたす。 + +- **安定化されたAPI**: シグナルフォヌム、非同期シグナル、Angular Ariaが安定版ずなり、プロダクションレディなリアクティブ基盀を提䟛したす。 +- **テンプレヌトの拡匵**: 新しいテンプレヌト機胜が、開発の効率化、゚ルゎノミクスの向䞊、コヌドの明確性の匷化を実珟したす。 +- **APIの改善**: コアAPIが、より良いパフォヌマンス、よりシンプルな構文、より堅牢な型付けを目指しお曎新されたした。 +- **Angular AI統合**: AI駆動の開発ワヌクフロヌのための合理化されたサポヌトずアップデヌト。 + +## 䞻芁リ゜ヌス {#key-resources} + + + + Angular v22のすべおの䞻芁機胜、コミュニティのアップデヌト、蚭蚈刀断の背景を知るこずができたす。 + + + 新機胜、バグ修正、砎壊的倉曎の詳现なコミット単䜍のリストを確認できたす。 + + + プロゞェクトをAngular v22ぞアップデヌトする手順を確認できたす。 + + + +## 開発者向けむベント {#developer-event} + +v22リリヌスビデオがたもなく公開されたす。[6月5日(金)倪平掋時間午前9時、Angular YouTubeチャンネルでご芖聎ください](https://goo.gle/angular-v22-yt)。 + +それたでの間、Angular v21開発者向けむベントの動画をご芧いただけたす。 + + diff --git a/adev-ja/src/content/guide/aria/accordion.en.md b/adev-ja/src/content/guide/aria/accordion.en.md index 4a27dc5e0b..d99a4a7ab8 100644 --- a/adev-ja/src/content/guide/aria/accordion.en.md +++ b/adev-ja/src/content/guide/aria/accordion.en.md @@ -145,8 +145,8 @@ Use the `ngAccordionContent` directive on an `ng-template` to defer rendering co ```angular-html
- -
+ +
Description @@ -159,6 +159,55 @@ Use the `ngAccordionContent` directive on an `ng-template` to defer rendering co By default, content remains in the DOM after the panel collapses. Set `[preserveContent]="false"` to remove the content from the DOM when the panel closes. +## Testing + +Angular Aria provides component harnesses for testing accordion components. +Here is an example of how to use the harnesses in a component test: + +```typescript +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {HarnessLoader} from '@angular/cdk/testing'; +import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed'; +import {AccordionGroupHarness} from '@angular/aria/accordion/testing'; +import {MyAccordionComponent} from './my-accordion'; // Your component + +describe('MyAccordionComponent', () => { + let fixture: ComponentFixture; + let loader: HarnessLoader; + + beforeEach(async () => { + TestBed.configureTestingModule({ + imports: [MyAccordionComponent], + }); + + fixture = TestBed.createComponent(MyAccordionComponent); + await fixture.whenStable(); + loader = TestbedHarnessEnvironment.loader(fixture); + }); + + it('should allow expanding panels', async () => { + // Load the accordion group harness + const group = await loader.getHarness(AccordionGroupHarness); + + // Get all individual accordions (items) in the group + const accordions = await group.getAccordions(); + expect(accordions.length).toBe(3); + + // Verify initial state (first expanded, others collapsed) + expect(await accordions[0].isExpanded()).toBe(true); + expect(await accordions[1].isExpanded()).toBe(false); + + // Expand the second panel + await accordions[1].expand(); + + // Verify updated state + expect(await accordions[1].isExpanded()).toBe(true); + // If multiExpandable is false, the first one should now be collapsed + expect(await accordions[0].isExpanded()).toBe(false); + }); +}); +``` + ## APIs ### AccordionGroup @@ -187,12 +236,12 @@ The directive applied to the button element that toggles panel visibility. #### Inputs -| Property | Type | Default | Description | -| ---------- | --------- | ------- | -------------------------------------------------------------- | -| `id` | `string` | auto | Unique identifier for the trigger | -| `panelId` | `string` | — | **Required.** Must match the `panelId` of the associated panel | -| `disabled` | `boolean` | `false` | Disables this trigger | -| `expanded` | `boolean` | `false` | Whether the panel is expanded (supports two-way binding) | +| Property | Type | Default | Description | +| ---------- | ---------------- | ------- | -------------------------------------------------------------- | +| `panel` | `AccordionPanel` | — | **Required.** The reference of the controlled accordion panel. | +| `id` | `string` | auto | Unique identifier for the trigger | +| `disabled` | `boolean` | `false` | Disables this trigger | +| `expanded` | `boolean` | `false` | Whether the panel is expanded (supports two-way binding) | #### Signals @@ -214,11 +263,10 @@ The directive applied to the element containing the collapsible content. #### Inputs -| Property | Type | Default | Description | -| ----------------- | --------- | ------- | ---------------------------------------------------------------- | -| `id` | `string` | auto | Unique identifier for the panel | -| `panelId` | `string` | — | **Required.** Must match the `panelId` of the associated trigger | -| `preserveContent` | `boolean` | `true` | Whether to keep content in DOM after panel collapses | +| Property | Type | Default | Description | +| ----------------- | --------- | ------- | ---------------------------------------------------- | +| `id` | `string` | auto | Unique identifier for the panel | +| `preserveContent` | `boolean` | `true` | Whether to keep content in DOM after panel collapses | #### Signals @@ -241,7 +289,7 @@ The structural directive applied to an `ng-template` inside an accordion panel t This directive has no inputs, outputs, or methods. Apply it to an `ng-template` element: ```angular-html -
+
diff --git a/adev-ja/src/content/guide/aria/accordion.md b/adev-ja/src/content/guide/aria/accordion.md index df3d224cf9..d5d3d600f5 100644 --- a/adev-ja/src/content/guide/aria/accordion.md +++ b/adev-ja/src/content/guide/aria/accordion.md @@ -145,10 +145,10 @@ NOTE: `multiExpandable`入力はデフォルトで`true`です。単䞀展開の ```angular-html
- -
+ +
- + Description @@ -159,6 +159,55 @@ NOTE: `multiExpandable`入力はデフォルトで`true`です。単䞀展開の デフォルトでは、パネルが折りたたたれた埌もコンテンツはDOMに残りたす。パネルが閉じたずきにDOMからコンテンツを削陀するには、`[preserveContent]="false"`を蚭定したす。 +## Testing {#testing} + +Angular Aria provides component harnesses for testing accordion components. +Here is an example of how to use the harnesses in a component test: + +```typescript +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {HarnessLoader} from '@angular/cdk/testing'; +import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed'; +import {AccordionGroupHarness} from '@angular/aria/accordion/testing'; +import {MyAccordionComponent} from './my-accordion'; // Your component + +describe('MyAccordionComponent', () => { + let fixture: ComponentFixture; + let loader: HarnessLoader; + + beforeEach(async () => { + TestBed.configureTestingModule({ + imports: [MyAccordionComponent], + }); + + fixture = TestBed.createComponent(MyAccordionComponent); + await fixture.whenStable(); + loader = TestbedHarnessEnvironment.loader(fixture); + }); + + it('should allow expanding panels', async () => { + // Load the accordion group harness + const group = await loader.getHarness(AccordionGroupHarness); + + // Get all individual accordions (items) in the group + const accordions = await group.getAccordions(); + expect(accordions.length).toBe(3); + + // Verify initial state (first expanded, others collapsed) + expect(await accordions[0].isExpanded()).toBe(true); + expect(await accordions[1].isExpanded()).toBe(false); + + // Expand the second panel + await accordions[1].expand(); + + // Verify updated state + expect(await accordions[1].isExpanded()).toBe(true); + // If multiExpandable is false, the first one should now be collapsed + expect(await accordions[0].isExpanded()).toBe(false); + }); +}); +``` + ## API ### AccordionGroup {#accordiongroup} @@ -187,12 +236,12 @@ NOTE: `multiExpandable`入力はデフォルトで`true`です。単䞀展開の #### Inputs {#inputs} -| プロパティ | 型 | デフォルト | 説明 | -| ---------- | --------- | ------- | -------------------------------------------------------------- | -| `id` | `string` | auto | トリガヌの䞀意の識別子 | -| `panelId` | `string` | — | **必須。**関連付けられたパネルの`panelId`ず䞀臎する必芁がありたす | -| `disabled` | `boolean` | `false` | このトリガヌを無効にしたす | -| `expanded` | `boolean` | `false` | パネルが展開されおいるかどうか双方向バむンディングをサポヌト | +| プロパティ | 型 | デフォルト | 説明 | +| ---------- | ---------------- | ------- | -------------------------------------------------------------- | +| `panel` | `AccordionPanel` | — | **必須。**制埡察象のアコヌディオンパネルぞの参照 | +| `id` | `string` | auto | トリガヌの䞀意の識別子 | +| `disabled` | `boolean` | `false` | このトリガヌを無効にしたす | +| `expanded` | `boolean` | `false` | パネルが展開されおいるかどうか双方向バむンディングをサポヌト | #### シグナル {#signals} @@ -214,11 +263,10 @@ NOTE: `multiExpandable`入力はデフォルトで`true`です。単䞀展開の #### Inputs {#inputs} -| プロパティ | 型 | デフォルト | 説明 | -| ----------------- | --------- | ------- | ---------------------------------------------------------------- | -| `id` | `string` | auto | パネルの䞀意の識別子 | -| `panelId` | `string` | — | **必須。**関連付けられたトリガヌの`panelId`ず䞀臎する必芁がありたす | -| `preserveContent` | `boolean` | `true` | パネルが折りたたたれた埌もコンテンツをDOMに保持するかどうか | +| プロパティ | 型 | デフォルト | 説明 | +| ----------------- | --------- | ------- | ---------------------------------------------------- | +| `id` | `string` | auto | パネルの䞀意の識別子 | +| `preserveContent` | `boolean` | `true` | パネルが折りたたたれた埌もコンテンツをDOMに保持するかどうか | #### シグナル {#signals} @@ -241,7 +289,7 @@ NOTE: `multiExpandable`入力はデフォルトで`true`です。単䞀展開の このディレクティブには、input、output、メ゜ッドはありたせん。`ng-template`芁玠に適甚しおください: ```angular-html -
+
diff --git a/adev-ja/src/content/guide/aria/autocomplete.en.md b/adev-ja/src/content/guide/aria/autocomplete.en.md index 73f2ab7a44..b7906c8ab5 100644 --- a/adev-ja/src/content/guide/aria/autocomplete.en.md +++ b/adev-ja/src/content/guide/aria/autocomplete.en.md @@ -52,7 +52,7 @@ Angular's autocomplete provides a fully accessible combobox implementation with: - **Keyboard Navigation** - Navigate options with arrow keys, select with Enter, close with Escape - **Screen Reader Support** - Built-in ARIA attributes for assistive technologies -- **Three Filter Modes** - Choose between auto-select, manual selection, or highlighting behavior +- **Dynamic Highlight Behavior** - Built-in support for inline selection suggestions - **Signal-Based Reactivity** - Reactive state management using Angular signals - **Popover API Integration** - Leverages the native HTML Popover API for optimal positioning - **Bidirectional Text Support** - Automatically handles right-to-left (RTL) languages @@ -149,42 +149,140 @@ Highlight mode allows the user to navigate options with arrow keys without chang +### Signal Forms Integration + +Angular Aria integrates seamlessly with the signal-based [Signal Forms](guide/forms/signals/overview) API. You can encapsulate complex inputs into reusable custom control components implementing `FormValueControl`. + +The following example demonstrates a country selector component implementing `FormValueControl`, bound to the parent form using `[formField]` and protected by schema validation rules. + + + + + + + + + + +## Testing + +The autocomplete pattern can be tested using a combination of `ComboboxHarness` and `ListboxHarness` from `@angular/aria/combobox/testing` and `@angular/aria/listbox/testing`. +Here is an example of how to use the harnesses to test an autocomplete component: + +```typescript +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {HarnessLoader} from '@angular/cdk/testing'; +import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed'; +import {ComboboxHarness} from '@angular/aria/combobox/testing'; +import {ListboxHarness} from '@angular/aria/listbox/testing'; +import {MyAutocompleteComponent} from './my-autocomplete'; // Your component + +describe('MyAutocompleteComponent', () => { + let fixture: ComponentFixture; + let loader: HarnessLoader; + + beforeEach(async () => { + TestBed.configureTestingModule({ + imports: [MyAutocompleteComponent], + }); + + fixture = TestBed.createComponent(MyAutocompleteComponent); + await fixture.whenStable(); + loader = TestbedHarnessEnvironment.loader(fixture); + }); + + it('should filter options based on input', async () => { + const combobox = await loader.getHarness(ComboboxHarness); + + // Type in the input to trigger filtering + await combobox.setValue('ap'); + expect(await combobox.isOpen()).toBe(true); + + // Get the listbox harness from the popup + const listbox = await combobox.getPopupWidget(ListboxHarness); + const options = await listbox.getOptions(); + + // Verify options are filtered (e.g., 'Apple', 'Apricot') + expect(options.length).toBe(2); + expect(await options[0].getText()).toBe('Apple'); + + // Select the first option + await options[0].click(); + + // Verify the input value is updated and popup is closed + expect(await combobox.isOpen()).toBe(false); + expect(await combobox.getValue()).toBe('Apple'); + }); +}); +``` + ## APIs ### Combobox Directive -The `ngCombobox` directive provides the container for autocomplete functionality. +The `ngCombobox` directive is applied directly onto the editable text `` or `