diff --git a/adev-ja/src/app/routing/sub-navigation-data.en.ts b/adev-ja/src/app/routing/sub-navigation-data.en.ts index e7813b6d56..b472670444 100644 --- a/adev-ja/src/app/routing/sub-navigation-data.en.ts +++ b/adev-ja/src/app/routing/sub-navigation-data.en.ts @@ -69,6 +69,7 @@ const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ label: 'Forms with signals', path: 'essentials/signal-forms', contentPath: 'introduction/essentials/signal-forms', + status: 'new', }, { label: 'Modular design with dependency injection', diff --git a/adev-ja/src/app/routing/sub-navigation-data.ts b/adev-ja/src/app/routing/sub-navigation-data.ts index eabaf8f7a9..f08a7ea773 100644 --- a/adev-ja/src/app/routing/sub-navigation-data.ts +++ b/adev-ja/src/app/routing/sub-navigation-data.ts @@ -69,6 +69,7 @@ const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ label: 'シグナルを使ったフォーム', path: 'essentials/signal-forms', contentPath: 'introduction/essentials/signal-forms', + status: 'new', }, { label: '依存性の注入によるモジュール設計', diff --git a/adev-ja/src/content/ai/mcp-server-setup.en.md b/adev-ja/src/content/ai/mcp-server-setup.en.md index c4451d50a3..148c431105 100644 --- a/adev-ja/src/content/ai/mcp-server-setup.en.md +++ b/adev-ja/src/content/ai/mcp-server-setup.en.md @@ -12,7 +12,7 @@ The Angular CLI MCP server provides several tools to assist you in your developm | `find_examples` | Finds authoritative code examples from a curated database of official, best-practice examples, focusing on **modern, new, and recently updated** Angular features. | ✅ | ✅ | | `get_best_practices` | Retrieves the Angular Best Practices Guide. This guide is essential for ensuring that all code adheres to modern standards, including standalone components, typed forms, and modern control flow. | ✅ | ✅ | | `list_projects` | Lists the names of all applications and libraries defined within an Angular workspace. It reads the `angular.json` configuration file to identify the projects. | ✅ | ✅ | -| `onpush-zoneless-migration` | Analyzes Angular code and provides a step-by-step, iterative plan to migrate it to `OnPush` change detection, a prerequisite for a zoneless application. | ✅ | ✅ | +| `onpush_zoneless_migration` | Analyzes Angular code and provides a step-by-step, iterative plan to migrate it to `OnPush` change detection, a prerequisite for a zoneless application. | ✅ | ✅ | | `search_documentation` | Searches the official Angular documentation at . This tool should be used to answer any questions about Angular, such as for APIs, tutorials, and best practices. | ❌ | ✅ | ### Experimental Tools diff --git a/adev-ja/src/content/ai/mcp-server-setup.md b/adev-ja/src/content/ai/mcp-server-setup.md index ab8a840453..f7c16047fe 100644 --- a/adev-ja/src/content/ai/mcp-server-setup.md +++ b/adev-ja/src/content/ai/mcp-server-setup.md @@ -12,7 +12,7 @@ Angular CLI MCPサーバーは、開発ワークフローを支援するいく | `find_examples` | 公式のベストプラクティス例の厳選されたデータベースから、権威ある コード例を検索します。**モダンで新しい、最近更新された**Angular機能に焦点を当てています。 | ✅ | ✅ | | `get_best_practices` | Angularベストプラクティスガイドを取得します。このガイドは、スタンドアロンコンポーネント、型付きフォーム、モダンな制御フローなど、すべてのコードが現代的な標準に準拠することを保証するために不可欠です。 | ✅ | ✅ | | `list_projects` | Angularワークスペース内で定義されたすべてのアプリケーションとライブラリの名前を一覧表示します。`angular.json`設定ファイルを読み取ってプロジェクトを識別します。 | ✅ | ✅ | -| `onpush-zoneless-migration` | Angularコードを分析し、ゾーンレスアプリケーションの前提条件である`OnPush`変更検知に移行するための段階的で反復的な計画を提供します。 | ✅ | ✅ | +| `onpush_zoneless_migration` | Angularコードを分析し、ゾーンレスアプリケーションの前提条件である`OnPush`変更検知に移行するための段階的で反復的な計画を提供します。 | ✅ | ✅ | | `search_documentation` | の公式Angularドキュメントを検索します。このツールは、API、チュートリアル、ベストプラクティスなど、Angularに関する質問に答えるために使用する必要があります。 | ❌ | ✅ | ### 実験的ツール {#experimental-tools} diff --git a/adev-ja/src/content/ecosystem/service-workers/config.md b/adev-ja/src/content/ecosystem/service-workers/config.md index ba05a1d7ba..8f1333947f 100644 --- a/adev-ja/src/content/ecosystem/service-workers/config.md +++ b/adev-ja/src/content/ecosystem/service-workers/config.md @@ -368,13 +368,12 @@ If the field is omitted, it defaults to: This optional property enables you to configure how the service worker handles navigation requests: - +```json { -"navigationRequestStrategy": "freshness" + "navigationRequestStrategy": "freshness" } - - +``` | Possible values | Details | | :-------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | diff --git a/adev-ja/src/content/events/v21.en.md b/adev-ja/src/content/events/v21.en.md index d26d5ce36c..e1a21e0c06 100644 --- a/adev-ja/src/content/events/v21.en.md +++ b/adev-ja/src/content/events/v21.en.md @@ -1,4 +1,4 @@ -![A retro 8-bit, pixel art style graphic announcing the upcoming release of Angular v21. The large, gradient 'v21' text dominates the frame. Next to it, in smaller text, are the words 'The Adventure Begins' and the release date '11-20-2025' inside a pink pixelated box. The Angular logo is in the bottom right corner.](assets/images/v21-event/angular-v21-hero.jpg 'Angular v21 Hero Image') +![A retro 8-bit, pixel art style graphic announcing the upcoming release of Angular v21. The large, gradient 'v21' text dominates the frame. Next to it, in smaller text, are the words 'The Adventure Begins' and the release date '11-20-2025' inside a pink pixelated box. The Angular logo is in the bottom right corner.](assets/images/angular-v21-hero.jpg {loading: 'eager', fetchpriority: 'high'} 'Angular v21 Hero Image') # Angular v21: The Adventure Begins diff --git a/adev-ja/src/content/events/v21.md b/adev-ja/src/content/events/v21.md index 8eb4396ce8..2afeaada31 100644 --- a/adev-ja/src/content/events/v21.md +++ b/adev-ja/src/content/events/v21.md @@ -1,4 +1,4 @@ -![Angular v21の今後のリリースを告知する、レトロな8ビットのピクセルアートスタイルのグラフィック。大きなグラデーションの「v21」テキストがフレームを占めています。その隣には、小さなテキストで「The Adventure Begins」という言葉と、ピンク色のピクセル化されたボックス内にリリース日「11-20-2025」が記載されています。Angularのロゴは右下隅にあります。](assets/images/v21-event/angular-v21-hero.jpg 'Angular v21ヒーロー画像') +![Angular v21の今後のリリースを告知する、レトロな8ビットのピクセルアートスタイルのグラフィック。大きなグラデーションの「v21」テキストがフレームを占めています。その隣には、小さなテキストで「The Adventure Begins」という言葉と、ピンク色のピクセル化されたボックス内にリリース日「11-20-2025」が記載されています。Angularのロゴは右下隅にあります。](assets/images/angular-v21-hero.jpg {loading: 'eager', fetchpriority: 'high'} 'Angular v21ヒーロー画像') # Angular v21: 冒険の始まり diff --git a/adev-ja/src/content/guide/aria/combobox.en.md b/adev-ja/src/content/guide/aria/combobox.en.md index 858eb4865e..a743fd2a42 100644 --- a/adev-ja/src/content/guide/aria/combobox.en.md +++ b/adev-ja/src/content/guide/aria/combobox.en.md @@ -3,7 +3,7 @@ - + ## Overview diff --git a/adev-ja/src/content/guide/aria/combobox.md b/adev-ja/src/content/guide/aria/combobox.md index 5c650d2725..317130f0a4 100644 --- a/adev-ja/src/content/guide/aria/combobox.md +++ b/adev-ja/src/content/guide/aria/combobox.md @@ -3,7 +3,7 @@ - + ## 概要 {#overview} diff --git a/adev-ja/src/content/guide/aria/grid.en.md b/adev-ja/src/content/guide/aria/grid.en.md index 6545e3045b..e690118ae9 100644 --- a/adev-ja/src/content/guide/aria/grid.en.md +++ b/adev-ja/src/content/guide/aria/grid.en.md @@ -3,7 +3,7 @@ - + ## Overview diff --git a/adev-ja/src/content/guide/aria/grid.md b/adev-ja/src/content/guide/aria/grid.md index 463ae853b4..a7a3d15b8d 100644 --- a/adev-ja/src/content/guide/aria/grid.md +++ b/adev-ja/src/content/guide/aria/grid.md @@ -3,7 +3,7 @@ - + ## 概要 {#overview} diff --git a/adev-ja/src/content/guide/aria/listbox.en.md b/adev-ja/src/content/guide/aria/listbox.en.md index 0255ee6894..a1863dc151 100644 --- a/adev-ja/src/content/guide/aria/listbox.en.md +++ b/adev-ja/src/content/guide/aria/listbox.en.md @@ -1,6 +1,11 @@ + + + + + ## Overview A directive that displays a list of options for users to select from, supporting keyboard navigation, single or multiple selection, and screen reader support. diff --git a/adev-ja/src/content/guide/aria/listbox.md b/adev-ja/src/content/guide/aria/listbox.md index 0e6fa9e2f8..3696517f80 100644 --- a/adev-ja/src/content/guide/aria/listbox.md +++ b/adev-ja/src/content/guide/aria/listbox.md @@ -1,6 +1,11 @@ + + + + + ## 概要 {#overview} ユーザーが選択するためのオプションのリストを表示するディレクティブで、キーボードナビゲーション、単一または複数選択、スクリーンリーダーをサポートしています。 diff --git a/adev-ja/src/content/guide/aria/menubar.en.md b/adev-ja/src/content/guide/aria/menubar.en.md index 780d7af8b7..1abedb0c8f 100644 --- a/adev-ja/src/content/guide/aria/menubar.en.md +++ b/adev-ja/src/content/guide/aria/menubar.en.md @@ -3,7 +3,7 @@ - + ## Overview diff --git a/adev-ja/src/content/guide/aria/menubar.md b/adev-ja/src/content/guide/aria/menubar.md index 592af724ee..4746d5266f 100644 --- a/adev-ja/src/content/guide/aria/menubar.md +++ b/adev-ja/src/content/guide/aria/menubar.md @@ -3,7 +3,7 @@ - + ## 概要 {#overview} diff --git a/adev-ja/src/content/guide/aria/overview.en.md b/adev-ja/src/content/guide/aria/overview.en.md index d0d04473b4..5b3808324f 100644 --- a/adev-ja/src/content/guide/aria/overview.en.md +++ b/adev-ja/src/content/guide/aria/overview.en.md @@ -66,18 +66,18 @@ Angular Aria includes directives with comprehensive documentation, working examp ### Navigation and call to actions -| Component | Description | -| ----------------------------- | ----------------------------------------------------------- | -| [Menu](guide/aria/menu) | Dropdown menus with nested submenus and keyboard shortcuts | -| [Menubar](guide/aria/menubar) | Horizontal navigation bar for persistent application menus | -| [Tabs](guide/aria/tabs) | Tabbed interfaces with automatic or manual activation modes | -| [Toolbar](guide/aria/toolbar) | Grouped sets of controls with logical keyboard navigation | +| Component | Description | +| ----------------------------- | ---------------------------------------------------------- | +| [Menu](guide/aria/menu) | Dropdown menus with nested submenus and keyboard shortcuts | +| [Menubar](guide/aria/menubar) | Horizontal navigation bar for persistent application menus | +| [Toolbar](guide/aria/toolbar) | Grouped sets of controls with logical keyboard navigation | ### Content organization | Component | Description | | --------------------------------- | ---------------------------------------------------------------------- | | [Accordion](guide/aria/accordion) | Collapsible content panels that can expand individually or exclusively | +| [Tabs](guide/aria/tabs) | Tabbed interfaces with automatic or manual activation modes | | [Tree](guide/aria/tree) | Hierarchical lists with expand/collapse functionality | | [Grid](guide/aria/grid) | Two-dimensional data display with cell-by-cell keyboard navigation | diff --git a/adev-ja/src/content/guide/aria/overview.md b/adev-ja/src/content/guide/aria/overview.md index 891ec331ea..caea8c457a 100644 --- a/adev-ja/src/content/guide/aria/overview.md +++ b/adev-ja/src/content/guide/aria/overview.md @@ -66,20 +66,20 @@ Angular Ariaには、包括的なドキュメント、動作するサンプル ### ナビゲーションとCTA {#navigation-and-call-to-actions} -| Component | 説明 | -| ----------------------------- | ---------------------------------------------------- | +| Component | 説明 | +| ----------------------------- | --------------------------------------------------- | | [Menu](guide/aria/menu) | ネストされたサブメニューとキーボードショートカットを持つドロップダウンメニュー | -| [Menubar](guide/aria/menubar) | 永続的なアプリケーションメニュー用の水平ナビゲーションバー | -| [Tabs](guide/aria/tabs) | 自動または手動のアクティベーションモードを持つタブ付きインターフェース | -| [Toolbar](guide/aria/toolbar) | 論理的なキーボードナビゲーションを持つ、グループ化されたコントロールのセット | +| [Menubar](guide/aria/menubar) | 永続的なアプリケーションメニュー用の水平ナビゲーションバー | +| [Toolbar](guide/aria/toolbar) | 論理的なキーボードナビゲーションを持つ、グループ化されたコントロールのセット | ### コンテンツの構成 {#content-organization} -| Component | 説明 | -| --------------------------------- | --------------------------------------------------------------- | -| [Accordion](guide/aria/accordion) | 個別に、または排他的に展開できる折りたたみ可能なコンテンツパネル | -| [Tree](guide/aria/tree) | 展開/折りたたみ機能を持つ階層的なリスト | -| [Grid](guide/aria/grid) | セル単位のキーボードナビゲーションを備えた2次元のデータ表示 | +| Component | 説明 | +| --------------------------------- | -------------------------------------------------------------- | +| [Accordion](guide/aria/accordion) | 個別に、または排他的に展開できる折りたたみ可能なコンテンツパネル | +| [Tabs](guide/aria/tabs) | 自動または手動のアクティベーションモードを持つタブ付きインターフェース | +| [Tree](guide/aria/tree) | 展開/折りたたみ機能を持つ階層的なリスト | +| [Grid](guide/aria/grid) | セル単位のキーボードナビゲーションを備えた2次元のデータ表示 | ## Angular Ariaを使用する場面 {#when-to-use-angular-aria} diff --git a/adev-ja/src/content/guide/aria/toolbar.en.md b/adev-ja/src/content/guide/aria/toolbar.en.md index 1684759c0c..5e187194bc 100644 --- a/adev-ja/src/content/guide/aria/toolbar.en.md +++ b/adev-ja/src/content/guide/aria/toolbar.en.md @@ -1,6 +1,11 @@ + + + + + ## Overview A container for grouping related controls and actions with keyboard navigation, commonly used for text formatting, toolbars, and command panels. diff --git a/adev-ja/src/content/guide/aria/toolbar.md b/adev-ja/src/content/guide/aria/toolbar.md index 512ab11ea2..f1ee27aaa5 100644 --- a/adev-ja/src/content/guide/aria/toolbar.md +++ b/adev-ja/src/content/guide/aria/toolbar.md @@ -1,6 +1,11 @@ + + + + + ## 概要 キーボードナビゲーションで関連するコントロールとアクションをグループ化するためのコンテナで、一般的にテキストフォーマット、ツールバー、コマンドパネルに使用されます。 diff --git a/adev-ja/src/content/guide/di/creating-injectable-service.md b/adev-ja/src/content/guide/di/creating-injectable-service.md index e90000c5d4..f8b15a9cc7 100644 --- a/adev-ja/src/content/guide/di/creating-injectable-service.md +++ b/adev-ja/src/content/guide/di/creating-injectable-service.md @@ -67,35 +67,35 @@ ng generate service heroes/hero This command creates the following default `HeroService`: - -import { Injectable } from '@angular/core'; +```ts {header: 'heroes/hero.service.ts (CLI-generated)'} +import {Injectable} from '@angular/core'; @Injectable({ -providedIn: 'root', + providedIn: 'root', }) export class HeroService {} - +``` The `@Injectable()` decorator specifies that Angular can use this class in the DI system. The metadata, `providedIn: 'root'`, means that the `HeroService` is provided throughout the application. Add a `getHeroes()` method that returns the heroes from `mock.heroes.ts` to get the hero mock data: - -import { Injectable } from '@angular/core'; -import { HEROES } from './mock-heroes'; +```ts {header: 'hero.service.ts'} +import {Injectable} from '@angular/core'; +import {HEROES} from './mock-heroes'; @Injectable({ -// declares that this service should be created -// by the root application injector. -providedIn: 'root', + // declares that this service should be created + // by the root application injector. + providedIn: 'root', }) export class HeroService { -getHeroes() { -return HEROES; -} + getHeroes() { + return HEROES; + } } - +``` For clarity and maintainability, it is recommended that you define components and services in separate files. @@ -106,19 +106,19 @@ To inject a service as a dependency into a component, you can declare a class fi The following example specifies the `HeroService` in the `HeroListComponent`. The type of `heroService` is `HeroService`. - -import { inject } from "@angular/core"; +```ts +import {inject} from '@angular/core'; export class HeroListComponent { -private heroService = inject(HeroService); + private heroService = inject(HeroService); } - +``` It is also possible to inject a service into a component using the component's constructor: - +```ts {header: 'hero-list.component.ts (constructor signature)'} constructor(private heroService: HeroService) - +``` The `inject` method can be used in both classes and functions, while the constructor method can naturally only be used in a class constructor. However, in either case a dependency may only be injected in a valid [injection context](guide/di/dependency-injection-context), usually in the construction or initialization of a component. @@ -127,24 +127,23 @@ The `inject` method can be used in both classes and functions, while the constru When a service depends on another service, follow the same pattern as injecting into a component. In the following example, `HeroService` depends on a `Logger` service to report its activities: - -import { inject, Injectable } from '@angular/core'; -import { HEROES } from './mock-heroes'; -import { Logger } from '../logger.service'; +```ts {header: 'hero.service.ts, highlight: [[3],[9],[12]]} +import {inject, Injectable} from '@angular/core'; +import {HEROES} from './mock-heroes'; +import {Logger} from '../logger.service'; @Injectable({ -providedIn: 'root', + providedIn: 'root', }) export class HeroService { -private logger = inject(Logger); + private logger = inject(Logger); -getHeroes() { -this.logger.log('Getting heroes.'); -return HEROES; + getHeroes() { + this.logger.log('Getting heroes.'); + return HEROES; + } } -} - +``` In this example, the `getHeroes()` method uses the `Logger` service by logging a message when fetching heroes. diff --git a/adev-ja/src/content/guide/di/di-in-action.en.md b/adev-ja/src/content/guide/di/di-in-action.en.md index cefb93787e..843fc1ba52 100644 --- a/adev-ja/src/content/guide/di/di-in-action.en.md +++ b/adev-ja/src/content/guide/di/di-in-action.en.md @@ -11,20 +11,21 @@ As a result, you might need to access a component's DOM element. Angular exposes the underlying element of a `@Component` or `@Directive` via injection using the `ElementRef` injection token: - -import { Directive, ElementRef } from '@angular/core'; +```ts {highlight:[7]} +import {Directive, ElementRef, inject} from '@angular/core'; @Directive({ -selector: '[appHighlight]' + selector: '[appHighlight]', }) export class HighlightDirective { -private element = inject(ElementRef) + private element = inject(ElementRef); -update() { -this.element.nativeElement.style.color = 'red'; + update() { + this.element.nativeElement.style.color = 'red'; + } } -} - + +``` ## Resolve circular dependencies with a forward reference @@ -42,11 +43,11 @@ For example, in its `providers` array. The `providers` array is a property of the `@Component()` decorator function, which must appear before the class definition. You can break such circular references by using `forwardRef`. - +```typescript {header: 'app.component.ts', highlight: [4]} providers: [ { provide: PARENT_MENU_ITEM, useExisting: forwardRef(() => MenuItem), }, ], - +``` diff --git a/adev-ja/src/content/guide/di/di-in-action.md b/adev-ja/src/content/guide/di/di-in-action.md index a9d80c0ec3..0ab209703c 100644 --- a/adev-ja/src/content/guide/di/di-in-action.md +++ b/adev-ja/src/content/guide/di/di-in-action.md @@ -11,20 +11,21 @@ NOTE: InjectionTokenとカスタムプロバイダーの包括的な説明につ Angularは、`@Component`または`@Directive`の基になる要素を、`ElementRef`インジェクショントークンを使用してインジェクションすることで公開します。 - -import { Directive, ElementRef } from '@angular/core'; +```ts {highlight:[7]} +import {Directive, ElementRef, inject} from '@angular/core'; @Directive({ -selector: '[appHighlight]' + selector: '[appHighlight]', }) export class HighlightDirective { -private element = inject(ElementRef) + private element = inject(ElementRef); -update() { -this.element.nativeElement.style.color = 'red'; + update() { + this.element.nativeElement.style.color = 'red'; + } } -} - + +``` ## 前方参照を使用して循環した依存関係を解決する {#resolve-circular-dependencies-with-a-forward-reference} @@ -42,11 +43,11 @@ Angularの`forwardRef()`関数は、Angularが後で解決できる_間接的な `providers`配列は、`@Component()`デコレーター関数のプロパティであり、クラス定義の前に表示される必要があります。 `forwardRef`を使用して、このような循環参照を解消できます。 - +```typescript {header: 'app.component.ts', highlight: [4]} providers: [ { provide: PARENT_MENU_ITEM, useExisting: forwardRef(() => MenuItem), }, ], - +``` diff --git a/adev-ja/src/content/guide/di/hierarchical-dependency-injection.en.md b/adev-ja/src/content/guide/di/hierarchical-dependency-injection.en.md index 065a9a4aa7..77dbde0e39 100644 --- a/adev-ja/src/content/guide/di/hierarchical-dependency-injection.en.md +++ b/adev-ja/src/content/guide/di/hierarchical-dependency-injection.en.md @@ -210,7 +210,7 @@ To avoid errors in this situation, combine `self` with `optional`. For example, in the following `SelfNoDataComponent`, notice the injected `LeafService` as a property. -```ts {header:"src/app/self-no-data/self-no-data.component.ts", highlight=[7]}> +```ts {header: 'self-no-data.component.ts', highlight: [7]} @Component({ selector: 'app-self-no-data', templateUrl: './self-no-data.component.html', @@ -246,7 +246,7 @@ So if the parent `ElementInjector` were using the fern 🌿 value f To see this in code, assume that the following value for `emoji` is what the parent component were using, as in this service: -```ts {header:"src/app/leaf.service.ts"} +```ts {header: 'leaf.service.ts'} export class LeafService { emoji = '🌿'; } @@ -255,7 +255,7 @@ export class LeafService { Imagine that in the child component, you had a different value, maple leaf 🍁 but you wanted to use the parent's value instead. This is when you'd use `skipSelf`: -```ts {header:"src/app/skipself/skipself.component.ts" highlight:[[6],[10]]} +```ts {header:"skipself.component.ts" highlight:[[6],[10]]} @Component({ selector: 'app-skipself', templateUrl: './skipself.component.html', @@ -293,17 +293,17 @@ class Person { Even if there is a service instance further up the tree, Angular won't continue looking. Use `host` as follows: -```ts {header:"src/app/host/host.component.ts" highlight:[[6],[10]]} +```ts {header:"host.component.ts" highlight:[[6],[9]]} @Component({ -selector: 'app-host', -templateUrl: './host.component.html', -styleUrls: ['./host.component.css'], -// provide the service -providers: [{ provide: FlowerService, useValue: { emoji: '🌷' } }] + selector: 'app-host', + templateUrl: './host.component.html', + styleUrls: ['./host.component.css'], + // provide the service + providers: [{provide: FlowerService, useValue: {emoji: '🌷'}}], }) export class HostComponent { -// use host when injecting the service -flower = inject(FlowerService, {host: true, optional: true}); + // use host when injecting the service + flower = inject(FlowerService, {host: true, optional: true}); } ``` @@ -315,7 +315,7 @@ Similarly as presented before, the behavior of constructor injection can be modi Import each of them from `@angular/core` and use each in the component class constructor when you inject your service. -```ts {header:"src/app/self-no-data/self-no-data.component.ts" highlight:[3]} +```ts {header:"self-no-data.component.ts" highlight:[2]} export class SelfNoDataComponent { constructor(@Self() @Optional() public leaf?: LeafService) { } } @@ -385,7 +385,7 @@ These aren't real attributes but are here to demonstrate what is going on under The example application has a `FlowerService` provided in `root` with an `emoji` value of red hibiscus 🌺. -```ts {header:"src/app/flower.service.ts"} +```ts {header:"lower.service.ts"} @Injectable({ providedIn: 'root' }) @@ -480,17 +480,17 @@ In the example case, the constraints are: Now, in the `ChildComponent` class, add a provider for `FlowerService` to demonstrate more complex resolution rules in the upcoming sections: -```typescript +```ts @Component({ -selector: 'app-child', -templateUrl: './child.component.html', -styleUrls: ['./child.component.css'], -// use the providers array to provide a service -providers: [{ provide: FlowerService, useValue: { emoji: '🌻' } }] + selector: 'app-child', + templateUrl: './child.component.html', + styleUrls: ['./child.component.css'], + // use the providers array to provide a service + providers: [{provide: FlowerService, useValue: {emoji: '🌻'}}], }) export class ChildComponent { -// inject the service -flower = inject(FlowerService); + // inject the service + flower = inject(FlowerService); } ``` @@ -548,22 +548,22 @@ For demonstration, we are building an `AnimalService` to demonstrate `viewProvid First, create an `AnimalService` with an `emoji` property of whale 🐳: ```typescript -import { Injectable } from '@angular/core'; +import {Injectable} from '@angular/core'; @Injectable({ -providedIn: 'root' + providedIn: 'root', }) export class AnimalService { -emoji = '🐳'; + emoji = '🐳'; } ``` Following the same pattern as with the `FlowerService`, inject the `AnimalService` in the `AppComponent` class: -```typescript +```ts export class AppComponent { - public flower = inject(FlowerService); - public animal = inject(AnimalService); + public flower = inject(FlowerService); + public animal = inject(AnimalService); } ``` @@ -574,18 +574,17 @@ Here, it has a value of dog 🐶. ```typescript @Component({ -selector: 'app-child', -templateUrl: './child.component.html', -styleUrls: ['./child.component.css'], -// provide services -providers: [{ provide: FlowerService, useValue: { emoji: '🌻' } }], -viewProviders: [{ provide: AnimalService, useValue: { emoji: '🐶' } }] + selector: 'app-child', + templateUrl: './child.component.html', + styleUrls: ['./child.component.css'], + // provide services + providers: [{provide: FlowerService, useValue: {emoji: '🌻'}}], + viewProviders: [{provide: AnimalService, useValue: {emoji: '🐶'}}], }) export class ChildComponent { -// inject services -flower = inject(FlowerService); -animal = inject(AnimalService) -... + // inject services + flower = inject(FlowerService); + animal = inject(AnimalService); } ``` @@ -660,10 +659,10 @@ Next, in `inspector.component.html`, add the same markup from previous component Remember to add the `InspectorComponent` to the `ChildComponent` `imports` array. -```typescript +```ts @Component({ -... -imports: [InspectorComponent] + ... + imports: [InspectorComponent] }) ``` @@ -754,7 +753,7 @@ To alter where the injector starts looking for `FlowerService`, add `skipSelf` t This invocation is a property initializer the `` as shown in `child.component.ts`: ```typescript -flower = inject(FlowerService, { skipSelf: true }) + flower = inject(FlowerService, { skipSelf: true }) ``` With `skipSelf`, the `` injector doesn't look to itself for the `FlowerService`. @@ -945,9 +944,9 @@ Instead, you should provide the `VillainsService` in the `providers` metadata of ```typescript @Component({ -selector: 'app-villains-list', -templateUrl: './villains-list.component.html', -providers: [VillainsService] + selector: 'app-villains-list', + templateUrl: './villains-list.component.html', + providers: [VillainsService], }) export class VillainsListComponent {} ``` @@ -982,85 +981,87 @@ The `HeroTaxReturnService` caches a single `HeroTaxReturn`, tracks changes to th It also delegates to the application-wide singleton `HeroService`, which it gets by injection. ```typescript -import { Injectable } from '@angular/core'; -import { HeroTaxReturn } from './hero'; -import { HeroesService } from './heroes.service'; +import {inject, Injectable} from '@angular/core'; +import {HeroTaxReturn} from './hero'; +import {HeroesService} from './heroes.service'; @Injectable() export class HeroTaxReturnService { -private currentTaxReturn!: HeroTaxReturn; -private originalTaxReturn!: HeroTaxReturn; + private currentTaxReturn!: HeroTaxReturn; + private originalTaxReturn!: HeroTaxReturn; -private heroService = inject(HeroesService); + private heroService = inject(HeroesService); -set taxReturn(htr: HeroTaxReturn) { -this.originalTaxReturn = htr; -this.currentTaxReturn = htr.clone(); -} + set taxReturn(htr: HeroTaxReturn) { + this.originalTaxReturn = htr; + this.currentTaxReturn = htr.clone(); + } -get taxReturn(): HeroTaxReturn { -return this.currentTaxReturn; -} + get taxReturn(): HeroTaxReturn { + return this.currentTaxReturn; + } -restoreTaxReturn() { -this.taxReturn = this.originalTaxReturn; -} + restoreTaxReturn() { + this.taxReturn = this.originalTaxReturn; + } -saveTaxReturn() { -this.taxReturn = this.currentTaxReturn; -this.heroService.saveTaxReturn(this.currentTaxReturn).subscribe(); -} + saveTaxReturn() { + this.taxReturn = this.currentTaxReturn; + this.heroService.saveTaxReturn(this.currentTaxReturn).subscribe(); + } } ``` Here is the `HeroTaxReturnComponent` that makes use of `HeroTaxReturnService`. ```typescript -import { Component, EventEmitter, input, output } from '@angular/core'; -import { HeroTaxReturn } from './hero'; -import { HeroTaxReturnService } from './hero-tax-return.service'; +import {Component, input, output} from '@angular/core'; +import {HeroTaxReturn} from './hero'; +import {HeroTaxReturnService} from './hero-tax-return.service'; @Component({ -selector: 'app-hero-tax-return', -templateUrl: './hero-tax-return.component.html', -styleUrls: [ './hero-tax-return.component.css' ], -providers: [ HeroTaxReturnService ] + selector: 'app-hero-tax-return', + templateUrl: './hero-tax-return.component.html', + styleUrls: ['./hero-tax-return.component.css'], + providers: [HeroTaxReturnService], }) export class HeroTaxReturnComponent { -message = ''; + message = ''; -close = output(); + close = output(); -get taxReturn(): HeroTaxReturn { -return this.heroTaxReturnService.taxReturn; -} + get taxReturn(): HeroTaxReturn { + return this.heroTaxReturnService.taxReturn; + } -taxReturn = input.required(); + taxReturn = input.required(); -constructor() { -effect(() => { -this.heroTaxReturnService.taxReturn = this.taxReturn(); -}) -} + constructor() { + effect(() => { + this.heroTaxReturnService.taxReturn = this.taxReturn(); + }); + } -private heroTaxReturnService = inject(HeroTaxReturnService); + private heroTaxReturnService = inject(HeroTaxReturnService); -onCanceled() { -this.flashMessage('Canceled'); -this.heroTaxReturnService.restoreTaxReturn(); -} + onCanceled() { + this.flashMessage('Canceled'); + this.heroTaxReturnService.restoreTaxReturn(); + } -onClose() { this.close.emit(); } + onClose() { + this.close.emit(); + } -onSaved() { -this.flashMessage('Saved'); -this.heroTaxReturnService.saveTaxReturn(); -} + onSaved() { + this.flashMessage('Saved'); + this.heroTaxReturnService.saveTaxReturn(); + } -flashMessage(msg: string) { -this.message = msg; -setTimeout(() => this.message = '', 500); -} + flashMessage(msg: string) { + this.message = msg; + setTimeout(() => (this.message = ''), 500); + } } ``` @@ -1075,7 +1076,7 @@ Every component would share the same service instance, and each component would To prevent this, configure the component-level injector of `HeroTaxReturnComponent` to provide the service, using the `providers` property in the component metadata. ```typescript -providers: [HeroTaxReturnService] + providers: [HeroTaxReturnService] ``` The `HeroTaxReturnComponent` has its own provider of the `HeroTaxReturnService`. diff --git a/adev-ja/src/content/guide/di/hierarchical-dependency-injection.md b/adev-ja/src/content/guide/di/hierarchical-dependency-injection.md index 33eaa8672e..03b5b144b1 100644 --- a/adev-ja/src/content/guide/di/hierarchical-dependency-injection.md +++ b/adev-ja/src/content/guide/di/hierarchical-dependency-injection.md @@ -210,7 +210,7 @@ export class OptionalComponent { たとえば、次の `SelfNoDataComponent` では、プロパティとして注入された `LeafService` に注目してください。 -```ts {header:"src/app/self-no-data/self-no-data.component.ts", highlight=[7]}> +```ts {header: 'self-no-data.component.ts', highlight: [7]} @Component({ selector: 'app-self-no-data', templateUrl: './self-no-data.component.html', @@ -246,7 +246,7 @@ export class SelfComponent { これをコードで確認するために、親コンポーネントが使用する `emoji` の次の値を想定します。これは、このサービスと同じです。 -```ts {header:"src/app/leaf.service.ts"} +```ts {header: 'leaf.service.ts'} export class LeafService { emoji = '🌿'; } @@ -255,7 +255,7 @@ export class LeafService { 子コンポーネントに、異なる値、カエデの葉 🍁 が含まれていると想像してください。ただし、親の値を使用したいとします。 これが `skipSelf` を使用する場合です。 -```ts {header:"src/app/skipself/skipself.component.ts" highlight:[[6],[10]]} +```ts {header:"skipself.component.ts" highlight:[[6],[10]]} @Component({ selector: 'app-skipself', templateUrl: './skipself.component.html', @@ -293,17 +293,17 @@ class Person { ツリーのさらに上にサービスインスタンスがある場合でも、Angularは検索を続けません。 `host` を次のように使用します。 -```ts {header:"src/app/host/host.component.ts" highlight:[[6],[10]]} +```ts {header:"host.component.ts" highlight:[[6],[9]]} @Component({ -selector: 'app-host', -templateUrl: './host.component.html', -styleUrls: ['./host.component.css'], -// provide the service -providers: [{ provide: FlowerService, useValue: { emoji: '🌷' } }] + selector: 'app-host', + templateUrl: './host.component.html', + styleUrls: ['./host.component.css'], + // provide the service + providers: [{provide: FlowerService, useValue: {emoji: '🌷'}}], }) export class HostComponent { -// use host when injecting the service -flower = inject(FlowerService, {host: true, optional: true}); + // use host when injecting the service + flower = inject(FlowerService, {host: true, optional: true}); } ``` @@ -315,7 +315,7 @@ flower = inject(FlowerService, {host: true, optional: true}); `@angular/core` からそれぞれをインポートし、サービスを注入するときにコンポーネントクラスのコンストラクターでそれぞれを使用します。 -```ts {header:"src/app/self-no-data/self-no-data.component.ts" highlight:[3]} +```ts {header:"self-no-data.component.ts" highlight:[2]} export class SelfNoDataComponent { constructor(@Self() @Optional() public leaf?: LeafService) { } } @@ -385,7 +385,7 @@ HELPFUL: 通常、コンポーネントとそのテンプレートは別々の この例では、 `emoji` の値が赤いハイビスカス 🌺 である、 `root` に提供される `FlowerService` があります。 -```ts {header:"src/app/flower.service.ts"} +```ts {header:"lower.service.ts"} @Injectable({ providedIn: 'root' }) @@ -480,17 +480,17 @@ Emoji from FlowerService: 🌺 次に、 `ChildComponent` クラスで、今後のセクションでより複雑な解決ルールを説明するために、 `FlowerService` のプロバイダーを追加します。 -```typescript +```ts @Component({ -selector: 'app-child', -templateUrl: './child.component.html', -styleUrls: ['./child.component.css'], -// use the providers array to provide a service -providers: [{ provide: FlowerService, useValue: { emoji: '🌻' } }] + selector: 'app-child', + templateUrl: './child.component.html', + styleUrls: ['./child.component.css'], + // use the providers array to provide a service + providers: [{provide: FlowerService, useValue: {emoji: '🌻'}}], }) export class ChildComponent { -// inject the service -flower = inject(FlowerService); + // inject the service + flower = inject(FlowerService); } ``` @@ -548,22 +548,22 @@ HELPFUL: ステップは `providers` 配列を使用する場合と同じです 最初に、 `emoji` プロパティがクジラ 🐳 である `AnimalService` を作成します。 ```typescript -import { Injectable } from '@angular/core'; +import {Injectable} from '@angular/core'; @Injectable({ -providedIn: 'root' + providedIn: 'root', }) export class AnimalService { -emoji = '🐳'; + emoji = '🐳'; } ``` `FlowerService` と同じパターンに従って、 `AppComponent` クラスに `AnimalService` を注入します。 -```typescript +```ts export class AppComponent { - public flower = inject(FlowerService); - public animal = inject(AnimalService); + public flower = inject(FlowerService); + public animal = inject(AnimalService); } ``` @@ -574,18 +574,17 @@ HELPFUL: `FlowerService` に関連するコードはすべてそのままにし ```typescript @Component({ -selector: 'app-child', -templateUrl: './child.component.html', -styleUrls: ['./child.component.css'], -// provide services -providers: [{ provide: FlowerService, useValue: { emoji: '🌻' } }], -viewProviders: [{ provide: AnimalService, useValue: { emoji: '🐶' } }] + selector: 'app-child', + templateUrl: './child.component.html', + styleUrls: ['./child.component.css'], + // provide services + providers: [{provide: FlowerService, useValue: {emoji: '🌻'}}], + viewProviders: [{provide: AnimalService, useValue: {emoji: '🐶'}}], }) export class ChildComponent { -// inject services -flower = inject(FlowerService); -animal = inject(AnimalService) -... + // inject services + flower = inject(FlowerService); + animal = inject(AnimalService); } ``` @@ -660,10 +659,10 @@ export class InspectorComponent { `InspectorComponent` を `ChildComponent` の `imports` 配列に追加することを忘れないでください。 -```typescript +```ts @Component({ -... -imports: [InspectorComponent] + ... + imports: [InspectorComponent] }) ``` @@ -754,7 +753,7 @@ Emoji from AnimalService: 🐶 この呼び出しは、`child.component.ts` に示すように、`` のプロパティ初期化子です。 ```typescript -flower = inject(FlowerService, { skipSelf: true }) + flower = inject(FlowerService, { skipSelf: true }) ``` `skipSelf` を使用すると、`` インジェクターは `FlowerService` を自分自身で探しません。 @@ -945,9 +944,9 @@ inject(AnimalService, {skipSelf:true, host: true, optional: true})=>"🦔"> ```typescript @Component({ -selector: 'app-villains-list', -templateUrl: './villains-list.component.html', -providers: [VillainsService] + selector: 'app-villains-list', + templateUrl: './villains-list.component.html', + providers: [VillainsService], }) export class VillainsListComponent {} ``` @@ -982,85 +981,87 @@ export class VillainsListComponent {} また、注入によって取得したアプリケーション全体のシングルトン `HeroService` に委任します。 ```typescript -import { Injectable } from '@angular/core'; -import { HeroTaxReturn } from './hero'; -import { HeroesService } from './heroes.service'; +import {inject, Injectable} from '@angular/core'; +import {HeroTaxReturn} from './hero'; +import {HeroesService} from './heroes.service'; @Injectable() export class HeroTaxReturnService { -private currentTaxReturn!: HeroTaxReturn; -private originalTaxReturn!: HeroTaxReturn; + private currentTaxReturn!: HeroTaxReturn; + private originalTaxReturn!: HeroTaxReturn; -private heroService = inject(HeroesService); + private heroService = inject(HeroesService); -set taxReturn(htr: HeroTaxReturn) { -this.originalTaxReturn = htr; -this.currentTaxReturn = htr.clone(); -} + set taxReturn(htr: HeroTaxReturn) { + this.originalTaxReturn = htr; + this.currentTaxReturn = htr.clone(); + } -get taxReturn(): HeroTaxReturn { -return this.currentTaxReturn; -} + get taxReturn(): HeroTaxReturn { + return this.currentTaxReturn; + } -restoreTaxReturn() { -this.taxReturn = this.originalTaxReturn; -} + restoreTaxReturn() { + this.taxReturn = this.originalTaxReturn; + } -saveTaxReturn() { -this.taxReturn = this.currentTaxReturn; -this.heroService.saveTaxReturn(this.currentTaxReturn).subscribe(); -} + saveTaxReturn() { + this.taxReturn = this.currentTaxReturn; + this.heroService.saveTaxReturn(this.currentTaxReturn).subscribe(); + } } ``` 以下は、 `HeroTaxReturnService` を使用する `HeroTaxReturnComponent` です。 ```typescript -import { Component, EventEmitter, input, output } from '@angular/core'; -import { HeroTaxReturn } from './hero'; -import { HeroTaxReturnService } from './hero-tax-return.service'; +import {Component, input, output} from '@angular/core'; +import {HeroTaxReturn} from './hero'; +import {HeroTaxReturnService} from './hero-tax-return.service'; @Component({ -selector: 'app-hero-tax-return', -templateUrl: './hero-tax-return.component.html', -styleUrls: [ './hero-tax-return.component.css' ], -providers: [ HeroTaxReturnService ] + selector: 'app-hero-tax-return', + templateUrl: './hero-tax-return.component.html', + styleUrls: ['./hero-tax-return.component.css'], + providers: [HeroTaxReturnService], }) export class HeroTaxReturnComponent { -message = ''; + message = ''; -close = output(); + close = output(); -get taxReturn(): HeroTaxReturn { -return this.heroTaxReturnService.taxReturn; -} + get taxReturn(): HeroTaxReturn { + return this.heroTaxReturnService.taxReturn; + } -taxReturn = input.required(); + taxReturn = input.required(); -constructor() { -effect(() => { -this.heroTaxReturnService.taxReturn = this.taxReturn(); -}) -} + constructor() { + effect(() => { + this.heroTaxReturnService.taxReturn = this.taxReturn(); + }); + } -private heroTaxReturnService = inject(HeroTaxReturnService); + private heroTaxReturnService = inject(HeroTaxReturnService); -onCanceled() { -this.flashMessage('Canceled'); -this.heroTaxReturnService.restoreTaxReturn(); -} + onCanceled() { + this.flashMessage('Canceled'); + this.heroTaxReturnService.restoreTaxReturn(); + } -onClose() { this.close.emit(); } + onClose() { + this.close.emit(); + } -onSaved() { -this.flashMessage('Saved'); -this.heroTaxReturnService.saveTaxReturn(); -} + onSaved() { + this.flashMessage('Saved'); + this.heroTaxReturnService.saveTaxReturn(); + } -flashMessage(msg: string) { -this.message = msg; -setTimeout(() => this.message = '', 500); -} + flashMessage(msg: string) { + this.message = msg; + setTimeout(() => (this.message = ''), 500); + } } ``` @@ -1075,7 +1076,7 @@ _編集対象の税務申告_ は、 `input` プロパティを介して到着 これを防ぐために、コンポーネントレベルのインジェクター `HeroTaxReturnComponent` を構成して、コンポーネントメタデータの `providers` プロパティを使用してサービスを提供します。 ```typescript -providers: [HeroTaxReturnService] + providers: [HeroTaxReturnService] ``` `HeroTaxReturnComponent` には、 `HeroTaxReturnService` の独自の提供者がいます。 diff --git a/adev-ja/src/content/guide/di/lightweight-injection-tokens.en.md b/adev-ja/src/content/guide/di/lightweight-injection-tokens.en.md index d7fe0e79f0..2475a4b99a 100644 --- a/adev-ja/src/content/guide/di/lightweight-injection-tokens.en.md +++ b/adev-ja/src/content/guide/di/lightweight-injection-tokens.en.md @@ -32,7 +32,9 @@ This component contains a body and can contain an optional header: In a likely implementation, the `` component uses `@ContentChild()` or `@ContentChildren()` to get `` and ``, as in the following: - +```ts {highlight: [14]} +import {Component, ContentChild} from '@angular/core'; + @Component({ selector: 'lib-header', …, @@ -40,22 +42,21 @@ In a likely implementation, the `` component uses `@ContentChild()` or class LibHeaderComponent {} @Component({ -selector: 'lib-card', -…, + selector: 'lib-card', + …, }) class LibCardComponent { -@ContentChild(LibHeaderComponent) header: LibHeaderComponent|null = null; + @ContentChild(LibHeaderComponent) header: LibHeaderComponent | null = null; } - - +``` Because `` is optional, the element can appear in the template in its minimal form, ``. In this case, `` is not used and you would expect it to be tree-shaken, but that is not what happens. This is because `LibCardComponent` actually contains two references to the `LibHeaderComponent`: - +```ts @ContentChild(LibHeaderComponent) header: LibHeaderComponent; - +``` - One of these reference is in the _type position_-- that is, it specifies `LibHeaderComponent` as a type: `header: LibHeaderComponent;`. - The other reference is in the _value position_-- that is, LibHeaderComponent is the value of the `@ContentChild()` parameter decorator: `@ContentChild(LibHeaderComponent)`. @@ -79,13 +80,13 @@ There are two cases when that can happen: In the following example, both uses of the `OtherComponent` token cause retention of `OtherComponent`, preventing it from being tree-shaken when it is not used: - +```ts {highlight: [[2],[4]]} class MyComponent { constructor(@Optional() other: OtherComponent) {} -@ContentChild(OtherComponent) other: OtherComponent|null; + @ContentChild(OtherComponent) other: OtherComponent | null; } - +``` Although tokens used only as type specifiers are removed when converted to JavaScript, all tokens used for dependency injection are needed at runtime. These effectively change `constructor(@Optional() other: OtherComponent)` to `constructor(@Optional() @Inject(OtherComponent) other)`. @@ -100,26 +101,24 @@ The abstract class is retained, not tree-shaken, but it is small and has no mate The following example shows how this works for the `LibHeaderComponent`: - +```ts {highlight: [[1],[5], [15]]} abstract class LibHeaderToken {} @Component({ -selector: 'lib-header', -providers: [ -{provide: LibHeaderToken, useExisting: LibHeaderComponent} -] -…, + selector: 'lib-header', + providers: [{provide: LibHeaderToken, useExisting: LibHeaderComponent}], + …, }) class LibHeaderComponent extends LibHeaderToken {} @Component({ -selector: 'lib-card', -…, + selector: 'lib-card', + …, }) class LibCardComponent { -@ContentChild(LibHeaderToken) header: LibHeaderToken|null = null; + @ContentChild(LibHeaderToken) header: LibHeaderToken | null = null; } - +``` In this example, the `LibCardComponent` implementation no longer refers to `LibHeaderComponent` in either the type position or the value position. This lets full tree-shaking of `LibHeaderComponent` take place. @@ -132,9 +131,9 @@ You can safely use that token as the provider in the component definition, allow To summarize, the lightweight injection token pattern consists of the following: 1. A lightweight injection token that is represented as an abstract class. -1. A component definition that implements the abstract class. -1. Injection of the lightweight pattern, using `@ContentChild()` or `@ContentChildren()`. -1. A provider in the implementation of the lightweight injection token which associates the lightweight injection token with the implementation. +2. A component definition that implements the abstract class. +3. Injection of the lightweight pattern, using `@ContentChild()` or `@ContentChildren()`. +4. A provider in the implementation of the lightweight injection token which associates the lightweight injection token with the implementation. ### Use the lightweight injection token for API definition @@ -146,38 +145,34 @@ This lets the parent communicate with the child, if it is present, in a type-saf For example, the `LibCardComponent` now queries `LibHeaderToken` rather than `LibHeaderComponent`. The following example shows how the pattern lets `LibCardComponent` communicate with the `LibHeaderComponent` without actually referring to `LibHeaderComponent`: - +```ts {highlight: [[2],[9],[11],[19]]} abstract class LibHeaderToken { abstract doSomething(): void; } @Component({ -selector: 'lib-header', -providers: [ -{provide: LibHeaderToken, useExisting: LibHeaderComponent} -] -…, + selector: 'lib-header', + providers: [{provide: LibHeaderToken, useExisting: LibHeaderComponent}], }) class LibHeaderComponent extends LibHeaderToken { -doSomething(): void { -// Concrete implementation of `doSomething` -} + doSomething(): void { + // Concrete implementation of `doSomething` + } } @Component({ -selector: 'lib-card', -…, + selector: 'lib-card', }) -class LibCardComponent implement AfterContentInit { -@ContentChild(LibHeaderToken) header: LibHeaderToken|null = null; - -ngAfterContentInit(): void { -if (this.header !== null) { -this.header?.doSomething(); -} +class LibCardComponent implements AfterContentInit { + @ContentChild(LibHeaderToken) header: LibHeaderToken | null = null; + + ngAfterContentInit(): void { + if (this.header !== null) { + this.header?.doSomething(); + } + } } -} - +``` In this example, the parent queries the token to get the child component, and stores the resulting component reference if it is present. Before calling a method in the child, the parent component checks to see if the child component is present. diff --git a/adev-ja/src/content/guide/di/lightweight-injection-tokens.md b/adev-ja/src/content/guide/di/lightweight-injection-tokens.md index 5239d4908f..e06c77ec37 100644 --- a/adev-ja/src/content/guide/di/lightweight-injection-tokens.md +++ b/adev-ja/src/content/guide/di/lightweight-injection-tokens.md @@ -32,7 +32,9 @@ Angularがインジェクショントークンを格納する方法により、 一般的な実装では、 `` コンポーネントは、次の例のように `@ContentChild()` または `@ContentChildren()` を使用して `` と `` を取得します。 - +```ts {highlight: [14]} +import {Component, ContentChild} from '@angular/core'; + @Component({ selector: 'lib-header', …, @@ -40,22 +42,21 @@ Angularがインジェクショントークンを格納する方法により、 class LibHeaderComponent {} @Component({ -selector: 'lib-card', -…, + selector: 'lib-card', + …, }) class LibCardComponent { -@ContentChild(LibHeaderComponent) header: LibHeaderComponent|null = null; + @ContentChild(LibHeaderComponent) header: LibHeaderComponent | null = null; } - - +``` `` はオプションなので、要素はテンプレートに最小限の形式 `` で表示できます。 この場合、 `` は使用されず、ツリーシェイクされることを期待しますが、実際にはそうなりません。 これは、 `LibCardComponent` には `LibHeaderComponent` への参照が2つあるためです。 - +```ts @ContentChild(LibHeaderComponent) header: LibHeaderComponent; - +``` - これらの参照の1つは _型の位置_ にあります。つまり、 `LibHeaderComponent` を型として指定します: `header: LibHeaderComponent;`。 - もう1つの参照は _値の位置_ にあります。つまり、LibHeaderComponentは `@ContentChild()` パラメータデコレーターの値です: `@ContentChild(LibHeaderComponent)`。 @@ -79,13 +80,13 @@ class LibCardComponent { 次の例では、 `OtherComponent` トークンの両方の使用により、 `OtherComponent` が保持され、使用されていない場合にツリーシェイクされることがなくなります。 - +```ts {highlight: [[2],[4]]} class MyComponent { constructor(@Optional() other: OtherComponent) {} -@ContentChild(OtherComponent) other: OtherComponent|null; + @ContentChild(OtherComponent) other: OtherComponent | null; } - +``` 型指定子としてのみ使用されるトークンは、JavaScriptに変換されると削除されますが、依存性の注入に使用されるすべてのトークンはランタイムで必要です。 これらは実質的に `constructor(@Optional() other: OtherComponent)` を `constructor(@Optional() @Inject(OtherComponent) other)` に変更されます。 @@ -100,26 +101,24 @@ HELPFUL: ライブラリは、[ツリーシェイク可能なプロバイダー] 次の例は、 `LibHeaderComponent` でどのように機能するかを示しています。 - +```ts {highlight: [[1],[5], [15]]} abstract class LibHeaderToken {} @Component({ -selector: 'lib-header', -providers: [ -{provide: LibHeaderToken, useExisting: LibHeaderComponent} -] -…, + selector: 'lib-header', + providers: [{provide: LibHeaderToken, useExisting: LibHeaderComponent}], + …, }) class LibHeaderComponent extends LibHeaderToken {} @Component({ -selector: 'lib-card', -…, + selector: 'lib-card', + …, }) class LibCardComponent { -@ContentChild(LibHeaderToken) header: LibHeaderToken|null = null; + @ContentChild(LibHeaderToken) header: LibHeaderToken | null = null; } - +``` この例では、 `LibCardComponent` 実装は、型位置と値位置のいずれでも `LibHeaderComponent` を参照しなくなりました。 これにより、 `LibHeaderComponent` の完全なツリーシェイクが可能になります。 @@ -132,9 +131,9 @@ class LibCardComponent { 要約すると、軽量インジェクショントークンパターンは次のとおりです。 1. 抽象クラスとして表される軽量なインジェクショントークン。 -1. 抽象クラスを実装するコンポーネント定義。 -1. `@ContentChild()` または `@ContentChildren()` を使用した軽量なパターンの注入。 -1. 軽量なインジェクショントークンを実装するプロバイダーであり、軽量インジェクショントークンを実装に関連付けます。 +2. 抽象クラスを実装するコンポーネント定義。 +3. `@ContentChild()` または `@ContentChildren()` を使用した軽量なパターンの注入。 +4. 軽量なインジェクショントークンを実装するプロバイダーであり、軽量インジェクショントークンを実装に関連付けます。 ### API 定義に軽量インジェクショントークンを使用する @@ -146,38 +145,34 @@ class LibCardComponent { たとえば、 `LibCardComponent` はこれで `LibHeaderComponent` ではなく `LibHeaderToken` をクエリします。 次の例は、パターンにより `LibCardComponent` が `LibHeaderComponent` を実際に参照せずに `LibHeaderComponent` と通信する方法を示しています。 - +```ts {highlight: [[2],[9],[11],[19]]} abstract class LibHeaderToken { abstract doSomething(): void; } @Component({ -selector: 'lib-header', -providers: [ -{provide: LibHeaderToken, useExisting: LibHeaderComponent} -] -…, + selector: 'lib-header', + providers: [{provide: LibHeaderToken, useExisting: LibHeaderComponent}], }) class LibHeaderComponent extends LibHeaderToken { -doSomething(): void { -// Concrete implementation of `doSomething` -} + doSomething(): void { + // Concrete implementation of `doSomething` + } } @Component({ -selector: 'lib-card', -…, + selector: 'lib-card', }) -class LibCardComponent implement AfterContentInit { -@ContentChild(LibHeaderToken) header: LibHeaderToken|null = null; - -ngAfterContentInit(): void { -if (this.header !== null) { -this.header?.doSomething(); -} +class LibCardComponent implements AfterContentInit { + @ContentChild(LibHeaderToken) header: LibHeaderToken | null = null; + + ngAfterContentInit(): void { + if (this.header !== null) { + this.header?.doSomething(); + } + } } -} - +``` この例では、親はトークンをクエリして子コンポーネントを取得し、存在する場合、結果のコンポーネント参照を保存します。 子コンポーネントのメソッドを呼び出す前に、親コンポーネントは子コンポーネントが存在するかどうかを確認します。 diff --git a/adev-ja/src/content/guide/forms/form-validation.en.md b/adev-ja/src/content/guide/forms/form-validation.en.md index 7b0ba0ca5c..4e9b634d1f 100644 --- a/adev-ja/src/content/guide/forms/form-validation.en.md +++ b/adev-ja/src/content/guide/forms/form-validation.en.md @@ -13,7 +13,7 @@ Every time the value of a form control changes, Angular runs validation and gene You can then inspect the control's state by exporting `ngModel` to a local template variable. The following example exports `NgModel` into a variable called `name`: - + Notice the following features illustrated by the example. @@ -62,7 +62,7 @@ For a full list of built-in validators, see the [Validators](api/forms/Validator To update the actor form to be a reactive form, use some of the same built-in validators —this time, in function form, as in the following example. - + In this example, the `name` control sets up two built-in validators —`Validators.required` and `Validators.minLength(4)`— and one custom validator, `forbiddenNameValidator`. @@ -74,7 +74,7 @@ In a reactive form, you can always access any form control through the `get` met If you look at the template for the `name` input again, it is fairly similar to the template-driven example. - + This form differs from the template-driven version in that it no longer exports any directives. Instead, it uses the `name` getter defined in the component class. @@ -87,7 +87,7 @@ The built-in validators don't always match the exact use case of your applicatio Consider the `forbiddenNameValidator` function from the previous example. Here's what the definition of that function looks like. - + The function is a factory that takes a regular expression to detect a _specific_ forbidden name and returns a validator function. @@ -105,7 +105,7 @@ In the case of an observable, the observable must complete, at which point the f In reactive forms, add a custom validator by passing the function directly to the `FormControl`. - + ### Adding custom validators to template-driven forms @@ -115,17 +115,17 @@ For example, the corresponding `ForbiddenValidatorDirective` serves as a wrapper Angular recognizes the directive's role in the validation process because the directive registers itself with the `NG_VALIDATORS` provider, as shown in the following example. `NG_VALIDATORS` is a predefined provider with an extensible collection of validators. - + The directive class then implements the `Validator` interface, so that it can easily integrate with Angular forms. Here is the rest of the directive to help you get an idea of how it all comes together. - + Once the `ForbiddenValidatorDirective` is ready, you can add its selector, `appForbiddenName`, to any input element to activate it. For example: - + HELPFUL: Notice that the custom validation directive is instantiated with `useExisting` rather than `useClass`. The registered validator must be _this instance_ of the `ForbiddenValidatorDirective` —the instance in the form with its `forbiddenName` property bound to "bob". @@ -170,15 +170,13 @@ The validators do this by checking that the actor names and roles do not match. The form has the following structure: - - +```ts const actorForm = new FormGroup({ -'name': new FormControl(), -'role': new FormControl(), -'skill': new FormControl() + 'name': new FormControl(), + 'role': new FormControl(), + 'skill': new FormControl(), }); - - +``` Notice that the `name` and `role` are sibling controls. To evaluate both controls in a single custom validator, you must perform the validation in a common ancestor control: the `FormGroup`. @@ -186,19 +184,20 @@ You query the `FormGroup` for its child controls so that you can compare their v To add a validator to the `FormGroup`, pass the new validator in as the second argument on creation. - - -const actorForm = new FormGroup({ -'name': new FormControl(), -'role': new FormControl(), -'skill': new FormControl() -}, { validators: unambiguousRoleValidator }); - - +```ts +const actorForm = new FormGroup( + { + 'name': new FormControl(), + 'role': new FormControl(), + 'skill': new FormControl(), + }, + {validators: unambiguousRoleValidator}, +); +``` The validator code is as follows. - + The `unambiguousRoleValidator` validator implements the `ValidatorFn` interface. It takes an Angular control object as an argument and returns either null if the form is valid, or `ValidationErrors` otherwise. @@ -210,7 +209,7 @@ If they do match, the actor's role is ambiguous and the validator must mark the To provide better user experience, the template shows an appropriate error message when the form is invalid. - + This `@if` displays the error if the `FormGroup` has the cross validation error returned by the `unambiguousRoleValidator` validator, but only if the user finished [interacting with the form](#control-status-css-classes). @@ -219,16 +218,16 @@ This `@if` displays the error if the `FormGroup` has the cross validation error For a template-driven form, you must create a directive to wrap the validator function. You provide that directive as the validator using the [`NG_VALIDATORS` token](/api/forms/NG_VALIDATORS), as shown in the following example. - + You must add the new directive to the HTML template. Because the validator must be registered at the highest level in the form, the following template puts the directive on the `form` tag. - + To provide better user experience, an appropriate error message appears when the form is invalid. - + This is the same in both template-driven and reactive forms. @@ -250,13 +249,13 @@ Inspect the control's `pending` property and use it to give visual feedback abou A common UI pattern is to show a spinner while the async validation is being performed. The following example shows how to achieve this in a template-driven form. - - +```angular-html + @if(model.pending) { - + } - +``` ### Implementing a custom async validator @@ -266,15 +265,15 @@ To validate the potential role entry, the validator must initiate an asynchronou The following code creates the validator class, `UniqueRoleValidator`, which implements the `AsyncValidator` interface. - + The `actorsService` property is initialized with an instance of the `ActorsService` token, which defines the following interface. - +```ts interface ActorsService { isRoleTaken: (role: string) => Observable; } - +``` In a real world application, the `ActorsService` would be responsible for making an HTTP request to the actor database to check if the role is available. From the validator's point of view, the actual implementation of the service is not important, so the example can just code against the `ActorsService` interface. @@ -297,7 +296,7 @@ The `pending` flag is set to `false`, and the form validity is updated. To use an async validator in reactive forms, begin by injecting the validator into a property of the component class. - + Then, pass the validator function directly to the `FormControl` to apply it. @@ -305,7 +304,7 @@ In the following example, the `validate` function of `UnambiguousRoleValidator` The value of `asyncValidators` can be either a single async validator function, or an array of functions. To learn more about `FormControl` options, see the [AbstractControlOptions](api/forms/AbstractControlOptions) API reference. - + ### Adding async validators to template-driven forms @@ -313,11 +312,11 @@ To use an async validator in template-driven forms, create a new directive and r In the example below, the directive injects the `UniqueRoleValidator` class that contains the actual validation logic and invokes it in the `validate` function, triggered by Angular when validation should happen. - + Then, as with synchronous validators, add the directive's selector to an input to activate it. - + ### Optimizing performance of async validators @@ -330,15 +329,15 @@ You can delay updating the form validity by changing the `updateOn` property fro With template-driven forms, set the property in the template. - +```angular-html - +``` With reactive forms, set the property in the `FormControl` instance. - +```ts new FormControl('', {updateOn: 'blur'}); - +``` ## Interaction with native HTML form validation diff --git a/adev-ja/src/content/guide/forms/form-validation.md b/adev-ja/src/content/guide/forms/form-validation.md index e6e4824aba..cc4f57c662 100644 --- a/adev-ja/src/content/guide/forms/form-validation.md +++ b/adev-ja/src/content/guide/forms/form-validation.md @@ -13,7 +13,7 @@ Angularは、これらの属性をフレームワーク内のバリデーター その後、`ngModel`をローカルテンプレート変数にエクスポートすることで、コントロールの状態を調べることができます。 次の例では、`NgModel`を`name`という変数にエクスポートします。 - + 例で示されている次の機能に注目してください。 @@ -42,7 +42,7 @@ HELPFUL: ユーザーがフォームを編集する機会がある前に、バ ### バリデーター関数 {#validator-functions} -バリデーター関数は、同期または非同期にすることができます。 +バリデーター関数は、同期または非同期にできます。 | バリデーターの種類 | 詳細 | | :------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -54,7 +54,7 @@ HELPFUL: ユーザーがフォームを編集する機会がある前に、バ ### 組み込みのバリデーター関数 {#built-in-validator-functions} -[独自のバリデーター関数](#defining-custom-validators)を作成することも、Angularの組み込みのバリデーターのいくつかを使用することもできます。 +[独自のバリデーター関数](#defining-custom-validators)を作成したり、Angularの組み込みのバリデーターのいくつかを使用したりできます。 `required`や`minlength`など、テンプレート駆動フォームで属性として使用できるものと同じ組み込みバリデーターはすべて、`Validators`クラスから関数として使用できます。 組み込みのバリデーターの完全なリストについては、[Validators](api/forms/Validators) APIリファレンスを参照してください。 @@ -62,7 +62,7 @@ HELPFUL: ユーザーがフォームを編集する機会がある前に、バ アクターフォームをリアクティブフォームに更新するには、いくつかの組み込みバリデーターを使用します。 今回は、関数形式で、次の例のようにします。 - + この例では、`name`コントロールは、2つの組み込みバリデーター(`Validators.required`と`Validators.minLength(4)`)と、1つのカスタムバリデーター`forbiddenNameValidator`を設定しています。 @@ -74,7 +74,7 @@ HELPFUL: ユーザーがフォームを編集する機会がある前に、バ `name`入力のテンプレートをもう一度見ると、テンプレート駆動の例とかなり似ています。 - + このフォームは、テンプレート駆動バージョンとは、ディレクティブをエクスポートしなくなった点が異なります。代わりに、コンポーネントクラスで定義された`name`ゲッターを使用します。 @@ -87,25 +87,25 @@ HELPFUL: ユーザーがフォームを編集する機会がある前に、バ 前の例の`forbiddenNameValidator`関数を考えてみてください。 その関数の定義は次のようになります。 - + 関数は、_特定の_禁止されている名前を検出するための正規表現を受け取り、バリデーター関数を返すファクトリです。 このサンプルでは、禁止されている名前は「bob」なので、バリデーターは「bob」を含むアクター名をすべて拒否します。 -他の場所では、「alice」や、構成された正規表現に一致する名前を拒否することもできます。 +他の場所では、「alice」や、構成された正規表現に一致する名前を拒否できます。 `forbiddenNameValidator`ファクトリは、構成されたバリデーター関数を返します。 その関数はAngularコントロールオブジェクトを受け取り、コントロール値が有効な場合は`null`を返し、_無効な場合は_検証エラーオブジェクトを返します。 検証エラーオブジェクトには通常、検証キーの名前である`'forbiddenName'`というプロパティと、エラーメッセージに挿入できる任意の値の辞書である`{name}`という値を持つプロパティがあります。 -カスタム非同期バリデーターは同期バリデーターに似ていますが、代わりに後で`null`または検証エラーオブジェクトを発行するPromiseまたはオブザーバブルを返す必要があります。 -オブザーバブルの場合、オブザーバブルは完了する必要があります。その時点で、フォームは最後の発行された値を検証に使用します。 +カスタム非同期バリデーターは同期バリデーターに似ていますが、代わりに後で`null`または検証エラーオブジェクトを発行するPromiseまたはObservableを返す必要があります。 +Observableの場合、Observableは完了する必要があります。その時点で、フォームは最後の発行された値を検証に使用します。 ### カスタムバリデーターをリアクティブフォームに追加する {#adding-custom-validators-to-reactive-forms} リアクティブフォームでは、`FormControl`に直接関数を渡すことで、カスタムバリデーターを追加します。 - + ### カスタムバリデーターをテンプレート駆動フォームに追加する {#adding-custom-validators-to-template-driven-forms} @@ -115,17 +115,17 @@ HELPFUL: ユーザーがフォームを編集する機会がある前に、バ Angularは、ディレクティブが`NG_VALIDATORS`プロバイダーに自身を登録するため、ディレクティブの検証プロセスにおける役割を認識します。次の例に示すように。 `NG_VALIDATORS`は、拡張可能なバリデーターのコレクションを持つ、定義済みのプロバイダーです。 - + その後、ディレクティブクラスは`Validator`インターフェースを実装するため、Angularフォームと簡単に統合できます。 以下は、ディレクティブ全体の概要です。 - + `ForbiddenValidatorDirective`の準備ができたら、セレクター`appForbiddenName`を入力要素に追加して、アクティブ化できます。 たとえば、次のとおりです。 - + HELPFUL: カスタム検証ディレクティブが`useExisting`ではなく`useClass`でインスタンス化されていることに注意してください。 登録されたバリデーターは、`ForbiddenValidatorDirective`の_このインスタンス_である必要があります。フォーム内のインスタンスで、`forbiddenName`プロパティが「bob」にバインドされています。 @@ -170,15 +170,13 @@ Angularは、多くのコントロールプロパティをフォームコント フォームは、次の構造になっています。 - - +```ts const actorForm = new FormGroup({ -'name': new FormControl(), -'role': new FormControl(), -'skill': new FormControl() + 'name': new FormControl(), + 'role': new FormControl(), + 'skill': new FormControl(), }); - - +``` `name`と`role`は兄弟コントロールであることに注意してください。 1つのカスタムバリデーターで両方のコントロールを評価するには、共通の祖先コントロールである`FormGroup`で検証する必要があります。 @@ -186,19 +184,20 @@ const actorForm = new FormGroup({ `FormGroup`にバリデーターを追加するには、作成時に第2引数として新しいバリデーターを渡します。 - - -const actorForm = new FormGroup({ -'name': new FormControl(), -'role': new FormControl(), -'skill': new FormControl() -}, { validators: unambiguousRoleValidator }); - - +```ts +const actorForm = new FormGroup( + { + 'name': new FormControl(), + 'role': new FormControl(), + 'skill': new FormControl(), + }, + {validators: unambiguousRoleValidator}, +); +``` バリデーターのコードは次のとおりです。 - + `unambiguousRoleValidator`バリデーターは、`ValidatorFn`インターフェースを実装しています。 これはAngularコントロールオブジェクトを引数として受け取り、フォームが有効な場合は`null`を返し、無効な場合は`ValidationErrors`を返します。 @@ -208,9 +207,9 @@ const actorForm = new FormGroup({ 値が一致しない場合、役割は曖昧ではなく、両方が有効で、バリデーターは`null`を返します。 値が一致する場合、アクターの役割は曖昧で、バリデーターはエラーオブジェクトを返すことでフォームを無効にする必要があります。 -より良いユーザーエクスペリエンスを提供するために、フォームが無効な場合、テンプレートに適切なエラーメッセージが表示されます。 +より良いユーザー体験を提供するために、フォームが無効な場合、テンプレートに適切なエラーメッセージが表示されます。 - + この`@if`は、`FormGroup`に`unambiguousRoleValidator`バリデーターが返したクロス検証エラーがある場合に、エラーを表示しますが、ユーザーが[フォームとやり取りを完了](#control-status-css-classes)した場合のみです。 @@ -219,16 +218,16 @@ const actorForm = new FormGroup({ テンプレート駆動フォームの場合、バリデーター関数をラップするディレクティブを作成する必要があります。 次の例に示すように、[`NG_VALIDATORS`トークン](/api/forms/NG_VALIDATORS)を使用して、そのディレクティブをバリデーターとして提供します。 - + 新しいディレクティブをHTMLテンプレートに追加する必要があります。 バリデーターはフォームの最上位レベルで登録する必要があるため、次のテンプレートは`form`タグにディレクティブを配置しています。 - + -より良いユーザーエクスペリエンスを提供するために、フォームが無効な場合、適切なエラーメッセージが表示されます。 +より良いユーザー体験を提供するために、フォームが無効な場合、適切なエラーメッセージが表示されます。 - + これは、テンプレート駆動フォームとリアクティブフォームの両方で同じです。 @@ -237,9 +236,9 @@ const actorForm = new FormGroup({ 非同期バリデーターは、`AsyncValidatorFn`と`AsyncValidator`インターフェースを実装します。 これらは、同期バリデーターと非常に似ており、次の点が異なります。 -- `validate()`関数はPromiseまたはオブザーバブルを返す必要があります。 -- 返されるオブザーバブルは有限である必要があります。つまり、ある時点で完了する必要があります。 - 無限のオブザーバブルを有限のオブザーバブルに変換するには、オブザーバブルを`first`、`last`、`take`、`takeUntil`などのフィルタリング演算子でパイプします。 +- `validate()`関数はPromiseまたはObservableを返す必要があります。 +- 返されるObservableは有限である必要があります。つまり、ある時点で完了する必要があります。 + 無限のObservableを有限のObservableに変換するには、Observableを`first`、`last`、`take`、`takeUntil`などのフィルタリング演算子でパイプします。 非同期検証は、同期検証の後に実行され、同期検証が成功した場合にのみ実行されます。 このチェックにより、フォームは、基本的な検証方法がすでに無効な入力を検出している場合、潜在的にコストのかかる非同期検証プロセス(HTTPリクエストなど)を回避できます。 @@ -250,13 +249,13 @@ const actorForm = new FormGroup({ 一般的なUIパターンは、非同期検証の実行中にスピナーを表示することです。 次の例は、テンプレート駆動フォームでこれを実現する方法を示しています。 - - +```angular-html + @if(model.pending) { - + } - +``` ### カスタム非同期バリデーターの実装 {#implementing-a-custom-async-validator} @@ -266,15 +265,15 @@ const actorForm = new FormGroup({ 次のコードは、`AsyncValidator`インターフェースを実装するバリデータークラス`UniqueRoleValidator`を作成します。 - + `actorsService`プロパティは、次のインターフェースを定義する`ActorsService`トークンのインスタンスで初期化されます。 - +```ts interface ActorsService { isRoleTaken: (role: string) => Observable; } - +``` 実際のアプリケーションでは、`ActorsService`は、アクターデータベースにHTTPリクエストを送信して役割が利用可能かどうかを確認する役割を担います。 バリデーターの観点から、サービスの実際の実装は重要でないため、例では`ActorsService`インターフェースに対してのみコードを作成できます。 @@ -297,27 +296,27 @@ interface ActorsService { リアクティブフォームで非同期バリデーターを使用するには、最初にバリデーターをコンポーネントクラスのプロパティに注入します。 - + 次に、バリデーター関数を`FormControl`に直接渡して、適用します。 次の例では、`UnambiguousRoleValidator`の`validate`関数が、`roleControl`に適用されています。この関数をコントロールの`asyncValidators`オプションに渡し、`ActorFormReactiveComponent`に注入された`UnambiguousRoleValidator`のインスタンスにバインドしています。 -`asyncValidators`の値は、単一の非同期バリデーター関数、または関数の配列にすることができます。 +`asyncValidators`の値は、単一の非同期バリデーター関数、または関数の配列にできます。 `FormControl`オプションの詳細については、[AbstractControlOptions](api/forms/AbstractControlOptions) APIリファレンスを参照してください。 - + ### 非同期バリデーターをテンプレート駆動フォームに追加する {#adding-async-validators-to-template-driven-forms} テンプレート駆動フォームで非同期バリデーターを使用するには、新しいディレクティブを作成し、そのディレクティブに`NG_ASYNC_VALIDATORS`プロバイダーを登録します。 -次の例では、ディレクティブは、実際の検証ロジックを含む`UniqueRoleValidator`クラスを注入し、検証を実行する必要があるときにAngularによってトリガーされる`validate`関数でそれを呼び出します。 +次の例では、ディレクティブは、実際の検証ロジックを含む`UniqueRoleValidator`クラスを注入し、Angularが検証する必要があるときにトリガーする`validate`関数でそれを呼び出します。 - + その後、同期バリデーターと同様に、ディレクティブのセレクターを入力に追加して、アクティブ化します。 - + ### 非同期バリデーターのパフォーマンスの最適化 {#optimizing-performance-of-async-validators} @@ -330,15 +329,15 @@ interface ActorsService { テンプレート駆動フォームでは、テンプレートでプロパティを設定します。 - +```angular-html - +``` リアクティブフォームでは、`FormControl`インスタンスでプロパティを設定します。 - +```ts new FormControl('', {updateOn: 'blur'}); - +``` ## ネイティブHTMLフォーム検証との相互作用 {#interaction-with-native-html-form-validation} diff --git a/adev-ja/src/content/guide/forms/signals/comparison.en.md b/adev-ja/src/content/guide/forms/signals/comparison.en.md index 209e70e06e..d2690a9298 100644 --- a/adev-ja/src/content/guide/forms/signals/comparison.en.md +++ b/adev-ja/src/content/guide/forms/signals/comparison.en.md @@ -158,6 +158,6 @@ TypeScript understands your component properties but has no knowledge of form st To learn more about each approach: -- **Signal Forms**: See the [Overview guide](guide/forms/signal-forms/overview) to get started, or dive into [Form Models](guide/forms/signal-forms/models), [Validation](guide/forms/signal-forms/validation), and [Field State Management](guide/forms/signal-forms/field-state-management) +- **Signal Forms**: See the [Overview guide](guide/forms/signals/overview) to get started, or dive into [Form Models](guide/forms/signals/models), [Validation](guide/forms/signals/validation), and [Field State Management](guide/forms/signals/field-state-management) - **Reactive Forms**: See the [Reactive Forms guide](guide/forms/reactive-forms) in Angular documentation - **Template-driven Forms**: See the [Template-driven Forms guide](guide/forms/template-driven-forms) in Angular documentation diff --git a/adev-ja/src/content/guide/forms/signals/comparison.md b/adev-ja/src/content/guide/forms/signals/comparison.md index a5d011f4a0..1837546ed0 100644 --- a/adev-ja/src/content/guide/forms/signals/comparison.md +++ b/adev-ja/src/content/guide/forms/signals/comparison.md @@ -158,6 +158,6 @@ TypeScriptはコンポーネントのプロパティを理解しますが、フ 各アプローチについてさらに学ぶには: -- **シグナルフォーム**: [概要ガイド](guide/forms/signal-forms/overview)から始めるか、[フォームモデル](guide/forms/signal-forms/models)、[バリデーション](guide/forms/signal-forms/validation)、[フィールド状態管理](guide/forms/signal-forms/field-state-management)を詳しく見てください +- **シグナルフォーム**: [概要ガイド](guide/forms/signals/overview)から始めるか、[フォームモデル](guide/forms/signals/models)、[バリデーション](guide/forms/signals/validation)、[フィールド状態管理](guide/forms/signals/field-state-management)を詳しく見てください - **リアクティブフォーム**: Angularドキュメントの[リアクティブフォームガイド](guide/forms/reactive-forms)を参照してください - **テンプレート駆動フォーム**: Angularドキュメントの[テンプレート駆動フォームガイド](guide/forms/template-driven-forms)を参照してください diff --git a/adev-ja/src/content/guide/forms/signals/custom-controls.en.md b/adev-ja/src/content/guide/forms/signals/custom-controls.en.md index ba33ed4f54..1ce7026b0f 100644 --- a/adev-ja/src/content/guide/forms/signals/custom-controls.en.md +++ b/adev-ja/src/content/guide/forms/signals/custom-controls.en.md @@ -241,7 +241,7 @@ export class MyForm { } ``` -TIP: For complete coverage of creating and managing form models, see the [Form Models guide](guide/forms/signal-forms/models). +TIP: For complete coverage of creating and managing form models, see the [Form Models guide](guide/forms/signals/models). When you bind `[field]="userForm.username"`, the Field directive: @@ -422,7 +422,7 @@ accountForm = form(this.accountModel, schemaPath => { This guide covered building custom controls that integrate with Signal Forms. Related guides explore other aspects of Signal Forms: -- [Form Models guide](guide/forms/signal-forms/models) - Creating and updating form models +- [Form Models guide](guide/forms/signals/models) - Creating and updating form models - - + + diff --git a/adev-ja/src/content/guide/forms/signals/custom-controls.md b/adev-ja/src/content/guide/forms/signals/custom-controls.md index 00b90fbe76..bb06b4479d 100644 --- a/adev-ja/src/content/guide/forms/signals/custom-controls.md +++ b/adev-ja/src/content/guide/forms/signals/custom-controls.md @@ -241,7 +241,7 @@ export class MyForm { } ``` -TIP: フォームモデルの作成と管理に関する完全な情報については、[フォームモデルガイド](guide/forms/signal-forms/models)を参照してください。 +TIP: フォームモデルの作成と管理に関する完全な情報については、[フォームモデルガイド](guide/forms/signals/models)を参照してください。 `[field]="userForm.username"`をバインドすると、Fieldディレクティブは次のようになります: @@ -422,7 +422,7 @@ accountForm = form(this.accountModel, schemaPath => { このガイドでは、シグナルフォームと連携するカスタムコントロールの構築について説明しました。関連ガイドでは、シグナルフォームの他の側面について探求します: -- [フォームモデルガイド](guide/forms/signal-forms/models) - フォームモデルの作成と更新 +- [フォームモデルガイド](guide/forms/signals/models) - フォームモデルの作成と更新 - - + + diff --git a/adev-ja/src/content/guide/forms/signals/field-state-management.en.md b/adev-ja/src/content/guide/forms/signals/field-state-management.en.md index f831a4d679..be707bdbec 100644 --- a/adev-ja/src/content/guide/forms/signals/field-state-management.en.md +++ b/adev-ja/src/content/guide/forms/signals/field-state-management.en.md @@ -47,7 +47,7 @@ In this example, the template checks `registrationForm.email().invalid()` to det ### Field state signals -The most commonly used signal is `value()`, a [writable signal](guide/forms/signal-forms/models#updating-models) that provides access to the field's current value: +The most commonly used signal is `value()`, a [writable signal](guide/forms/signals/models#updating-models) that provides access to the field's current value: ```ts const emailValue = registrationForm.email().value() @@ -691,5 +691,5 @@ Checking both `touched()` and validation state ensures styles only appear after Here are other related guides on Signal Forms: -- [Form Models guide](guide/forms/signal-forms/models) - Creating models and updating values +- [Form Models guide](guide/forms/signals/models) - Creating models and updating values - Validation guide - Defining validation rules and custom validators (coming soon) diff --git a/adev-ja/src/content/guide/forms/signals/field-state-management.md b/adev-ja/src/content/guide/forms/signals/field-state-management.md index 7c5d0caf03..9eead5b424 100644 --- a/adev-ja/src/content/guide/forms/signals/field-state-management.md +++ b/adev-ja/src/content/guide/forms/signals/field-state-management.md @@ -47,7 +47,7 @@ export class Registration { ### フィールドの状態シグナル {#field-state-signals} -最も一般的に使用されるシグナルは`value()`です。これはフィールドの現在の値へのアクセスを提供する[書き込み可能なシグナル](guide/forms/signal-forms/models#updating-models)です: +最も一般的に使用されるシグナルは`value()`です。これはフィールドの現在の値へのアクセスを提供する[書き込み可能なシグナル](guide/forms/signals/models#updating-models)です: ```ts const emailValue = registrationForm.email().value() @@ -691,5 +691,5 @@ export class StyleExample { シグナルフォームに関するその他の関連ガイドは次のとおりです: -- [フォームモデルガイド](guide/forms/signal-forms/models) - モデルの作成と値の更新 +- [フォームモデルガイド](guide/forms/signals/models) - モデルの作成と値の更新 - バリデーションガイド - バリデーションルールの定義とカスタムバリデーター (近日公開の予定) diff --git a/adev-ja/src/content/guide/forms/signals/models.en.md b/adev-ja/src/content/guide/forms/signals/models.en.md index 92a871918a..64cd1dabd7 100644 --- a/adev-ja/src/content/guide/forms/signals/models.en.md +++ b/adev-ja/src/content/guide/forms/signals/models.en.md @@ -172,7 +172,7 @@ Field state provides reactive signals for each field's value, making it suitable TIP: Field state includes many more signals beyond `value()`, such as validation state (e.g., valid, invalid, errors), interaction tracking (e.g., touched, dirty), and visibility (e.g., hidden, disabled). - + ## Updating form models programmatically @@ -419,7 +419,7 @@ orderForm.items[0].quantity // FieldTree Array items containing objects automatically receive tracking identities, which helps maintain field state even when items change position in the array. This ensures validation state and user interactions persist correctly when arrays are reordered. - + ## Model design best practices @@ -530,7 +530,7 @@ For forms that always start with existing data, you might wait to render the for diff --git a/adev-ja/src/content/guide/forms/signals/models.md b/adev-ja/src/content/guide/forms/signals/models.md index b4d3a7e74f..8db1f34724 100644 --- a/adev-ja/src/content/guide/forms/signals/models.md +++ b/adev-ja/src/content/guide/forms/signals/models.md @@ -172,7 +172,7 @@ export class LoginComponent { TIP: フィールドの状態には、`value()`以外にも、バリデーションの状態(例: valid、invalid、errors)、インタラクションの追跡(例: touched、dirty)、可視性(例: hidden、disabled)など、さらに多くのシグナルが含まれています。 - + ## フォームモデルをプログラム的に更新する {#updating-form-models-programmatically} @@ -419,7 +419,7 @@ orderForm.items[0].quantity // FieldTree オブジェクトを含む配列のアイテムは自動的に追跡IDを受け取ります。これにより、配列内でアイテムの位置が変わってもフィールドの状態を維持できます。これにより、配列が並べ替えられた場合でも、バリデーションの状態とユーザーインタラクションが正しく維持されることが保証されます。 - + ## モデル設計のベストプラクティス {#model-design-best-practices} @@ -530,7 +530,7 @@ async loadExistingUser() { diff --git a/adev-ja/src/content/guide/forms/signals/overview.en.md b/adev-ja/src/content/guide/forms/signals/overview.en.md index fea36bd132..73102a101f 100644 --- a/adev-ja/src/content/guide/forms/signals/overview.en.md +++ b/adev-ja/src/content/guide/forms/signals/overview.en.md @@ -20,7 +20,7 @@ Signal Forms address these challenges by: Signal Forms work best in new applications built with signals. If you're working with an existing application that uses reactive forms, or if you need production stability guarantees, reactive forms remain a solid choice. - + ## Prerequisites @@ -52,8 +52,8 @@ To learn more about how Signal Forms work, check out the following guides: - - - - + + + + --> diff --git a/adev-ja/src/content/guide/forms/signals/overview.md b/adev-ja/src/content/guide/forms/signals/overview.md index e0121ef447..9c80e94782 100644 --- a/adev-ja/src/content/guide/forms/signals/overview.md +++ b/adev-ja/src/content/guide/forms/signals/overview.md @@ -20,7 +20,7 @@ Webアプリケーションにおけるフォームの構築には、フィー シグナルフォームは、シグナルを使用して構築された新しいアプリケーションで最適に機能します。リアクティブフォームを使用している既存のアプリケーションで作業している場合や、本番環境での安定性の保証が必要な場合は、リアクティブフォームが依然として確実な選択肢です。 - + ## 前提条件 {#prerequisites} @@ -52,8 +52,8 @@ To learn more about how Signal Forms work, check out the following guides: - - - - + + + + --> diff --git a/adev-ja/src/content/guide/forms/signals/validation.en.md b/adev-ja/src/content/guide/forms/signals/validation.en.md index aeddf0c086..63ba327a94 100644 --- a/adev-ja/src/content/guide/forms/signals/validation.en.md +++ b/adev-ja/src/content/guide/forms/signals/validation.en.md @@ -299,7 +299,7 @@ When validation rules fail, they produce error objects that describe what went w +NOTE: This section covers the errors that validation rules produce. For displaying and using validation errors in your UI, see the [Field State Management guide](guide/forms/signals/field-state-management). --> ### Error structure @@ -374,7 +374,7 @@ signupForm = form(this.signupModel, (schemaPath) => { If the email field is empty, only the `required()` error appears. If the user types "a@b", both `email()` and `minLength()` errors appear. All validation rules run - validation doesn't stop after the first failure. -TIP: Use the `touched() && invalid()` pattern in your templates to prevent errors from appearing before users have interacted with a field. For comprehensive guidance on displaying validation errors, see the [Field State Management guide](guide/forms/signal-forms/field-state-management#conditional-error-display). +TIP: Use the `touched() && invalid()` pattern in your templates to prevent errors from appearing before users have interacted with a field. For comprehensive guidance on displaying validation errors, see the [Field State Management guide](guide/forms/signals/field-state-management#conditional-error-display). ## Custom validation rules @@ -624,6 +624,6 @@ The `valid()` signal returns `false` while validation is pending, even if there This guide covered creating and applying validation rules. Related guides explore other aspects of Signal Forms: -- [Form Models guide](guide/forms/signal-forms/models) - Creating and updating form models +- [Form Models guide](guide/forms/signals/models) - Creating and updating form models - + diff --git a/adev-ja/src/content/guide/forms/signals/validation.md b/adev-ja/src/content/guide/forms/signals/validation.md index 5ba8f0d504..9f9d45e773 100644 --- a/adev-ja/src/content/guide/forms/signals/validation.md +++ b/adev-ja/src/content/guide/forms/signals/validation.md @@ -299,7 +299,7 @@ export class PhoneFormComponent { +NOTE: このセクションでは、バリデーションルールが生成するエラーについて説明します。UIでバリデーションエラーを表示して使用する方法については、[フィールド状態管理ガイド](guide/forms/signals/field-state-management)を参照してください。 --> ### エラーの構造 {#error-structure} @@ -374,7 +374,7 @@ signupForm = form(this.signupModel, (schemaPath) => { emailフィールドが空の場合、`required()`エラーのみが表示されます。ユーザーが"a@b"と入力すると、`email()`と`minLength()`の両方のエラーが表示されます。すべてのバリデーションルールが実行され、最初の失敗でバリデーションが停止することはありません。 -TIP: テンプレートで`touched() && invalid()`パターンを使用すると、ユーザーがフィールドを操作する前にエラーが表示されるのを防ぐことができます。バリデーションエラーの表示に関する包括的なガイダンスについては、[フィールド状態管理ガイド](guide/forms/signal-forms/field-state-management#conditional-error-display)を参照してください。 +TIP: テンプレートで`touched() && invalid()`パターンを使用すると、ユーザーがフィールドを操作する前にエラーが表示されるのを防ぐことができます。バリデーションエラーの表示に関する包括的なガイダンスについては、[フィールド状態管理ガイド](guide/forms/signals/field-state-management#conditional-error-display)を参照してください。 ## カスタムバリデーションルール {#custom-validation-rules} @@ -624,6 +624,6 @@ export class UsernameFormComponent { このガイドでは、バリデーションルールの作成と適用について説明しました。関連ガイドでは、シグナルフォームの他の側面について解説します: -- [フォームモデルガイド](guide/forms/signal-forms/models) - フォームモデルの作成と更新 +- [フォームモデルガイド](guide/forms/signals/models) - フォームモデルの作成と更新 - + diff --git a/adev-ja/src/content/guide/forms/template-driven-forms.en.md b/adev-ja/src/content/guide/forms/template-driven-forms.en.md index 468c68ba17..e1fbd215b1 100644 --- a/adev-ja/src/content/guide/forms/template-driven-forms.en.md +++ b/adev-ja/src/content/guide/forms/template-driven-forms.en.md @@ -59,7 +59,7 @@ In the course of this tutorial, you bind a sample form to data and handle user i 1. The provided sample application creates the `Actor` class which defines the data model reflected in the form. - + 1. The form layout and details are defined in the `ActorFormComponent` class. @@ -67,18 +67,18 @@ In the course of this tutorial, you bind a sample form to data and handle user i The component's `selector` value of "app-actor-form" means you can drop this form in a parent template using the `` tag. -2. The following code creates a new actor instance, so that the initial form can show an example actor. +1. The following code creates a new actor instance, so that the initial form can show an example actor. This demo uses dummy data for `model` and `skills`. In a real app, you would inject a data service to get and save real data, or expose these properties as inputs and outputs. -3. The component enables the Forms feature by importing the `FormsModule` module. +1. The component enables the Forms feature by importing the `FormsModule` module. -4. The form is displayed in the application layout defined by the root component's template. +1. The form is displayed in the application layout defined by the root component's template. @@ -91,15 +91,15 @@ In the course of this tutorial, you bind a sample form to data and handle user i The **Submit** button has some classes on it for styling. At this point, the form layout is all plain HTML5, with no bindings or directives. -5. The sample form uses some style classes from [Twitter Bootstrap](https://getbootstrap.com/css): `container`, `form-group`, `form-control`, and `btn`. +1. The sample form uses some style classes from [Twitter Bootstrap](https://getbootstrap.com/css): `container`, `form-group`, `form-control`, and `btn`. To use these styles, the application's style sheet imports the library. - + 1. The form requires that an actor's skill is chosen from a predefined list of `skills` maintained internally in `ActorFormComponent`. The Angular `@for` loop iterates over the data values to populate the ``要素を生成します。 - + アプリケーションを今すぐ実行すると、選択コントロールにスキルのリストが表示されます。 入力要素は、まだデータ値やイベントにバインドされていないため、空欄であり、動作しません。 @@ -230,11 +230,11 @@ Angularは、`form`要素に`ng-submitted`クラスを適用しますが、 1. これらのクラス定義を新しい`forms.css`ファイルに追加します。 1. 新しいファイルを、`index.html`と同じレベルにプロジェクトに追加します。 - + 1. `index.html`ファイルで、新しいスタイルシートを含めるように``タグを更新します。 - + ### 検証エラーメッセージの表示と非表示 @@ -291,11 +291,11 @@ Angularは、`form`要素に`ng-submitted`クラスを適用しますが、 1. テンプレートで、フォームの下部に"New Actor"`