diff --git a/adev-ja/src/app/features/update/recommendations.en.ts b/adev-ja/src/app/features/update/recommendations.en.ts index 55b054da1..f0c49b207 100644 --- a/adev-ja/src/app/features/update/recommendations.en.ts +++ b/adev-ja/src/app/features/update/recommendations.en.ts @@ -14,6 +14,12 @@ export enum ApplicationComplexity { export interface Step { step: string; + /** + * Action text rendered as Markdown. Use Markdown link syntax `[text](url)` + * for any links — raw `` HTML tags bypass the custom link renderer in + * `update.component.ts` and will not pick up `target="_blank"` or the + * external-link icon. + */ action: string; possibleIn: number; necessaryAsOf: number; @@ -155,7 +161,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Advanced, step: 'gendir', action: - 'Do not rely on `gendir`, instead look at using `skipTemplateCodeGen`. Read More', + 'Do not rely on `gendir`, instead look at using `skipTemplateCodeGen`. [Read More](https://github.com/angular/angular/issues/19339#issuecomment-332607471)', }, { possibleIn: 220, @@ -239,7 +245,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'node 8', action: - 'Make sure you are using Node 8 or later', + 'Make sure you are using [Node 8 or later](http://www.hostingadvice.com/how-to/update-node-js-latest-version/)', }, { possibleIn: 600, @@ -248,7 +254,7 @@ export const RECOMMENDATIONS: Step[] = [ windows: false, step: 'Update to CLI v6', action: - 'Update your Angular CLI, and migrate the configuration to the new angular.json format by running the following:

`NG_DISABLE_VERSION_CHECK=1 npx @angular/cli@6 update @angular/cli@6`
', + 'Update your Angular CLI, and migrate the configuration to the [new angular.json format](https://github.com/angular/angular-cli/wiki/angular-workspace) by running the following:

`NG_DISABLE_VERSION_CHECK=1 npx @angular/cli@6 update @angular/cli@6`
', }, { possibleIn: 600, @@ -257,7 +263,7 @@ export const RECOMMENDATIONS: Step[] = [ windows: true, step: 'Update to CLI v6', action: - 'Update your Angular CLI, and migrate the configuration to the new angular.json format by running the following:

`cmd /C "set "NG_DISABLE_VERSION_CHECK=1" && npx @angular/cli@6 update @angular/cli@6 @angular/core@6"`
', + 'Update your Angular CLI, and migrate the configuration to the [new angular.json format](https://github.com/angular/angular-cli/wiki/angular-workspace) by running the following:

`cmd /C "set "NG_DISABLE_VERSION_CHECK=1" && npx @angular/cli@6 update @angular/cli@6 @angular/core@6"`
', }, { possibleIn: 600, @@ -343,7 +349,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Medium, step: 'strictPropertyInitializer', action: - 'If you have TypeScript configured to be strict (if you have set `strict` to `true` in your `tsconfig.json` file), update your `tsconfig.json` to disable `strictPropertyInitialization` or move property initialization from `ngOnInit` to your constructor. You can learn more about this flag on the TypeScript 2.7 release notes.', + 'If you have TypeScript configured to be strict (if you have set `strict` to `true` in your `tsconfig.json` file), update your `tsconfig.json` to disable `strictPropertyInitialization` or move property initialization from `ngOnInit` to your constructor. You can learn more about this flag on the [TypeScript 2.7 release notes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#strict-class-initialization).', }, { possibleIn: 600, @@ -351,7 +357,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'update to RxJS 6', action: - 'Remove deprecated RxJS 5 features using rxjs-tslint auto update rules

For most applications this will mean running the following two commands:

`npx rxjs-tslint`
`rxjs-5-to-6-migrate -p src/tsconfig.app.json`', + 'Remove deprecated RxJS 5 features using [rxjs-tslint auto update rules](https://github.com/ReactiveX/rxjs-tslint)

For most applications this will mean running the following two commands:

`npx rxjs-tslint`
`rxjs-5-to-6-migrate -p src/tsconfig.app.json`', }, { possibleIn: 600, @@ -374,7 +380,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'TypeScript 3.1', action: - 'Angular now uses TypeScript 3.1, read more about any potential breaking changes: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html', + 'Angular now uses TypeScript 3.1, read more about [any potential breaking changes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html).', }, { possibleIn: 700, @@ -382,7 +388,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'Node 10', action: - 'Angular has now added support for Node 10: https://nodejs.org/en/blog/release/v10.0.0/', + 'Angular has now added support for [Node 10](https://nodejs.org/en/blog/release/v10.0.0/).', }, { possibleIn: 700, @@ -464,7 +470,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'use ::ng-deep instead of /deep/', action: - 'Replace `/deep/` with `::ng-deep` in your styles, [read more about angular component styles and ::ng-deep](https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep). `/deep/` and `::ng-deep` both are deprecated but using `::ng-deep` is preferred until the shadow-piercing descendant combinator is [removed from browsers and tools](https://www.chromestatus.com/features/6750456638341120) completely.', + 'Replace `/deep/` with `::ng-deep` in your styles, [read more about angular component styles and ::ng-deep](https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep). `/deep/` and `::ng-deep` both are deprecated but using `::ng-deep` is preferred until the shadow-piercing descendant combinator is [removed from browsers and tools](https://chromestatus.com/feature/5045542597951488) completely.', }, { possibleIn: 800, @@ -480,7 +486,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'node 10', action: - 'Make sure you are using Node 10 or later.', + 'Make sure you are using [Node 10 or later](http://www.hostingadvice.com/how-to/update-node-js-latest-version/).', }, { possibleIn: 800, @@ -573,7 +579,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'node 10.13', action: - 'Make sure you are using Node 10.13 or later.', + 'Make sure you are using [Node 10.13 or later](http://www.hostingadvice.com/how-to/update-node-js-latest-version/).', }, { possibleIn: 900, @@ -781,9 +787,8 @@ export const RECOMMENDATIONS: Step[] = [ possibleIn: 1000, necessaryAsOf: 1000, level: ApplicationComplexity.Basic, - step: 'v10 NodeJS 12', - action: - 'Make sure you are using Node 12 or later.', + step: 'v10 Node.js 12', + action: 'Make sure you are using [Node 12 or later](https://nodejs.org/dist/latest-v12.x/).', }, { possibleIn: 1000, @@ -847,7 +852,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Advanced, step: 'closure-jsdoc-comments', action: - "Angular's NPM packages no longer contain jsdoc comments, which are necessary for use with closure compiler (extremely uncommon). This support was experimental and only worked in some use cases. There will be an alternative recommended path announced shortly.", + "Angular's npm packages no longer contain jsdoc comments, which are necessary for use with closure compiler (extremely uncommon). This support was experimental and only worked in some use cases. There will be an alternative recommended path announced shortly.", }, { possibleIn: 1000, @@ -871,7 +876,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Medium, step: 'esm5-bundles', action: - "The [Angular Package Format](https://g.co/ng/apf) has been updated to remove `esm5` and `fesm5` formats. These are no longer distributed in our npm packages. If you don't use the CLI, you may need to downlevel Angular code to ES5 yourself.", + "The [Angular Package Format](https://angular.dev/tools/libraries/angular-package-format) has been updated to remove `esm5` and `fesm5` formats. These are no longer distributed in our npm packages. If you don't use the CLI, you may need to downlevel Angular code to ES5 yourself.", }, { possibleIn: 1000, @@ -1335,7 +1340,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'TypeScript 4.4', action: - 'Angular now uses TypeScript 4.4, read more about any potential breaking changes: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html', + 'Angular now uses TypeScript 4.4, read more about [any potential breaking changes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html).', }, { possibleIn: 1300, @@ -1343,7 +1348,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'v13 node', action: - 'Make sure you are using Node 12.20.0 or later', + 'Make sure you are using [Node 12.20.0 or later](http://www.hostingadvice.com/how-to/update-node-js-latest-version/)', }, { possibleIn: 1300, @@ -1457,7 +1462,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'TypeScript 4.6', action: - 'Angular now uses TypeScript 4.6, read more about any potential breaking changes: https://devblogs.microsoft.com/typescript/announcing-typescript-4-6/', + 'Angular now uses TypeScript 4.6, read more about [any potential breaking changes](https://devblogs.microsoft.com/typescript/announcing-typescript-4-6/).', }, { @@ -1466,7 +1471,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'v14 node', action: - 'Make sure you are using Node 14.15.0 or later', + 'Make sure you are using [Node 14.15.0 or later](http://www.hostingadvice.com/how-to/update-node-js-latest-version/)', }, { possibleIn: 1400, @@ -1669,7 +1674,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'v15 node support', action: - 'Make sure that you are using a supported version of node.js before you upgrade your application. Angular v15 supports node.js versions: 14.20.x, 16.13.x and 18.10.x. Read further', + 'Make sure that you are using a supported version of node.js before you upgrade your application. Angular v15 supports node.js versions: 14.20.x, 16.13.x and 18.10.x. [Read further](https://v15.angular.io/guide/update-to-version-15#v15-bc-01)', }, { possibleIn: 1500, @@ -1677,7 +1682,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'v15 ts support', action: - 'Make sure that you are using a supported version of TypeScript before you upgrade your application. Angular v15 supports TypeScript version 4.8 or later. Read further', + 'Make sure that you are using a supported version of TypeScript before you upgrade your application. Angular v15 supports TypeScript version 4.8 or later. [Read further](https://v15.angular.io/guide/update-to-version-15#v15-bc-02)', }, { possibleIn: 1500, @@ -1701,7 +1706,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Medium, step: 'v15 keyframe', action: - 'In v15, the Angular compiler prefixes `@keyframes` in CSS with the component\'s scope. This means that any TypeScript code that relies on `keyframes` names no longer works in v15. Update any such instances to: define keyframes programmatically, use global stylesheets, or change the component\'s view encapsulation. Read further', + "In v15, the Angular compiler prefixes `@keyframes` in CSS with the component's scope. This means that any TypeScript code that relies on `keyframes` names no longer works in v15. Update any such instances to: define keyframes programmatically, use global stylesheets, or change the component's view encapsulation. [Read further](https://v15.angular.io/guide/update-to-version-15#v15-bc-03)", }, { possibleIn: 1500, @@ -1717,7 +1722,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Medium, step: 'v15 base-decorators', action: - 'Make sure to use decorators in base classes with child classes that inherit constructors and use dependency injection. Such base classes should be decorated with either `@Injectable` or `@Directive` or the compiler returns an error. Read further', + 'Make sure to use decorators in base classes with child classes that inherit constructors and use dependency injection. Such base classes should be decorated with either `@Injectable` or `@Directive` or the compiler returns an error. [Read further](https://v15.angular.io/guide/update-to-version-15#v15-bc-05)', }, { possibleIn: 1500, @@ -1725,7 +1730,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Medium, step: 'v15 setDisabledState', action: - 'In v15, `setDisabledState` is always called when a `ControlValueAccessor` is attached. To opt-out of this behavior, use `FormsModule.withConfig` or `ReactiveFormsModule.withConfig`. Read further', + 'In v15, `setDisabledState` is always called when a `ControlValueAccessor` is attached. To opt-out of this behavior, use `FormsModule.withConfig` or `ReactiveFormsModule.withConfig`. [Read further](https://v15.angular.io/guide/update-to-version-15#v15-bc-06)', }, { possibleIn: 1500, @@ -1733,7 +1738,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Advanced, step: 'v15 canParse', action: - 'Applications that use `canParse` should use `analyze` from `@angular/localize/tools` instead. In v15, the `canParse` method was removed from all translation parsers in `@angular/localize/tools`. Read further', + 'Applications that use `canParse` should use `analyze` from `@angular/localize/tools` instead. In v15, the `canParse` method was removed from all translation parsers in `@angular/localize/tools`. [Read further](https://v15.angular.io/guide/update-to-version-15#v15-bc-07)', }, { possibleIn: 1500, @@ -1741,7 +1746,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'v15 ActivatedRoutSnapshot', action: - 'Make sure that all `ActivatedRouteSnapshot` objects have a `title` property. In v15, the `title` property is a required property of `ActivatedRouteSnapshot`. Read further', + 'Make sure that all `ActivatedRouteSnapshot` objects have a `title` property. In v15, the `title` property is a required property of `ActivatedRouteSnapshot`. [Read further](https://v15.angular.io/guide/update-to-version-15#v15-bc-08)', }, { possibleIn: 1500, @@ -1749,7 +1754,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Advanced, step: 'v15 RouterOutlet', action: - 'If your tests with `RouterOutlet` break, make sure they don\'t depend on the instantiation order of the corresponding component relative to change detection. In v15, `RouterOutlet` instantiates the component after change detection. Read further', + "If your tests with `RouterOutlet` break, make sure they don't depend on the instantiation order of the corresponding component relative to change detection. In v15, `RouterOutlet` instantiates the component after change detection. [Read further](https://v15.angular.io/guide/update-to-version-15#v15-bc-09)", }, { possibleIn: 1500, @@ -1757,7 +1762,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'v15 relativeLinkResolution', action: - 'In v15, `relativeLinkResolution` is not configurable in the Router. It was used to opt out of an earlier bug fix that is now standard. Read further', + 'In v15, `relativeLinkResolution` is not configurable in the Router. It was used to opt out of an earlier bug fix that is now standard. [Read further](https://v15.angular.io/guide/update-to-version-15#v15-bc-10)', }, { possibleIn: 1500, @@ -1765,7 +1770,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Medium, step: 'v15 DATE_PIPE_DEFAULT_OPTIONS', action: - 'Change instances of the `DATE_PIPE_DEFAULT_TIMEZONE` token to use `DATE_PIPE_DEFAULT_OPTIONS` to configure time zones. In v15, the `DATE_PIPE_DEFAULT_TIMEZONE` token is deprecated. Read further', + 'Change instances of the `DATE_PIPE_DEFAULT_TIMEZONE` token to use `DATE_PIPE_DEFAULT_OPTIONS` to configure time zones. In v15, the `DATE_PIPE_DEFAULT_TIMEZONE` token is deprecated. [Read further](https://v15.angular.io/guide/update-to-version-15#v15-dp-01)', }, { possibleIn: 1500, @@ -1781,7 +1786,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Medium, step: 'v15 Injector.get', action: - 'Update instances of `Injector.get()` that use an `InjectFlags` parameter to use an `InjectOptions` parameter. The `InjectFlags` parameter of `Injector.get()` is deprecated in v15. Read further', + 'Update instances of `Injector.get()` that use an `InjectFlags` parameter to use an `InjectOptions` parameter. The `InjectFlags` parameter of `Injector.get()` is deprecated in v15. [Read further](https://v15.angular.io/guide/update-to-version-15#v15-dp-02)', }, { possibleIn: 1500, @@ -1789,7 +1794,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'v15 TestBed.inject', action: - 'Update instances of `TestBed.inject()` that use an `InjectFlags` parameter to use an `InjectOptions` parameter. The `InjectFlags` parameter of `TestBed.inject()` is deprecated in v15. Read further', + 'Update instances of `TestBed.inject()` that use an `InjectFlags` parameter to use an `InjectOptions` parameter. The `InjectFlags` parameter of `TestBed.inject()` is deprecated in v15. [Read further](https://v15.angular.io/guide/update-to-version-15#v15-dp-01)', }, { possibleIn: 1500, @@ -1797,7 +1802,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Medium, step: 'v15 ngModule in providedIn', action: - 'Using `providedIn: ngModule` for an `@Injectable` and `InjectionToken` is deprecated in v15. Read further', + 'Using `providedIn: ngModule` for an `@Injectable` and `InjectionToken` is deprecated in v15. [Read further](https://v15.angular.io/guide/update-to-version-15#v15-dp-04)', }, { possibleIn: 1500, @@ -1805,7 +1810,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'v15 providedIn any', action: - 'Using `providedIn: \'any\'` for an `@Injectable` or `InjectionToken` is deprecated in v15. Read further', + "Using `providedIn: 'any'` for an `@Injectable` or `InjectionToken` is deprecated in v15. [Read further](https://v15.angular.io/guide/update-to-version-15#v15-dp-05)", }, { possibleIn: 1500, @@ -1813,7 +1818,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Medium, step: 'v15 RouterLinkWithHref', action: - 'Update instances of the `RouterLinkWithHref`directive to use the `RouterLink` directive. The `RouterLinkWithHref` directive is deprecated in v15. Read further', + 'Update instances of the `RouterLinkWithHref`directive to use the `RouterLink` directive. The `RouterLinkWithHref` directive is deprecated in v15. [Read further](https://v15.angular.io/guide/update-to-version-15#v15-dp-06)', }, { possibleIn: 1500, @@ -1822,7 +1827,7 @@ export const RECOMMENDATIONS: Step[] = [ material: true, step: 'v15 mat refactor', action: - 'In Angular Material v15, many of the components have been refactored to be based on the official Material Design Components for Web (MDC). This change affected the DOM and CSS classes of many components. Read further', + 'In Angular Material v15, many of the components have been refactored to be based on the official Material Design Components for Web (MDC). This change affected the DOM and CSS classes of many components. [Read further](https://rc.material.angular.dev/guide/mdc-migration)', }, { possibleIn: 1500, @@ -2669,7 +2674,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: '20.0.0_update_nodejs_version', action: - 'Ensure your Node.js version is at least 20.11.1 and not v18 or v22.0-v22.10 before upgrading to Angular v20. Check https://angular.dev/reference/versions for the full list of supported Node.js versions.', + 'Ensure your Node.js version is at least 20.11.1 and not v18 or v22.0-v22.10 before upgrading to Angular v20. Check the [full list of supported Node.js versions](https://angular.dev/reference/versions).', }, { possibleIn: 2000, @@ -2920,4 +2925,12 @@ export const RECOMMENDATIONS: Step[] = [ action: 'The `lastSuccessfulNavigation` property on the Router has been converted to a signal. To get its value, you now need to invoke it as a function: `router.lastSuccessfulNavigation()`.', }, + { + possibleIn: 2100, + necessaryAsOf: 2100, + level: ApplicationComplexity.Medium, + step: '21.0.0-configure-commonengine-allowed-hosts', + 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).", + }, ]; diff --git a/adev-ja/src/app/features/update/recommendations.ts b/adev-ja/src/app/features/update/recommendations.ts index d98d4017a..911cf2669 100644 --- a/adev-ja/src/app/features/update/recommendations.ts +++ b/adev-ja/src/app/features/update/recommendations.ts @@ -14,6 +14,12 @@ export enum ApplicationComplexity { export interface Step { step: string; + /** + * Action text rendered as Markdown. Use Markdown link syntax `[text](url)` + * for any links — raw `` HTML tags bypass the custom link renderer in + * `update.component.ts` and will not pick up `target="_blank"` or the + * external-link icon. + */ action: string; possibleIn: number; necessaryAsOf: number; @@ -155,7 +161,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Advanced, step: 'gendir', action: - '`gendir`に依存せず、代わりに`skipTemplateCodeGen`の使用を検討してください。詳細はこちら', + '`gendir`に依存せず、代わりに`skipTemplateCodeGen`の使用を検討してください。[詳細はこちら](https://github.com/angular/angular/issues/19339#issuecomment-332607471)', }, { possibleIn: 220, @@ -239,7 +245,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'node 8', action: - 'Node 8以降を使用していることを確認してください。', + '[Node 8以降](http://www.hostingadvice.com/how-to/update-node-js-latest-version/)を使用していることを確認してください。', }, { possibleIn: 600, @@ -248,7 +254,7 @@ export const RECOMMENDATIONS: Step[] = [ windows: false, step: 'Update to CLI v6', action: - 'Angular CLIを更新し、次のコマンドを実行して設定を新しいangular.json形式に移行してください。

`NG_DISABLE_VERSION_CHECK=1 npx @angular/cli@6 update @angular/cli@6`
', + 'Angular CLIを更新し、次のコマンドを実行して設定を[新しいangular.json形式](https://github.com/angular/angular-cli/wiki/angular-workspace)に移行してください。

`NG_DISABLE_VERSION_CHECK=1 npx @angular/cli@6 update @angular/cli@6`
', }, { possibleIn: 600, @@ -257,7 +263,7 @@ export const RECOMMENDATIONS: Step[] = [ windows: true, step: 'Update to CLI v6', action: - 'Angular CLIを更新し、次のコマンドを実行して設定を新しいangular.json形式に移行してください。

`cmd /C "set "NG_DISABLE_VERSION_CHECK=1" && npx @angular/cli@6 update @angular/cli@6 @angular/core@6"`
', + 'Angular CLIを更新し、次のコマンドを実行して設定を[新しいangular.json形式](https://github.com/angular/angular-cli/wiki/angular-workspace)に移行してください。

`cmd /C "set "NG_DISABLE_VERSION_CHECK=1" && npx @angular/cli@6 update @angular/cli@6 @angular/core@6"`
', }, { possibleIn: 600, @@ -343,7 +349,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Medium, step: 'strictPropertyInitializer', action: - 'TypeScriptが厳格に設定されている場合(`tsconfig.json`ファイルで`strict`を`true`に設定している場合)、`tsconfig.json`を更新して`strictPropertyInitialization`を無効にするか、プロパティの初期化を`ngOnInit`からコンストラクターに移動してください。このフラグの詳細については、TypeScript 2.7リリースノートを参照してください。', + 'TypeScriptが厳格に設定されている場合(`tsconfig.json`ファイルで`strict`を`true`に設定している場合)、`tsconfig.json`を更新して`strictPropertyInitialization`を無効にするか、プロパティの初期化を`ngOnInit`からコンストラクターに移動してください。このフラグの詳細については、[TypeScript 2.7リリースノート](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#strict-class-initialization)を参照してください。', }, { possibleIn: 600, @@ -351,7 +357,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'update to RxJS 6', action: - 'rxjs-tslint自動更新ルールを使用して、非推奨のRxJS 5機能を削除してください。

ほとんどのアプリケーションでは、次の2つのコマンドを実行することになります。

`npx rxjs-tslint`
`rxjs-5-to-6-migrate -p src/tsconfig.app.json`', + '[rxjs-tslint自動更新ルール](https://github.com/ReactiveX/rxjs-tslint)を使用して、非推奨のRxJS 5機能を削除してください。

ほとんどのアプリケーションでは、次の2つのコマンドを実行することになります。

`npx rxjs-tslint`
`rxjs-5-to-6-migrate -p src/tsconfig.app.json`', }, { possibleIn: 600, @@ -374,7 +380,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'TypeScript 3.1', action: - 'AngularはTypeScript 3.1を使用するようになりました。潜在的な破壊的変更については、https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.htmlを参照してください。', + 'AngularはTypeScript 3.1を使用するようになりました。[潜在的な破壊的変更](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html)について参照してください。', }, { possibleIn: 700, @@ -382,7 +388,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'Node 10', action: - 'AngularはNode 10のサポートを追加しました: https://nodejs.org/en/blog/release/v10.0.0/', + 'Angularは[Node 10](https://nodejs.org/en/blog/release/v10.0.0/)のサポートを追加しました。', }, { possibleIn: 700, @@ -464,7 +470,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'use ::ng-deep instead of /deep/', action: - 'スタイル内の`/deep/`を`::ng-deep`に置き換えてください。Angularコンポーネントスタイルと`::ng-deep`について詳しくはこちら。`/deep/`と`::ng-deep`はどちらも非推奨ですが、シャドウピアシング子孫コンビネーターがブラウザとツールから完全に削除されるまでは`::ng-deep`の使用が推奨されます。', + 'スタイル内の`/deep/`を`::ng-deep`に置き換えてください。[Angularコンポーネントスタイルと`::ng-deep`について詳しくはこちら](https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep)。`/deep/`と`::ng-deep`はどちらも非推奨ですが、シャドウピアシング子孫コンビネーターが[ブラウザとツールから完全に削除される](https://chromestatus.com/feature/5045542597951488)までは`::ng-deep`の使用が推奨されます。', }, { possibleIn: 800, @@ -480,7 +486,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'node 10', action: - 'Node 10以降を使用していることを確認してください。', + '[Node 10以降](http://www.hostingadvice.com/how-to/update-node-js-latest-version/)を使用していることを確認してください。', }, { possibleIn: 800, @@ -573,7 +579,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'node 10.13', action: - 'Node 10.13以降を使用していることを確認してください。', + '[Node 10.13以降](http://www.hostingadvice.com/how-to/update-node-js-latest-version/)を使用していることを確認してください。', }, { possibleIn: 900, @@ -781,9 +787,8 @@ export const RECOMMENDATIONS: Step[] = [ possibleIn: 1000, necessaryAsOf: 1000, level: ApplicationComplexity.Basic, - step: 'v10 NodeJS 12', - action: - 'Node 12以降を使用していることを確認してください。', + step: 'v10 Node.js 12', + action: '[Node 12以降](https://nodejs.org/dist/latest-v12.x/)を使用していることを確認してください。', }, { possibleIn: 1000, @@ -847,7 +852,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Advanced, step: 'closure-jsdoc-comments', action: - 'AngularのNPMパッケージには、Closure Compiler(非常に稀)で使用するために必要なjsdocコメントが含まれなくなりました。このサポートは実験的であり、一部のユースケースでのみ機能しました。代替の推奨パスがまもなく発表されます。', + 'Angularのnpmパッケージには、Closure Compiler(非常に稀)で使用するために必要なjsdocコメントが含まれなくなりました。このサポートは実験的であり、一部のユースケースでのみ機能しました。代替の推奨パスがまもなく発表されます。', }, { possibleIn: 1000, @@ -871,7 +876,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Medium, step: 'esm5-bundles', action: - '[Angular Package Format](https://g.co/ng/apf)が更新され、`esm5`および`fesm5`形式が削除されました。これらはnpmパッケージでは配布されなくなりました。CLIを使用しない場合、Angularコードを自分でES5にダウンレベルする必要があるかもしれません。', + '[Angular Package Format](https://angular.dev/tools/libraries/angular-package-format)が更新され、`esm5`および`fesm5`形式が削除されました。これらはnpmパッケージでは配布されなくなりました。CLIを使用しない場合、Angularコードを自分でES5にダウンレベルする必要があるかもしれません。', }, { possibleIn: 1000, @@ -1335,7 +1340,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'TypeScript 4.4', action: - 'AngularはTypeScript 4.4を使用するようになりました。潜在的な破壊的変更については、https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.htmlを参照してください。', + 'AngularはTypeScript 4.4を使用するようになりました。[潜在的な破壊的変更](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html)について参照してください。', }, { possibleIn: 1300, @@ -1343,7 +1348,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'v13 node', action: - 'Node 12.20.0以降を使用していることを確認してください。', + '[Node 12.20.0以降](http://www.hostingadvice.com/how-to/update-node-js-latest-version/)を使用していることを確認してください。', }, { possibleIn: 1300, @@ -1457,7 +1462,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'TypeScript 4.6', action: - 'AngularはTypeScript 4.6を使用するようになりました。潜在的な破壊的変更については、https://devblogs.microsoft.com/typescript/announcing-typescript-4-6/を参照してください。', + 'AngularはTypeScript 4.6を使用するようになりました。[潜在的な破壊的変更](https://devblogs.microsoft.com/typescript/announcing-typescript-4-6/)について参照してください。', }, { @@ -1466,7 +1471,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'v14 node', action: - 'Node 14.15.0以降を使用していることを確認してください。', + '[Node 14.15.0以降](http://www.hostingadvice.com/how-to/update-node-js-latest-version/)を使用していることを確認してください。', }, { possibleIn: 1400, @@ -1669,7 +1674,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'v15 node support', action: - 'アプリケーションをアップグレードする前に、サポートされているバージョンのNode.jsを使用していることを確認してください。Angular v15はNode.jsバージョン14.20.x、16.13.x、18.10.xをサポートしています。詳細はこちら', + 'アプリケーションをアップグレードする前に、サポートされているバージョンのNode.jsを使用していることを確認してください。Angular v15はNode.jsバージョン14.20.x、16.13.x、18.10.xをサポートしています。[詳細はこちら](https://v15.angular.io/guide/update-to-version-15#v15-bc-01)', }, { possibleIn: 1500, @@ -1677,7 +1682,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'v15 ts support', action: - 'アプリケーションをアップグレードする前に、サポートされているバージョンのTypeScriptを使用していることを確認してください。Angular v15はTypeScriptバージョン4.8以降をサポートしています。詳細はこちら', + 'アプリケーションをアップグレードする前に、サポートされているバージョンのTypeScriptを使用していることを確認してください。Angular v15はTypeScriptバージョン4.8以降をサポートしています。[詳細はこちら](https://v15.angular.io/guide/update-to-version-15#v15-bc-02)', }, { possibleIn: 1500, @@ -1749,7 +1754,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Advanced, step: 'v15 RouterOutlet', action: - '`RouterOutlet`を使用するテストが壊れた場合、変更検知に対する対応するコンポーネントのインスタンス化順序に依存していないことを確認してください。v15では、`RouterOutlet`は変更検知後にコンポーネントをインスタンス化します。詳細はこちら', + '`RouterOutlet`を使用するテストが壊れた場合、変更検知に対する対応するコンポーネントのインスタンス化順序に依存していないことを確認してください。v15では、`RouterOutlet`は変更検知後にコンポーネントをインスタンス化します。[詳細はこちら](https://v15.angular.io/guide/update-to-version-15#v15-bc-09)', }, { possibleIn: 1500, @@ -1757,7 +1762,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'v15 relativeLinkResolution', action: - 'v15では、`relativeLinkResolution`はルーターで設定できません。これは、以前のバグ修正からオプトアウトするために使用されていましたが、現在は標準となっています。詳細はこちら', + 'v15では、`relativeLinkResolution`はルーターで設定できません。これは、以前のバグ修正からオプトアウトするために使用されていましたが、現在は標準となっています。[詳細はこちら](https://v15.angular.io/guide/update-to-version-15#v15-bc-10)', }, { possibleIn: 1500, @@ -1765,7 +1770,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Medium, step: 'v15 DATE_PIPE_DEFAULT_OPTIONS', action: - 'タイムゾーンを設定するために、`DATE_PIPE_DEFAULT_TIMEZONE`トークンのインスタンスを`DATE_PIPE_DEFAULT_OPTIONS`を使用するように変更してください。v15では、`DATE_PIPE_DEFAULT_TIMEZONE`トークンは非推奨です。詳細はこちら', + 'タイムゾーンを設定するために、`DATE_PIPE_DEFAULT_TIMEZONE`トークンのインスタンスを`DATE_PIPE_DEFAULT_OPTIONS`を使用するように変更してください。v15では、`DATE_PIPE_DEFAULT_TIMEZONE`トークンは非推奨です。[詳細はこちら](https://v15.angular.io/guide/update-to-version-15#v15-dp-01)', }, { possibleIn: 1500, @@ -1781,7 +1786,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Medium, step: 'v15 Injector.get', action: - '`InjectFlags`パラメータを使用する`Injector.get()`のインスタンスを、`InjectOptions`パラメータを使用するように更新してください。`Injector.get()`の`InjectFlags`パラメータはv15で非推奨です。詳細はこちら', + '`InjectFlags`パラメータを使用する`Injector.get()`のインスタンスを、`InjectOptions`パラメータを使用するように更新してください。`Injector.get()`の`InjectFlags`パラメータはv15で非推奨です。[詳細はこちら](https://v15.angular.io/guide/update-to-version-15#v15-dp-02)', }, { possibleIn: 1500, @@ -1789,7 +1794,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'v15 TestBed.inject', action: - '`InjectFlags`パラメータを使用する`TestBed.inject()`のインスタンスを、`InjectOptions`パラメータを使用するように更新してください。`TestBed.inject()`の`InjectFlags`パラメータはv15で非推奨です。詳細はこちら', + '`InjectFlags`パラメータを使用する`TestBed.inject()`のインスタンスを、`InjectOptions`パラメータを使用するように更新してください。`TestBed.inject()`の`InjectFlags`パラメータはv15で非推奨です。[詳細はこちら](https://v15.angular.io/guide/update-to-version-15#v15-dp-01)', }, { possibleIn: 1500, @@ -1797,7 +1802,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Medium, step: 'v15 ngModule in providedIn', action: - '`@Injectable`および`InjectionToken`に対して`providedIn: ngModule`を使用することはv15で非推奨です。詳細はこちら', + '`@Injectable`および`InjectionToken`に対して`providedIn: ngModule`を使用することはv15で非推奨です。[詳細はこちら](https://v15.angular.io/guide/update-to-version-15#v15-dp-04)', }, { possibleIn: 1500, @@ -1805,7 +1810,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: 'v15 providedIn any', action: - '`@Injectable`または`InjectionToken`に対して`providedIn: \'any\'`を使用することはv15で非推奨です。詳細はこちら', + "`@Injectable`または`InjectionToken`に対して`providedIn: 'any'`を使用することはv15で非推奨です。[詳細はこちら](https://v15.angular.io/guide/update-to-version-15#v15-dp-05)", }, { possibleIn: 1500, @@ -1813,7 +1818,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Medium, step: 'v15 RouterLinkWithHref', action: - '`RouterLinkWithHref`ディレクティブのインスタンスを`RouterLink`ディレクティブを使用するように更新してください。`RouterLinkWithHref`ディレクティブはv15で非推奨です。詳細はこちら', + '`RouterLinkWithHref`ディレクティブのインスタンスを`RouterLink`ディレクティブを使用するように更新してください。`RouterLinkWithHref`ディレクティブはv15で非推奨です。[詳細はこちら](https://v15.angular.io/guide/update-to-version-15#v15-dp-06)', }, { possibleIn: 1500, @@ -1822,7 +1827,7 @@ export const RECOMMENDATIONS: Step[] = [ material: true, step: 'v15 mat refactor', action: - 'Angular Material v15では、多くのコンポーネントが公式のMaterial Design Components for Web (MDC) に基づくようにリファクタリングされました。この変更は、多くのコンポーネントのDOMとCSSクラスに影響を与えました。詳細はこちら', + 'Angular Material v15では、多くのコンポーネントが公式のMaterial Design Components for Web (MDC) に基づくようにリファクタリングされました。この変更は、多くのコンポーネントのDOMとCSSクラスに影響を与えました。[詳細はこちら](https://rc.material.angular.dev/guide/mdc-migration)', }, { possibleIn: 1500, @@ -2669,7 +2674,7 @@ export const RECOMMENDATIONS: Step[] = [ level: ApplicationComplexity.Basic, step: '20.0.0_update_nodejs_version', action: - 'Angular v20に更新する前に、Node.jsのバージョンが20.11.1以上であり、v18またはv22.0-v22.10ではないことを確認してください。サポートされているNode.jsバージョンの完全なリストはhttps://angular.dev/reference/versionsで確認してください。', + 'Angular v20に更新する前に、Node.jsのバージョンが20.11.1以上であり、v18またはv22.0-v22.10ではないことを確認してください。[サポートされているNode.jsバージョンの完全なリスト](https://angular.dev/reference/versions)を確認してください。', }, { possibleIn: 2000, @@ -2920,4 +2925,12 @@ export const RECOMMENDATIONS: Step[] = [ action: 'Router の `lastSuccessfulNavigation` プロパティがシグナルに変換されました。その値を取得するには、関数として呼び出す必要があります: `router.lastSuccessfulNavigation()`。', }, + { + possibleIn: 2100, + necessaryAsOf: 2100, + level: ApplicationComplexity.Medium, + step: '21.0.0-configure-commonengine-allowed-hosts', + 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にもバックポートされています)。", + }, ]; 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 4eea44e25..79745cf95 100644 --- a/adev-ja/src/app/features/update/update.component.en.ts +++ b/adev-ja/src/app/features/update/update.component.en.ts @@ -17,6 +17,20 @@ import {ActivatedRoute, Router} from '@angular/router'; import {marked} from 'marked'; import {MatSnackBar} from '@angular/material/snack-bar'; +/** + * Configure marked with a custom link renderer so external links in the + * update guide open in a new tab, matching the convention applied elsewhere + * in adev via the `ExternalLink` directive. + */ +marked.use({ + renderer: { + link({href, title, text}) { + const titleAttr = title ? ` title="${title}"` : ''; + return `${text}`; + }, + }, +}); + interface Option { id: keyof Step; name: string; diff --git a/adev-ja/src/app/features/update/update.component.ts b/adev-ja/src/app/features/update/update.component.ts index 76d12660e..2e753be1c 100644 --- a/adev-ja/src/app/features/update/update.component.ts +++ b/adev-ja/src/app/features/update/update.component.ts @@ -17,6 +17,20 @@ import {ActivatedRoute, Router} from '@angular/router'; import {marked} from 'marked'; import {MatSnackBar} from '@angular/material/snack-bar'; +/** + * Configure marked with a custom link renderer so external links in the + * update guide open in a new tab, matching the convention applied elsewhere + * in adev via the `ExternalLink` directive. + */ +marked.use({ + renderer: { + link({href, title, text}) { + const titleAttr = title ? ` title="${title}"` : ''; + return `${text}`; + }, + }, +}); + interface Option { id: keyof Step; name: string; 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 32990b1af..02adf87b2 100644 --- a/adev-ja/src/app/routing/navigation-entries/index.en.ts +++ b/adev-ja/src/app/routing/navigation-entries/index.en.ts @@ -517,6 +517,13 @@ export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ category: 'Signal Forms', status: 'new', }, + { + label: 'Field metadata', + path: 'guide/forms/signals/field-metadata', + contentPath: 'guide/forms/signals/field-metadata', + category: 'Signal Forms', + status: 'new', + }, { label: 'Async operations', path: 'guide/forms/signals/async-operations', diff --git a/adev-ja/src/app/routing/navigation-entries/index.ts b/adev-ja/src/app/routing/navigation-entries/index.ts index d6f85f826..b4431358f 100644 --- a/adev-ja/src/app/routing/navigation-entries/index.ts +++ b/adev-ja/src/app/routing/navigation-entries/index.ts @@ -517,6 +517,13 @@ export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ category: 'Signal Forms', status: 'new', }, + { + label: 'フィールドメタデータ', + path: 'guide/forms/signals/field-metadata', + contentPath: 'guide/forms/signals/field-metadata', + category: 'Signal Forms', + status: 'new', + }, { label: '非同期処理', path: 'guide/forms/signals/async-operations', diff --git a/adev-ja/src/content/ai/develop-with-ai.en.md b/adev-ja/src/content/ai/develop-with-ai.en.md index 4641f6158..8e4e3c518 100644 --- a/adev-ja/src/content/ai/develop-with-ai.en.md +++ b/adev-ja/src/content/ai/develop-with-ai.en.md @@ -18,11 +18,11 @@ Here is a set of instructions to help LLMs generate correct code that follows An ## Rules Files -Several editors, such as Firebase Studio have rules files useful for providing critical context to LLMs. +Several editors, such as Firebase Studio have rules files useful for providing critical context to LLMs. | Environment/IDE | Rules File | Installation Instructions | | :------------------- | :--------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Firebase Studio | airules.md | Configure `airules.md` | +| Firebase Studio | airules.md | Configure `airules.md` | | Copilot powered IDEs | copilot-instructions.md | Configure `.github/copilot-instructions.md` | | Cursor | cursor.md | Configure `cursorrules.md` | | JetBrains IDEs | guidelines.md | Configure `guidelines.md` | diff --git a/adev-ja/src/content/ai/develop-with-ai.md b/adev-ja/src/content/ai/develop-with-ai.md index c9718591a..2bc8e0387 100644 --- a/adev-ja/src/content/ai/develop-with-ai.md +++ b/adev-ja/src/content/ai/develop-with-ai.md @@ -18,11 +18,11 @@ NOTE: これらのファイルは、Angularの規約に準拠するために定 ## ルールファイル {#rules-files} -いくつかのエディター(例: Firebase Studio)には、LLMに重要なコンテキストを提供するのに役立つルールファイルがあります。 +いくつかのエディター(例: Firebase Studio)には、LLMに重要なコンテキストを提供するのに役立つルールファイルがあります。 | 環境/IDE | ルールファイル | インストール手順 | |:----------------|:----------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------| -| Firebase Studio | airules.md | `airules.md`を設定 | +| Firebase Studio | airules.md | `airules.md`を設定 | | Copilot powered IDEs | copilot-instructions.md | `.github/copilot-instructions.md`を設定 | | Cursor | cursor.md | `cursorrules.md`を設定 | | JetBrains IDEs | guidelines.md | `guidelines.md`を設定 | diff --git a/adev-ja/src/content/best-practices/update.en.md b/adev-ja/src/content/best-practices/update.en.md index 0e2cabdfa..1a7cd0d08 100644 --- a/adev-ja/src/content/best-practices/update.en.md +++ b/adev-ja/src/content/best-practices/update.en.md @@ -6,9 +6,9 @@ Keeping your Angular application up-to-date enables you to take advantage of lea This document contains information and resources to help you keep your Angular applications and libraries up-to-date. -For information about our versioning policy and practices —including support and deprecation practices, as well as the release schedule— see [Angular versioning and releases](reference/releases 'Angular versioning and releases'). +For information about our versioning policy and practices — including support and deprecation practices, as well as the release schedule — see [Angular versioning and releases](reference/releases 'Angular versioning and releases'). -HELPFUL: If you are currently using AngularJS, see [Upgrading from AngularJS](https://angular.io/guide/upgrade 'Upgrading from Angular JS'). +HELPFUL: If you are currently using AngularJS, see [Upgrading from AngularJS](https://angular.io/guide/upgrade 'Upgrading from AngularJS'). _AngularJS_ is the name for all v1.x versions of Angular. ## Getting notified of new releases @@ -30,7 +30,7 @@ To check your application's version of Angular use the `ng version` command from The most recent stable released version of Angular appears [on npm](https://www.npmjs.com/package/@angular/core 'Angular on npm') under "Version." For example, `16.2.4`. You can also find the most current version of Angular by using the CLI command [`ng update`](cli/update). -By default, [`ng update`](cli/update)(without additional arguments) lists the updates that are available to you. +By default, [`ng update`](cli/update) (without additional arguments) lists the updates that are available to you. ## Updating your environment and apps diff --git a/adev-ja/src/content/best-practices/update.md b/adev-ja/src/content/best-practices/update.md index b4b773566..1c8a3dfb6 100644 --- a/adev-ja/src/content/best-practices/update.md +++ b/adev-ja/src/content/best-practices/update.md @@ -8,7 +8,7 @@ Angularアプリケーションを最新の状態に保つことで、最先端 バージョン管理ポリシーとプラクティス(サポートと非推奨のプラクティス、リリーススケジュールを含む)については、[Angular バージョン管理とリリース](reference/releases 'Angular バージョン管理とリリース')をご覧ください。 -HELPFUL: 現在AngularJSを使用している場合は、[AngularJS からのアップグレード](https://angular.io/guide/upgrade 'Angular JS からのアップグレード')をご覧ください。 +HELPFUL: 現在AngularJSを使用している場合は、[AngularJS からのアップグレード](https://angular.io/guide/upgrade 'AngularJS からのアップグレード')をご覧ください。 _AngularJS_ は、Angularのすべてのv1.xバージョンを表します。 ## 新しいリリースの通知を受け取る diff --git a/adev-ja/src/content/ecosystem/service-workers/config.md b/adev-ja/src/content/ecosystem/service-workers/config.md index 9a6500f88..d0ea43baa 100644 --- a/adev-ja/src/content/ecosystem/service-workers/config.md +++ b/adev-ja/src/content/ecosystem/service-workers/config.md @@ -85,7 +85,7 @@ For example, an asset group that matches `/foo.js` should appear before one that Each asset group specifies both a group of resources and a policy that governs them. This policy determines when the resources are fetched and what happens when changes are detected. -Asset groups follow the Typescript interface shown here: +Asset groups follow the TypeScript interface shown here: ```ts interface AssetGroup { @@ -179,7 +179,7 @@ The first data group that matches the requested resource handles the request. It is recommended that you put the more specific data groups higher in the list. For example, a data group that matches `/api/foo.json` should appear before one that matches `/api/*.json`. -Data groups follow this Typescript interface: +Data groups follow this TypeScript interface: ```ts export interface DataGroup { diff --git a/adev-ja/src/content/ecosystem/service-workers/devops.md b/adev-ja/src/content/ecosystem/service-workers/devops.md index a2fc1876e..498cceabd 100644 --- a/adev-ja/src/content/ecosystem/service-workers/devops.md +++ b/adev-ja/src/content/ecosystem/service-workers/devops.md @@ -283,7 +283,7 @@ When the service worker's request for `ngsw.json` returns a `404`, then the serv -A small script, `safety-worker.js`, is also included in the `@angular/service-worker` NPM package. +A small script, `safety-worker.js`, is also included in the `@angular/service-worker` npm package. When loaded, it un-registers itself from the browser and removes the service worker caches. This script can be used as a last resort to get rid of unwanted service workers already installed on client pages. diff --git a/adev-ja/src/content/guide/animations/complex-sequences.en.md b/adev-ja/src/content/guide/animations/complex-sequences.en.md index 4070303ce..0efe9729d 100644 --- a/adev-ja/src/content/guide/animations/complex-sequences.en.md +++ b/adev-ja/src/content/guide/animations/complex-sequences.en.md @@ -17,12 +17,12 @@ The functions that control complex animation sequences are: ## The query() function -Most complex animations rely on the `query()` function to find child elements and apply animations to them, basic examples of such are: +Most complex animations rely on the `query()` function to find child elements and apply animations to them. Basic examples include: -| Examples | Details | -| :------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `query()` followed by `animate()` | Used to query simple HTML elements and directly apply animations to them. | -| `query()` followed by `animateChild()` | Used to query child elements, which themselves have animations metadata applied to them and trigger such animation \(which would be otherwise be blocked by the current/parent element's animation\). | +| Examples | Details | +| :------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `query()` followed by `animate()` | Used to query simple HTML elements and directly apply animations to them. | +| `query()` followed by `animateChild()` | Used to query child elements, which themselves have animation metadata applied to them and trigger such animations \(which would otherwise be blocked by the current/parent element's animation\). | The first argument of `query()` is a [css selector](https://developer.mozilla.org/docs/Web/CSS/CSS_Selectors) string which can also contain the following Angular-specific tokens: @@ -43,7 +43,7 @@ You can also see an illustration of this in the animations example \(introduced ## Animate multiple elements using query() and stagger() functions -After having queried child elements via `query()`, the `stagger()` function lets you define a timing gap between each queried item that is animated and thus animates elements with a delay between them. +After querying child elements via `query()`, the `stagger()` function lets you define a timing gap between each item, animating elements with a delay between them. The following example demonstrates how to use the `query()` and `stagger()` functions to animate a list \(of heroes\) adding each in sequence, with a slight delay, from top to bottom. diff --git a/adev-ja/src/content/guide/animations/css.en.md b/adev-ja/src/content/guide/animations/css.en.md index 4ad6d5e0a..578164302 100644 --- a/adev-ja/src/content/guide/animations/css.en.md +++ b/adev-ja/src/content/guide/animations/css.en.md @@ -4,7 +4,7 @@ CSS offers a robust set of tools for you to create beautiful and engaging animat ## How to write animations in native CSS -If you've never written any native CSS animations, there are a number of excellent guides to get you started. Here's a few of them: +If you've never written any native CSS animations, there are a number of excellent guides to get you started. Here are a few of them: [MDN's CSS Animations guide](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animations/Using_CSS_animations) [W3Schools CSS3 Animations guide](https://www.w3schools.com/css/css3_animations.asp) [The Complete CSS Animations Tutorial](https://www.lambdatest.com/blog/css-animations-tutorial/) @@ -14,7 +14,7 @@ and a couple of videos: [Learn CSS Animation in 9 Minutes](https://www.youtube.com/watch?v=z2LQYsZhsFw) [Net Ninja CSS Animation Tutorial Playlist](https://www.youtube.com/watch?v=jgw82b5Y2MU&list=PL4cUxeGkcC9iGYgmEd2dm3zAKzyCGDtM5) -Check some of these various guides and tutorials out, and then come back to this guide. +Check out some of these guides and tutorials, then come back to this guide. ## Creating Reusable Animations @@ -28,7 +28,7 @@ Adding the class `animated-class` to an element would trigger the animation on t ### Animating State and Styles -You may want to animate between two different states, for example when an element is opened or closed. You can accomplish this by using CSS classes either using a keyframe animation or transition styling. +You may want to animate between two different states, for example when an element is opened or closed. You can accomplish this by using CSS classes, either with a keyframe animation or transition styling. @@ -38,7 +38,7 @@ You can see similar examples in the template guide for [animating styles directl ### Transitions, Timing, and Easing -Animating often requires adjusting timing, delays and easeing behaviors. This can be done using several css properties or shorthand properties. +Animating often requires adjusting timing, delays, and easing behaviors. This can be done using several css properties or shorthand properties. Specify `animation-duration`, `animation-delay`, and `animation-timing-function` for a keyframe animation in CSS, or alternatively use the `animation` shorthand property. @@ -62,7 +62,7 @@ Animations can be triggered by toggling CSS styles or classes. Once a class is p ### Animating Auto Height -You can use css-grid to animate to auto height. +You can use CSS Grid to animate to auto height. diff --git a/adev-ja/src/content/guide/animations/enter-and-leave.en.md b/adev-ja/src/content/guide/animations/enter-and-leave.en.md index 8a8db2f3b..7817950ed 100644 --- a/adev-ja/src/content/guide/animations/enter-and-leave.en.md +++ b/adev-ja/src/content/guide/animations/enter-and-leave.en.md @@ -1,13 +1,13 @@ # Animating your applications with `animate.enter` and `animate.leave` -Well-designed animations can make your application more fun and straightforward to use, but they aren't just cosmetic. -Animations can improve your application and user experience in a number of ways: +Well-designed animations can make your application more intuitive and engaging, but they aren't just cosmetic. +Animations can improve your application and the user experience in a number of ways: - Without animations, web page transitions can seem abrupt and jarring - Motion greatly enhances the user experience, so animations give users a chance to detect the application's response to their actions - Good animations can smoothly direct the user's attention throughout a workflow -Angular provides `animate.enter` and `animate.leave` to animate your application's elements. These two features apply enter and leave CSS classes at the appropriate times or call functions to apply animations from third party libraries. `animate.enter` and `animate.leave` are not directives. They are special API supported directly by the Angular compiler. They can be used on elements directly and can also be used as a host binding. +Angular provides `animate.enter` and `animate.leave` to animate your application's elements. These two features apply enter and leave CSS classes at the appropriate times or call functions to apply animations from third party libraries. `animate.enter` and `animate.leave` are not directives. They are special API supported directly by the Angular compiler. They can be used directly on elements and also as a host binding. ## `animate.enter` @@ -19,7 +19,7 @@ You can use `animate.enter` to animate elements as they _enter_ the DOM. You can -When the animation completes, Angular removes the class or classes that you specified in `animate.enter` from the DOM. Animation classes are only be present while the animation is active. +When the animation completes, Angular removes the class or classes that you specified in `animate.enter` from the DOM. Animation classes are only present while the animation is active. NOTE: When using multiple keyframe animations or transition properties on an element, Angular removes all classes only _after_ the longest animation has completed. diff --git a/adev-ja/src/content/guide/animations/enter-and-leave.md b/adev-ja/src/content/guide/animations/enter-and-leave.md index 152b1c03a..1012a124c 100644 --- a/adev-ja/src/content/guide/animations/enter-and-leave.md +++ b/adev-ja/src/content/guide/animations/enter-and-leave.md @@ -1,6 +1,6 @@ # `animate.enter`と`animate.leave`を使ったアプリケーションのアニメーション -適切に設計されたアニメーションは、アプリケーションをより楽しく、分かりやすく使用できるようにしますが、単なる装飾ではありません。 +適切に設計されたアニメーションは、アプリケーションをより直感的で魅力的にしますが、単なる装飾ではありません。 アニメーションは、いくつかの方法でアプリケーションとユーザー体験を向上させることができます。 - アニメーションがないと、ウェブページの遷移は突然で不快に感じられることがあります diff --git a/adev-ja/src/content/guide/animations/migration.en.md b/adev-ja/src/content/guide/animations/migration.en.md index e3a3e8dff..7aa4258b5 100644 --- a/adev-ja/src/content/guide/animations/migration.en.md +++ b/adev-ja/src/content/guide/animations/migration.en.md @@ -4,7 +4,7 @@ The `@angular/animations` package is deprecated as of v20.2, which also introduc ## How to write animations in native CSS -If you've never written any native CSS animations, there are a number of excellent guides to get you started. Here's a few of them: +If you've never written any native CSS animations, there are a number of excellent guides to get you started. Here are a few of them: [MDN's CSS Animations guide](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animations/Using_CSS_animations) [W3Schools CSS3 Animations guide](https://www.w3schools.com/css/css3_animations.asp) [The Complete CSS Animations Tutorial](https://www.lambdatest.com/blog/css-animations-tutorial/) @@ -14,7 +14,7 @@ and a couple of videos: [Learn CSS Animation in 9 Minutes](https://www.youtube.com/watch?v=z2LQYsZhsFw) [Net Ninja CSS Animation Tutorial Playlist](https://www.youtube.com/watch?v=jgw82b5Y2MU&list=PL4cUxeGkcC9iGYgmEd2dm3zAKzyCGDtM5) -Check some of these various guides and tutorials out, and then come back to this guide. +Check out some of these guides and tutorials, then come back to this guide. ## Creating Reusable Animations @@ -40,7 +40,7 @@ The animations package allowed you to define various states using the [`state()` -This same behavior can be accomplished natively by using CSS classes either using a keyframe animation or transition styling. +This same behavior can be accomplished natively by using CSS classes, either with a keyframe animation or transition styling. #### With Native CSS @@ -102,7 +102,7 @@ The animations package offers the ability to animate things that have been histo -You can use css-grid to animate to auto height. +You can use CSS Grid to animate to auto height. #### With Native CSS diff --git a/adev-ja/src/content/guide/animations/overview.en.md b/adev-ja/src/content/guide/animations/overview.en.md index ec2ee0d7c..db2a70fa8 100644 --- a/adev-ja/src/content/guide/animations/overview.en.md +++ b/adev-ja/src/content/guide/animations/overview.en.md @@ -2,9 +2,9 @@ IMPORTANT: The `@angular/animations` package is now deprecated. The Angular team recommends using native CSS with `animate.enter` and `animate.leave` for animations for all new code. Learn more at the new enter and leave [animation guide](guide/animations). Also see [Migrating away from Angular's Animations package](guide/animations/migration) to learn how you can start migrating to pure CSS animations in your apps. -Animation provides the illusion of motion: HTML elements change styling over time. -Well-designed animations can make your application more fun and straightforward to use, but they aren't just cosmetic. -Animations can improve your application and user experience in a number of ways: +Animation provides the illusion of motion: HTML elements change styles over time. +Well-designed animations can make your application more intuitive and engaging, but they aren't just cosmetic. +Animations can improve your application and the user experience in a number of ways: - Without animations, web page transitions can seem abrupt and jarring - Motion greatly enhances the user experience, so animations give users a chance to detect the application's response to their actions @@ -70,7 +70,7 @@ You put the trigger that defines an animation within the `animations` metadata p Let's animate a transition that changes a single HTML element from one state to another. For example, you can specify that a button displays either **Open** or **Closed** based on the user's last action. When the button is in the `open` state, it's visible and yellow. -When it's the `closed` state, it's translucent and blue. +When it's in the `closed` state, it's translucent and blue. In HTML, these attributes are set using ordinary CSS styles such as color and opacity. In Angular, use the `style()` function to specify a set of CSS styles for use with animations. diff --git a/adev-ja/src/content/guide/animations/overview.md b/adev-ja/src/content/guide/animations/overview.md index 768eef56f..7e674c200 100644 --- a/adev-ja/src/content/guide/animations/overview.md +++ b/adev-ja/src/content/guide/animations/overview.md @@ -3,7 +3,7 @@ IMPORTANT: `@angular/animations`パッケージは現在非推奨です。Angularチームは、新しく書くコードのアニメーションには`animate.enter`と`animate.leave`を使ったネイティブCSSの利用を推奨します。詳しくは、新しいenterとleaveの[アニメーションガイド](guide/animations)を参照してください。また、アプリケーションで純粋なCSSアニメーションへの移行を始める方法については、[AngularのAnimationsパッケージからの移行](guide/animations/migration)も参照してください。 アニメーションは動いているように見せる効果を生み出します。HTML要素のスタイルは時間の経過とともに変化します。 -適切に設計されたアニメーションは、アプリケーションをより楽しく、分かりやすく使えるようにしますが、単なる装飾ではありません。 +適切に設計されたアニメーションは、アプリケーションをより直感的で魅力的にしますが、単なる装飾ではありません。 アニメーションは、いくつかの方法でアプリケーションとユーザー体験を向上させます。 - アニメーションがないと、ウェブページの遷移は唐突でぎこちなく感じられることがあります diff --git a/adev-ja/src/content/guide/animations/reusable-animations.en.md b/adev-ja/src/content/guide/animations/reusable-animations.en.md index b1519edfe..7aa3fcab4 100644 --- a/adev-ja/src/content/guide/animations/reusable-animations.en.md +++ b/adev-ja/src/content/guide/animations/reusable-animations.en.md @@ -2,12 +2,12 @@ IMPORTANT: The `@angular/animations` package is now deprecated. The Angular team recommends using native CSS with `animate.enter` and `animate.leave` for animations for all new code. Learn more at the new enter and leave [animation guide](guide/animations). Also see [Migrating away from Angular's Animations package](guide/animations/migration) to learn how you can start migrating to pure CSS animations in your apps. -This topic provides some examples of how to create reusable animations. +This topic provides examples of how to create reusable animations. ## Create reusable animations To create a reusable animation, use the [`animation()`](api/animations/animation) function to define an animation in a separate `.ts` file and declare this animation definition as a `const` export variable. -You can then import and reuse this animation in any of your application components using the [`useAnimation()`](api/animations/useAnimation) function. +You can then import and reuse this animation in your application components using the [`useAnimation()`](api/animations/useAnimation) function. @@ -20,7 +20,7 @@ For example, the following snippet exports the animation `trigger`. -From this point, you can import reusable animation variables in your component class. +From this point, you can import reusable animation variables into your component class. For example, the following code snippet imports the `transitionAnimation` variable and uses it via the `useAnimation()` function. diff --git a/adev-ja/src/content/guide/animations/reusable-animations.md b/adev-ja/src/content/guide/animations/reusable-animations.md index d2ff46632..c72f09264 100644 --- a/adev-ja/src/content/guide/animations/reusable-animations.md +++ b/adev-ja/src/content/guide/animations/reusable-animations.md @@ -2,12 +2,12 @@ IMPORTANT: `@angular/animations`パッケージは現在非推奨です。Angularチームは、新しく書くコードのアニメーションには`animate.enter`と`animate.leave`を使ったネイティブCSSの利用を推奨します。詳しくは、新しいenterとleaveの[アニメーションガイド](guide/animations)を参照してください。また、アプリケーションで純粋なCSSアニメーションへの移行を始める方法については、[AngularのAnimationsパッケージからの移行](guide/animations/migration)も参照してください。 -このトピックでは、再利用可能なアニメーションを作成する方法の例をいくつか紹介します。 +このトピックでは、再利用可能なアニメーションを作成する方法の例を紹介します。 ## 再利用可能なアニメーションを作成する {#create-reusable-animations} 再利用可能なアニメーションを作成するには、[`animation()`](api/animations/animation)関数を使って別の`.ts`ファイルにアニメーションを定義し、そのアニメーション定義を`const`のエクスポート変数として宣言します。 -その後、[`useAnimation()`](api/animations/useAnimation)関数を使って、このアニメーションをアプリケーション内の任意のコンポーネントにインポートして再利用できます。 +その後、[`useAnimation()`](api/animations/useAnimation)関数を使って、このアニメーションをアプリケーションのコンポーネントにインポートして再利用できます。 diff --git a/adev-ja/src/content/guide/animations/transition-and-triggers.en.md b/adev-ja/src/content/guide/animations/transition-and-triggers.en.md index 1e03b72ed..7cfe75968 100644 --- a/adev-ja/src/content/guide/animations/transition-and-triggers.en.md +++ b/adev-ja/src/content/guide/animations/transition-and-triggers.en.md @@ -2,7 +2,7 @@ IMPORTANT: The `@angular/animations` package is now deprecated. The Angular team recommends using native CSS with `animate.enter` and `animate.leave` for animations for all new code. Learn more at the new enter and leave [animation guide](guide/animations). Also see [Migrating away from Angular's Animations package](guide/animations/migration) to learn how you can start migrating to pure CSS animations in your apps. -This guide goes into depth on special transition states such as the `*` wildcard and `void`. It shows how these special states are used for elements entering and leaving a view. +This guide goes into depth on special transition states such as the `*` wildcard and `void`. It also shows how these states are used for elements entering and leaving a view. This section also explores multiple animation triggers, animation callbacks, and sequence-based animation using keyframes. ## Predefined states and wildcard matching @@ -99,7 +99,7 @@ Use the aliases `:enter` and `:leave` to target HTML elements that are inserted The `:enter` transition runs when any `*ngIf` or `*ngFor` views are placed on the page, and `:leave` runs when those views are removed from the page. -IMPORTANT: Entering/leaving behaviors can sometime be confusing. +IMPORTANT: Entering/leaving behaviors can sometimes be confusing. As a rule of thumb consider that any element being added to the DOM by Angular passes via the `:enter` transition. Only elements being directly removed from the DOM by Angular pass via the `:leave` transition. For example, an element's view is removed from the DOM because its parent is being removed from the DOM. This example has a special trigger for the enter and leave animation called `myInsertRemoveTrigger`. @@ -239,7 +239,7 @@ You can combine keyframes with `duration`, `delay`, and `easing` within a single ### Keyframes with a pulsation -Use keyframes to create a pulse effect in your animations by defining styles at specific offset throughout the animation. +Use keyframes to create a pulse effect in your animations by defining styles at specific offsets throughout the animation. Here's an example of using keyframes to create a pulse effect: @@ -254,7 +254,7 @@ The code snippet for this animation might look like this. ### Animatable properties and units -Angular animations support builds on top of web animations, so you can animate any property that the browser considers animatable. +Angular animations are built on top of web animations, so you can animate any property that the browser considers animatable. This includes positions, sizes, transforms, colors, borders, and more. The W3C maintains a list of animatable properties on its [CSS Transitions](https://www.w3.org/TR/css-transitions-1) page. diff --git a/adev-ja/src/content/guide/animations/transition-and-triggers.md b/adev-ja/src/content/guide/animations/transition-and-triggers.md index e1d6671c2..9681fbefd 100644 --- a/adev-ja/src/content/guide/animations/transition-and-triggers.md +++ b/adev-ja/src/content/guide/animations/transition-and-triggers.md @@ -2,7 +2,7 @@ IMPORTANT: `@angular/animations`パッケージは現在非推奨です。Angularチームは、新しく書くコードのアニメーションには`animate.enter`と`animate.leave`を使ったネイティブCSSの利用を推奨します。詳しくは、新しいenterとleaveの[アニメーションガイド](guide/animations)を参照してください。また、アプリケーションで純粋なCSSアニメーションへの移行を始める方法については、[AngularのAnimationsパッケージからの移行](guide/animations/migration)も参照してください。 -このガイドでは、`*` ワイルドカードや `void` などの特殊なトランジション状態を詳しく説明します。これらの特殊な状態が、ビューに入る要素やビューから離れる要素でどのように使われるかを示します。 +このガイドでは、`*` ワイルドカードや `void` などの特殊なトランジション状態を詳しく説明します。また、これらの状態が、ビューに入る要素やビューから離れる要素でどのように使われるかも示します。 このセクションでは、複数のアニメーショントリガー、アニメーションコールバック、キーフレームを使ったシーケンスベースのアニメーションも扱います。 ## 事前定義された状態とワイルドカードマッチング {#predefined-states-and-wildcard-matching} @@ -166,6 +166,7 @@ HTMLテンプレート内の要素で `@.disabled` ホストバインディン 1つの要素で複数のアニメーションを個別に無効化できません。 無効化された親の下でも、次のいずれかの方法で個別の子アニメーションを実行できます: + - 親アニメーションは、`query()` 関数を使ってHTMLテンプレートの無効化された領域にある内側の要素を収集できます。 それらの要素は引き続きアニメーションできます。 @@ -187,8 +188,7 @@ HELPFUL: アプリケーション全体でアニメーションを無効にす -HTMLテンプレートでは、アニメーションイベントは `$event` を通じて `@triggerName.start` と `@triggerName.done` として返されます。 -ここで `triggerName` は使用中のトリガー名です。 +HTMLテンプレートでは、アニメーションイベントは `$event` を通じて `@triggerName.start` と `@triggerName.done` として返されます。ここで `triggerName` は使用中のトリガー名です。 この例では、`openClose` トリガーは次のようになります。 diff --git a/adev-ja/src/content/guide/components/content-projection.en.md b/adev-ja/src/content/guide/components/content-projection.en.md index f11feb7f7..5459aead6 100644 --- a/adev-ja/src/content/guide/components/content-projection.en.md +++ b/adev-ja/src/content/guide/components/content-projection.en.md @@ -249,3 +249,29 @@ placeholder, Angular compares against the `ngProjectAs` value instead of the ele ``` `ngProjectAs` supports only static values and cannot be bound to dynamic expressions. + +## Caveats + +### Projected content lives in the parent's view + +Even though projected content is _rendered_ inside the receiving component, it is still owned by the component that declared it. Angular tracks it as part of the parent's view, which has a couple of side effects worth knowing about. + +**Change detection:** Projected content is checked when the _parent_ runs change detection. If the receiving component uses `OnPush`, Angular can skip checking that component's own template — but it won't skip the projected content, because that belongs to the parent. + +```angular-html + + + + + +``` + +**Dependency injection:** Projected content gets its dependencies from the parent's injector, not from the receiving component's `viewProviders`. See [Providers and viewProviders](guide/di/hierarchical-dependency-injection) for details. + +### Some library components don't support projected children + +Certain components — menus, tabs, lists — use `ContentChildren` to find their children and wire up behavior like keyboard navigation, focus management, or ARIA attributes. They're written assuming they own their children directly, so projecting external content into them tends to break things in subtle ways. + +For example, wrapping `` elements in an extra layer and projecting them into `` can silently break keyboard navigation and screen reader support. The query still finds the items, but the internal setup that makes them interactive may not work correctly when the items come from a different view context. + +If a library component manages its children's behavior, check its docs before reaching for content projection — it may not be supported. diff --git a/adev-ja/src/content/guide/components/content-projection.md b/adev-ja/src/content/guide/components/content-projection.md index ff4496994..cfb307df5 100644 --- a/adev-ja/src/content/guide/components/content-projection.md +++ b/adev-ja/src/content/guide/components/content-projection.md @@ -249,3 +249,29 @@ Angularは要素のIDではなく`ngProjectAs`の値と比較します。 ``` `ngProjectAs`は静的な値のみをサポートし、動的な式にはバインドできません。 + +## 注意点 {#caveats} + +### 投影されたコンテンツは親のビューに属する {#projected-content-lives-in-the-parents-view} + +投影されたコンテンツは受け取り側のコンポーネント内で*レンダリング*されますが、それでもそれを宣言したコンポーネントが所有しています。Angularは投影されたコンテンツを親のビューの一部として追跡するため、知っておくべき副作用がいくつかあります。 + +**変更検知:** 投影されたコンテンツは、*親*が変更検知を実行する際にチェックされます。受け取り側のコンポーネントが`OnPush`を使用している場合、Angularはそのコンポーネント自身のテンプレートのチェックをスキップできますが、投影されたコンテンツは親に属するためスキップしません。 + +```angular-html + + + + + +``` + +**依存性の注入:** 投影されたコンテンツは、受け取り側のコンポーネントの`viewProviders`ではなく、親のインジェクターから依存性を取得します。詳細は[Providers and viewProviders](guide/di/hierarchical-dependency-injection)を参照してください。 + +### 一部のライブラリコンポーネントは投影された子要素をサポートしない {#some-library-components-dont-support-projected-children} + +メニュー、タブ、リストといった特定のコンポーネントは、`ContentChildren`を使って子要素を見つけ、キーボードナビゲーション、フォーカス管理、ARIA属性などの動作を組み込みます。これらは子要素を直接所有していることを前提に書かれているため、外部のコンテンツを投影すると、目に見えにくい形で壊れることがよくあります。 + +たとえば、``要素を追加のレイヤーで包んで``に投影すると、キーボードナビゲーションやスクリーンリーダーのサポートが密かに壊れる可能性があります。クエリ自体はアイテムを見つけられますが、それらをインタラクティブにする内部のセットアップは、アイテムが異なるビューコンテキストから来た場合に正しく動作しないことがあります。 + +ライブラリコンポーネントが子要素の動作を管理している場合は、コンテンツ投影に手を伸ばす前にそのドキュメントを確認してください。サポートされていない可能性があります。 diff --git a/adev-ja/src/content/guide/components/inheritance.en.md b/adev-ja/src/content/guide/components/inheritance.en.md index 78dbda57c..163e305dd 100644 --- a/adev-ja/src/content/guide/components/inheritance.en.md +++ b/adev-ja/src/content/guide/components/inheritance.en.md @@ -65,7 +65,25 @@ and their own. ### Forwarding injected dependencies -If a base class injects dependencies as constructor parameters, the child class must explicitly class these dependencies to `super`. +When a base class uses `inject()` as a property initializer, the child class inherits the property automatically. No `super` forwarding is needed. + +```ts +@Component({ + /*...*/ +}) +export class ListboxBase { + protected element = inject(ElementRef); +} + +@Component({ + /*...*/ +}) +export class CustomListbox extends ListboxBase { + // `element` is inherited from `ListboxBase`. +} +``` + +If a base class injects dependencies as constructor parameters, the child class must explicitly pass these dependencies to `super`. ```ts @Component({ diff --git a/adev-ja/src/content/guide/components/inheritance.md b/adev-ja/src/content/guide/components/inheritance.md index 6b815c5b5..72dd9893d 100644 --- a/adev-ja/src/content/guide/components/inheritance.md +++ b/adev-ja/src/content/guide/components/inheritance.md @@ -65,7 +65,25 @@ export class CustomListbox extends ListboxBase { ### 注入された依存性の転送 -もし基底クラスがコンストラクターのパラメーターとして依存性を注入している場合、子クラスではその依存性を明示的にsuper()に渡す必要があります。 +基底クラスが`inject()`をプロパティイニシャライザーとして使用する場合、子クラスはそのプロパティを自動的に継承します。`super`への転送は不要です。 + +```ts +@Component({ + /*...*/ +}) +export class ListboxBase { + protected element = inject(ElementRef); +} + +@Component({ + /*...*/ +}) +export class CustomListbox extends ListboxBase { + // `element` is inherited from `ListboxBase`. +} +``` + +もし基底クラスがコンストラクターのパラメーターとして依存性を注入している場合、子クラスではその依存性を明示的に`super`に渡す必要があります。 ```ts @Component({ diff --git a/adev-ja/src/content/guide/components/styling.en.md b/adev-ja/src/content/guide/components/styling.en.md index b2bad65c8..456f767b7 100644 --- a/adev-ja/src/content/guide/components/styling.en.md +++ b/adev-ja/src/content/guide/components/styling.en.md @@ -34,8 +34,8 @@ render an Angular component, the framework automatically includes its associated lazy-loading a component. Angular works with any tool that outputs CSS, -including [Sass](https://sass-lang.com), [less](https://lesscss.org), -and [stylus](https://stylus-lang.com). +including [Sass](https://sass-lang.com), [Less](https://lesscss.org), +and [Stylus](https://stylus-lang.com). ## Style scoping diff --git a/adev-ja/src/content/guide/components/styling.md b/adev-ja/src/content/guide/components/styling.md index 896adad0c..9fde2c00e 100644 --- a/adev-ja/src/content/guide/components/styling.md +++ b/adev-ja/src/content/guide/components/styling.md @@ -34,7 +34,7 @@ Angularコンポーネントをレンダリングすると、フレームワー これは、コンポーネントを遅延読み込みする場合でも同様です。 Angularは、[Sass](https://sass-lang.com)、 -[less](https://lesscss.org)、[stylus](https://stylus-lang.com)など、 +[Less](https://lesscss.org)、[Stylus](https://stylus-lang.com)など、 CSSを出力するすべてのツールと連携します。 ## スタイルのスコープ {#style-scoping} diff --git a/adev-ja/src/content/guide/di/creating-and-using-services.en.md b/adev-ja/src/content/guide/di/creating-and-using-services.en.md index a9cdc0532..dfbfb4ff6 100644 --- a/adev-ja/src/content/guide/di/creating-and-using-services.en.md +++ b/adev-ja/src/content/guide/di/creating-and-using-services.en.md @@ -1,20 +1,20 @@ # Creating and using services -Services are reusable pieces of code that can be shared across your Angular application. They typically handle data fetching, business logic, or other functionality that multiple components need to access. +Services are reusable pieces of code that you can share across your Angular application. You commonly use them to handle data fetching, business logic, or other functionality that multiple components need to access. ## Creating a service -You can create a service with the [Angular CLI](tools/cli) with the following command: +You can create a service using the [Angular CLI](tools/cli) with the following command: ```bash ng generate service CUSTOM_NAME ``` -This creates a dedicated `CUSTOM_NAME.ts` file in your `src` directory. +This command creates a dedicated `CUSTOM_NAME.ts` file in your `src` directory. -You can also manually create a service by adding the `@Injectable()` decorator to a TypeScript class. This tells Angular that the service can be injected as a dependency. +You can also manually create a service by adding the `@Injectable()` decorator to a TypeScript class. This tells Angular that you can use the class as an injectable dependency. -Here is an example of a service that allows users to add and request data: +The following example defines a service that allows users to add and retrieve data: ```ts // 📄 src/app/basic-data-store.ts @@ -38,9 +38,9 @@ export class BasicDataStore { When you use `@Injectable({ providedIn: 'root' })` in your service, Angular: -- **Creates a single instance** (singleton) for your entire application -- **Makes it available everywhere** without any additional configuration -- **Enables tree-shaking** so the service is only included in your JavaScript bundle if it's actually used +- **Creates a single instance** (a singleton) for the entire application +- **Makes it available throughout your application** without additional configuration +- **Enables tree-shaking** so Angular only includes the service in your JavaScript bundle if you actually use it This is the recommended approach for most services. @@ -93,7 +93,7 @@ export class BasicDataStore { ## Next steps -While `providedIn: 'root'` covers most use cases, Angular offers additional ways to provide services for specialized scenarios: +While `providedIn: 'root'` covers most use cases, Angular also provides additional ways you can configure services for more specialized scenarios: - **Component-specific instances** - When components need their own isolated service instances - **Manual configuration** - For services that require runtime configuration diff --git a/adev-ja/src/content/guide/di/creating-and-using-services.md b/adev-ja/src/content/guide/di/creating-and-using-services.md index 742fcc229..c16d2928a 100644 --- a/adev-ja/src/content/guide/di/creating-and-using-services.md +++ b/adev-ja/src/content/guide/di/creating-and-using-services.md @@ -1,20 +1,20 @@ # サービスの作成と使用 -サービスは、Angularアプリケーション全体で共有できる再利用可能なコードです。サービスは通常、複数のコンポーネントがアクセスする必要のあるデータ取得、ビジネスロジック、またはその他の機能を扱います。 +サービスは、Angularアプリケーション全体で共有できる再利用可能なコードです。一般的に、複数のコンポーネントがアクセスする必要のあるデータ取得、ビジネスロジック、またはその他の機能を扱うために使用します。 ## サービスの作成 {#creating-a-service} -次のコマンドで[Angular CLI](tools/cli)を使用してサービスを作成できます。 +次のコマンドで[Angular CLI](tools/cli)を使ってサービスを作成できます。 ```bash ng generate service CUSTOM_NAME ``` -これにより、`src`ディレクトリに専用の`CUSTOM_NAME.ts`ファイルが作成されます。 +このコマンドにより、`src`ディレクトリに専用の`CUSTOM_NAME.ts`ファイルが作成されます。 -TypeScriptクラスに`@Injectable()`デコレーターを追加して、手動でサービスを作成できます。これにより、そのサービスが依存性として注入可能であることがAngularに伝播します。 +TypeScriptクラスに`@Injectable()`デコレーターを追加して、手動でサービスを作成する方法もあります。これにより、そのクラスを注入可能な依存性として使用できることがAngularに伝播します。 -以下は、ユーザーがデータを追加したり要求したりできるサービスの例です。 +次の例では、ユーザーがデータを追加したり取得したりできるサービスを定義しています。 ```ts // 📄 src/app/basic-data-store.ts @@ -39,8 +39,8 @@ export class BasicDataStore { サービスで`@Injectable({ providedIn: 'root' })`を使用すると、Angularは次のことを行います: - **アプリケーション全体で単一のインスタンス** (シングルトン) を作成します -- **追加の設定なしでどこでも利用可能**にします -- **ツリーシェイキングを有効にし**、サービスが実際に使用される場合にのみJavaScriptバンドルに含まれるようにします +- **アプリケーション全体で利用可能**にします (追加の設定は不要です) +- **ツリーシェイキングを有効にし**、実際に使用される場合にのみAngularがJavaScriptバンドルにサービスを含めるようにします これは、ほとんどのサービスで推奨されるアプローチです。 @@ -93,7 +93,7 @@ export class BasicDataStore { ## 次のステップ {#next-steps} -`providedIn: 'root'`はほとんどのユースケースをカバーしていますが、Angularは特殊なシナリオのためにサービスを提供するための追加の方法を提供しています: +`providedIn: 'root'`はほとんどのユースケースをカバーしていますが、Angularは、より特殊なシナリオに向けてサービスを設定する追加の方法も提供しています: - **コンポーネント固有のインスタンス** - コンポーネントが独自の独立したサービスインスタンスを必要とする場合 - **手動設定** - 実行時の設定が必要なサービス向け 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 30123b8a6..7776a6091 100644 --- a/adev-ja/src/content/guide/di/creating-injectable-service.md +++ b/adev-ja/src/content/guide/di/creating-injectable-service.md @@ -1,21 +1,21 @@ # Creating an injectable service -Service is a broad category encompassing any value, function, or feature that an application needs. -A service is typically a class with a narrow, well-defined purpose. -A component is one type of class that can use DI. +A service is a broad category that encompasses any value, function, or feature that your application needs. +A service is typically a class with a focused and well-defined purpose. +A component is one type of class that you can use with dependency injection (DI). -Angular distinguishes components from services to increase modularity and reusability. -By separating a component's view-related features from other kinds of processing, you can make your component classes lean and efficient. +Angular distinguishes components from services to improve modularity and reusability. +By separating a component's view-related features from other types of processing, you can keep your component classes lean and efficient. -Ideally, a component's job is to enable the user experience and nothing more. +Ideally, your component's responsibility is to enable the user experience and nothing more. A component should present properties and methods for data binding, to mediate between the view (rendered by the template) and the application logic (which often includes some notion of a model). -A component can delegate certain tasks to services, such as fetching data from the server, validating user input, or logging directly to the console. -By defining such processing tasks in an injectable service class, you make those tasks available to any component. -You can also make your application more adaptable by configuring different providers of the same kind of service, as appropriate in different circumstances. +You can delegate tasks from a component to services, such as fetching data from a server, validating user input, or logging to the console. +By defining such tasks in an injectable service class, you make those capabilities available to any component. +You can also make your application more adaptable by configuring different providers for the same type of service based on different circumstances. -Angular does not enforce these principles. -Angular helps you follow these principles by making it easy to factor your application logic into services and make those services available to components through DI. +Angular does not strictly enforce these principles. +Angular helps you follow these principles by making it easy to organize your application logic into services and make those services available to components through DI. ## Service examples @@ -82,7 +82,7 @@ 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. +The `providedIn: 'root'` metadata specifies that the `HeroService` is available throughout your application. Add a `getHeroes()` method that returns the heroes from `mock.heroes.ts` to get the hero mock data: @@ -106,7 +106,7 @@ For clarity and maintainability, it is recommended that you define components an ## Injecting services -To inject a service as a dependency into a component, you can declare a class field representing the dependency and use Angular's [`inject`](/api/core/inject) function to initialize it. +To inject a service into a component, declare a class field for the dependency and use Angular's [`inject`](/api/core/inject) function to initialize it. The following example specifies the `HeroService` in the `HeroList`. The type of `heroService` is `HeroService`. @@ -125,7 +125,7 @@ It is also possible to inject a service into a component using the component's c constructor(private heroService: HeroService) ``` -The [`inject`](/api/core/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. +The [`inject`](/api/core/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 both cases, you can only inject a dependency within a valid [injection context](guide/di/dependency-injection-context), typically during the construction or initialization of a component. ## Injecting services in other services diff --git a/adev-ja/src/content/guide/di/dependency-injection-context.en.md b/adev-ja/src/content/guide/di/dependency-injection-context.en.md index e0b6f7aec..f6ce92a02 100644 --- a/adev-ja/src/content/guide/di/dependency-injection-context.en.md +++ b/adev-ja/src/content/guide/di/dependency-injection-context.en.md @@ -1,24 +1,24 @@ # Injection context -The dependency injection (DI) system relies internally on a runtime context where the current injector is available. +The dependency injection (DI) system relies on a runtime context where the current injector is available. -This means that injectors can only work when code is executed in such a context. +This means that injectors only work when you execute code within this context. -The injection context is available in these situations: +You have an injection context available in the following situations: -- During construction (via the `constructor`) of a class being instantiated by the DI system, such as an `@Injectable` or `@Component`. -- In the initializer for fields of such classes. +- During construction (via the `constructor`) of a class instantiated by the DI system, such as an `@Injectable` or `@Component`. +- In field initializers of such classes. - In the factory function specified for `useFactory` of a `Provider` or an `@Injectable`. - In the `factory` function specified for an `InjectionToken`. - Within a stack frame that runs in an injection context. -Knowing when you are in an injection context will allow you to use the [`inject`](api/core/inject) function to inject instances. +Knowing when you are in an injection context allows you to use the [`inject`](api/core/inject) function to retrieve dependencies. NOTE: For basic examples of using `inject()` in class constructors and field initializers, see the [overview guide](/guide/di#where-can-inject-be-used). ## Stack frame in context -Some APIs are designed to be run in an injection context. This is the case, for example, with router guards. This allows the use of [`inject`](api/core/inject) within the guard function to access a service. +Some APIs are designed to run within an injection context. This is the case, for example, with router guards. This allows you to use [`inject`](api/core/inject) within the guard function to access services. Here is an example for `CanActivateFn` @@ -33,8 +33,8 @@ const canActivateTeam: CanActivateFn = ( ## Run within an injection context -When you want to run a given function in an injection context without already being in one, you can do so with `runInInjectionContext`. -This requires access to a given injector, like the `EnvironmentInjector`, for example: +If you need to run a function within an injection context without already being in one, you can use `runInInjectionContext`. +This requires access to an injector, such as the `EnvironmentInjector`: ```ts {highlight: [9], header"hero.service.ts"} @Injectable({ @@ -51,11 +51,11 @@ export class HeroService { } ``` -Note that [`inject`](/api/core/inject) will return an instance only if the injector can resolve the required token. +Note that [`inject`](/api/core/inject) returns an instance only if the injector can resolve the requested token. ## Asserts the context -Angular provides the `assertInInjectionContext` helper function to assert that the current context is an injection context and throws a clear error if not. Pass a reference to the calling function so the error message points to the correct API entry point. This produces a clearer, more actionable message than the default generic injection error. +Angular provides the `assertInInjectionContext` helper function to verify that the current context is an injection context and throw a clear error if it is not. Pass a reference to the calling function so the error message points to the correct API entry point. This produces a clearer, more actionable message than the default generic injection error. ```ts import {ElementRef, assertInInjectionContext, inject} from '@angular/core'; @@ -86,4 +86,4 @@ export class PreviewCard { ## Using DI outside of a context -Calling [`inject`](api/core/inject) or calling `assertInInjectionContext` outside of an injection context will throw [error NG0203](/errors/NG0203). +If you call [`inject`](api/core/inject) or `assertInInjectionContext` outside of an injection context, Angular throws [error NG0203](/errors/NG0203). diff --git a/adev-ja/src/content/guide/di/dependency-injection-context.md b/adev-ja/src/content/guide/di/dependency-injection-context.md index e23ba8eb6..fa8e7e02d 100644 --- a/adev-ja/src/content/guide/di/dependency-injection-context.md +++ b/adev-ja/src/content/guide/di/dependency-injection-context.md @@ -1,24 +1,24 @@ # 注入コンテキスト -依存性の注入 (DI) システムは、内部的に現在のインジェクターが利用可能なランタイムコンテキストに依存しています。 +依存性の注入 (DI) システムは、現在のインジェクターが利用可能なランタイムコンテキストに依存しています。 -これは、インジェクターは、このようなコンテキストでコードが実行される場合にのみ動作することを意味します。 +これは、このコンテキスト内でコードを実行する場合にのみインジェクターが動作することを意味します。 -注入コンテキストは、次の状況で使用できます。 +注入コンテキストは、次の状況で利用できます。 - DIシステムによってインスタンス化されるクラス(`@Injectable` または `@Component` など)の構築(`constructor` を使用)中。 -- このようなクラスのフィールドのイニシャライザー。 +- そのようなクラスのフィールドイニシャライザー内。 - `Provider` または `@Injectable` の `useFactory` に指定されたファクトリー関数。 - `InjectionToken` に指定された `factory` 関数。 - 注入コンテキストで実行されるスタックフレーム内。 -注入コンテキストにいるかどうかを知ることで、[`inject`](api/core/inject) 関数を使用してインスタンスを注入できます。 +注入コンテキストにいるかどうかを知ることで、[`inject`](api/core/inject) 関数を使用して依存性を取得できます。 NOTE: クラスコンストラクターとフィールドイニシャライザーでの `inject()` の基本的な使用例については、[概要ガイド](/guide/di#where-can-inject-be-used)を参照してください。 ## コンテキスト内のスタックフレーム -一部のAPIは、注入コンテキストで実行されるように設計されています。これは、たとえば、ルーターガードの場合です。これにより、ガード関数内で [`inject`](api/core/inject) を使用してサービスにアクセスできます。 +一部のAPIは、注入コンテキスト内で実行されるように設計されています。これは、たとえば、ルーターガードの場合です。これにより、ガード関数内で [`inject`](api/core/inject) を使用してサービスにアクセスできます。 `CanActivateFn` の例を次に示します。 @@ -33,8 +33,8 @@ const canActivateTeam: CanActivateFn = ( ## 注入コンテキスト内で実行する {#run-within-an-injection-context} -すでに注入コンテキスト内にいない状態で、特定の関数を注入コンテキスト内で実行したい場合は、`runInInjectionContext` を使用できます。 -これには、たとえば `EnvironmentInjector` のような特定のインジェクターへのアクセスが必要です。 +すでに注入コンテキスト内にいない状態で関数を注入コンテキスト内で実行する必要がある場合は、`runInInjectionContext` を使用できます。 +これには、`EnvironmentInjector` のようなインジェクターへのアクセスが必要です。 ```ts {highlight: [9], header"hero.service.ts"} @Injectable({ @@ -51,11 +51,11 @@ export class HeroService { } ``` -[`inject`](/api/core/inject) は、インジェクターが要求されたトークンを解決できる場合にのみインスタンスを返します。 +[`inject`](/api/core/inject) は、インジェクターが要求されたトークンを解決できる場合にのみインスタンスを返すことに注意してください。 ## コンテキストのアサート {#asserts-the-context} -Angularは、現在のコンテキストが注入コンテキストであることをアサートし、そうでない場合は明確なエラーをスローするための `assertInInjectionContext` ヘルパー関数を提供します。呼び出し元の関数への参照を渡すと、エラーメッセージが正しいAPIエントリーポイントを指し示すようになります。これにより、デフォルトの汎用的な注入エラーよりも明確で実用的なメッセージが生成されます。 +Angularは、現在のコンテキストが注入コンテキストであることを検証し、そうでない場合は明確なエラーをスローするための `assertInInjectionContext` ヘルパー関数を提供します。呼び出し元の関数への参照を渡すと、エラーメッセージが正しいAPIエントリーポイントを指し示すようになります。これにより、デフォルトの汎用的な注入エラーよりも明確で実用的なメッセージが生成されます。 ```ts import {ElementRef, assertInInjectionContext, inject} from '@angular/core'; @@ -86,4 +86,4 @@ export class PreviewCard { ## コンテキスト外での DI の使用 -注入コンテキスト外で [`inject`](api/core/inject) を呼び出したり、`assertInInjectionContext` を呼び出したりすると、[エラー NG0203](/errors/NG0203) がスローされます。 +注入コンテキスト外で [`inject`](api/core/inject) や `assertInInjectionContext` を呼び出すと、Angularは [エラー NG0203](/errors/NG0203) をスローします。 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 5d866b3cf..de0b7f5dc 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 @@ -1,15 +1,15 @@ # DI in action -This guide explores additional features of dependency injection in Angular. +This guide explores additional features of dependency injection (DI) in Angular. NOTE: For comprehensive coverage of InjectionToken and custom providers, see the [defining dependency providers guide](guide/di/defining-dependency-providers#injection-tokens). ## Inject the component's DOM element -Although developers strive to avoid it, some visual effects and third-party tools require direct DOM access. -As a result, you might need to access a component's DOM element. +Although developers generally avoid it, some visual effects and third-party tools require you to access the DOM directly. +In such cases, you may 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: +Angular exposes the underlying DOM element of a `@Component` or `@Directive` through injection using the `ElementRef` token: ```ts {highlight:[7]} import {Directive, ElementRef, inject} from '@angular/core'; @@ -28,7 +28,7 @@ export class HighlightDirective { ## Inject the host element's tag name -When you need the tag name of a host element, inject it using the `HOST_TAG_NAME` token. +To get the tag name of a host element, inject it using the `HOST_TAG_NAME` token. ```ts import {Directive, HOST_TAG_NAME, inject} from '@angular/core'; @@ -59,19 +59,19 @@ NOTE: If the host element might not have a tag name (e.g., `ng-container` or `ng ## Resolve circular dependencies with a forward reference -The order of class declaration matters in TypeScript. -You can't refer directly to a class until it's been defined. +In TypeScript, the order of class declarations matters. +You cannot reference a class directly until you define it. This isn't usually a problem, especially if you adhere to the recommended _one class per file_ rule. -But sometimes circular references are unavoidable. -For example, when class 'A' refers to class 'B' and 'B' refers to 'A', one of them has to be defined first. +However, in some cases, circular references are unavoidable. +For example, if class 'A' refers to class 'B' and class 'B' refers to class 'A', one of them must be defined first. The Angular `forwardRef()` function creates an _indirect_ reference that Angular can resolve later. You face a similar problem when a class makes _a reference to itself_. 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`. +Such circular references can be resolved using `forwardRef`. ```typescript {header: 'app.component.ts', highlight: [4]} providers: [ 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 f1b419e12..952f7bb82 100644 --- a/adev-ja/src/content/guide/di/di-in-action.md +++ b/adev-ja/src/content/guide/di/di-in-action.md @@ -1,15 +1,15 @@ # DIの実践 -このガイドでは、Angularにおける依存性の注入の追加機能について説明します。 +このガイドでは、Angularにおける依存性の注入 (DI) の追加機能について説明します。 NOTE: InjectionTokenとカスタムプロバイダーの包括的な説明については、[依存性プロバイダーの定義ガイド](guide/di/defining-dependency-providers#injection-tokens)を参照してください。 ## コンポーネントのDOM要素を注入する {#inject-the-components-dom-element} -開発者は避けるように努めていても、一部の視覚効果とサードパーティツールでは、直接DOMにアクセスする必要があります。 -そのため、コンポーネントのDOM要素にアクセスする必要がある場合があります。 +一般的に開発者は避けるものですが、一部の視覚効果やサードパーティツールでは、直接DOMにアクセスする必要があります。 +そのような場合には、コンポーネントのDOM要素にアクセスする必要が生じることがあります。 -Angularは、`@Component`または`@Directive`の基になる要素を、`ElementRef`インジェクショントークンを使用してインジェクションすることで公開します。 +Angularは、`@Component`または`@Directive`の基になるDOM要素を、`ElementRef`トークンを使用したインジェクションを通じて公開します。 ```ts {highlight:[7]} import {Directive, ElementRef, inject} from '@angular/core'; @@ -28,7 +28,7 @@ export class HighlightDirective { ## ホスト要素のタグ名を注入する {#inject-the-host-elements-tag-name} -ホスト要素のタグ名が必要な場合は、`HOST_TAG_NAME`トークンを使用して注入します。 +ホスト要素のタグ名を取得するには、`HOST_TAG_NAME`トークンを使用して注入します。 ```ts import {Directive, HOST_TAG_NAME, inject} from '@angular/core'; @@ -60,18 +60,18 @@ NOTE: ホスト要素がタグ名を持たない可能性がある場合(例: ## 前方参照を使用して循環した依存関係を解決する {#resolve-circular-dependencies-with-a-forward-reference} TypeScriptでは、クラスの宣言順序が重要です。 -定義されるまでは、クラスを直接参照できません。 +クラスは定義するまで直接参照できません。 これは、特に推奨される_1ファイルにつき1クラス_ルールに従っている場合は通常問題ありません。 -しかし、循環参照は避けられない場合があります。 -たとえば、クラス'A'がクラス'B'を参照し、'B'が'A'を参照する場合、いずれか一方を最初に定義する必要があります。 +しかし、場合によっては循環参照が避けられないことがあります。 +たとえば、クラス'A'がクラス'B'を参照し、クラス'B'がクラス'A'を参照する場合、いずれか一方を最初に定義する必要があります。 Angularの`forwardRef()`関数は、Angularが後で解決できる_間接的な_参照を作成します。 クラスが_自分自身を参照する_場合にも、同様の問題が発生します。 たとえば、`providers`配列内です。 `providers`配列は、`@Component()`デコレーター関数のプロパティであり、クラス定義の前に表示される必要があります。 -`forwardRef`を使用して、このような循環参照を解消できます。 +このような循環参照は`forwardRef`を使用して解決できます。 ```typescript {header: 'app.component.ts', highlight: [4]} providers: [ 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 ccc5bf0b3..13c679ffa 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 @@ -634,7 +634,7 @@ It doesn't need to continue searching the `ElementInjector` tree, nor does it ne ### `providers` vs. `viewProviders` The `viewProviders` field is conceptually similar to `providers`, but there is one notable difference. -Configured providers in `viewProviders` are not visible to projected content that ends up as a logical children of the component. +Providers in `viewProviders` are only visible inside the component's own view — content projected into the component via `` cannot see them. To see the difference between using `providers` and `viewProviders`, add another component to the example and call it `Inspector`. `Inspector` will be a child of the `Child`. @@ -705,6 +705,11 @@ These four bindings demonstrate the difference between `providers` and `viewProv Remember that the dog emoji 🐶 is declared inside the `<#VIEW>` of `Child` and isn't visible to the projected content. Instead, the projected content sees the whale 🐳. +You might wonder why the projected `` can still see 🐳 from `App`'s `viewProviders`. +The reason is that Angular DI tracks **where a component was declared**, not where it ends up being rendered. +`` lives in `App`'s template — inside `App`'s `<#VIEW>` — so `App`'s `viewProviders` are fair game. +Projecting it into `Child` cuts off access to `Child`'s `viewProviders` (🐶), but `App`'s providers (🐳) are still reachable up the tree. + However, in the next output section though, the `Inspector` is an actual child component of `Child`, `Inspector` is inside the `<#VIEW>`, so when it asks for the `AnimalService`, it sees the dog 🐶. The `AnimalService` in the logical tree would look like this: @@ -741,8 +746,10 @@ The `AnimalService` in the logical tree would look like this: ``` -The projected content of `` sees the whale 🐳, not the dog 🐶, because the dog 🐶 is inside the `` `<#VIEW>`. -The `` can only see the dog 🐶 if it is also within the `<#VIEW>`. +The projected `` gets 🐳 because 🐶 belongs to `Child`'s view and projected content can't reach it. +🐳 is accessible because `` was declared in `App`'s template, so it can still walk up to `App`'s `viewProviders`. + +The `` that lives directly inside `Child`'s template (not projected) gets 🐶 — it's inside the `<#VIEW>`, so no boundary to cross. ### Visibility of provided tokens 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 51745375b..053b84909 100644 --- a/adev-ja/src/content/guide/di/hierarchical-dependency-injection.md +++ b/adev-ja/src/content/guide/di/hierarchical-dependency-injection.md @@ -634,7 +634,7 @@ Emoji from AnimalService: 🐶 ### `providers` と `viewProviders` の違い {#providers-vs-viewproviders} `viewProviders` フィールドは、概念的には `providers` と似ていますが、1つの顕著な違いがあります。 -`viewProviders` で構成されたプロバイダーは、コンポーネントの論理的な子になる投影されたコンテンツには可視ではありません。 +`viewProviders` のプロバイダーは、コンポーネント自身のビュー内でのみ可視です。`` を介してコンポーネントに投影されたコンテンツからは、これらのプロバイダーは見えません。 `providers` と `viewProviders` の違いを確認するために、別のコンポーネントを例に追加して、 `Inspector` と呼びます。 `Inspector` は、 `Child` の子になります。 @@ -705,6 +705,11 @@ Emoji from AnimalService: 🐶 犬の絵文字 🐶 は、 `Child` の `<#VIEW>` 内に宣言され、投影されたコンテンツには可視ではないことを覚えておいてください。 代わりに、投影されたコンテンツには、クジラ 🐳 が表示されます。 +なぜ投影された `` が、`App` の `viewProviders` から 🐳 を依然として見られるのか疑問に思うかもしれません。 +その理由は、Angular DIは**コンポーネントが宣言された場所**を追跡し、最終的にレンダリングされる場所は追跡しないためです。 +`` は `App` のテンプレート内、つまり `App` の `<#VIEW>` 内にあるので、`App` の `viewProviders` は利用可能です。 +`Child` に投影することで、`Child` の `viewProviders` (🐶) へのアクセスは遮断されますが、`App` のプロバイダー (🐳) はツリーを上に辿って引き続き到達可能です。 + ただし、次の出力セクションでは `Inspector` は `Child` の実際の子コンポーネントです。そして `Inspector` は `<#VIEW>` の内側にあるため、 `AnimalService` を要求すると、犬 🐶 が表示されます。 論理ツリー内の `AnimalService` は、次のようになります。 @@ -741,8 +746,10 @@ Emoji from AnimalService: 🐶 ``` -`` の投影されたコンテンツには、クジラ 🐳 が表示され、犬 🐶 は表示されません。これは、犬 🐶 が `` の `<#VIEW>` の内側にあるためです。 -`` は、 `<#VIEW>` の内側にある場合にのみ、犬 🐶 を表示できます。 +投影された `` がクジラ 🐳 を取得するのは、犬 🐶 が `Child` のビューに属しており、投影されたコンテンツからは到達できないためです。 +クジラ 🐳 にアクセスできるのは、`` が `App` のテンプレートで宣言されているため、`App` の `viewProviders` まで辿れるからです。 + +一方、`Child` のテンプレート内に直接置かれた(投影されていない)`` は、犬 🐶 を取得します。これは `<#VIEW>` の内側にあるため、超えるべき境界がないからです。 ### 提供されたトークンの可視性 {#visibility-of-provided-tokens} diff --git a/adev-ja/src/content/guide/di/overview.en.md b/adev-ja/src/content/guide/di/overview.en.md index 879dd8e8a..a6c9dc9bc 100644 --- a/adev-ja/src/content/guide/di/overview.en.md +++ b/adev-ja/src/content/guide/di/overview.en.md @@ -1,38 +1,38 @@ -Dependency Injection (DI) is a design pattern used to organize and share code across an application. +Dependency Injection (DI) is a design pattern you use to organize and share code across your application by supplying dependencies to a class instead of creating them inside it. TIP: Check out Angular's [Essentials](essentials/dependency-injection) before diving into this comprehensive guide. -As an application grows, developers often need to reuse and share features across different parts of the codebase. [Dependency Injection (DI)](https://en.wikipedia.org/wiki/Dependency_injection) is a design pattern used to organize and share code across an application by allowing you to "inject" features into different parts. +As an application grows, developers often need to reuse and share functionality across different parts of the codebase. [Dependency Injection (DI)](https://en.wikipedia.org/wiki/Dependency_injection) helps you achieve this by allowing you to provide dependencies to a class instead of creating them directly inside it. This makes different parts of the application more reusable and easier to manage. Dependency injection is a popular pattern because it allows developers to address common challenges such as: -- **Improved code maintainability**: Dependency injection allows cleaner separation of concerns which enables easier refactoring and reducing code duplication. -- **Scalability**: Modular functionality can be reused across multiple contexts and allows for easier scaling. -- **Better testing**: DI allows unit tests to easily use [test doubles](https://en.wikipedia.org/wiki/Test_double) for situations when using a real implementation is not practical. +- **Improved code maintainability**: Dependency injection promotes a clear separation of concerns, making code easier to refactor and reducing duplication. +- **Scalability**: You can reuse modular functionality across different parts of an application, making it easier to scale. +- **Better testing**: DI allows unit tests to use [test doubles](https://en.wikipedia.org/wiki/Test_double) in place of real implementations when needed. ## How does dependency injection work in Angular? -A dependency is any object, value, function or service that a class needs to work but does not create itself. In other words, it creates a relationship between different parts of your application since it wouldn't work without the dependency. +A dependency is any object, value, function, or service that a class requires to work but does not create itself. Instead, you provide it from the outside, creating a clear relationship between different parts of the application. -There are two ways that code interacts with any dependency injection system: +You interact with a dependency injection system in two main ways: -- Code can _provide_, or make available, values. -- Code can _inject_, or ask for, those values as dependencies. +- You can _provide_, or make available, values. +- You can _inject_, or ask for, those values as dependencies. -"Values," in this context, can be any JavaScript value, including objects and functions. Common types of injected dependencies include: +In this context, "values" can refer to any JavaScript value, including objects, functions, or class instances. Common types of injected dependencies include: - **Configuration values**: Environment-specific constants, API URLs, feature flags, etc. - **Factories**: Functions that create objects or values based on runtime conditions - **Services**: Classes that provide common functionality, business logic, or state -Angular components and directives automatically participate in DI, meaning that they can inject dependencies _and_ they are available to be injected. +Angular components and directives automatically participate in DI, meaning that you can inject dependencies into them and make them available for injection. ## What are services? -An Angular _service_ is a TypeScript class decorated with `@Injectable`, which makes an instance of the class available to be injected as a dependency. Services are the most common way of sharing data and functionality across an application. +An Angular _service_ is a TypeScript class decorated with `@Injectable`, which allows you to inject an instance of the class as a dependency. Services are the most common way of sharing data and functionality across an application. Common types of services include: diff --git a/adev-ja/src/content/guide/di/overview.md b/adev-ja/src/content/guide/di/overview.md index 4503768c0..947b1e315 100644 --- a/adev-ja/src/content/guide/di/overview.md +++ b/adev-ja/src/content/guide/di/overview.md @@ -1,38 +1,38 @@ -依存性の注入 (DI) は、アプリケーション全体でコードを整理し共有するために使用される設計パターンです。 +依存性の注入 (DI) は、依存性をクラスの内部で生成する代わりに供給することで、アプリケーション全体でコードを整理し共有するために使用する設計パターンです。 TIP: この包括的なガイドに取り組む前に、Angularの [基本ガイド](essentials/dependency-injection) を確認してください。 -アプリケーションが成長するにつれて、開発者はコードベースのさまざまな部分で機能を再利用し共有する必要がでてきます。[依存性の注入 (DI)](https://en.wikipedia.org/wiki/Dependency_injection) は、さまざまな部分に機能を「注入」できるようにすることで、アプリケーション全体でコードを整理し共有するために使用される設計パターンです。 +アプリケーションが成長するにつれて、開発者はコードベースのさまざまな部分で機能を再利用し共有する必要がでてきます。[依存性の注入 (DI)](https://en.wikipedia.org/wiki/Dependency_injection) は、クラスの内部で依存性を直接生成する代わりにクラスに依存性を供給できるようにすることで、これを実現する手助けをします。これにより、アプリケーションのさまざまな部分の再利用性が向上し、管理しやすくなります。 依存性の注入は、開発者が次のような一般的な課題に対処できるため、人気のあるパターンです。 -- **コードの保守性の向上**: 依存性の注入により、関心事をよりクリーンに分離でき、リファクタリングを容易にし、コードの重複を減らせます。 -- **スケーラビリティ**: モジュール化された機能を複数のコンテキストで再利用でき、スケーリングが容易になります。 -- **テストの改善**: DIを使用すると、実際の実装を使用することが実用的でない状況で、ユニットテストが簡単に[テストダブル](https://en.wikipedia.org/wiki/Test_double)を使用できるようになります。 +- **コードの保守性の向上**: 依存性の注入により、関心事の明確な分離が促され、コードのリファクタリングが容易になり、重複が減ります。 +- **スケーラビリティ**: モジュール化された機能をアプリケーションのさまざまな部分で再利用でき、スケーリングが容易になります。 +- **テストの改善**: DIを使用すると、必要に応じて実際の実装の代わりに[テストダブル](https://en.wikipedia.org/wiki/Test_double)をユニットテストで使用できます。 ## Angularでの依存性の注入の仕組み {#how-does-dependency-injection-work-in-angular} -依存関係とは、クラスが動作するために必要であるが、自分自身では作成しないオブジェクト、値、関数、またはサービスのことです。言い換えれば、依存関係がなければ機能しないため、アプリケーションのさまざまな部分間の関係を作成します。 +依存関係とは、クラスが動作するために必要だが、自分自身では作成しないオブジェクト、値、関数、またはサービスのことです。代わりに、外部から提供することで、アプリケーションのさまざまな部分間に明確な関係を作ります。 -コードが依存性の注入システムとやり取りする方法は2つあります。 +依存性の注入システムとやり取りする主な方法は2つあります。 -- コードは値を _提供_ (利用可能にする) できます。 -- コードは依存関係としてそれらの値を _注入_ (要求) できます。 +- 値を _提供_ (利用可能に) できます。 +- それらの値を依存関係として _注入_ (要求) できます。 -この文脈での「値」とは、オブジェクトや関数を含む任意のJavaScriptの値です。注入される依存関係の一般的なタイプには次のものがあります。 +この文脈での「値」とは、オブジェクト、関数、クラスインスタンスを含む任意のJavaScriptの値を指します。注入される依存関係の一般的なタイプには次のものがあります。 - **設定値**: 環境固有の定数、API URL、機能フラグなど - **ファクトリー**: 実行時の条件に基づいてオブジェクトまたは値を作成する関数 - **サービス**: 共通の機能、ビジネスロジック、または状態を提供するクラス -AngularのコンポーネントとディレクティブはDIに自動的に参加します。つまり、依存関係を注入でき、_かつ_ 注入される対象として利用可能になります。 +AngularのコンポーネントとディレクティブはDIに自動的に参加します。つまり、それらに依存関係を注入でき、かつ注入される対象として利用可能になります。 ## サービスとは {#what-are-services} -Angular _サービス_ は `@Injectable` で装飾されたTypeScriptクラスで、クラスのインスタンスを依存関係として注入できるようにします。サービスは、アプリケーション全体でデータと機能を共有する最も一般的な方法です。 +Angular _サービス_ は `@Injectable` で装飾されたTypeScriptクラスで、クラスのインスタンスを依存関係として注入できます。サービスは、アプリケーション全体でデータと機能を共有する最も一般的な方法です。 サービスの一般的なタイプには次のものがあります。 diff --git a/adev-ja/src/content/guide/forms/reactive-forms.en.md b/adev-ja/src/content/guide/forms/reactive-forms.en.md index d4fe7f488..c1dc1aa74 100644 --- a/adev-ja/src/content/guide/forms/reactive-forms.en.md +++ b/adev-ja/src/content/guide/forms/reactive-forms.en.md @@ -151,7 +151,7 @@ The `ProfileEditor` component accepts input from the user, but in a real scenari -The `onSubmit()` method in the `ProfileEditor` component captures the current value of `profileForm`. Use `EventEmitter` to keep the form encapsulated and to provide the form value outside the component. The following example uses `console.warn` to log a message to the browser console. +The `onSubmit()` method in the `ProfileEditor` component captures the current value of `profileForm`. Use `output()` to keep the form encapsulated and to provide the form value outside the component. The following example uses `console.warn` to log a message to the browser console. diff --git a/adev-ja/src/content/guide/forms/reactive-forms.md b/adev-ja/src/content/guide/forms/reactive-forms.md index 74fb10f3b..0224ed48f 100644 --- a/adev-ja/src/content/guide/forms/reactive-forms.md +++ b/adev-ja/src/content/guide/forms/reactive-forms.md @@ -151,7 +151,7 @@ Just as a form group contains a group of controls, the _profileForm_ `FormGroup` -`ProfileEditor` コンポーネントの `onSubmit()` メソッドは、`profileForm` の現在の値をキャプチャします。`EventEmitter` を使用してフォームをカプセル化し、コンポーネント外部にフォーム値を提供します。次の例では、`console.warn` を使用して、ブラウザコンソールにメッセージをログ出力します。 +`ProfileEditor` コンポーネントの `onSubmit()` メソッドは、`profileForm` の現在の値をキャプチャします。`output()` を使用してフォームをカプセル化し、コンポーネント外部にフォーム値を提供します。次の例では、`console.warn` を使用して、ブラウザコンソールにメッセージをログ出力します。 diff --git a/adev-ja/src/content/guide/forms/signals/async-operations.md b/adev-ja/src/content/guide/forms/signals/async-operations.md index 47352590f..fab01f32a 100644 --- a/adev-ja/src/content/guide/forms/signals/async-operations.md +++ b/adev-ja/src/content/guide/forms/signals/async-operations.md @@ -350,6 +350,229 @@ export class Registration { The `rxResource` function works directly with Observables and handles subscription cleanup automatically when the field value changes. +## Debouncing + +The `debounce` rule delays when a user's input is committed to the form model. You can think of it as the rule holding back values until the user pauses typing. This is useful when downstream behavior shouldn't react to every keystroke, such as expensive derived computations, validation that flashes errors mid-word, or search filters that reapply on each character. + +Add the `debounce` rule inside a schema to delay how a form field's UI changes reach the form model. In its simplest form, `debounce(path, ms)` holds each UI change for the given number of milliseconds before writing it to the model. A new change within that window resets the timer. + +The following example applies `debounce` and `validateHttp` to the username field to delay the username availability check in a registration form until the user pauses typing: + +```angular-ts +import {Component, signal} from '@angular/core'; +import {form, debounce, validateHttp, FormField} from '@angular/forms/signals'; + +@Component({ + selector: 'app-registration', + imports: [FormField], + template: ` + + + @if (registrationForm.username().pending()) { + Checking availability... + } + `, +}) +export class Registration { + registrationModel = signal({username: ''}); + + registrationForm = form(this.registrationModel, (schemaPath) => { + // Hold UI updates for 300 ms before writing to the model + debounce(schemaPath.username, 300); + + // Runs against the debounced model value, not every keystroke + validateHttp(schemaPath.username, { + request: ({value}) => { + const username = value(); + // Skip the request for blank values + return username ? `/api/users/check?username=${username}` : undefined; + }, + onSuccess: (response) => + response.available ? null : {kind: 'usernameTaken', message: 'Username is already taken'}, + onError: () => ({ + kind: 'serverError', + message: 'Could not verify username availability', + }), + }); + }); +} +``` + +With a 300 ms debounce, the model updates and validates only after the user pauses typing longer than the configured duration. For example, typing "signal forms" in a quick burst fires one validation request instead of twelve. + +### Touch flushes the model + +Regardless of the debounce duration, the framework writes the field's `controlValue()` to the model immediately when the field becomes touched. Native inputs become touched on blur, so a user who finishes typing and tabs away doesn't have to wait for the debounce timer to expire. Custom controls can mark the field as touched in response to any event they choose. + +In the typical case, this matters for form submission. When the user clicks a submit button, the focused input blurs, which touches that field and flushes its pending debounce before the submission handler runs. + +### Commit only on blur + +Some fields shouldn't update mid-typing at all, and instead should only update after the user has finished entering a value. For example, if you have a search filter that reapplies on every change or a form that triggers expensive derived state, it is often better for the model to wait until the user finishes typing. + +In these scenarios, pass `'blur'` instead of a duration to defer all updates until the field becomes touched: + +```ts +form(this.registrationModel, (schemaPath) => { + debounce(schemaPath.username, 'blur'); +}); +``` + +With `'blur'`, the model keeps its previous value while the user is typing. Sync and async validation, derived signals, and any reactive rules reading the field all see the previous value until the field becomes touched. This commonly occurs when the user blurs a native input, or when a custom control signals touch on its own. + +### Custom timing logic + +For timing logic that a duration or `'blur'` can't express, pass a `Debouncer` function. The function receives the field context and an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal), and returns a `Promise` that resolves when the model should update: + +```ts +import {debounce, type Debouncer} from '@angular/forms/signals'; + +const shorterWhenLonger: Debouncer = ({value}, abortSignal) => { + // Shorter queries get a longer delay since the user is likely still typing. + const ms = value().length < 3 ? 500 : 200; + return new Promise((resolve) => { + const timeoutId = setTimeout(resolve, ms); + // Abort fires when this field is touched or its value changes, so the pending timer is cleared + abortSignal.addEventListener( + 'abort', + () => { + clearTimeout(timeoutId); + resolve(); + }, + {once: true}, + ); + }); +}; + +form(this.registrationModel, (schemaPath) => { + debounce(schemaPath.username, shorterWhenLonger); +}); +``` + +The `abortSignal` fires when the field is touched, or when its value changes before the debounce resolves. Resolve the promise on abort so your debouncer releases any pending timers. The framework writes the pending value to the model on touch, and discards it when a newer value arrives. See the [`debounce` API reference](api/forms/signals/debounce) for the full `Debouncer` signature. + +### Debouncing a single async validator + +The `debounce` rule holds back every reaction to the field, from sync validation to derived signals to async validation. However, there are times when you want the opposite: cheap sync validators like `required` or `email` running immediately for instant feedback, while only the expensive async call waits for the user to settle. Both `validateHttp()` and `validateAsync()` accept their own [`debounce` option](api/forms/signals/validateAsync) that throttles just that validator: + +```ts +form(this.registrationModel, (schemaPath) => { + validateHttp(schemaPath.username, { + // Throttles only this HTTP call + debounce: 300, + request: ({value}) => { + const username = value(); + // Skip the request for blank values + return username ? `/api/users/check?username=${username}` : undefined; + }, + onSuccess: (response) => + response.available ? null : {kind: 'usernameTaken', message: 'Username is already taken'}, + onError: () => ({ + kind: 'serverError', + message: 'Could not verify username availability', + }), + }); +}); +``` + +The model still updates on every keystroke, and any other rules attached to the field still react immediately. Only the HTTP request is debounced: each change waits 300 ms of quiet before firing, so a request only goes out once the user has paused typing. + +Choose between the two layers based on scope: + +| Option | When to use | +| ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| `debounce()` rule | Sync validation, derived state, and submission should all wait until the field commits. The whole field shouldn't react mid-typing. | +| `validateHttp({ debounce })` or `validateAsync({ debounce })` | Cheap sync validators should give immediate feedback, but expensive async calls should wait for the user to pause. | + +Both options accept a duration in milliseconds. Their custom-timing callbacks differ: the form-level rule takes a `Debouncer`, and the validator-level option takes a `DebounceTimer` from `@angular/core`. The two signatures are not interchangeable. + +## Composing resources in async validation with a factory + +The built-in [`debounce` option](api/forms/signals/validateAsync) covers throttling, but `validateAsync()` exposes a deeper composition point: the `factory` function. The factory receives the params as a signal and returns a resource. Between those two points, you're free to compose whatever you need. + +In its simplest form, a factory wraps a single resource. A username-availability check can live as a method on the component class, and then be wired into `validateAsync` by reference: + +```ts +export class Registration { + registrationModel = signal({username: ''}); + private usernameValidator = inject(UsernameValidator); + + // Factory function + checkUsernameAvailable = (username: Signal) => + resource({ + params: () => username(), + loader: async ({params: name}) => this.usernameValidator.checkAvailability(name), + }); + + registrationForm = form(this.registrationModel, (schemaPath) => { + validateAsync(schemaPath.username, { + params: ({value}) => { + const username = value(); + // Skip validation for short usernames + return username.length >= 3 ? username : undefined; + }, + debounce: 300, + // Reference to the factory defined above + factory: this.checkUsernameAvailable, + onSuccess: (result) => + result?.available ? null : {kind: 'usernameTaken', message: 'Username taken'}, + onError: () => ({kind: 'serverError', message: 'Could not verify'}), + }); + }); +} +``` + +The `params` callback returns `undefined` for short usernames, signaling that validation should skip. With `debounce: 300` applied, the resource waits until the user pauses typing for 300 ms before acting on each change. It then runs the loader for valid usernames and stays idle once the debounced value settles to `undefined`. + +### Combining debounce with additional logic + +When you need logic beyond a plain duration debounce, use a custom factory to combine debouncing with that logic. A common case is caching validated responses. For example, once the server has confirmed a username, you don't need to ask again on subsequent keystrokes that revisit the same value. + +```ts +export class Registration { + registrationModel = signal({username: ''}); + private usernameValidator = inject(UsernameValidator); + + registrationForm = form(this.registrationModel, (schemaPath) => { + validateAsync(schemaPath.username, { + params: ({value}) => { + const username = value(); + return username.length >= 3 ? username : undefined; + }, + factory: (username) => { + // Core primitive: settles 300 ms after the source stops changing + const debouncedUsername = debounced(username, 300); + // Cache lives in the factory's closure and persists for the field's lifetime + const cache = new Map(); + return resource({ + // Read from the debounced signal, not the raw one + params: () => debouncedUsername.value(), + loader: async ({params: name}) => { + const cached = cache.get(name); + if (cached) return cached; + + const result = await this.usernameValidator.checkAvailability(name); + cache.set(name, result); + return result; + }, + }); + }, + onSuccess: (result) => + result?.available ? null : {kind: 'usernameTaken', message: 'Username taken'}, + onError: () => ({ + kind: 'serverError', + message: 'Could not verify username', + }), + }); + }); +} +``` + +The `cache` lives in the factory's closure, so it persists for the field's lifetime. Once the user has typed a username the server has already checked, the loader reads from the cache instead of making a new network request. + ## Understanding pending state When async validation runs, the field's `pending()` signal returns `true`. During this time: diff --git a/adev-ja/src/content/guide/forms/signals/field-metadata.md b/adev-ja/src/content/guide/forms/signals/field-metadata.md new file mode 100644 index 000000000..d2f5d7092 --- /dev/null +++ b/adev-ja/src/content/guide/forms/signals/field-metadata.md @@ -0,0 +1,389 @@ +# Field metadata + +Field metadata is reactive data you can attach to an individual field. Angular's built-in constraint validators like `required()` and `min()` use this system internally. In other words, every time you call a validator, you're contributing to a metadata key for that particular field. + +This guide covers the metadata system in depth: how reducers combine contributions from multiple schema rules, how to write custom reducers, how reading composes with `hasMetadata()`, and how managed metadata ties lifecycle-aware objects to individual fields. + +## You have already been using metadata + +When you call `required()` in a schema and read `.required()` on the resulting field in a template, you are using the metadata system. `state.required` is not a special-case property. It is a convenience getter that returns the current value of a built-in `REQUIRED` metadata key. + +```angular-ts +import {Component, signal} from '@angular/core'; +import {form, required, FormField} from '@angular/forms/signals'; + +@Component({ + selector: 'app-registration', + imports: [FormField], + template: ` +
+ +
+ `, +}) +export class Registration { + registrationModel = signal({username: ''}); + + registrationForm = form(this.registrationModel, (path) => { + required(path.username); + }); +} +``` + +Calling `required(path.username)` contributes a value to the `REQUIRED` metadata key on that field. Reading `registrationForm.username().required()` returns the accumulated value. The metadata key is the bridge connecting the two. + +Several built-in constraint validators follow this pattern: + +| Validator | Metadata key | Type | `FieldState` getter | +| ------------- | ------------ | --------------------- | ------------------- | +| `required()` | `REQUIRED` | `boolean` | `required` | +| `min()` | `MIN` | `number \| undefined` | `min` | +| `max()` | `MAX` | `number \| undefined` | `max` | +| `minLength()` | `MIN_LENGTH` | `number \| undefined` | `minLength` | +| `maxLength()` | `MAX_LENGTH` | `number \| undefined` | `maxLength` | +| `pattern()` | `PATTERN` | `RegExp[]` | `pattern` | + +Non-constraint validators like `email()` and `validate()` do not contribute to metadata. They run their check and surface a validation error, but they do not publish a reactive value for templates to read. + +## When to use custom metadata + +When you need reactive data attached to a specific field that built-in state signals like `valid()`, `disabled()`, and `touched()` do not cover, use **custom metadata**. + +Some examples might include: + +- **Configuration attached to reusable field schemas.** A currency symbol on a price field, so any template or custom control rendering the field can display it. Or `MIN_DATE` and `MAX_DATE` on a date field, read by a reusable range picker. +- **Parsed values shared between rules on one field.** A phone number parsed once into E.164 format, so a format validator and a uniqueness check both read the same canonical form without reparsing. +- **Display hints assembled from the field's state.** A severity level (`'info' | 'warning' | 'error'`) that the UI maps to badges and icons, or a context-aware help message that changes based on what the user has typed and which other fields are filled in. + +If you find yourself keeping a parallel `Map` alongside your form to track something per field, that is a sign metadata is the right tool. Metadata stays colocated with the schema, stays reactive, and participates in the field's lifecycle. + +## Creating a metadata key + +When you want to create a custom key, call `createMetadataKey()`. The type parameter describes the value your schema rules will contribute. + +```ts +import {createMetadataKey} from '@angular/forms/signals'; + +export const USERNAME_HELP = createMetadataKey(); +``` + +Every `createMetadataKey()` call creates a new unique key. Two calls with matching type parameters are still two distinct keys, so define each key once at module scope and import it wherever it's needed. + +NOTE: A key created without a reducer uses "override" semantics by default: the last contribution wins if multiple rules set the key. + +## Setting values from a schema + +When you need to register a value for the key on a specific field, use `metadata(path, key, logic)` inside a schema function. + +```angular-ts +import {Component, computed, signal} from '@angular/core'; +import {form, metadata, FormField} from '@angular/forms/signals'; +import {USERNAME_HELP} from './metadata-keys'; + +@Component({ + selector: 'app-registration', + imports: [FormField], + template: ` +
+ +

{{ usernameHelp() }}

+
+ `, +}) +export class Registration { + registrationModel = signal({username: ''}); + + registrationForm = form(this.registrationModel, (path) => { + metadata(path.username, USERNAME_HELP, ({value}) => { + const username = value(); + if (username.length === 0) { + return 'Choose a unique username between 3 and 20 characters.'; + } + if (username.length < 3) { + return 'Keep typing, usernames are at least 3 characters.'; + } + if (username.length > 20) { + return 'Usernames are at most 20 characters.'; + } + return 'Looks good.'; + }); + }); + + usernameHelp = computed(() => this.registrationForm.username().metadata(USERNAME_HELP)?.() ?? ''); +} +``` + +The logic function receives the field's context, which exposes `value` as a signal of the field's current value, `state` as the field's `FieldState`, and methods like `valueOf(path)` and `stateOf(path)` for reading other fields in the same form. Any signal the function reads becomes a reactive dependency: when `value()` changes, the metadata recomputes, and any template reading the key updates. + +## Reading metadata from a field + +`hasMetadata(key)` returns `true` if any schema rule registered the key on this field. `state.metadata(key)` returns `undefined` when no rule has registered the key, and a signal of the current reduced value otherwise. + +```ts +registrationForm.username().hasMetadata(USERNAME_HELP); // true if any metadata() rule registered this key +``` + +The shape of that inner value (whether it can itself be `undefined`, what type it holds) depends on the key's reducer. Reducers are covered in the next section. + +When the key may not be registered, gate the read with `hasMetadata()`: + +```angular-html +@if (registrationForm.username().hasMetadata(USERNAME_HELP)) { +

{{ registrationForm.username().metadata(USERNAME_HELP)!() }}

+} +``` + +When you know a rule always registers the key (because the schema in the same file does so), you can skip the `hasMetadata()` check and use optional chaining as a compact alternative: + +```ts +const message = registrationForm.username().metadata(USERNAME_HELP)?.(); +// message: string | undefined +``` + +Or, when the rule is guaranteed to have registered, drop the optional chain and assert: + +```ts +const message = registrationForm.username().metadata(USERNAME_HELP)!(); +// message: string | undefined (still, because the inner value may be undefined) +``` + +The component example above uses optional chaining inside a `computed()` so the template binds to a plain `string`, with an empty fallback for the initial frame. + +This is the whole API for a single contributor. The next section covers what happens when more than one schema rule contributes to the same key, and how to combine those contributions with reducers. + +## Combining contributions with reducers + +Override semantics work when only one rule contributes to a key on a given field. As soon as two rules contribute, the first value is silently discarded: + +```ts +const HELP = createMetadataKey(); + +form(model, (path) => { + metadata(path.username, HELP, () => 'Choose something unique across the system.'); + metadata(path.username, HELP, () => 'Usernames are 3 to 20 characters.'); +}); +``` + +After both rules run, `state.metadata(HELP)!()` returns only the second message. This is almost never what you want. Contributions often come from different sources: two schemas composed with `apply()` that each attach help text, or multiple validation rules that each contribute a hint. + +To combine contributions, pass a reducer to `createMetadataKey()`. A reducer describes how to fold individual values into an accumulated result: + +```ts +import {createMetadataKey, MetadataReducer} from '@angular/forms/signals'; + +const HELP = createMetadataKey(MetadataReducer.list()); + +form(model, (path) => { + metadata(path.username, HELP, () => 'Choose something unique across the system.'); + metadata(path.username, HELP, () => 'Usernames are 3 to 20 characters.'); +}); + +// state.metadata(HELP)!() === [ +// 'Choose something unique across the system.', +// 'Usernames are 3 to 20 characters.', +// ] +``` + +Notice the two type parameters on `createMetadataKey`: the first is the type each rule contributes, the second is the type the reducer produces. With `list()`, rules contribute a `string` and the field reads back a `string[]`. + +### Built-in reducers + +Angular provides six built-in reducers on the [`MetadataReducer`](api/forms/signals/MetadataReducer) namespace. `override()` has two forms with slightly different semantics, listed separately in the table: + +| Reducer | Accumulator type | What it does | Initial value | +| -------------- | --------------------- | ---------------------------------------------------------------------- | ------------- | +| `list()` | `T[]` | Accepts `T \| undefined` contributions; appends non-`undefined` values | `[]` | +| `or()` | `boolean` | `true` if any contribution is `true` | `false` | +| `and()` | `boolean` | `true` only if every contribution is `true` | `true` | +| `min()` | `number \| undefined` | Keeps the smallest contributed number | `undefined` | +| `max()` | `number \| undefined` | Keeps the largest contributed number | `undefined` | +| `override()` | `T \| undefined` | Last contribution replaces previous (the default) | `undefined` | +| `override(fn)` | `T` | Same, but with a provided initial value | `fn()` | + +`list()` is the only built-in reducer whose item type is wider than its accumulator's element type. A rule may contribute `undefined` and the reducer will silently drop it. This is how the built-in `PATTERN` key handles dynamic `pattern()` rules whose logic function returns `undefined`: the `undefined` contribution is skipped rather than included in the final regex list. + +### How built-in validator keys use reducers + +While `MetadataReducer.min()` and `MetadataReducer.max()` are reducers, you may be surprised to learn that they are not validators. `MetadataReducer.min()` picks the smallest contribution to a key, while the `min()` validator enforces a lower bound on a field's value. They share a name but solve different problems. + +The built-in constraint keys pick their reducers based on what "strictest" means for the constraint, which is often the opposite of what the key's name suggests: + +| Key | Reducer | Reasoning | +| ------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------- | +| `REQUIRED` | `or()` | If any `required()` rule evaluates to `true`, the field is required. | +| `MIN` | `max()` | A minimum-value constraint is strictest when largest. If one rule requires `>= 5` and another `>= 10`, the effective minimum is `10`. | +| `MAX` | `min()` | A maximum-value constraint is strictest when smallest. If one rule caps at `100` and another at `50`, the effective maximum is `50`. | +| `MIN_LENGTH` | `max()` | Same logic as `MIN`: the longest required length wins. | +| `MAX_LENGTH` | `min()` | Same logic as `MAX`: the shortest allowed length wins. | +| `PATTERN` | `list()` | Each `pattern()` call contributes a regex; the value must match all of them. | + +This pairing of "strictest wins" is why calling `min(path.age, 18)` and `min(path.age, 21)` in two composed schemas works correctly. Each call registers its own validator that enforces its specific bound (so a value below either bound fails validation). Separately, each call contributes to the public `MIN` key, and `state.metadata(MIN)!()` reports the aggregate (`21`) so UI and custom controls can read the effective minimum. + +### Writing a custom reducer + +When you want to write your own reducer, implement an object matching the `MetadataReducer` interface: + +```ts +interface MetadataReducer { + reduce: (acc: TAcc, item: TItem) => TAcc; + getInitial: () => TAcc; +} +``` + +You can define a custom reducer when none of the built-ins match the semantics you need. For example, a `SEVERITY` key that keeps the most severe level contributed by any rule: + +```ts +import {createMetadataKey, type MetadataReducer} from '@angular/forms/signals'; + +type Severity = 'info' | 'warning' | 'error'; + +const SEVERITY_RANK: Record = {info: 0, warning: 1, error: 2}; + +const maxSeverity: MetadataReducer = { + reduce(acc, item) { + if (acc === undefined) return item; + return SEVERITY_RANK[item] > SEVERITY_RANK[acc] ? item : acc; + }, + getInitial: () => undefined, +}; + +export const SEVERITY = createMetadataKey(maxSeverity); +``` + +Any number of rules can now contribute a severity, and the field reports the highest: + +```ts +form(model, (path) => { + metadata(path.password, SEVERITY, () => 'info'); + metadata(path.password, SEVERITY, ({value}) => (value().length < 12 ? 'warning' : 'info')); + metadata(path.password, SEVERITY, ({value}) => + /password|1234/i.test(value()) ? 'error' : 'info', + ); +}); +``` + +The reducer runs whenever any contribution's signals change, so `state.metadata(SEVERITY)!()` stays in sync with the current worst case across all rules. + +TIP: Keep your reducers pure: `reduce()` should depend only on its two arguments, and `getInitial()` should return the same value every time it is called. Reducers run inside a reactive computation that re-executes when any contribution's signals change, so impure reducers produce inconsistent metadata. + +## Attaching lifecycle-aware objects with managed metadata + +Managed metadata stores a lifecycle-aware object on a field instead of a reactive value. Use it for per-field objects like a `resource()` that fetches external data, an `effect()` that syncs to an outside system, or a service handle scoped to a single field. + +### Creating a managed key + +When you want to define a managed key, call `createManagedMetadataKey(create)`. The `create` function you pass produces the value the key holds. + +```ts +import {Signal} from '@angular/core'; +import {httpResource} from '@angular/common/http'; +import {createManagedMetadataKey} from '@angular/forms/signals'; + +export interface UrlPreview { + title: string; + description?: string; + image?: string; +} + +export const URL_PREVIEW = createManagedMetadataKey((_state, url: Signal) => { + return httpResource(() => { + const currentUrl = url(); + return currentUrl ? {url: '/api/url-preview', params: {url: currentUrl}} : undefined; + }); +}); +``` + +The `create` function receives the field's `FieldState` and a `Signal` of data contributed by `metadata()` rules for this key, and returns whatever object should live on the field. The return value is stored as-is: unlike non-managed keys, the framework does not wrap it in a `computed()`. + +`create` runs once when a field is constructed, inside the field's injection context. That lets you call `inject()`, `resource()`, and `effect()` inside `create`, and ties cleanup to the field's lifecycle: when the field is destroyed, Angular destroys the injection context, and any `resource()`, `effect()`, or `DestroyRef` callback you registered there cleans up automatically. + +Because `create` itself is not reactive, any behavior that needs to respond to signal changes has to live inside an `effect()`, `resource()`, or `httpResource()` set up during that initial call. `URL_PREVIEW` demonstrates the pattern: the `httpResource()` reads the URL signal inside its request function, so the request re-runs whenever the signal changes. The schema rule (`metadata(path.url, URL_PREVIEW, ({value}) => value())`) decides what data to feed in; the managed key decides what to do with it. + +### Using a managed key in a form + +When you need to use a managed key in a form, register a `metadata()` rule for the key, and then read the returned object from the field state. + +```angular-ts +import {Component, computed, signal} from '@angular/core'; +import {applyEach, form, metadata, FormField} from '@angular/forms/signals'; +import {URL_PREVIEW} from './url-preview'; + +@Component({ + selector: 'app-link-editor', + imports: [FormField], + template: ` +
+ @for (link of linksForm.links; track link) { +
+ + + @let preview = link.url().metadata(URL_PREVIEW); + @if (preview?.isLoading()) { +

Loading preview...

+ } @else if (preview?.hasValue() && preview.value(); as data) { +
+

{{ data.title }}

+ @if (data.description) { +

{{ data.description }}

+ } +
+ } @else if (preview?.error()) { +

Could not load preview.

+ } +
+ } + +
+ `, +}) +export class LinkEditor { + linksModel = signal({links: [{url: ''}]}); + + linksForm = form(this.linksModel, (path) => { + // Register the URL_PREVIEW key on each link's url field. + // applyEach runs the schema per item, so create() runs once per link + // and each link gets its own resource. + applyEach(path.links, (itemPath) => { + metadata(itemPath.url, URL_PREVIEW, ({value}) => value()); + }); + }); + + addLink() { + this.linksForm.links().value.update((links) => [...links, {url: ''}]); + } +} +``` + +Each array item gets its own `URL_PREVIEW` resource because `applyEach` registers the schema rules against each item independently. When the user adds a link, `create` runs for the new item's field. When a link is removed (not shown here, but a common pattern), the framework tears down that field's injector along with the resource. + +## Next steps + +Remember that metadata exists so reactive data can travel with the field through schema composition, accumulate across rules, and tear down with the field's lifecycle. It leverages the same system Angular's built-in validators use, and can be tailored to your own use cases. + +For detailed API documentation, see: + +- [`createMetadataKey()`](api/forms/signals/createMetadataKey) - Define a metadata key with optional reducer +- [`createManagedMetadataKey()`](api/forms/signals/createManagedMetadataKey) - Define a lifecycle-aware metadata key +- [`metadata()`](api/forms/signals/metadata) - Contribute a value to a metadata key in a schema +- [`MetadataReducer`](api/forms/signals/MetadataReducer) - Built-in reducers for combining contributions + +For additional related guides on Signal Forms, check out: + + + + + + + diff --git a/adev-ja/src/content/guide/forms/signals/form-logic.md b/adev-ja/src/content/guide/forms/signals/form-logic.md index fe49c6e34..181c92701 100644 --- a/adev-ja/src/content/guide/forms/signals/form-logic.md +++ b/adev-ja/src/content/guide/forms/signals/form-logic.md @@ -454,24 +454,20 @@ Don't use debouncing if: ## Associate data with a field using `metadata()` -Metadata allows you to attach computed information to fields that can be read by [custom controls](guide/forms/signals/custom-controls) or form logic. Common use cases include HTML input attributes (min, max, maxlength, pattern), custom UI hints (placeholder text, help text), and accessibility information. +Metadata attaches reactive data to a field. Validation rules use this system internally, and you can publish your own keys for application-specific information like help text, configuration, or computed display values. -### Pre-defined metadata keys +Signal Forms provides six pre-defined metadata keys that built-in validators populate automatically: -Signal Forms provides six pre-defined metadata keys that validation rules automatically populate: +| Key | Populated by | Read via | +| ------------ | ------------- | --------------------- | +| `REQUIRED` | `required()` | `field().required()` | +| `MIN` | `min()` | `field().min()` | +| `MAX` | `max()` | `field().max()` | +| `MIN_LENGTH` | `minLength()` | `field().minLength()` | +| `MAX_LENGTH` | `maxLength()` | `field().maxLength()` | +| `PATTERN` | `pattern()` | `field().pattern()` | -- `REQUIRED` - Whether the field is required (`boolean`) -- `MIN` - Minimum numeric value (`number | undefined`) -- `MAX` - Maximum numeric value (`number | undefined`) -- `MIN_LENGTH` - Minimum string/array length (`number | undefined`) -- `MAX_LENGTH` - Maximum string/array length (`number | undefined`) -- `PATTERN` - Regular expression pattern (`RegExp[]` - array to support multiple patterns) - -When you use validation rules like `required()` or `min()`, they automatically set the corresponding metadata. The `metadata()` function provides a way to publish additional data associated with a field. - -### Reading pre-defined metadata - -The `[FormField]` directive automatically binds built-in metadata to HTML attributes. You can also read metadata directly using the built-in accessors on field state: +The `[formField]` directive automatically binds five of these (`REQUIRED`, `MIN`, `MAX`, `MIN_LENGTH`, and `MAX_LENGTH`) to the corresponding HTML attribute on a native form control. `PATTERN` is the exception, because Signal Forms supports multiple patterns per field but the HTML `pattern` attribute accepts only a single regular expression. ```angular-ts import {Component, signal} from '@angular/core'; @@ -492,9 +488,7 @@ import {form, FormField, required, min, max} from '@angular/forms/signals'; `, }) export class Age { - ageModel = signal({ - age: 0, - }); + ageModel = signal({age: 0}); ageForm = form(this.ageModel, (schemaPath) => { required(schemaPath.age); @@ -504,138 +498,9 @@ export class Age { } ``` -The `[formField]` directive automatically binds `required`, `min`, and `max` attributes to the input. You can read these values using `field().required()`, `field().min()`, and `field().max()` for display or logic purposes. - -### Setting metadata manually - -Use the `metadata()` function to set metadata values when validation rules don't automatically set them. For built-in metadata like `MIN` and `MAX`, prefer using the validation rules: - -```angular-ts -import {Component, signal} from '@angular/core'; -import {form, FormField, min, max, validate} from '@angular/forms/signals'; - -@Component({ - selector: 'app-custom', - imports: [FormField], - template: ` `, -}) -export class Custom { - customModel = signal({score: 0}); - - customForm = form(this.customModel, (schemaPath) => { - // Use built-in validation rules - they automatically set metadata - min(schemaPath.score, 0); - max(schemaPath.score, 100); - - // Add custom validation logic if needed - validate(schemaPath.score, ({value}) => { - const score = value(); - // Custom validation beyond min/max (e.g., must be multiple of 5) - if (score % 5 !== 0) { - return {kind: 'increment', message: 'Score must be a multiple of 5'}; - } - return null; - }); - }); -} -``` - -### Creating custom metadata keys - -Create your own metadata keys for application-specific information: - -```angular-ts -import {createMetadataKey, metadata} from '@angular/forms/signals'; - -// Define at module level (not inside components) -export const PLACEHOLDER = createMetadataKey(); -export const HELP_TEXT = createMetadataKey(); - -// Use in schema -form(model, (schemaPath) => { - metadata(schemaPath.email, PLACEHOLDER, () => 'user@example.com'); - metadata(schemaPath.email, HELP_TEXT, () => 'We will never share your email'); -}); - -// Read in component -const placeholderText = myForm.email().metadata(PLACEHOLDER); -const helpText = myForm.email().metadata(HELP_TEXT); -``` - -By default, custom metadata keys use a "last write wins" strategy - if you call `metadata()` multiple times with the same key, only the last value is kept. - -**Important:** Always define metadata keys at module level, never inside components. Metadata keys rely on object identity, and recreating them loses that identity. - -### Accumulating metadata with reducers - -By default, calling `metadata()` multiple times with the same key uses "last write wins" - only the final value is kept. To accumulate values instead, pass a reducer to `createMetadataKey()`: - -```angular-ts -import {createMetadataKey, metadata, MetadataReducer} from '@angular/forms/signals'; - -// Create a key that accumulates values into an array -export const HINTS = createMetadataKey(MetadataReducer.list()); - -// Multiple calls accumulate values -form(model, (schemaPath) => { - metadata(schemaPath.password, HINTS, () => 'At least 8 characters'); - metadata(schemaPath.password, HINTS, () => 'Include a number'); - metadata(schemaPath.password, HINTS, () => 'Include a special character'); -}); - -// Result: Signal containing the accumulated array -const passwordHints = passwordForm.password().metadata(HINTS)(); -// ['At least 8 characters', 'Include a number', 'Include a special character'] -``` - -Angular provides built-in reducers through `MetadataReducer`: - -- `MetadataReducer.list()` - Accumulates values into an array -- `MetadataReducer.min()` - Keeps the minimum value -- `MetadataReducer.max()` - Keeps the maximum value -- `MetadataReducer.or()` - Logical OR of boolean values -- `MetadataReducer.and()` - Logical AND of boolean values - -### Managed metadata keys - -Use `createManagedMetadataKey()` when you need to compute a new value from the accumulated result. The transform function receives a signal of the reduced value and returns the computed result: - -```angular-ts -import {createManagedMetadataKey, metadata, MetadataReducer} from '@angular/forms/signals'; - -// Accumulate hints and compute additional data from the result -export const HINTS = createManagedMetadataKey( - (signal) => - computed(() => { - const hints = signal(); - return { - messages: hints, - count: hints?.length ?? 0, - }; - }), - MetadataReducer.list(), -); - -// Multiple calls accumulate values -form(model, (schemaPath) => { - metadata(schemaPath.password, HINTS, () => 'At least 8 characters'); - metadata(schemaPath.password, HINTS, () => 'Include a number'); - metadata(schemaPath.password, HINTS, () => 'Include a special character'); -}); - -// Result: Signal with transformed value -const passwordHints = passwordForm.password().metadata(HINTS)(); -// { messages: ['At least 8 characters', 'Include a number', 'Include a special character'], count: 3 } -``` - -The managed metadata key takes two arguments: - -1. **Transform function** - Computes a new value from the accumulated result (receives a signal of the reduced value) -2. **Reducer** - Determines how values accumulate (optional - defaults to "last write wins") - ### Reactive metadata -Make metadata reactive to other field values: +Validation rules can derive their constraints from other fields, making the published metadata reactive: ```angular-ts import {Component, signal} from '@angular/core'; @@ -678,47 +543,9 @@ export class Inventory { } ``` -The `max()` validation rule sets the `MAX` metadata reactively based on the selected item. This demonstrates how validation rules can have conditional values that change when other fields update. - -### Using metadata in custom controls +The `max()` validation rule sets the `MAX` metadata reactively based on the selected item, so any template or control reading `field().max()` updates whenever the item changes. -Custom controls can read metadata to configure their HTML attributes and behavior: - -```angular-ts -import {Component, input, computed, model} from '@angular/core'; -import {FormValueControl, Field, PLACEHOLDER} from '@angular/forms/signals'; - -@Component({ - selector: 'custom-input', - template: ` - - `, -}) -export class CustomInput implements FormValueControl { - // Bind to the form field. - formField = input.required>(); - - // Compute the current field state. - state = computed(() => this.formField()()); - - // Required property of the FormValueControl interface. - value = model(0); - - placeholderText = computed(() => this.state().metadata(PLACEHOLDER)() ?? ''); -} -``` - -This pattern allows custom controls to automatically configure themselves based on the validation rules and metadata defined in the schema. - -TIP: For more information on creating custom controls, see the [Custom Controls guide](guide/forms/signals/custom-controls). +For deeper coverage, including how to define custom keys, combine contributions with reducers, and use managed metadata for lifecycle-aware objects, see the [Field metadata guide](guide/forms/signals/field-metadata). ## Combining rules @@ -730,15 +557,8 @@ Apply multiple rules to configure all aspects of a field's behavior: ```angular-ts import {Component, signal} from '@angular/core'; -import { - form, - FormField, - disabled, - hidden, - debounce, - metadata, - PLACEHOLDER, -} from '@angular/forms/signals'; +import {form, FormField, disabled, hidden, debounce, metadata} from '@angular/forms/signals'; +import {PLACEHOLDER} from './metadata-keys'; @Component({ selector: 'app-promo', @@ -835,8 +655,9 @@ The conditional rules only run when the condition is true. This is useful for co Extract common rule configurations into reusable functions: -```angular-ts -import {SchemaPath, debounce, metadata, maxLength, PLACEHOLDER} from '@angular/forms/signals'; +```ts +import {SchemaPath, debounce, metadata, maxLength} from '@angular/forms/signals'; +import {PLACEHOLDER} from './metadata-keys'; function emailFieldConfig(path: SchemaPath) { debounce(path, 300); diff --git a/adev-ja/src/content/guide/forms/signals/form-submission.md b/adev-ja/src/content/guide/forms/signals/form-submission.md index e40a827a1..b67608446 100644 --- a/adev-ja/src/content/guide/forms/signals/form-submission.md +++ b/adev-ja/src/content/guide/forms/signals/form-submission.md @@ -312,6 +312,10 @@ submission: { } ``` +## Concurrent submissions + +When a submission is in progress, subsequent calls to `submit()` for the same form or any of its parents return `false` immediately without running the action. This prevents duplicate submissions and side effects if a user triggers the submit action multiple times quickly. + ## Next steps This guide covered submitting forms and handling form submission errors. Related guides explore other aspects of Signal Forms: 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 3c1cf674f..ff503909a 100644 --- a/adev-ja/src/content/guide/forms/signals/models.en.md +++ b/adev-ja/src/content/guide/forms/signals/models.en.md @@ -40,6 +40,40 @@ The [`form()`](api/forms/signals/form) function accepts the model signal and cre The `[formField]` directive binds each input element to its corresponding field in the field tree, enabling automatic two-way synchronization between the UI and model. +### Supported model structures + +Signal Forms builds the field tree by walking your model. The objects and arrays it walks through (the **structural layer**) must be plain JavaScript objects and arrays. The values at the **leaves** (positions with no nested fields) are usually primitives (strings, numbers, booleans) or `null`. Native `date`, `month`, `time`, and `week` inputs also accept `Date`, and custom controls can accept any value type they understand. + +```ts {prefer, header: 'Plain structure'} +interface UserFormModel { + name: string; + birthday: Date | null; + preferences: { + theme: string; + notifications: boolean; + }; + tags: string[]; +} + +const userModel = signal({ + name: '', + birthday: null, + preferences: { + theme: 'dark', + notifications: true, + }, + tags: [], +}); +``` + +IMPORTANT: Class instances, `Map`, and `Set` are **not supported in the structural layer**, even though TypeScript will accept them. Signal Forms does not validate the model shape at runtime, so the framework accepts these values without throwing, then produces incorrect behavior in different ways depending on shape: + +- **Class instances** lose their prototype on the first write because Signal Forms shallow-copies parent objects on update. Methods, getters, and `instanceof` checks are gone afterward. +- **Non-extensible or frozen objects inside arrays** throw when Signal Forms assigns a tracking symbol to preserve item identity across reorders. +- **`Map` and `Set`** produce empty field trees, because Signal Forms enumerates children with `Object.keys`. + +If your application uses classes for domain modeling, translate to plain objects at the form boundary. See [Translating between form model and domain model](guide/forms/signals/model-design#translating-between-form-model-and-domain-model). + ### Using TypeScript types While TypeScript infers types from object literals, defining explicit types improves code quality and provides better IntelliSense support. diff --git a/adev-ja/src/content/guide/forms/signals/models.md b/adev-ja/src/content/guide/forms/signals/models.md index e3bb43bd5..98b3c1c9e 100644 --- a/adev-ja/src/content/guide/forms/signals/models.md +++ b/adev-ja/src/content/guide/forms/signals/models.md @@ -40,6 +40,40 @@ export class LoginComponent { `[formField]`ディレクティブは、各入力要素をフィールドツリー内の対応するフィールドにバインドし、UIとモデル間の自動的な双方向同期を可能にします。 +### サポートされるモデル構造 {#supported-model-structures} + +シグナルフォームはモデルを走査してフィールドツリーを構築します。走査されるオブジェクトと配列(**構造レイヤー**)は、プレーンなJavaScriptオブジェクトと配列でなければなりません。**リーフ**(ネストされたフィールドを持たない位置)の値は、通常プリミティブ(文字列、数値、真偽値)または `null` です。ネイティブの `date`、`month`、`time`、`week` 入力は `Date` も受け入れ、カスタムコントロールは理解できる任意の値型を受け入れます。 + +```ts {prefer, header: 'Plain structure'} +interface UserFormModel { + name: string; + birthday: Date | null; + preferences: { + theme: string; + notifications: boolean; + }; + tags: string[]; +} + +const userModel = signal({ + name: '', + birthday: null, + preferences: { + theme: 'dark', + notifications: true, + }, + tags: [], +}); +``` + +IMPORTANT: クラスインスタンス、`Map`、`Set` は、TypeScriptが受け入れるとしても**構造レイヤーではサポートされません**。シグナルフォームは実行時にモデルの形状を検証しないため、フレームワークはこれらの値を例外を投げずに受け入れ、その後、形状に応じて異なる形で誤った挙動を引き起こします: + +- **クラスインスタンス**は、シグナルフォームが更新時に親オブジェクトをシャローコピーするため、最初の書き込みでプロトタイプを失います。それ以降、メソッド、ゲッター、`instanceof` チェックは機能しなくなります。 +- **配列内の拡張不可または凍結されたオブジェクト**は、シグナルフォームが並び替え時にアイテムの同一性を保持するためのトラッキングシンボルを割り当てる際に例外を投げます。 +- **`Map` および `Set`** は、シグナルフォームが `Object.keys` で子要素を列挙するため、空のフィールドツリーを生成します。 + +アプリケーションがドメインモデリングにクラスを使用している場合は、フォームの境界でプレーンなオブジェクトに変換してください。[フォームモデルとドメインモデル間の変換](guide/forms/signals/model-design#translating-between-form-model-and-domain-model)を参照してください。 + ### TypeScriptの型を使用する {#using-typescript-types} TypeScriptはオブジェクトリテラルから型を推論しますが、明示的な型を定義することでコードの品質が向上し、より良いIntelliSenseのサポートが提供されます。 diff --git a/adev-ja/src/content/guide/http/making-requests.en.md b/adev-ja/src/content/guide/http/making-requests.en.md index 7ba303fe2..d85c289ab 100644 --- a/adev-ja/src/content/guide/http/making-requests.en.md +++ b/adev-ja/src/content/guide/http/making-requests.en.md @@ -247,7 +247,7 @@ Each `HttpEvent` reported in the event stream has a `type` which distinguishes w | `HttpEventType.ResponseHeader` | The head of the response has been received, including status and headers | | `HttpEventType.DownloadProgress` | An `HttpDownloadProgressEvent` reporting progress on downloading the response body | | `HttpEventType.Response` | The entire response has been received, including the response body | -| `HttpEventType.User` | A custom event from an Http interceptor. | +| `HttpEventType.User` | A custom event from an HTTP interceptor. | ## Handling request failure @@ -614,7 +614,7 @@ IMPORTANT: The `integrity` option requires an exact match between the response c TIP: Use subresource integrity when loading critical resources from external sources to ensure they haven't been modified. Generate hashes using tools like `openssl`. -## Http `Observable`s +## HTTP `Observable`s Each request method on `HttpClient` constructs and returns an `Observable` of the requested response type. Understanding how these `Observable`s work is important when using `HttpClient`. diff --git a/adev-ja/src/content/guide/http/making-requests.md b/adev-ja/src/content/guide/http/making-requests.md index d0566312b..add6571b5 100644 --- a/adev-ja/src/content/guide/http/making-requests.md +++ b/adev-ja/src/content/guide/http/making-requests.md @@ -247,7 +247,7 @@ http | `HttpEventType.ResponseHeader` | レスポンスのヘッダーが受信されました。ステータスとヘッダーが含まれています | | `HttpEventType.DownloadProgress` | レスポンスボディのダウンロードの進捗状況を報告する `HttpDownloadProgressEvent` | | `HttpEventType.Response` | レスポンス全体が受信されました。レスポンスボディが含まれています | -| `HttpEventType.User` | Http インターセプターからのカスタムイベント | +| `HttpEventType.User` | HTTP インターセプターからのカスタムイベント | ## リクエスト失敗の処理 {#handling-request-failure} @@ -614,7 +614,7 @@ IMPORTANT: `integrity` オプションには、レスポンスコンテンツと TIP: 外部ソースから重要なリソースを読み込む際は、それらが変更されていないことを確実にするため、サブリソースの整合性を使用してください。`openssl` などのツールを使用してハッシュを生成してください。 -## Http `Observable` {#http-observables} +## HTTP `Observable` {#http-observables} `HttpClient` の各リクエストメソッドは、要求されたレスポンス型の `Observable` を構築して返します。これらの `Observable` の仕組みを理解することは、`HttpClient` を使用する場合に重要です。 diff --git a/adev-ja/src/content/guide/http/testing.en.md b/adev-ja/src/content/guide/http/testing.en.md index 558efc8d5..58ae0c8ad 100644 --- a/adev-ja/src/content/guide/http/testing.en.md +++ b/adev-ja/src/content/guide/http/testing.en.md @@ -8,15 +8,12 @@ At the end, tests can verify that the app made no unexpected requests. ## Setup for testing -To begin testing usage of `HttpClient`, configure `TestBed` and include `provideHttpClient()` and `provideHttpClientTesting()` in your test's setup. This configures `HttpClient` to use a test backend instead of the real network. It also provides `HttpTestingController`, which you'll use to interact with the test backend, set expectations about which requests have been made, and flush responses to those requests. `HttpTestingController` can be injected from `TestBed` once configured. - -IMPORTANT: Keep in mind to provide `provideHttpClient()` **before** `provideHttpClientTesting()`, as `provideHttpClientTesting()` will overwrite parts of `provideHttpClient()`. Doing it the other way around can potentially break your tests. +To begin testing usage of `HttpClient`, configure `TestBed` and include `provideHttpClientTesting()` in your test's setup. `HttpClient` is provided by Angular's test environment, and `provideHttpClientTesting()` configures it to use a test backend instead of the real network. It also provides `HttpTestingController`, which you'll use to interact with the test backend, set expectations about which requests have been made, and flush responses to those requests. `HttpTestingController` can be injected from `TestBed` once configured. ```ts TestBed.configureTestingModule({ providers: [ // ... other test providers - provideHttpClient(), provideHttpClientTesting(), ], }); @@ -26,13 +23,24 @@ const httpTesting = TestBed.inject(HttpTestingController); Now when your tests make requests, they will hit the testing backend instead of the normal one. You can use `httpTesting` to make assertions about those requests. +### Configuring `HttpClient` in tests + +If a test needs to configure `HttpClient` features, such as interceptors, include `provideHttpClient(...)` before `provideHttpClientTesting()`. +IMPORTANT: Keep in mind to provide `provideHttpClient()` **before** `provideHttpClientTesting()`, as `provideHttpClientTesting()` will overwrite parts of `provideHttpClient()`. Doing it the other way around can potentially break your tests. + +```ts +TestBed.configureTestingModule({ + providers: [provideHttpClient(withInterceptors([authInterceptor])), provideHttpClientTesting()], +}); +``` + ## Expecting and answering requests For example, you can write a test that expects a GET request to occur and provides a mock response: ```ts TestBed.configureTestingModule({ - providers: [ConfigService, provideHttpClient(), provideHttpClientTesting()], + providers: [ConfigService, provideHttpClientTesting()], }); const httpTesting = TestBed.inject(HttpTestingController); diff --git a/adev-ja/src/content/guide/http/testing.md b/adev-ja/src/content/guide/http/testing.md index b4e41788d..bf16da47e 100644 --- a/adev-ja/src/content/guide/http/testing.md +++ b/adev-ja/src/content/guide/http/testing.md @@ -8,15 +8,12 @@ ## テストの設定 -`HttpClient` の使用のテストを開始するには、`TestBed` を構成してテストの設定に `provideHttpClient()` と `provideHttpClientTesting()` を含めます。これにより、`HttpClient` が実際のネットワークではなくテストバックエンドを使用するように構成されます。また、`HttpTestingController` も提供され、これを使用してテストバックエンドとやり取ります。そして、どのリクエストが行われたかについての期待を設定し、それらのリクエストに対するレスポンスを流します。`HttpTestingController` は、構成されたら `TestBed` から注入できます。 - -IMPORTANT: `provideHttpClientTesting()` は `provideHttpClient()` の一部を上書きするため、`provideHttpClient()` を `provideHttpClientTesting()` の**前**に提供することに留意してください。これを逆に行うと、テストが壊れてしまう可能性があります。 +`HttpClient` の使用のテストを開始するには、`TestBed` を構成してテストの設定に `provideHttpClientTesting()` を含めます。`HttpClient` はAngularのテスト環境によって提供され、`provideHttpClientTesting()` がそれを実際のネットワークではなくテストバックエンドを使用するように構成します。また、`HttpTestingController` も提供され、これを使用してテストバックエンドとやり取ります。そして、どのリクエストが行われたかについての期待を設定し、それらのリクエストに対するレスポンスを流します。`HttpTestingController` は、構成されたら `TestBed` から注入できます。 ```ts TestBed.configureTestingModule({ providers: [ // ...その他のテストプロバイダー - provideHttpClient(), provideHttpClientTesting(), ], }); @@ -26,13 +23,24 @@ const httpTesting = TestBed.inject(HttpTestingController); これで、テストでリクエストを行うと、通常のバックエンドではなくテストバックエンドにヒットするようになります。`httpTesting` を使用して、それらのリクエストについてアサーションを行うことができます。 +### テストにおける `HttpClient` の構成 + +テストでインターセプターなどの `HttpClient` の機能を構成する必要がある場合は、`provideHttpClientTesting()` の前に `provideHttpClient(...)` を含めます。 +IMPORTANT: `provideHttpClientTesting()` は `provideHttpClient()` の一部を上書きするため、`provideHttpClient()` を `provideHttpClientTesting()` の**前**に提供することに留意してください。これを逆に行うと、テストが壊れてしまう可能性があります。 + +```ts +TestBed.configureTestingModule({ + providers: [provideHttpClient(withInterceptors([authInterceptor])), provideHttpClientTesting()], +}); +``` + ## リクエストの期待と応答 たとえば、GETリクエストが発生することを期待し、モックレスポンスを提供するテストを作成できます。 ```ts TestBed.configureTestingModule({ - providers: [ConfigService, provideHttpClient(), provideHttpClientTesting()], + providers: [ConfigService, provideHttpClientTesting()], }); const httpTesting = TestBed.inject(HttpTestingController); diff --git a/adev-ja/src/content/guide/i18n/add-package.md b/adev-ja/src/content/guide/i18n/add-package.md index 92f4a6be8..c81ff0a2d 100644 --- a/adev-ja/src/content/guide/i18n/add-package.md +++ b/adev-ja/src/content/guide/i18n/add-package.md @@ -9,7 +9,7 @@ To add the `@angular/localize` package, use the following command to update the It adds `types: ["@angular/localize"]` in the TypeScript configuration files. It also adds line `/// ` at the top of the `main.ts` file which is the reference to the type definition. -HELPFUL: For more information about `package.json` and `tsconfig.json` files, see [Workspace npm dependencies][GuideNpmPackages] and [TypeScript Configuration][GuideTsConfig]. To learn about Triple-slash Directives visit [Typescript Handbook](https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html#-reference-types-). +HELPFUL: For more information about `package.json` and `tsconfig.json` files, see [Workspace npm dependencies][GuideNpmPackages] and [TypeScript Configuration][GuideTsConfig]. To learn about Triple-slash Directives visit [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html#-reference-types-). If `@angular/localize` is not installed and you try to build a localized version of your project (for example, while using the `i18n` attributes in templates), the [Angular CLI][CliMain] will generate an error, which would contain the steps that you can take to enable i18n for your project. diff --git a/adev-ja/src/content/guide/image-optimization.en.md b/adev-ja/src/content/guide/image-optimization.en.md index 2d5d14be7..a09871404 100644 --- a/adev-ja/src/content/guide/image-optimization.en.md +++ b/adev-ja/src/content/guide/image-optimization.en.md @@ -468,7 +468,7 @@ For maintenance reasons, we don't currently plan to support additional built-in No, but this is on our roadmap, so stay tuned. -If you're waiting on this feature, please upvote the Github issue [here](https://github.com/angular/angular/issues/56594). +If you're waiting on this feature, please upvote the GitHub issue [here](https://github.com/angular/angular/issues/56594). ### How do I find my LCP image with Chrome DevTools? diff --git a/adev-ja/src/content/guide/image-optimization.md b/adev-ja/src/content/guide/image-optimization.md index 23b147329..a0ac18467 100644 --- a/adev-ja/src/content/guide/image-optimization.md +++ b/adev-ja/src/content/guide/image-optimization.md @@ -468,7 +468,7 @@ providers: [ いいえ、しかしこれは私たちのロードマップにありますので、ご期待ください。 -この機能を待っている場合は、Githubのイシューを[こちら](https://github.com/angular/angular/issues/56594)でアップボートしてください。 +この機能を待っている場合は、GitHubのイシューを[こちら](https://github.com/angular/angular/issues/56594)でアップボートしてください。 ### Chrome DevToolsでLCP画像を見つけるにはどうすればよいですか? {#how-do-i-find-my-lcp-image-with-chrome-devtools} diff --git a/adev-ja/src/content/guide/signals/effect.md b/adev-ja/src/content/guide/signals/effect.md index 3d3e66205..0f02c3558 100644 --- a/adev-ja/src/content/guide/signals/effect.md +++ b/adev-ja/src/content/guide/signals/effect.md @@ -3,6 +3,8 @@ Signals are useful because they notify interested consumers when they change. An **effect** is an operation that runs whenever one or more signal values change. You can create an effect with the `effect` function: ```ts +import {effect} from '@angular/core'; + effect(() => { console.log(`The current count is: ${count()}`); }); diff --git a/adev-ja/src/content/guide/signals/overview.en.md b/adev-ja/src/content/guide/signals/overview.en.md index c558ec1b6..f4d71d4c4 100644 --- a/adev-ja/src/content/guide/signals/overview.en.md +++ b/adev-ja/src/content/guide/signals/overview.en.md @@ -75,7 +75,7 @@ IMPORTANT: The readonly signals do **not** have any built-in mechanism that woul ### Computed signals -**Computed signal** are read-only signals that derive their value from other signals. You define computed signals using the `computed` function and specifying a derivation: +**Computed signals** are read-only signals that derive their value from other signals. You define computed signals using the `computed` function and specifying a derivation: ```typescript const count: WritableSignal = signal(0); diff --git a/adev-ja/src/content/guide/signals/resource.en.md b/adev-ja/src/content/guide/signals/resource.en.md index ddff96f5f..64a5642eb 100644 --- a/adev-ja/src/content/guide/signals/resource.en.md +++ b/adev-ja/src/content/guide/signals/resource.en.md @@ -28,7 +28,7 @@ const firstName = computed(() => { if (userResource.hasValue()) { // `hasValue` serves 2 purposes: // - It acts as type guard to strip `undefined` from the type - // - If protects against reading a throwing `value` when the resource is in error state + // - It protects against reading a throwing `value` when the resource is in error state return userResource.value().firstName; } @@ -116,11 +116,11 @@ The `status` signal provides a specific `ResourceStatus` that describes the stat | `'idle'` | `undefined` | The resource has no valid request and the loader has not run. | | `'error'` | `undefined` | The loader has encountered an error. | | `'loading'` | `undefined` | The loader is running as a result of the `params` value changing. | -| `'reloading'` | Previous value | The loader is running as a result calling of the resource's `reload` method. | +| `'reloading'` | Previous value | The loader is running as a result of calling the resource's `reload` method. | | `'resolved'` | Resolved value | The loader has completed. | | `'local'` | Locally set value | The resource's value has been set locally via `.set()` or `.update()` | -You can use this status information to conditionally display user interface elements, such loading indicators and error messages. +You can use this status information to conditionally display user interface elements, such as loading indicators and error messages. ## Reactive data fetching with `httpResource` diff --git a/adev-ja/src/content/guide/signals/resource.md b/adev-ja/src/content/guide/signals/resource.md index 6a796cabc..83bebb81f 100644 --- a/adev-ja/src/content/guide/signals/resource.md +++ b/adev-ja/src/content/guide/signals/resource.md @@ -28,7 +28,7 @@ const firstName = computed(() => { if (userResource.hasValue()) { // `hasValue` serves 2 purposes: // - It acts as type guard to strip `undefined` from the type - // - If protects against reading a throwing `value` when the resource is in error state + // - It protects against reading a throwing `value` when the resource is in error state return userResource.value().firstName; } diff --git a/adev-ja/src/content/guide/ssr.en.md b/adev-ja/src/content/guide/ssr.en.md index eca4beb22..7fa99205a 100644 --- a/adev-ja/src/content/guide/ssr.en.md +++ b/adev-ja/src/content/guide/ssr.en.md @@ -432,7 +432,7 @@ To configure this, update your `angular.json` file as follows: You can customize how Angular caches HTTP responses during server‑side rendering (SSR) and reuses them during hydration by configuring `HttpTransferCacheOptions`. This configuration is provided globally using `withHttpTransferCacheOptions` inside `provideClientHydration()`. -By default, `HttpClient` caches all `HEAD` and `GET` requests which don't contain `Authorization` or `Proxy-Authorization` headers. You can override those settings by using `withHttpTransferCacheOptions` to the hydration configuration. +By default, `HttpClient` caches all `HEAD` and `GET` requests which don't contain `Authorization`, `Proxy-Authorization`, or `Cookie` headers and are not sent with `withCredentials`. You can override those settings by using `withHttpTransferCacheOptions` to the hydration configuration. ```ts import {bootstrapApplication} from '@angular/platform-browser'; @@ -486,8 +486,8 @@ Use this only when `POST` requests are **idempotent** and safe to reuse between ### `includeRequestsWithAuthHeaders` -Determines whether requests containing `Authorization` or `Proxy‑Authorization` headers are eligible for caching. -By default, these are excluded to prevent caching user‑specific responses. +Determines whether requests containing `Authorization`, `Proxy‑Authorization`, or `Cookie` headers are eligible for caching. +By default, these are excluded to prevent caching user‑specific responses. Requests sent with `withCredentials` are also excluded by default. ```ts withHttpTransferCacheOptions({ diff --git a/adev-ja/src/content/guide/ssr.md b/adev-ja/src/content/guide/ssr.md index 52475a06f..3ebc57344 100644 --- a/adev-ja/src/content/guide/ssr.md +++ b/adev-ja/src/content/guide/ssr.md @@ -432,7 +432,7 @@ IMPORTANT: 上記のトークンは、次のシナリオでは `null` になり サーバーサイドレンダリング (SSR) 中にAngularがHTTPレスポンスをキャッシュし、ハイドレーション中にそれらを再利用する方法を、`HttpTransferCacheOptions` を設定することでカスタマイズできます。 この設定は、`provideClientHydration()` 内で `withHttpTransferCacheOptions` を使用してグローバルに提供されます。 -デフォルトでは、`HttpClient` は `Authorization` または `Proxy-Authorization` ヘッダーを含まないすべての `HEAD` および `GET` リクエストをキャッシュします。ハイドレーション設定に `withHttpTransferCacheOptions` を使用することで、これらの設定をオーバーライドできます。 +デフォルトでは、`HttpClient` は `Authorization`、`Proxy-Authorization`、または `Cookie` ヘッダーを含まず、`withCredentials` で送信されないすべての `HEAD` および `GET` リクエストをキャッシュします。ハイドレーション設定に `withHttpTransferCacheOptions` を使用することで、これらの設定をオーバーライドできます。 ```ts import {bootstrapApplication} from '@angular/platform-browser'; @@ -486,8 +486,8 @@ withHttpTransferCacheOptions({ ### `includeRequestsWithAuthHeaders` {#includerequestswithauthheaders} -`Authorization` または `Proxy-Authorization` ヘッダーを含むリクエストをキャッシュ対象とするかどうかを決定します。 -デフォルトでは、ユーザー固有のレスポンスのキャッシュを防ぐために、これらは除外されます。 +`Authorization`、`Proxy‑Authorization`、または `Cookie` ヘッダーを含むリクエストをキャッシュ対象とするかどうかを決定します。 +デフォルトでは、ユーザー固有のレスポンスのキャッシュを防ぐために、これらは除外されます。`withCredentials` で送信されるリクエストもデフォルトで除外されます。 ```ts withHttpTransferCacheOptions({ diff --git a/adev-ja/src/content/guide/templates/defer.en.md b/adev-ja/src/content/guide/templates/defer.en.md index cee24edc0..f2ee96031 100644 --- a/adev-ja/src/content/guide/templates/defer.en.md +++ b/adev-ja/src/content/guide/templates/defer.en.md @@ -349,6 +349,37 @@ By default, when rendering an application on the server (either using SSR or SSG To render the main content of `@defer` blocks on the server (both SSR and SSG), you can enable [the Incremental Hydration feature](/guide/incremental-hydration) and configure `hydrate` triggers for the necessary blocks. +## Barrel files and lazy chunks + +If you're using `@defer` but not seeing a separate lazy chunk in your build output, check how you're importing the deferred component. Importing through a barrel file (`index.ts`) is a common culprit — bundlers see the barrel as a single module and keep all its exports together, so your component ends up in the main bundle regardless of `@defer`. + +```typescript +// index.ts +export {HeavyComponent} from './heavy.component'; +export {OtherComponent} from './other.component'; +``` + +```typescript +// parent.component.ts +import {HeavyComponent} from './index'; // pulls in OtherComponent too + +@Component({ + imports: [HeavyComponent], + template: `@defer { + + }`, +}) +export class ParentComponent {} +``` + +The fix is straightforward — import directly from the component's own file: + +```typescript +import {HeavyComponent} from './heavy.component'; +``` + +That's enough for the bundler to split it into its own chunk and load it lazily when the trigger fires. + ## Best practices for deferring views ### Avoid cascading loads with nested `@defer` blocks diff --git a/adev-ja/src/content/guide/templates/defer.md b/adev-ja/src/content/guide/templates/defer.md index 4bc5889ab..5933dc3d4 100644 --- a/adev-ja/src/content/guide/templates/defer.md +++ b/adev-ja/src/content/guide/templates/defer.md @@ -349,6 +349,37 @@ it('さまざまな状態で`@defer`ブロックをレンダリングする', as サーバー上(SSRとSSGの両方)で`@defer`ブロックのメインコンテンツをレンダリングするには、[Incremental Hydration機能](/guide/incremental-hydration)を有効にして、必要なブロックの`hydrate`トリガーを構成できます。 +## Barrel files and lazy chunks + +If you're using `@defer` but not seeing a separate lazy chunk in your build output, check how you're importing the deferred component. Importing through a barrel file (`index.ts`) is a common culprit — bundlers see the barrel as a single module and keep all its exports together, so your component ends up in the main bundle regardless of `@defer`. + +```typescript +// index.ts +export {HeavyComponent} from './heavy.component'; +export {OtherComponent} from './other.component'; +``` + +```typescript +// parent.component.ts +import {HeavyComponent} from './index'; // pulls in OtherComponent too + +@Component({ + imports: [HeavyComponent], + template: `@defer { + + }`, +}) +export class ParentComponent {} +``` + +The fix is straightforward — import directly from the component's own file: + +```typescript +import {HeavyComponent} from './heavy.component'; +``` + +That's enough for the bundler to split it into its own chunk and load it lazily when the trigger fires. + ## ビューを遅延させるためのベストプラクティス ### ネストされた`@defer`ブロックによるカスケード読み込みを避ける diff --git a/adev-ja/src/content/guide/templates/event-listeners.en.md b/adev-ja/src/content/guide/templates/event-listeners.en.md index 151677be7..8c0134f6f 100644 --- a/adev-ja/src/content/guide/templates/event-listeners.en.md +++ b/adev-ja/src/content/guide/templates/event-listeners.en.md @@ -96,7 +96,7 @@ Angular also allows you to specify [Code values for keyboard events](https://dev ``` -This can be useful for handling keyboard events consistently across different operating systems. For example, when using the Alt key on MacOS devices, the `key` property reports the key based on the character already modified by the Alt key. This means that a combination like Alt + S reports a `key` value of `'ß'`. The `code` property, however, corresponds to the physical or virtual button pressed rather than the character produced. +This can be useful for handling keyboard events consistently across different operating systems. For example, when using the Alt key on macOS devices, the `key` property reports the key based on the character already modified by the Alt key. This means that a combination like Alt + S reports a `key` value of `'ß'`. The `code` property, however, corresponds to the physical or virtual button pressed rather than the character produced. ## Listening on global targets diff --git a/adev-ja/src/content/guide/templates/pipes.en.md b/adev-ja/src/content/guide/templates/pipes.en.md index ec8ccf5ce..396af6103 100644 --- a/adev-ja/src/content/guide/templates/pipes.en.md +++ b/adev-ja/src/content/guide/templates/pipes.en.md @@ -2,7 +2,7 @@ ## Overview -Pipes are a special operator in Angular template expressions that allows you to transform data declaratively in your template. Pipes let you declare a transformation function once and then use that transformation across multiple templates. Angular pipes use the vertical bar character (`|`), inspired by the [Unix pipe](). +Pipes are special operators in Angular template expressions that allow you to transform data declaratively in your template. Pipes let you declare a transformation function once and then use that transformation across multiple templates. Angular pipes use the vertical bar character (`|`), inspired by the [Unix pipe](). NOTE: Angular's pipe syntax deviates from standard JavaScript, which uses the vertical bar character for the [bitwise OR operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_OR). Angular template expressions do not support bitwise operators. @@ -33,7 +33,7 @@ export class ShoppingCart { } ``` -When Angular renders the component, it will ensure that the appropriate date format and currency is based on the locale of the user. If the user is in the United States, it would render: +When Angular renders the component, it will ensure that the appropriate date format and currency are based on the locale of the user. If the user is in the United States, it would render: ```angular-html
@@ -162,7 +162,7 @@ Always use parentheses in your expressions when operator precedence may be ambig ### Change detection with pipes -By default, all pipes are considered `pure`, which means that it only executes when a primitive input value (such as a `String`, `Number`, `Boolean`, or `Symbol`) or a object reference (such as `Array`, `Object`, `Function`, or `Date`) is changed. Pure pipes offer a performance advantage because Angular can avoid calling the transformation function if the passed value has not changed. +By default, all pipes are considered `pure`, which means that they only execute when a primitive input value (such as a `String`, `Number`, `Boolean`, or `Symbol`) or an object reference (such as `Array`, `Object`, `Function`, or `Date`) is changed. Pure pipes offer a performance advantage because Angular can avoid calling the transformation function if the passed value has not changed. As a result, this means that mutations to object properties or array items are not detected unless the entire object or array reference is replaced with a different instance. If you want this level of change detection, refer to [detecting changes within arrays or objects](#detecting-change-within-arrays-or-objects). diff --git a/adev-ja/src/content/guide/templates/pipes.md b/adev-ja/src/content/guide/templates/pipes.md index bdf115953..9c94cd98d 100644 --- a/adev-ja/src/content/guide/templates/pipes.md +++ b/adev-ja/src/content/guide/templates/pipes.md @@ -162,7 +162,7 @@ export class AppComponent { ### パイプによる変更検知 -By default, all pipes are considered `pure`, which means that it only executes when a primitive input value (such as a `String`, `Number`, `Boolean`, or `Symbol`) or a object reference (such as `Array`, `Object`, `Function`, or `Date`) is changed. Pure pipes offer a performance advantage because Angular can avoid calling the transformation function if the passed value has not changed. +デフォルトでは、すべてのパイプは`pure`とみなされます。これは、プリミティブな入力値(`String`、`Number`、`Boolean`、`Symbol`など)またはオブジェクト参照(`Array`、`Object`、`Function`、`Date`など)が変更されたときにのみ実行されることを意味します。Pureなパイプは、渡された値が変更されていない場合にAngularが変換関数の呼び出しを回避できるため、パフォーマンス上の利点があります。 その結果、オブジェクトプロパティや配列項目の変更は、オブジェクトまたは配列参照の全体が別のインスタンスに置き換えられない限り検出されません。このレベルの変更検知が必要な場合は、[配列やオブジェクト内の変更の検出](#detecting-change-within-arrays-or-objects)を参照してください。 diff --git a/adev-ja/src/content/guide/templates/variables.en.md b/adev-ja/src/content/guide/templates/variables.en.md index 9e8f69d1c..e262dd77f 100644 --- a/adev-ja/src/content/guide/templates/variables.en.md +++ b/adev-ja/src/content/guide/templates/variables.en.md @@ -2,6 +2,8 @@ Angular has two types of variable declarations in templates: local template variables and template reference variables. +HELPFUL: In this guide, “template” does not mean the entire HTML template file. It refers only to a specific template construct or expression within the file. + ## Local template variables with `@let` Angular's `@let` syntax allows you to define a local variable and re-use it across a template, similar to the [JavaScript `let` syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let). @@ -194,3 +196,35 @@ export class AppComponent { ``` See [Referencing children with queries](/guide/components/queries) for more information on queries. + +### Template variable scope + +Just like variables in JavaScript or TypeScript code, template variables are scoped to the template that declares them. + +Similarly, [Structural directives](guide/directives/structural-directives) or `` declarations create a new nested template scope, much like JavaScript's control flow statements like `if` and `for` create new lexical scopes. You cannot access template variables within one of these structural directives from outside of its boundaries. + +HELPFUL: Define a variable only once in the template so the runtime value remains predictable. + +#### Accessing in a nested template + +An inner template can access template variables that the outer template defines. + +In the following example, changing the text in the `` changes the value in the `` because Angular immediately updates changes through the template variable, `ref1`. + +```html + + +Value: {{ ref1.value }} +``` + +In this case, the `*ngIf` on `` creates a new template scope, which includes the `ref1` variable from its parent scope. + +However, accessing a template variable from a child scope in the parent template doesn't work: + +```html {avoid} + + +Value: {{ ref2?.value }} +``` + +Here, `ref2` is declared in the child scope created by `*ngIf`, and is not accessible from the parent template. diff --git a/adev-ja/src/content/guide/templates/variables.md b/adev-ja/src/content/guide/templates/variables.md index fee97e0c8..fff925e72 100644 --- a/adev-ja/src/content/guide/templates/variables.md +++ b/adev-ja/src/content/guide/templates/variables.md @@ -2,6 +2,8 @@ Angularには、テンプレート内で2種類の変数宣言があります。 ローカルテンプレート変数とテンプレート参照変数です。 +HELPFUL: In this guide, “template” does not mean the entire HTML template file. It refers only to a specific template construct or expression within the file. + ## `@let` を使ったローカルテンプレート変数 Angularの `@let` 構文を使用すると、ローカル変数を定義し、テンプレート全体で再利用できます。これは、[JavaScriptの`let`構文](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let)に似ています。 @@ -194,3 +196,35 @@ export class AppComponent { ``` クエリの詳細については、[クエリによる子の参照](/guide/components/queries)を参照してください。 + +### Template variable scope + +Just like variables in JavaScript or TypeScript code, template variables are scoped to the template that declares them. + +Similarly, [Structural directives](guide/directives/structural-directives) or `` declarations create a new nested template scope, much like JavaScript's control flow statements like `if` and `for` create new lexical scopes. You cannot access template variables within one of these structural directives from outside of its boundaries. + +HELPFUL: Define a variable only once in the template so the runtime value remains predictable. + +#### Accessing in a nested template + +An inner template can access template variables that the outer template defines. + +In the following example, changing the text in the `` changes the value in the `` because Angular immediately updates changes through the template variable, `ref1`. + +```html + + +Value: {{ ref1.value }} +``` + +In this case, the `*ngIf` on `` creates a new template scope, which includes the `ref1` variable from its parent scope. + +However, accessing a template variable from a child scope in the parent template doesn't work: + +```html {avoid} + + +Value: {{ ref2?.value }} +``` + +Here, `ref2` is declared in the child scope created by `*ngIf`, and is not accessible from the parent template. diff --git a/adev-ja/src/content/guide/testing/migrating-to-vitest.en.md b/adev-ja/src/content/guide/testing/migrating-to-vitest.en.md index aef9828e9..7d8e7eccc 100644 --- a/adev-ja/src/content/guide/testing/migrating-to-vitest.en.md +++ b/adev-ja/src/content/guide/testing/migrating-to-vitest.en.md @@ -92,7 +92,7 @@ Choose one of the following browser providers based on your needs: - **Playwright**: `@vitest/browser-playwright` for Chromium, Firefox, and WebKit. - **WebdriverIO**: `@vitest/browser-webdriverio` for Chrome, Firefox, Safari, and Edge. -- **Preview**: `@vitest/browser-preview` for Webcontainer environments (like StackBlitz). +- **Preview**: `@vitest/browser-preview` for WebContainer environments (like StackBlitz). @@ -132,8 +132,6 @@ Add the `browsers` option to your `test` target's options. The browser name depe Headless mode is enabled automatically if the `CI` environment variable is set or if a browser name includes "Headless" (e.g., `ChromeHeadless`). Otherwise, tests will run in a headed browser. -NOTE: Debugging with `ng test --debug` is not supported by browser mode. - ## Automated test refactoring with schematics IMPORTANT: The `refactor-jasmine-vitest` schematic is experimental and may not cover all possible test patterns. Always review the changes made by the schematic. diff --git a/adev-ja/src/content/guide/testing/migrating-to-vitest.md b/adev-ja/src/content/guide/testing/migrating-to-vitest.md index b8998e2a3..77c39f243 100644 --- a/adev-ja/src/content/guide/testing/migrating-to-vitest.md +++ b/adev-ja/src/content/guide/testing/migrating-to-vitest.md @@ -92,7 +92,7 @@ IMPORTANT: 既存のプロジェクトをVitestに移行することは実験的 - **Playwright**: Chromium、Firefox、WebKit用の`@vitest/browser-playwright`。 - **WebdriverIO**: Chrome、Firefox、Safari、Edge用の`@vitest/browser-webdriverio`。 -- **Preview**: Webcontainer環境(StackBlitzなど)用の`@vitest/browser-preview`。 +- **Preview**: WebContainer環境(StackBlitzなど)用の`@vitest/browser-preview`。 @@ -132,8 +132,6 @@ IMPORTANT: 既存のプロジェクトをVitestに移行することは実験的 ヘッドレスモードは、`CI`環境変数が設定されている場合や、ブラウザ名に"Headless"が含まれている場合(例: `ChromeHeadless`)に自動的に有効になります。それ以外の場合、テストはヘッド付きブラウザで実行されます。 -NOTE: `ng test --debug`を使用したデバッグは、ブラウザモードではサポートされていません。 - ## schematicsによる自動テストリファクタリング {#automated-test-refactoring-with-schematics} IMPORTANT: `refactor-jasmine-vitest` schematicは実験的なものであり、すべての可能なテストパターンをカバーしているとは限りません。schematicによって行われた変更は必ずレビューしてください。 diff --git a/adev-ja/src/content/guide/testing/overview.en.md b/adev-ja/src/content/guide/testing/overview.en.md index 4dddcfda5..7ed2e0866 100644 --- a/adev-ja/src/content/guide/testing/overview.en.md +++ b/adev-ja/src/content/guide/testing/overview.en.md @@ -53,11 +53,10 @@ The `setupFiles` and `providersFile` options are particularly useful for managin For example, you could create a `src/test-providers.ts` file to provide `provideHttpClientTesting` to all your tests: ```typescript {header: "src/test-providers.ts"} -import {Provider} from '@angular/core'; -import {provideHttpClient} from '@angular/common/http'; +import {EnvironmentProviders, Provider} from '@angular/core'; import {provideHttpClientTesting} from '@angular/common/http/testing'; -const testProviders: Provider[] = [provideHttpClient(), provideHttpClientTesting()]; +const testProviders: (Provider | EnvironmentProviders)[] = [provideHttpClientTesting()]; export default testProviders; ``` @@ -188,7 +187,7 @@ Choose one of the following browser providers based on your needs: ### Preview -The `@vitest/browser-preview` provider is designed for Webcontainer environments like StackBlitz and is not intended for use in CI/CD. +The `@vitest/browser-preview` provider is designed for WebContainer environments like StackBlitz and is not intended for use in CI/CD. diff --git a/adev-ja/src/content/guide/testing/overview.md b/adev-ja/src/content/guide/testing/overview.md index ee1fc8a82..33c1b4bf7 100644 --- a/adev-ja/src/content/guide/testing/overview.md +++ b/adev-ja/src/content/guide/testing/overview.md @@ -53,11 +53,10 @@ Angular CLIは、Vitestの設定のほとんどを処理します。`angular.jso たとえば、`src/test-providers.ts`ファイルを作成して、すべてのテストに`provideHttpClientTesting`を提供できます: ```typescript {header: "src/test-providers.ts"} -import {Provider} from '@angular/core'; -import {provideHttpClient} from '@angular/common/http'; +import {EnvironmentProviders, Provider} from '@angular/core'; import {provideHttpClientTesting} from '@angular/common/http/testing'; -const testProviders: Provider[] = [provideHttpClient(), provideHttpClientTesting()]; +const testProviders: (Provider | EnvironmentProviders)[] = [provideHttpClientTesting()]; export default testProviders; ``` @@ -188,7 +187,7 @@ ng test --browsers=chromeHeadless ### Preview -`@vitest/browser-preview`プロバイダーは、StackBlitzなどのWebcontainer環境向けに設計されており、CI/CDでの使用を目的としていません。 +`@vitest/browser-preview`プロバイダーは、StackBlitzなどのWebContainer環境向けに設計されており、CI/CDでの使用を目的としていません。 diff --git a/adev-ja/src/content/introduction/installation.en.md b/adev-ja/src/content/introduction/installation.en.md index a6538b3e2..b8051f512 100644 --- a/adev-ja/src/content/introduction/installation.en.md +++ b/adev-ja/src/content/introduction/installation.en.md @@ -62,7 +62,7 @@ If you are having issues running this command in Windows or Unix, check out the #### Create a new project -In your terminal, run the CLI command `ng new` with the desired project name. In the following examples, we'll be using the example project name of `my-first-angular-app`. +In your terminal, run the CLI command [`ng new`](cli/new) with the desired project name. In the following examples, we'll be using the example project name of `my-first-angular-app`. ```shell ng new diff --git a/adev-ja/src/content/introduction/installation.md b/adev-ja/src/content/introduction/installation.md index 7cd4ecc5c..002f5255f 100644 --- a/adev-ja/src/content/introduction/installation.md +++ b/adev-ja/src/content/introduction/installation.md @@ -62,7 +62,7 @@ WindowsまたはUnixでこのコマンドを実行する際に問題が発生し #### 新しいプロジェクトを作成する {#create-a-new-project} -ターミナルで、CLIコマンド`ng new`を実行し、目的のプロジェクト名を入力します。次の例では、`my-first-angular-app`というプロジェクト名を使用します。 +ターミナルで、CLIコマンド[`ng new`](cli/new)を実行し、目的のプロジェクト名を入力します。次の例では、`my-first-angular-app`というプロジェクト名を使用します。 ```shell ng new diff --git a/adev-ja/src/content/introduction/what-is-angular.en.md b/adev-ja/src/content/introduction/what-is-angular.en.md index 82c6dd0e2..809c93a9c 100644 --- a/adev-ja/src/content/introduction/what-is-angular.en.md +++ b/adev-ja/src/content/introduction/what-is-angular.en.md @@ -108,7 +108,7 @@

Angular partners closely with other Google technologies and teams to improve the web.

Our ongoing partnership with Chrome’s Aurora actively explores improvements to user experience across the web, developing built-in performance optimizations like NgOptimizedImage and improvements to Angular’s Core Web Vitals.

-

We are also working with Firebase, Tensorflow, Flutter, Material Design, and Google Cloud to ensure we provide meaningful integrations across the developer workflow.

+

We are also working with Firebase, Tensorflow, Flutter, Material Design, and Google Cloud to ensure we provide meaningful integrations across the developer workflow.

diff --git a/adev-ja/src/content/introduction/what-is-angular.md b/adev-ja/src/content/introduction/what-is-angular.md index 90f6fcffe..5b8c44e4e 100644 --- a/adev-ja/src/content/introduction/what-is-angular.md +++ b/adev-ja/src/content/introduction/what-is-angular.md @@ -108,7 +108,7 @@

Angularは、Webを改善するために他のGoogleテクノロジーやチームと緊密に連携しています。

ChromeのAuroraとの継続的なパートナーシップは、NgOptimizedImageなどの組み込みパフォーマンス最適化やAngularのCore Web Vitalsの改善など、Web全体でユーザー体験の向上を積極的に模索しています。

-

また、FirebaseTensorflowFlutterMaterial DesignGoogle Cloudと連携して、開発者ワークフロー全体で有意義な統合を提供しています。

+

また、FirebaseTensorflowFlutterMaterial DesignGoogle Cloudと連携して、開発者ワークフロー全体で有意義な統合を提供しています。

diff --git a/adev-ja/src/content/reference/configs/angular-compiler-options.md b/adev-ja/src/content/reference/configs/angular-compiler-options.md index 4fccf7bef..3a5e57ca7 100644 --- a/adev-ja/src/content/reference/configs/angular-compiler-options.md +++ b/adev-ja/src/content/reference/configs/angular-compiler-options.md @@ -60,7 +60,7 @@ The default value is `'full'`. For most applications, `'full'` is the correct compilation mode. -Use `'partial'` for independently published libraries, such as NPM packages. +Use `'partial'` for independently published libraries, such as npm packages. `'partial'` compilations output a stable, intermediate format which better supports usage by applications built at different Angular versions from the library. Libraries built at "HEAD" alongside their applications and using the same version of Angular such as in a mono-repository can use `'full'` since there is no risk of version skew. @@ -222,6 +222,11 @@ When `true`, reports an error if a component, directive, or pipe is not standalo When `true`, prints extra information while compiling templates. Default is `false`. +### `typeCheckHostBindings` + +When `true`, enables type checking of expressions in the `host` object literal and `@HostBinding`/`@HostListener` decorators of components and directives. +Default is `true`. + ## Command line options Most of the time, you interact with the Angular Compiler indirectly using [Angular CLI](reference/configs/angular-compiler-options). When debugging certain issues, you might find it useful to invoke the Angular Compiler directly. diff --git a/adev-ja/src/content/reference/migrations/outputs.md b/adev-ja/src/content/reference/migrations/outputs.md index 6b9ae54c8..d08328432 100644 --- a/adev-ja/src/content/reference/migrations/outputs.md +++ b/adev-ja/src/content/reference/migrations/outputs.md @@ -16,7 +16,7 @@ ng generate @angular/core:output-migration ## What does the migration change? 1. `@Output()` class members are updated to their `output()` equivalent. -2. Imports in the file of components or directives, at Typescript module level, are updated as well. +2. Imports in the file of components or directives, at TypeScript module level, are updated as well. 3. Migrates API calls like `event.next()`, whose use is not recommended, to `event.emit()` and removes `event.complete()` calls. **Before** diff --git a/adev-ja/src/content/reference/releases.en.md b/adev-ja/src/content/reference/releases.en.md index 1f1303b8a..c07b09d76 100644 --- a/adev-ja/src/content/reference/releases.en.md +++ b/adev-ja/src/content/reference/releases.en.md @@ -19,7 +19,7 @@ To make these transitions as straightforward as possible, the Angular team makes - We follow the deprecation policy described here, so you have time to update your applications to the latest APIs and best practices HELPFUL: The practices described in this document apply to Angular 2.0 and later. -If you are currently using AngularJS, see [Upgrading from AngularJS](https://angular.io/guide/upgrade 'Upgrading from Angular JS'). +If you are currently using AngularJS, see [Upgrading from AngularJS](https://angular.io/guide/upgrade 'Upgrading from AngularJS'). _AngularJS_ is the name for all v1.x versions of Angular. ## Angular versioning @@ -97,9 +97,8 @@ The following table provides the status for Angular versions under support. | :------ | :----- | :--------- | :---------- | :--------- | | ^21.0.0 | Active | 2025-11-19 | 2026-05-19 | 2027-05-19 | | ^20.0.0 | LTS | 2025-05-28 | 2025-11-19 | 2026-11-28 | -| ^19.0.0 | LTS | 2024-11-19 | 2025-05-28 | 2026-05-19 | -Angular versions v2 to v18 are no longer supported. +Angular versions v2 to v19 are no longer supported. ### LTS fixes diff --git a/adev-ja/src/content/reference/releases.md b/adev-ja/src/content/reference/releases.md index 03c1c3383..8f309ee12 100644 --- a/adev-ja/src/content/reference/releases.md +++ b/adev-ja/src/content/reference/releases.md @@ -19,7 +19,7 @@ _破壊的変更_ はAPIや機能の削除など、進化するベストプラ - ここに記載されている非推奨ポリシーに従うため、アプリケーションを最新のAPIとベストプラクティスに更新するための時間があります。 HELPFUL: このドキュメントに記載されている慣行は、Angular 2.0以降に適用されます。 -現在AngularJSを使用している場合は、[AngularJS からアップグレード](https://angular.io/guide/upgrade 'Angular JS からアップグレード')をご覧ください。 +現在AngularJSを使用している場合は、[AngularJS からアップグレード](https://angular.io/guide/upgrade 'AngularJSからアップグレード')をご覧ください。 _AngularJS_ は、Angularのすべてのv1.xバージョンの名前です。 ## Angular のバージョン管理 {#angular-versioning} @@ -97,9 +97,8 @@ HELPFUL: 概算の日付は一般的なガイダンスとして提供されて | :--------- | :--------- | :----------- | :------------- | :--------- | | ^21.0.0 | Active | 2025-11-19 | 2026-05-19 | 2027-05-19 | | ^20.0.0 | LTS | 2025-05-28 | 2025-11-19 | 2026-11-28 | -| ^19.0.0 | LTS | 2024-11-19 | 2025-05-28 | 2026-05-19 | -Angularバージョンv2からv18はサポートされなくなりました。 +Angularバージョンv2からv19はサポートされなくなりました。 ### LTSの修正 {#lts-fixes} diff --git a/adev-ja/src/content/reference/roadmap.en.md b/adev-ja/src/content/reference/roadmap.en.md index 93696b79f..ec24b3573 100644 --- a/adev-ja/src/content/reference/roadmap.en.md +++ b/adev-ja/src/content/reference/roadmap.en.md @@ -109,7 +109,7 @@ In Angular v19 we shipped initial support for CSS and template HMR and in v20 we In v18 we shipped experimental zoneless support in Angular. It enables developers to use the framework without including zone.js in their bundle, which improves performance, debugging experience, and interoperability. As part of the initial release we also introduced zoneless support to the Angular CDK and Angular Material. -In v19 we introduced zoneless support in server-side rendering, addressed some edge cases, and created a schematic to scaffold zoneless projects. We transitioned Google Fonts to zoneless which improved performance, developer experience, and allowed us to identify gaps that we need to address before moving this feature to developer preview. +In v19 we introduced zoneless support in server-side rendering, addressed some edge cases, and created a schematic to scaffold zoneless projects. We transitioned Google Fonts to zoneless which improved performance, developer experience, and allowed us to identify gaps that we need to address before moving this feature to developer preview. As of Angular v20.2, Zoneless Angular is now stable and includes improvements in error handling and server-side rendering. @@ -163,7 +163,7 @@ In v17 we shipped a vite and esbuild-based application builder and enabled it fo Angular.dev is the new site, domain and home for Angular development. The new site contains updated documentation, tutorials and guidance that will help developers build with Angular’s latest features. - + In v17 we shipped a developer preview version of a new control flow. It brings significant performance improvements and better ergonomics for template authoring. We also provided a migration of existing `*ngIf`, `*ngFor`, and `*ngSwitch` which you can run to move your project to the new implementation. As of v18 the built-in control flow is now stable. @@ -175,7 +175,7 @@ In Angular v16, we released a developer preview of an esbuild-based builder with To improve the debugging utilities of Angular and Angular DevTools, we'll work on APIs that provide access to the dependency injection runtime. As part of the project, we'll expose debugging methods that allow us to explore the injector hierarchy and the dependencies across their associated providers. As of v17, we shipped a feature that enables us to plug into the dependency injection life-cycle. We also launched a visualization of the injector tree and inspection of the providers declared inside each individual node, - + We released a developer preview of the `ng new --standalone` schematics collection, allowing you to create apps free of NgModules. In v17 we switched the new application authoring format to standalone APIs and changed the documentation to reflect the recommendation. Additionally, we shipped schematics which support updating existing applications to standalone components, directives, and pipes. Even though NgModules will stick around for foreseeable future, we recommend you to explore the benefits of the new APIs to improve developer experience and benefit from the new features we build for them. diff --git a/adev-ja/src/content/reference/roadmap.md b/adev-ja/src/content/reference/roadmap.md index fac4344cb..200912afd 100644 --- a/adev-ja/src/content/reference/roadmap.md +++ b/adev-ja/src/content/reference/roadmap.md @@ -109,7 +109,7 @@ Angular v19では、CSSとテンプレートのHMRの初期サポートを提供 v18では、Angularに実験的なZonelessサポートを提供しました。これにより、バンドルにzone.jsを含めずにフレームワークを使用できるようになり、パフォーマンス、デバッグエクスペリエンス、相互運用性が向上します。初期リリースの一環として、Angular CDKとAngular MaterialにもZonelessサポートを導入しました。 -In v19 we introduced zoneless support in server-side rendering, addressed some edge cases, and created a schematic to scaffold zoneless projects. We transitioned Google Fonts to zoneless which improved performance, developer experience, and allowed us to identify gaps that we need to address before moving this feature to developer preview. +In v19 we introduced zoneless support in server-side rendering, addressed some edge cases, and created a schematic to scaffold zoneless projects. We transitioned Google Fonts to zoneless which improved performance, developer experience, and allowed us to identify gaps that we need to address before moving this feature to developer preview. As of Angular v20.2, Zoneless Angular is now stable and includes improvements in error handling and server-side rendering. @@ -163,7 +163,7 @@ v17では、viteとesbuildベースのアプリケーションビルダーを提 Angular.devは、Angular開発のための新しいサイト・ドメイン・ホームです。新しいサイトには、開発者がAngularの最新機能を使用して構築するのに役立つ、更新されたドキュメント、チュートリアル、およびガイダンスが含まれています。 - + v17では、新しい制御フローの開発者プレビューバージョンを提供しました。これは、テンプレートオーサリングのパフォーマンスを大幅に向上させ、使いやすさを高めます。加えて、既存の`*ngIf`、`*ngFor`、`*ngSwitch`のマイグレーションを提供しており、これを実行してプロジェクトを新しい実装に移行できます。v18以降、組み込みの制御フローは安定しています。 @@ -175,7 +175,7 @@ Angular v16では、`ng build`と`ng serve`をサポートするesbuildベース AngularとAngular DevToolsのデバッグユーティリティを改善するために、依存性の注入ランタイムにアクセスできるAPIに取り組んでいます。このプロジェクトでは、インジェクター階層とその関連するプロバイダー全体での依存関係を探索できるデバッグメソッドを公開します。v17では、依存性の注入のライフサイクルにプラグインできる機能を提供しました。さらに、インジェクターツリーの可視化と、各ノード内に宣言されたプロバイダーの検査を開始しました。 - + `ng new --standalone`シェーマティックコレクションの開発者プレビューをリリースしました。これにより、NgModuleを使用せずにアプリケーションを作成できます。v17では、新しいアプリケーションのオーサリング形式をスタンドアロンAPIに変更し、ドキュメントを反映するように変更しました。加えて、既存のアプリケーションをスタンドアロンコンポーネント・ディレクティブ・パイプに更新するシェーマティックを提供しました。NgModuleは当面の間残りますが、新しいAPIの利点を活用して開発者エクスペリエンスを向上させ、構築した新機能を活用することをお勧めします。 diff --git a/adev-ja/src/content/tools/cli/cli-builder.md b/adev-ja/src/content/tools/cli/cli-builder.md index 64e86541d..cf4f3d01b 100644 --- a/adev-ja/src/content/tools/cli/cli-builder.md +++ b/adev-ja/src/content/tools/cli/cli-builder.md @@ -56,7 +56,7 @@ To create a builder, use the `createBuilder()` CLI Builder function, and return Now let's add some logic to it. -The following code retrieves the source and destination file paths from user options and copies the file from the source to the destination \(using the [Promise version of the built-in NodeJS `copyFile()` function](https://nodejs.org/api/fs.html#fs_fspromises_copyfile_src_dest_mode)\). +The following code retrieves the source and destination file paths from user options and copies the file from the source to the destination \(using the [Promise version of the built-in Node.js `copyFile()` function](https://nodejs.org/api/fs.html#fs_fspromises_copyfile_src_dest_mode)\). If the copy operation fails, it returns an error with a message about the underlying problem. diff --git a/adev-ja/src/content/tools/cli/deployment.en.md b/adev-ja/src/content/tools/cli/deployment.en.md index f89914718..22d72563b 100644 --- a/adev-ja/src/content/tools/cli/deployment.en.md +++ b/adev-ja/src/content/tools/cli/deployment.en.md @@ -33,7 +33,7 @@ You can read more by following the links associated with the package names below | [Firebase hosting](https://firebase.google.com/docs/hosting) | [`ng add @angular/fire`](https://npmjs.org/package/@angular/fire) | | [Vercel](https://vercel.com/solutions/angular) | [`vercel init angular`](https://github.com/vercel/vercel/tree/main/examples/angular) | | [Netlify](https://www.netlify.com) | [`ng add @netlify-builder/deploy`](https://npmjs.org/package/@netlify-builder/deploy) | -| [GitHub pages](https://pages.github.com) | [`ng add angular-cli-ghpages`](https://npmjs.org/package/angular-cli-ghpages) | +| [GitHub Pages](https://pages.github.com) | [`ng add angular-cli-ghpages`](https://npmjs.org/package/angular-cli-ghpages) | | [Amazon Cloud S3](https://aws.amazon.com/s3/?nc2=h_ql_prod_st_s3) | [`ng add @jefiozie/ngx-aws-deploy`](https://www.npmjs.com/package/@jefiozie/ngx-aws-deploy) | If you're deploying to a self-managed server or there's no builder for your favorite cloud platform, you can either [create a builder](tools/cli/cli-builder) that allows you to use the `ng deploy` command, or read through this guide to learn how to manually deploy your application. diff --git a/adev-ja/src/content/tools/cli/deployment.md b/adev-ja/src/content/tools/cli/deployment.md index 347a04778..ef3872342 100644 --- a/adev-ja/src/content/tools/cli/deployment.md +++ b/adev-ja/src/content/tools/cli/deployment.md @@ -33,7 +33,7 @@ ng deploy | [Firebase hosting](https://firebase.google.com/docs/hosting) | [`ng add @angular/fire`](https://npmjs.org/package/@angular/fire) | | [Vercel](https://vercel.com/solutions/angular) | [`vercel init angular`](https://github.com/vercel/vercel/tree/main/examples/angular) | | [Netlify](https://www.netlify.com) | [`ng add @netlify-builder/deploy`](https://npmjs.org/package/@netlify-builder/deploy) | -| [GitHub pages](https://pages.github.com) | [`ng add angular-cli-ghpages`](https://npmjs.org/package/angular-cli-ghpages) | +| [GitHub Pages](https://pages.github.com) | [`ng add angular-cli-ghpages`](https://npmjs.org/package/angular-cli-ghpages) | | [Amazon Cloud S3](https://aws.amazon.com/s3/?nc2=h_ql_prod_st_s3) | [`ng add @jefiozie/ngx-aws-deploy`](https://www.npmjs.com/package/@jefiozie/ngx-aws-deploy) | もし自己管理されたサーバーにデプロイする場合や、お気に入りのクラウドプラットフォームのビルダーがない場合、`ng deploy`コマンドを使うことを許容する[ビルダーを作成する](tools/cli/cli-builder)か、アプリケーションを手動でデプロイする方法を学ぶためのこのガイドを読み通すか、どちらかの方法を取る事が可能です。 diff --git a/adev-ja/src/content/tools/cli/schematics-for-libraries.md b/adev-ja/src/content/tools/cli/schematics-for-libraries.md index beb6ce970..eb59c775c 100644 --- a/adev-ja/src/content/tools/cli/schematics-for-libraries.md +++ b/adev-ja/src/content/tools/cli/schematics-for-libraries.md @@ -63,7 +63,7 @@ Possible values are: To bundle your schematics together with your library, you must configure the library to build the schematics separately, then add them to the bundle. You must build your schematics _after_ you build your library, so they are placed in the correct directory. -- Your library needs a custom Typescript configuration file with instructions on how to compile your schematics into your distributed library +- Your library needs a custom TypeScript configuration file with instructions on how to compile your schematics into your distributed library - To add the schematics to the library bundle, add scripts to the library's `package.json` file Assume you have a library project `my-lib` in your Angular workspace. diff --git a/adev-ja/src/content/tools/cli/setup-local.en.md b/adev-ja/src/content/tools/cli/setup-local.en.md index 58ce7fdbb..ff71578f6 100644 --- a/adev-ja/src/content/tools/cli/setup-local.en.md +++ b/adev-ja/src/content/tools/cli/setup-local.en.md @@ -68,7 +68,7 @@ To install the Angular CLI, open a terminal window and run the following command ### Powershell execution policy On Windows client computers, the execution of PowerShell scripts is disabled by default, so the above command may fail with an error. -To allow the execution of PowerShell scripts, which is needed for npm global binaries, you must set the following execution policy: +To allow the execution of PowerShell scripts, which is needed for npm global binaries, you must set the following execution policy: ```sh diff --git a/adev-ja/src/content/tools/cli/setup-local.md b/adev-ja/src/content/tools/cli/setup-local.md index dcf9eaa0a..3fd3f9e25 100644 --- a/adev-ja/src/content/tools/cli/setup-local.md +++ b/adev-ja/src/content/tools/cli/setup-local.md @@ -68,7 +68,7 @@ Angular CLIをインストールするには、ターミナルウィンドウを ### PowerShell実行ポリシー {#powershell-execution-policy} Windowsクライアントコンピューターでは、PowerShellスクリプトの実行はデフォルトで無効になっているため、上記のコマンドはエラーで失敗する可能性があります。 -npmグローバルバイナリに必要なPowerShellスクリプトの実行を許可するには、次の実行ポリシーを設定する必要があります。 +npmグローバルバイナリに必要なPowerShellスクリプトの実行を許可するには、次の実行ポリシーを設定する必要があります。 ```sh diff --git a/adev-ja/src/content/tools/libraries/angular-package-format.md b/adev-ja/src/content/tools/libraries/angular-package-format.md index 4254feed8..912dbbbec 100644 --- a/adev-ja/src/content/tools/libraries/angular-package-format.md +++ b/adev-ja/src/content/tools/libraries/angular-package-format.md @@ -280,7 +280,7 @@ In this section are the definitions of all of them to provide additional clarity ### Package -The smallest set of files that are published to NPM and installed together, for example `@angular/core`. +The smallest set of files that are published to npm and installed together, for example `@angular/core`. This package includes a manifest called package.json, compiled source code, typescript definition files, source maps, metadata, etc. The package is installed with `npm install @angular/core`. diff --git a/adev-ja/src/content/tools/libraries/creating-libraries.md b/adev-ja/src/content/tools/libraries/creating-libraries.md index da4cda818..c1a755b2c 100644 --- a/adev-ja/src/content/tools/libraries/creating-libraries.md +++ b/adev-ja/src/content/tools/libraries/creating-libraries.md @@ -23,7 +23,7 @@ You should be very careful when choosing the name of your library if you want to See [Publishing your library](tools/libraries/creating-libraries#publishing-your-library). Avoid using a name that is prefixed with `ng-`, such as `ng-library`. -The `ng-` prefix is a reserved keyword used from the Angular framework and its libraries. +The `ng-` prefix is a reserved keyword used by the Angular framework and its libraries. The `ngx-` prefix is preferred as a convention used to denote that the library is suitable for use with Angular. It is also an excellent indication to consumers of the registry to differentiate between libraries of different JavaScript frameworks. @@ -242,7 +242,7 @@ TypeScript path mappings should _not_ point to the library source `.ts` files. This section explains how to use your package manager's local linking feature (such as [`npm link`](https://docs.npmjs.com/cli/v11/commands/npm-link) or [`pnpm link`](https://pnpm.io/cli/link)) to test a standalone Angular library with an external application during -local development, without relying on the monorepo workspace structure or publishing to the NPM registry. +local development, without relying on the monorepo workspace structure or publishing to the npm registry. NOTE: If your library and application are in the same Angular workspace (a monorepo setup), the standard monorepo workflow automatically handles the linking and is generally more efficient. This local linking approach is best when: diff --git a/adev-ja/src/content/tools/libraries/using-libraries.md b/adev-ja/src/content/tools/libraries/using-libraries.md index 67f6db62a..031cd5c8c 100644 --- a/adev-ja/src/content/tools/libraries/using-libraries.md +++ b/adev-ja/src/content/tools/libraries/using-libraries.md @@ -120,7 +120,7 @@ import * as $ from 'jquery'; ``` If you import it using import statements, you have two different copies of the library: one imported as a global library, and one imported as a module. -This is especially bad for libraries with plugins, like JQuery, because each copy includes different plugins. +This is especially bad for libraries with plugins, like jQuery, because each copy includes different plugins. Instead, run the `npm install @types/jquery` Angular CLI command to download typings for your library and then follow the library installation steps. This gives you access to the global variables exposed by that library. @@ -135,7 +135,7 @@ For example: declare var libraryName: any; ``` -Some scripts extend other libraries; for instance with JQuery plugins: +Some scripts extend other libraries; for instance with jQuery plugins: ```ts $('.test').myPlugin(); diff --git a/adev-ja/src/content/tutorials/first-app/intro/README.en.md b/adev-ja/src/content/tutorials/first-app/intro/README.en.md index 1b6d8c9fc..8627604e0 100644 --- a/adev-ja/src/content/tutorials/first-app/intro/README.en.md +++ b/adev-ja/src/content/tutorials/first-app/intro/README.en.md @@ -23,7 +23,7 @@ The lessons in this tutorial assume that you have experience with the following: ### Your equipment -These lessons can be completed using a local installation of the Angular tools or in our embedded editor. Local Angular development can be completed on Windows, MacOS or Linux based systems. +These lessons can be completed using a local installation of the Angular tools or in our embedded editor. Local Angular development can be completed on Windows, macOS or Linux based systems. NOTE: Look for alerts like this one, which call out steps that may only be for your local editor. diff --git a/adev-ja/src/content/tutorials/first-app/intro/README.md b/adev-ja/src/content/tutorials/first-app/intro/README.md index 5c0ffedd5..eda56980a 100644 --- a/adev-ja/src/content/tutorials/first-app/intro/README.md +++ b/adev-ja/src/content/tutorials/first-app/intro/README.md @@ -23,7 +23,7 @@ HELPFUL: 動画の方が良いですか?このチュートリアルには、[Y ### あなたの環境 -これらのレッスンはローカルにインストールされたAngularのツール、または組み込みエディタのどちらでも進めることができます。ローカルでのAngularの開発は、Windows, MacOSあるいはLinuxベースのシステムで行えます。 +これらのレッスンはローカルにインストールされたAngularのツール、または組み込みエディタのどちらでも進めることができます。ローカルでのAngularの開発は、Windows, macOSあるいはLinuxベースのシステムで行えます。 NOTE: このようなアラートに注意してください、ローカルエディタで作業している場合にのみ必要となる手順が示されていることがあります diff --git a/adev-ja/src/content/tutorials/first-app/steps/14-http/README.md b/adev-ja/src/content/tutorials/first-app/steps/14-http/README.md index 2515b3e60..05b510549 100644 --- a/adev-ja/src/content/tutorials/first-app/steps/14-http/README.md +++ b/adev-ja/src/content/tutorials/first-app/steps/14-http/README.md @@ -198,7 +198,7 @@ The server is now reading data from the HTTP request but the components that rel -NOTE: This lesson relies on the `fetch` browser API. For the support of interceptors, please refer to the [Http Client documentation](/guide/http) +NOTE: This lesson relies on the `fetch` browser API. For the support of interceptors, please refer to the [HTTP client documentation](/guide/http) SUMMARY: In this lesson, you updated your app to use a local web server (`json-server`), and use asynchronous service methods to retrieve data. diff --git a/adev-ja/src/content/tutorials/learn-angular/steps/5-control-flow-for/README.en.md b/adev-ja/src/content/tutorials/learn-angular/steps/5-control-flow-for/README.en.md index f906ef7e0..9b961c728 100644 --- a/adev-ja/src/content/tutorials/learn-angular/steps/5-control-flow-for/README.en.md +++ b/adev-ja/src/content/tutorials/learn-angular/steps/5-control-flow-for/README.en.md @@ -22,7 +22,7 @@ Here's an example of how to use the `@for` syntax in a component: `, }) export class App { - operatingSystems = [{id: 'win', name: 'Windows'}, {id: 'osx', name: 'MacOS'}, {id: 'linux', name: 'Linux'}]; + operatingSystems = [{id: 'win', name: 'Windows'}, {id: 'osx', name: 'macOS'}, {id: 'linux', name: 'Linux'}]; } ``` diff --git a/adev-ja/src/content/tutorials/learn-angular/steps/5-control-flow-for/README.md b/adev-ja/src/content/tutorials/learn-angular/steps/5-control-flow-for/README.md index 6ba54013d..019f537ee 100644 --- a/adev-ja/src/content/tutorials/learn-angular/steps/5-control-flow-for/README.md +++ b/adev-ja/src/content/tutorials/learn-angular/steps/5-control-flow-for/README.md @@ -22,7 +22,7 @@ NOTE: [エッセンシャルガイドの制御フロー](/essentials/templates#c `, }) export class App { - operatingSystems = [{id: 'win', name: 'Windows'}, {id: 'osx', name: 'MacOS'}, {id: 'linux', name: 'Linux'}]; + operatingSystems = [{id: 'win', name: 'Windows'}, {id: 'osx', name: 'macOS'}, {id: 'linux', name: 'Linux'}]; } ``` diff --git a/origin b/origin index 42d57c357..cea6588bb 160000 --- a/origin +++ b/origin @@ -1 +1 @@ -Subproject commit 42d57c35781fb65fc4d44df59b6a85287664216a +Subproject commit cea6588bb301c9a71fe703fd1cb3a2165fd768b4