diff --git a/adev-ja/src/app/core/services/a-dev-title-strategy.en.ts b/adev-ja/src/app/core/services/a-dev-title-strategy.en.ts index 60662a00dd..adbf7dcda6 100644 --- a/adev-ja/src/app/core/services/a-dev-title-strategy.en.ts +++ b/adev-ja/src/app/core/services/a-dev-title-strategy.en.ts @@ -11,14 +11,12 @@ import {NavigationItem} from '@angular/docs'; import {Meta, Title} from '@angular/platform-browser'; import {ActivatedRouteSnapshot, RouterStateSnapshot, TitleStrategy} from '@angular/router'; -export const ROUTE_TITLE_PROPERTY = 'label'; -export const ROUTE_PARENT_PROPERTY = 'parent'; export const TITLE_SUFFIX = 'Angular'; -export const TITLE_SEPARATOR = ' • '; +const TITLE_SEPARATOR = ' • '; export const DEFAULT_PAGE_TITLE = 'Overview'; -export const TITLE_OG_META_TAG = 'og:title'; -export const TITLE_TWITTER_META_TAG = 'twitter:title'; +const TITLE_OG_META_TAG = 'og:title'; +const TITLE_TWITTER_META_TAG = 'twitter:title'; export const ALL_TITLE_META_TAGS = [TITLE_OG_META_TAG, TITLE_TWITTER_META_TAG]; diff --git a/adev-ja/src/app/core/services/a-dev-title-strategy.ts b/adev-ja/src/app/core/services/a-dev-title-strategy.ts index 0ebdf56b4c..7731db4ec1 100644 --- a/adev-ja/src/app/core/services/a-dev-title-strategy.ts +++ b/adev-ja/src/app/core/services/a-dev-title-strategy.ts @@ -11,14 +11,12 @@ import {NavigationItem} from '@angular/docs'; import {Meta, Title} from '@angular/platform-browser'; import {ActivatedRouteSnapshot, RouterStateSnapshot, TitleStrategy} from '@angular/router'; -export const ROUTE_TITLE_PROPERTY = 'label'; -export const ROUTE_PARENT_PROPERTY = 'parent'; export const TITLE_SUFFIX = 'Angular 日本語版'; -export const TITLE_SEPARATOR = ' • '; +const TITLE_SEPARATOR = ' • '; export const DEFAULT_PAGE_TITLE = 'Overview'; -export const TITLE_OG_META_TAG = 'og:title'; -export const TITLE_TWITTER_META_TAG = 'twitter:title'; +const TITLE_OG_META_TAG = 'og:title'; +const TITLE_TWITTER_META_TAG = 'twitter:title'; export const ALL_TITLE_META_TAGS = [TITLE_OG_META_TAG, TITLE_TWITTER_META_TAG]; diff --git a/adev-ja/src/app/features/home/components/hydration-example/hydration-example.en.html b/adev-ja/src/app/features/home/components/hydration-example/hydration-example.en.html index 24af1eda1a..72aff61660 100644 --- a/adev-ja/src/app/features/home/components/hydration-example/hydration-example.en.html +++ b/adev-ja/src/app/features/home/components/hydration-example/hydration-example.en.html @@ -57,8 +57,7 @@

Hydration Engine Log

event: {{ evt }} - } - @if (eventQueue().length === 0) { + } @empty {
Awaiting app bootstrap...
} diff --git a/adev-ja/src/app/features/home/components/hydration-example/hydration-example.html b/adev-ja/src/app/features/home/components/hydration-example/hydration-example.html index 1133d9f577..e7e8ba29b6 100644 --- a/adev-ja/src/app/features/home/components/hydration-example/hydration-example.html +++ b/adev-ja/src/app/features/home/components/hydration-example/hydration-example.html @@ -57,8 +57,7 @@

ハイドレーションエンジンログ< event: {{ evt }} - } - @if (eventQueue().length === 0) { + } @empty {
アプリのブートストラップを待機中...
} diff --git a/adev-ja/src/app/features/home/home.component.en.html b/adev-ja/src/app/features/home/home.component.en.html index 45b0809e94..4e55dce261 100644 --- a/adev-ja/src/app/features/home/home.component.en.html +++ b/adev-ja/src/app/features/home/home.component.en.html @@ -9,7 +9,7 @@

Angular v22 is here!

- +
diff --git a/adev-ja/src/app/features/home/home.component.html b/adev-ja/src/app/features/home/home.component.html index 8899e45a43..94b2a79f6b 100644 --- a/adev-ja/src/app/features/home/home.component.html +++ b/adev-ja/src/app/features/home/home.component.html @@ -9,7 +9,7 @@

Angular v22がリリースされました!

- +
diff --git a/adev-ja/src/app/features/update/recommendations.en.ts b/adev-ja/src/app/features/update/recommendations.en.ts index 0ac863dafd..597e0f017c 100644 --- a/adev-ja/src/app/features/update/recommendations.en.ts +++ b/adev-ja/src/app/features/update/recommendations.en.ts @@ -2780,6 +2780,14 @@ export const RECOMMENDATIONS: Step[] = [ possibleIn: 2100, step: '21.0.0_ng_update', }, + { + possibleIn: 2100, + necessaryAsOf: 2100, + level: ApplicationComplexity.Advanced, + step: '21.0.0-safe-resource-url-audio-src', + action: + 'If you use `SafeResourceUrl` values with `audio[src]` bindings, be aware that `audio[src]` is no longer sanitized in Angular v21. Existing uses of `bypassSecurityTrustResourceUrl` may therefore produce the `SafeValue must use [property]=binding` message. Remove the unnecessary sanitization and bind the URL directly instead.', + }, { possibleIn: 2100, diff --git a/adev-ja/src/app/features/update/recommendations.ts b/adev-ja/src/app/features/update/recommendations.ts index 09b024c64f..f24c74a0d3 100644 --- a/adev-ja/src/app/features/update/recommendations.ts +++ b/adev-ja/src/app/features/update/recommendations.ts @@ -2780,6 +2780,14 @@ export const RECOMMENDATIONS: Step[] = [ possibleIn: 2100, step: '21.0.0_ng_update', }, + { + possibleIn: 2100, + necessaryAsOf: 2100, + level: ApplicationComplexity.Advanced, + step: '21.0.0-safe-resource-url-audio-src', + action: + '`SafeResourceUrl` の値を `audio[src]` バインディングで使用している場合、Angular v21 では `audio[src]` がサニタイズされなくなる点に注意してください。そのため、既存の `bypassSecurityTrustResourceUrl` の使用が `SafeValue must use [property]=binding` というメッセージを出力することがあります。不要なサニタイズを削除し、URLを直接バインドしてください。', + }, { possibleIn: 2100, diff --git a/adev-ja/src/app/features/update/update.component.en.html b/adev-ja/src/app/features/update/update.component.en.html index c143eedff7..163a6ed63e 100644 --- a/adev-ja/src/app/features/update/update.component.en.html +++ b/adev-ja/src/app/features/update/update.component.en.html @@ -147,8 +147,12 @@

{{ title() }}

Before you update

@for (r of beforeRecommendations; track $index) {
- -
+ +
{{ getComplexityLevelName(r.level) }} @@ -171,8 +175,12 @@

Update to the new version

@for (r of duringRecommendations; track $index) {
- -
+ +
{{ getComplexityLevelName(r.level) }} @@ -189,8 +197,12 @@

Update to the new version

After you update

@for (r of afterRecommendations; track $index) {
- -
+ +
{{ getComplexityLevelName(r.level) }} 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 6445d9188c..f0814b62d8 100644 --- a/adev-ja/src/app/features/update/update.component.en.ts +++ b/adev-ja/src/app/features/update/update.component.en.ts @@ -154,6 +154,18 @@ export default class UpdateComponent { } } + protected toggleRecommendation(event: MouseEvent, checkbox: MatCheckbox): void { + const target = event.target as Element | null; + + // Keep links in the recommendation independently operable. + if (target?.closest('a')) { + return; + } + + checkbox.toggle(); + checkbox.focus(); + } + async showUpdatePath() { this.beforeRecommendations = []; this.duringRecommendations = []; diff --git a/adev-ja/src/app/features/update/update.component.html b/adev-ja/src/app/features/update/update.component.html index bba218f140..1b8dca6b4d 100644 --- a/adev-ja/src/app/features/update/update.component.html +++ b/adev-ja/src/app/features/update/update.component.html @@ -147,8 +147,12 @@

{{ title() }}

アップデート前

@for (r of beforeRecommendations; track $index) {
- -
+ +
{{ getComplexityLevelName(r.level) }} @@ -171,8 +175,12 @@

新しいバージョンにアップデートする

@for (r of duringRecommendations; track $index) {
- -
+ +
{{ getComplexityLevelName(r.level) }} @@ -189,8 +197,12 @@

新しいバージョンにアップデートする

アップデート後

@for (r of afterRecommendations; track $index) {
- -
+ +
{{ getComplexityLevelName(r.level) }} diff --git a/adev-ja/src/app/features/update/update.component.ts b/adev-ja/src/app/features/update/update.component.ts index 9e8f471bb6..2ec67d7f65 100644 --- a/adev-ja/src/app/features/update/update.component.ts +++ b/adev-ja/src/app/features/update/update.component.ts @@ -154,6 +154,18 @@ export default class UpdateComponent { } } + protected toggleRecommendation(event: MouseEvent, checkbox: MatCheckbox): void { + const target = event.target as Element | null; + + // Keep links in the recommendation independently operable. + if (target?.closest('a')) { + return; + } + + checkbox.toggle(); + checkbox.focus(); + } + async showUpdatePath() { this.beforeRecommendations = []; this.duringRecommendations = []; 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 c9dc4f0168..d0d9e19988 100644 --- a/adev-ja/src/app/routing/navigation-entries/index.en.ts +++ b/adev-ja/src/app/routing/navigation-entries/index.en.ts @@ -26,13 +26,6 @@ import SIGNAL_FORMS_TUTORIAL_NAV_DATA from '../../../content/tutorials/signal-fo // @ts-ignore import API_MANIFEST_JSON from '../../../assets/manifest.json' with {type: 'json'}; -interface SubNavigationData { - docs: NavigationItem[]; - reference: NavigationItem[]; - tutorials: NavigationItem[]; - footer: NavigationItem[]; -} - export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ { label: 'Introduction', @@ -263,6 +256,12 @@ export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ path: 'guide/templates/defer', contentPath: 'guide/templates/defer', }, + { + label: 'Error boundaries with @boundary', + path: 'guide/templates/error-boundaries', + contentPath: 'guide/templates/error-boundaries', + status: 'new', + }, { label: 'Expression syntax', path: 'guide/templates/expression-syntax', @@ -406,6 +405,12 @@ export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ path: 'guide/routing/data-resolvers', contentPath: 'guide/routing/data-resolvers', }, + { + label: 'Data fetching with resources', + path: 'guide/routing/data-fetching-with-resources', + contentPath: 'guide/routing/data-fetching-with-resources', + status: 'new', + }, { label: 'Lifecycle and events', path: 'guide/routing/lifecycle-and-events', @@ -1768,6 +1773,11 @@ export const REFERENCE_SUB_NAVIGATION_DATA: NavigationItem[] = [ path: 'reference/migrations/common-to-standalone', contentPath: 'reference/migrations/common-to-standalone', }, + { + label: 'Injectable to Service', + path: 'reference/migrations/injectable-to-service', + contentPath: 'reference/migrations/injectable-to-service', + }, ], }, ]; @@ -1792,15 +1802,21 @@ export const ALL_ITEMS = [ ...TUTORIALS_SUB_NAVIGATION_DATA, ]; +interface ApiManifestPackage { + normalizedModuleName: string; + moduleLabel: string; + entries: {name: string; category: string | undefined}[]; +} + function getApiNavigationItems(): NavigationItem[] { - const manifest = API_MANIFEST_JSON as any; // TODO(mri): Use proper type when the refactoring of #66252 gets in. + const manifest = API_MANIFEST_JSON as ApiManifestPackage[]; const apiNavigationItems: NavigationItem[] = []; for (const packageEntry of manifest) { const packageNavigationItem: NavigationItem = { label: packageEntry.moduleLabel, - children: packageEntry.entries.map((api: any) => ({ + children: packageEntry.entries.map((api) => ({ path: getApiUrl(packageEntry, api.name), label: api.name, category: api.category, @@ -1813,7 +1829,7 @@ function getApiNavigationItems(): NavigationItem[] { return apiNavigationItems; } -function getApiUrl(packageEntry: any, apiName: string): string { +function getApiUrl(packageEntry: ApiManifestPackage, apiName: string): string { const packageName = packageEntry.normalizedModuleName // packages like `angular_core` should be `core` // packages like `angular_animation_browser` should be `animation/browser` diff --git a/adev-ja/src/app/routing/navigation-entries/index.ts b/adev-ja/src/app/routing/navigation-entries/index.ts index c71e83a98c..eb34c1eb8c 100644 --- a/adev-ja/src/app/routing/navigation-entries/index.ts +++ b/adev-ja/src/app/routing/navigation-entries/index.ts @@ -26,13 +26,6 @@ import SIGNAL_FORMS_TUTORIAL_NAV_DATA from '../../../content/tutorials/signal-fo // @ts-ignore import API_MANIFEST_JSON from '../../../assets/manifest.json' with {type: 'json'}; -interface SubNavigationData { - docs: NavigationItem[]; - reference: NavigationItem[]; - tutorials: NavigationItem[]; - footer: NavigationItem[]; -} - export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ { label: '入門', @@ -263,6 +256,12 @@ export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ path: 'guide/templates/defer', contentPath: 'guide/templates/defer', }, + { + label: 'Error boundaries with @boundary', + path: 'guide/templates/error-boundaries', + contentPath: 'guide/templates/error-boundaries', + status: 'new', + }, { label: '式の構文', path: 'guide/templates/expression-syntax', @@ -406,6 +405,12 @@ export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ path: 'guide/routing/data-resolvers', contentPath: 'guide/routing/data-resolvers', }, + { + label: 'Data fetching with resources', + path: 'guide/routing/data-fetching-with-resources', + contentPath: 'guide/routing/data-fetching-with-resources', + status: 'new', + }, { label: 'ライフサイクルとイベント', path: 'guide/routing/lifecycle-and-events', @@ -1768,6 +1773,11 @@ export const REFERENCE_SUB_NAVIGATION_DATA: NavigationItem[] = [ path: 'reference/migrations/common-to-standalone', contentPath: 'reference/migrations/common-to-standalone', }, + { + label: 'Injectable to Service', + path: 'reference/migrations/injectable-to-service', + contentPath: 'reference/migrations/injectable-to-service', + }, ], }, ]; @@ -1792,15 +1802,21 @@ export const ALL_ITEMS = [ ...TUTORIALS_SUB_NAVIGATION_DATA, ]; +interface ApiManifestPackage { + normalizedModuleName: string; + moduleLabel: string; + entries: {name: string; category: string | undefined}[]; +} + function getApiNavigationItems(): NavigationItem[] { - const manifest = API_MANIFEST_JSON as any; // TODO(mri): Use proper type when the refactoring of #66252 gets in. + const manifest = API_MANIFEST_JSON as ApiManifestPackage[]; const apiNavigationItems: NavigationItem[] = []; for (const packageEntry of manifest) { const packageNavigationItem: NavigationItem = { label: packageEntry.moduleLabel, - children: packageEntry.entries.map((api: any) => ({ + children: packageEntry.entries.map((api) => ({ path: getApiUrl(packageEntry, api.name), label: api.name, category: api.category, @@ -1813,7 +1829,7 @@ function getApiNavigationItems(): NavigationItem[] { return apiNavigationItems; } -function getApiUrl(packageEntry: any, apiName: string): string { +function getApiUrl(packageEntry: ApiManifestPackage, apiName: string): string { const packageName = packageEntry.normalizedModuleName // packages like `angular_core` should be `core` // packages like `angular_animation_browser` should be `animation/browser` 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 33edbf2370..3d402700b8 100644 --- a/adev-ja/src/content/ai/develop-with-ai.en.md +++ b/adev-ja/src/content/ai/develop-with-ai.en.md @@ -22,10 +22,10 @@ Several tools, such as GEMINI.md | Configure GEMINI.md | +| Antigravity | GEMINI.md | Configure `GEMINI.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` | +| JetBrains IDEs | AGENTS.md | Configure `AGENTS.md` | | VS Code | .instructions.md | Configure `.instructions.md` | | Windsurf | guidelines.md | Configure `guidelines.md` | @@ -43,7 +43,3 @@ The Angular CLI includes an experimental [Model Context Protocol (MCP) server](h - llms-full.txt - a more robust compiled set of resources describing how Angular works and how to build Angular applications. Be sure to check out the [overview page](/ai) for more information on how to integrate AI into your Angular applications. - -## Web Codegen Scorer - -The Angular team developed and open-sourced the [Web Codegen Scorer](https://github.com/angular/web-codegen-scorer), a tool to evaluate and score the quality of AI generated web code. You can use this tool to make evidence-based decisions relating to AI-generated code, such as fine-tuning prompts to improve the accuracy of LLM-generated code for Angular. These prompts can be included as system instructions for your AI tooling or as context with your prompt. You can also use this tool to compare the quality of code produced by different models and monitor quality over time as models and agents evolve. diff --git a/adev-ja/src/content/ai/develop-with-ai.md b/adev-ja/src/content/ai/develop-with-ai.md index 50b2776098..4fdf381069 100644 --- a/adev-ja/src/content/ai/develop-with-ai.md +++ b/adev-ja/src/content/ai/develop-with-ai.md @@ -25,7 +25,7 @@ NOTE: これらのファイルは、Angularの規約に準拠するために定 | Antigravity | GEMINI.md | `GEMINI.md`を設定 | | Copilot powered IDEs | copilot-instructions.md | `.github/copilot-instructions.md`を設定 | | Cursor | cursor.md | `cursorrules.md`を設定 | -| JetBrains IDEs | guidelines.md | `guidelines.md`を設定 | +| JetBrains IDEs | AGENTS.md | `AGENTS.md`を設定 | | VS Code | .instructions.md | `.instructions.md`を設定 | | Windsurf | guidelines.md | `guidelines.md`を設定 | @@ -43,7 +43,3 @@ Angular CLIには、開発環境のAIアシスタントがAngular CLIと連携 - llms-full.txt - Angularの動作方法とAngularアプリケーションの構築方法を記述した、より堅牢なコンパイル済みリソースセット。 AngularアプリケーションにAIを統合する方法に関する詳細情報については、[概要ページ](/ai)もご確認ください。 - -## Web Codegen Scorer - -Angularチームは[Web Codegen Scorer](https://github.com/angular/web-codegen-scorer)を開発し、オープンソース化しました。これは、AI生成ウェブコードの品質を評価・スコア化するためのツールです。このツールを使用して、Angular向けにLLM生成コードの精度を向上させるプロンプトの微調整など、AI生成コードに関するエビデンスベースの意思決定を行うことができます。これらのプロンプトは、AIツールのシステム指示として含めたり、プロンプトとともにコンテキストとして含めたりできます。また、このツールを使用して、異なるモデルが生成するコードの品質を比較したり、モデルやエージェントの進化に伴う品質の経時変化を監視したりできます。 diff --git a/adev-ja/src/content/ai/webmcp.en.md b/adev-ja/src/content/ai/webmcp.en.md index b175a4dc85..4d2d2a4bef 100644 --- a/adev-ja/src/content/ai/webmcp.en.md +++ b/adev-ja/src/content/ai/webmcp.en.md @@ -124,15 +124,15 @@ export const routes: Routes = [ ]; ``` -NOTE: When registering tools to a particular route, consider configuring the router to use [`withExperimentalAutoCleanupInjectors`](api/router/withExperimentalAutoCleanupInjectors) to ensure tools are automatically _unregistered_ when the user navigates away from the route. Without this option, WebMCP tools declared on routes will remain accessible to AI agents even after the user has navigated to a different route. +NOTE: When registering tools to a particular route, consider configuring the router to use [`withAutoCleanupInjectors`](api/router/withAutoCleanupInjectors) to ensure tools are automatically _unregistered_ when the user navigates away from the route. Without this option, WebMCP tools declared on routes will remain accessible to AI agents even after the user has navigated to a different route. ```ts {header:"app.config.ts"} import {ApplicationConfig} from '@angular/core'; -import {provideRouter, withExperimentalAutoCleanupInjectors} from '@angular/router'; +import {provideRouter, withAutoCleanupInjectors} from '@angular/router'; import {routes} from './routes'; export const appConfig: ApplicationConfig = { - providers: [provideRouter(routes, withExperimentalAutoCleanupInjectors())], + providers: [provideRouter(routes, withAutoCleanupInjectors())], }; ``` @@ -214,7 +214,7 @@ export class UserRegistration { }, submission: { action: async (formValue) => { - console.log('Submitting user:', formValue); + console.log('Submitting user:', formValue().value()); // ... }, }, diff --git a/adev-ja/src/content/ai/webmcp.md b/adev-ja/src/content/ai/webmcp.md index a0dfe26049..0db7a57f90 100644 --- a/adev-ja/src/content/ai/webmcp.md +++ b/adev-ja/src/content/ai/webmcp.md @@ -124,15 +124,15 @@ export const routes: Routes = [ ]; ``` -NOTE: 特定のルートにツールを登録する場合、ユーザーがルートから移動したときにツールが自動的に_登録解除_されるように、ルーターを構成して[`withExperimentalAutoCleanupInjectors`](api/router/withExperimentalAutoCleanupInjectors)を使用することを検討してください。このオプションがない場合、ルートで宣言されたWebMCPツールは、ユーザーが別のルートに移動した後でもAIエージェントからアクセス可能なままになります。 +NOTE: 特定のルートにツールを登録する場合、ユーザーがルートから移動したときにツールが自動的に_登録解除_されるように、ルーターを構成して[`withAutoCleanupInjectors`](api/router/withAutoCleanupInjectors)を使用することを検討してください。このオプションがない場合、ルートで宣言されたWebMCPツールは、ユーザーが別のルートに移動した後でもAIエージェントからアクセス可能なままになります。 ```ts {header:"app.config.ts"} import {ApplicationConfig} from '@angular/core'; -import {provideRouter, withExperimentalAutoCleanupInjectors} from '@angular/router'; +import {provideRouter, withAutoCleanupInjectors} from '@angular/router'; import {routes} from './routes'; export const appConfig: ApplicationConfig = { - providers: [provideRouter(routes, withExperimentalAutoCleanupInjectors())], + providers: [provideRouter(routes, withAutoCleanupInjectors())], }; ``` @@ -214,7 +214,7 @@ export class UserRegistration { }, submission: { action: async (formValue) => { - console.log('Submitting user:', formValue); + console.log('Submitting user:', formValue().value()); // ... }, }, diff --git a/adev-ja/src/content/best-practices/error-handling.en.md b/adev-ja/src/content/best-practices/error-handling.en.md index 8f88da54dd..16f8323fc2 100644 --- a/adev-ja/src/content/best-practices/error-handling.en.md +++ b/adev-ja/src/content/best-practices/error-handling.en.md @@ -46,6 +46,20 @@ export class GlobalErrorHandler implements ErrorHandler { In many cases, `ErrorHandler` may only log errors and otherwise allow the application to continue running. In tests, however, you almost always want to surface these errors. Angular's `TestBed` rethrows unexpected errors to ensure that errors caught by the framework cannot be unintentionally missed or ignored. In rare circumstances, a test may specifically attempt to ensure errors do not cause the application to be unresponsive or crash. In these situations, you can [configure `TestBed` to _not_ rethrow application errors](api/core/testing/TestModuleMetadata#rethrowApplicationErrors) with `TestBed.configureTestingModule({rethrowApplicationErrors: false})`. +### Errors thrown while your app is still starting up + +There's a brief moment when Angular can't send errors to your `ErrorHandler` yet: while it is still creating your app's root module or root component. Angular needs that root instance to exist before it can look up the `ErrorHandler` you provided, so an error thrown before then has nowhere to go. It behaves like a normal uncaught error instead of being reported through `ErrorHandler`. + +You're most likely to run into this with [Angular elements](guide/elements). If you define a custom element while its tag is already present on the page, the browser upgrades it right away, running the component's constructor and `ngOnInit` as part of that early startup work. Any error thrown there can get lost. + +If this happens to you, move the code that throws so it runs after your app has finished starting up, for example: + +- Wrap it in `setTimeout(() => /* your code */)` so it runs on its own turn instead of during startup. +- Provide it as an `APP_BOOTSTRAP_LISTENER` instead of running it from a constructor. +- Define your custom elements in `ngDoBootstrap` instead of your root module's constructor. + +Turning on `provideBrowserGlobalErrorListeners()` (see below) can also help catch these errors, since they still reach the browser as uncaught errors. + ## Global error listeners Errors that are caught neither by the application code nor by the framework's application instance may reach the global scope. Errors reaching the global scope can have unintended consequences if not accounted for. In non-browser environments, they may cause the process to crash. In the browser, these errors may go unreported and site visitors may see the errors in the browser console. Angular provides global listeners for both environments to account for these issues. diff --git a/adev-ja/src/content/best-practices/error-handling.md b/adev-ja/src/content/best-practices/error-handling.md index 3fc3e38128..45446d7e14 100644 --- a/adev-ja/src/content/best-practices/error-handling.md +++ b/adev-ja/src/content/best-practices/error-handling.md @@ -46,6 +46,20 @@ export class GlobalErrorHandler implements ErrorHandler { 多くの場合、`ErrorHandler`はエラーをログに記録するだけで、アプリケーションの実行を継続させることがあります。しかし、テストでは、ほとんどの場合、これらのエラーを表面化させたいと考えます。Angularの`TestBed`は、フレームワークによってキャッチされたエラーが意図せず見逃されたり無視されたりしないように、予期しないエラーを再スローします。まれに、テストがエラーによってアプリケーションが無応答になったりクラッシュしたりしないことを特に確認しようとすることがあります。このような状況では、`TestBed.configureTestingModule({rethrowApplicationErrors: false})`を使用して、[`TestBed`がアプリケーションエラーを再スローし_ない_ように設定できます](api/core/testing/TestModuleMetadata#rethrowApplicationErrors)。 +### アプリケーションの起動中にスローされるエラー {#errors-thrown-while-your-app-is-still-starting-up} + +Angularがエラーを`ErrorHandler`へ送れない短い期間があります。アプリケーションのルートモジュールまたはルートコンポーネントをまだ作成している間です。Angularは、指定された`ErrorHandler`を取得するために、先にそのルートインスタンスが存在している必要があります。そのため、この時点より前にスローされたエラーは送り先がなく、`ErrorHandler`経由では報告されず、通常のキャッチされないエラーとして扱われます。 + +この問題に遭遇しやすいのは、[Angular elements](guide/elements)を使う場合です。タグがすでにページ上にある状態でカスタム要素を定義すると、ブラウザは直ちにその要素をアップグレードし、起動初期の処理の一部としてコンポーネントのコンストラクターと`ngOnInit`を実行します。ここでスローされたエラーは失われることがあります。 + +この問題が起きた場合は、スローするコードを、アプリケーションの起動完了後に実行されるように移動してください。例: + +- `setTimeout(() => /* your code */)`で囲み、起動中ではなく別のターンで実行されるようにする。 +- コンストラクターから実行する代わりに、`APP_BOOTSTRAP_LISTENER`として提供する。 +- カスタム要素を、ルートモジュールのコンストラクターではなく`ngDoBootstrap`で定義する。 + +`provideBrowserGlobalErrorListeners()`を有効にする (後述) と、これらのエラーもキャッチされないエラーとしてブラウザに到達するため、捕捉に役立つことがあります。 + ## グローバルエラーリスナー {#global-error-listeners} アプリケーションコードやフレームワークのアプリケーションインスタンスによってキャッチされなかったエラーは、グローバルスコープに到達することがあります。グローバルスコープに到達したエラーは、対処しないと意図しない結果を引き起こす可能性があります。ブラウザ以外の環境では、プロセスがクラッシュする原因になることがあります。ブラウザでは、これらのエラーは報告されず、サイトの訪問者はブラウザコンソールでエラーを見ることになるかもしれません。Angularは、これらの問題に対応するため、両方の環境にグローバルリスナーを提供しています。 diff --git a/adev-ja/src/content/best-practices/runtime-performance/skipping-subtrees.en.md b/adev-ja/src/content/best-practices/runtime-performance/skipping-subtrees.en.md index 405836da6e..f5379f6af7 100644 --- a/adev-ja/src/content/best-practices/runtime-performance/skipping-subtrees.en.md +++ b/adev-ja/src/content/best-practices/runtime-performance/skipping-subtrees.en.md @@ -8,7 +8,7 @@ Change detection is sufficiently fast for most applications. However, when an ap OnPush is the default change detection strategy in Angular (since v22). It instructs Angular to run change detection for a component subtree **only** when: -- The root component of the subtree receives new inputs as the result of a template binding. Angular compares the current and past value of the input with `==`. +- The root component of the subtree receives new inputs as the result of a template binding. Angular compares the current and past value of the input with `Object.is`. - Angular handles an event _(for example using event binding, output binding, or `@HostListener` )_ in the subtree's root component or any of its children whether they are using OnPush change detection or not. ## Common change detection scenarios diff --git a/adev-ja/src/content/best-practices/runtime-performance/skipping-subtrees.md b/adev-ja/src/content/best-practices/runtime-performance/skipping-subtrees.md index bbd639bdf4..ad0404dd32 100644 --- a/adev-ja/src/content/best-practices/runtime-performance/skipping-subtrees.md +++ b/adev-ja/src/content/best-practices/runtime-performance/skipping-subtrees.md @@ -8,7 +8,7 @@ JavaScriptは、デフォルトでは、複数の異なるコンポーネント OnPushはAngularのデフォルトの変更検知戦略です(v22以降)。Angularにコンポーネントのサブツリーの変更検知を次の場合**のみ**実行するように指示します。 -- サブツリーのルートコンポーネントが、テンプレートバインディングの結果として新しいインプットを受け取った場合。Angularは、インプットの現在と過去の値を`==`で比較します。 +- サブツリーのルートコンポーネントが、テンプレートバインディングの結果として新しいインプットを受け取った場合。Angularは、インプットの現在と過去の値を`Object.is`で比較します。 - Angularが、OnPush変更検知を使用しているかどうかに関係なく、サブツリーのルートコンポーネント、または、その子でイベント *(例えば、イベントバインディング、アウトプットバインディング、または`@HostListener`を使用)* を処理する場合。 ## 一般的な変更検知のシナリオ diff --git a/adev-ja/src/content/best-practices/runtime-performance/zone-pollution.md b/adev-ja/src/content/best-practices/runtime-performance/zone-pollution.md index 38dfda071a..1519a9914f 100644 --- a/adev-ja/src/content/best-practices/runtime-performance/zone-pollution.md +++ b/adev-ja/src/content/best-practices/runtime-performance/zone-pollution.md @@ -25,7 +25,7 @@ In such cases, you can instruct Angular to avoid calling change detection for ta import { Component, NgZone, OnInit, inject } from '@angular/core'; @Component(...) -class AppComponent implements OnInit { +class App implements OnInit { private ngZone = inject(NgZone); ngOnInit() { @@ -43,7 +43,7 @@ import { Component, NgZone, OnInit, inject } from '@angular/core'; import * as Plotly from 'plotly.js-dist-min'; @Component(...) -class AppComponent implements OnInit { +class App implements OnInit { private ngZone = inject(NgZone); ngOnInit() { @@ -65,7 +65,7 @@ import { Component, NgZone, OnInit, output, inject } from '@angular/core'; import * as Plotly from 'plotly.js-dist-min'; @Component(...) -class AppComponent implements OnInit { +class App implements OnInit { private ngZone = inject(NgZone); plotlyClick = output(); @@ -97,7 +97,7 @@ import { Component, NgZone, OnInit, output, inject } from '@angular/core'; import * as Plotly from 'plotly.js-dist-min'; @Component(...) -class AppComponent implements OnInit { +class App implements OnInit { private ngZone = inject(NgZone); plotlyClick = output(); diff --git a/adev-ja/src/content/ecosystem/rxjs-interop/output-interop.md b/adev-ja/src/content/ecosystem/rxjs-interop/output-interop.md index 3a5fef2cd3..d2fe7e59e4 100644 --- a/adev-ja/src/content/ecosystem/rxjs-interop/output-interop.md +++ b/adev-ja/src/content/ecosystem/rxjs-interop/output-interop.md @@ -2,13 +2,13 @@ TIP: This guide assumes you're familiar with [component and directive outputs](guide/components/outputs). -The `@angular/rxjs-interop` package offers two APIs related to component and directive outputs. +The `@angular/core/rxjs-interop` package offers two APIs related to component and directive outputs. ## Creating an output based on an RxJs Observable The `outputFromObservable` lets you create a component or directive output that emits based on an RxJS observable: -```ts {highlight:[11]} +```ts {highlight:[9]} import {Directive} from '@angular/core'; import {outputFromObservable} from '@angular/core/rxjs-interop'; diff --git a/adev-ja/src/content/ecosystem/rxjs-interop/signals-interop.md b/adev-ja/src/content/ecosystem/rxjs-interop/signals-interop.md index 3e8fd13c9c..db1ff36999 100644 --- a/adev-ja/src/content/ecosystem/rxjs-interop/signals-interop.md +++ b/adev-ja/src/content/ecosystem/rxjs-interop/signals-interop.md @@ -105,7 +105,7 @@ export class SearchResults { As the `query` signal changes, the `query$` Observable emits the latest query and triggers a new HTTP request. -### Injection context +### Injection context {#injection-context-to-observable} `toObservable` by default needs to run in an [injection context](guide/di/dependency-injection-context), such as during construction of a component or service. If an injection context is not available, you can manually specify the `Injector` to use instead. @@ -128,7 +128,7 @@ Here, only the last value (3) will be logged. ## Using `rxResource` for async data -Angular's [`resource` function](/guide/signals/resource) gives you a way to incorporate async data into your application's signal-based code. Building on top of this pattern, `rxResource` lets you define a resource where the source of your data is defined in terms of an RxJS `Observable`. Instead of accepting a `loader` function, `rxResource` accepts a `stream` function that accepts an RxJS `Observable`. +Angular's [`resource` function](/guide/signals/resource) gives you a way to incorporate async data into your application's signal-based code. Building on top of this pattern, `rxResource` lets you define a resource where the source of your data is defined in terms of an RxJS `Observable`. Instead of accepting a `loader` function, `rxResource` accepts a `stream` function that returns an RxJS `Observable`. ```typescript import {Component, inject} from '@angular/core'; @@ -154,3 +154,5 @@ export class UserProfile { The `stream` property accepts a factory function for an RxJS `Observable`. This factory function is passed the resource's `params` value and returns an `Observable`. The resource calls this factory function every time the `params` computation produces a new value. See [Resource loaders](/guide/signals/resource#resource-loaders) for more details on the parameters passed to the factory function. In all other ways, `rxResource` behaves like and provides the same APIs as `resource` for specifying parameters, reading values, checking loading state, and examining errors. + +The `Observable` returned from `stream` must always emit a value or an error before it completes; see [`NG0991`](/errors/NG0991) for what happens otherwise and how to avoid it. diff --git a/adev-ja/src/content/ecosystem/service-workers/app-shell.md b/adev-ja/src/content/ecosystem/service-workers/app-shell.md index 7a7d9afc4c..a68e1739a6 100644 --- a/adev-ja/src/content/ecosystem/service-workers/app-shell.md +++ b/adev-ja/src/content/ecosystem/service-workers/app-shell.md @@ -38,6 +38,7 @@ src └── main.server.ts # main server application bootstrapping ``` + ```shell diff --git a/adev-ja/src/content/ecosystem/service-workers/communications.md b/adev-ja/src/content/ecosystem/service-workers/communications.md index 22822c68f2..f10efab147 100644 --- a/adev-ja/src/content/ecosystem/service-workers/communications.md +++ b/adev-ja/src/content/ecosystem/service-workers/communications.md @@ -14,15 +14,14 @@ The `SwUpdate` service supports three separate operations: ### Version updates -The `versionUpdates` is an `Observable` property of `SwUpdate` and emits five event types: - -| Event types | Details | -| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `VersionDetectedEvent` | Emitted when the service worker has detected a new version of the app on the server and is about to start downloading it. | -| `NoNewVersionDetectedEvent` | Emitted when the service worker has checked the version of the app on the server and did not find a new version. | -| `VersionReadyEvent` | Emitted when a new version of the app is available to be activated by clients. It may be used to notify the user of an available update or prompt them to refresh the page. | -| `VersionInstallationFailedEvent` | Emitted when the installation of a new version failed. It may be used for logging/monitoring purposes. | -| `VersionFailedEvent` | Emitted when a version encounters a critical failure (such as broken hash errors) that affects all clients using that version. Provides error details for debugging and transparency. | +The `versionUpdates` is an `Observable` property of `SwUpdate` and emits four event types: + +| Event types | Details | +| :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `VersionDetectedEvent` | Emitted when the service worker has detected a new version of the app on the server and is about to start downloading it. | +| `NoNewVersionDetectedEvent` | Emitted when the service worker has checked the version of the app on the server and did not find a new version. | +| `VersionReadyEvent` | Emitted when a new version of the app is available to be activated by clients. It may be used to notify the user of an available update or prompt them to refresh the page. | +| `VersionInstallationFailedEvent` | Emitted when the installation of a new version failed. It may be used for logging/monitoring purposes. | diff --git a/adev-ja/src/content/ecosystem/service-workers/config.md b/adev-ja/src/content/ecosystem/service-workers/config.md index d0ea43baa8..a65c9628a0 100644 --- a/adev-ja/src/content/ecosystem/service-workers/config.md +++ b/adev-ja/src/content/ecosystem/service-workers/config.md @@ -201,7 +201,7 @@ export interface DataGroup { Each `DataGroup` is defined by the following data group properties. -#### `name` +#### `name` {#datagroups-name} Similar to `assetGroups`, every data group has a `name` which uniquely identifies it. @@ -318,7 +318,7 @@ If you are not able to implement CORS — for example, if you don't control the -#### `cacheQueryOptions` +#### `cacheQueryOptions` {#datagroups-cachequeryoptions} See [assetGroups](#assetgroups) for details. @@ -332,7 +332,7 @@ The ServiceWorker redirects navigation requests that don't match any `asset` or A request is considered to be a navigation request if: - Its [method](https://developer.mozilla.org/docs/Web/API/Request/method) is `GET` -- Its [mode](https://developer.mozilla.org/docs/Web/API/Request/mode) is `navigation` +- Its [mode](https://developer.mozilla.org/docs/Web/API/Request/mode) is `navigate` - It accepts a `text/html` response as determined by the value of the `Accept` header - Its URL matches the following criteria: - The URL must not contain a file extension (that is, a `.`) in the last path segment diff --git a/adev-ja/src/content/ecosystem/service-workers/devops.md b/adev-ja/src/content/ecosystem/service-workers/devops.md index 498cceabd6..38830ddd54 100644 --- a/adev-ja/src/content/ecosystem/service-workers/devops.md +++ b/adev-ja/src/content/ecosystem/service-workers/devops.md @@ -110,6 +110,24 @@ Most updates to the Angular service worker are transparent to the application. T Occasionally, a bug fix or feature in the Angular service worker might require the invalidation of old caches. In this case, the service worker transparently refreshes the application from the network. +#### Updating the service worker when only its response headers change + +Browsers only install a new service worker when the service worker script is byte-different from the installed one. +Because `ngsw-worker.js` is usually identical across builds, changing only the response headers that the server sends with it, such as a `Content-Security-Policy`, does not update the installed service worker. +The service worker keeps running with the headers it was installed with. + +To make browsers install the service worker again, register it with a versioned script URL, and change the version whenever those headers change: + +```ts +provideServiceWorker('ngsw-worker.js?v=2', { + enabled: !isDevMode(), + registrationStrategy: 'registerWhenStable:30000', +}); +``` + +Registering a different script URL makes the browser fetch and install the service worker again, even if its content is unchanged. +The Angular service worker resolves its caches and `ngsw.json` relative to its registration scope, not its script URL, so the query parameter doesn't affect cached content. + ### Bypassing the service worker In some cases, you might want to bypass the service worker entirely and let the browser handle the request. diff --git a/adev-ja/src/content/ecosystem/service-workers/getting-started.md b/adev-ja/src/content/ecosystem/service-workers/getting-started.md index a99bb75ca7..26c2bfc8d2 100644 --- a/adev-ja/src/content/ecosystem/service-workers/getting-started.md +++ b/adev-ja/src/content/ecosystem/service-workers/getting-started.md @@ -256,6 +256,7 @@ export const appConfig: ApplicationConfig = { Available registration strategies: - **`'registerWhenStable:timeout'`** (default: `'registerWhenStable:30000'`) - Register as soon as the application stabilizes (no pending micro-/macro-tasks) but no later than the specified timeout in milliseconds + The timeout is required. Without it, `'registerWhenStable'` registers the service worker immediately. - **`'registerImmediately'`** - Register the service worker immediately - **`'registerWithDelay:timeout'`** - Register with a delay of the specified timeout in milliseconds diff --git a/adev-ja/src/content/ecosystem/service-workers/overview.md b/adev-ja/src/content/ecosystem/service-workers/overview.md index dc80edeb79..6834f37e62 100644 --- a/adev-ja/src/content/ecosystem/service-workers/overview.md +++ b/adev-ja/src/content/ecosystem/service-workers/overview.md @@ -73,7 +73,7 @@ More specifically: - The browser does not download the service worker script and the `ngsw.json` manifest file - Active attempts to interact with the service worker, such as calling `SwUpdate.checkForUpdate()`, return rejected promises -- The observable events of related services, such as `SwUpdate.available`, are not triggered +- The observable events of related services, such as `SwUpdate.versionUpdates`, are not triggered It is highly recommended that you ensure that your application works even without service worker support in the browser. Although an unsupported browser ignores service worker caching, it still reports errors if the application attempts to interact with the service worker. diff --git a/adev-ja/src/content/guide/animations/css.en.md b/adev-ja/src/content/guide/animations/css.en.md index 30e4c802d4..41267bd8a7 100644 --- a/adev-ja/src/content/guide/animations/css.en.md +++ b/adev-ja/src/content/guide/animations/css.en.md @@ -90,6 +90,8 @@ Animating an element when it leaves the view is similar to animating when enteri +NOTE: Child `animate.leave` animations fire only within the same component template. Nested component `animate.leave` animations will not fire when a parent element is removed. + For more information on `animate.enter` and `animate.leave`, see the [Enter and Leave animations guide](guide/animations). ### Animating increment and decrement diff --git a/adev-ja/src/content/guide/animations/css.md b/adev-ja/src/content/guide/animations/css.md index 9c991483cb..2d14392937 100644 --- a/adev-ja/src/content/guide/animations/css.md +++ b/adev-ja/src/content/guide/animations/css.md @@ -90,6 +90,8 @@ CSS Gridを使用すると、`height: auto`へのアニメーションを実現 +NOTE: 子要素の`animate.leave`アニメーションは、同じコンポーネントのテンプレート内でのみ発火します。親要素が削除されたとき、ネストしたコンポーネントの`animate.leave`アニメーションは発火しません。 + `animate.enter`と`animate.leave`について詳しくは、[EnterとLeaveのアニメーションガイド](guide/animations)を参照してください。 ### インクリメントとデクリメントをアニメーション化する {#animating-increment-and-decrement} 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 7817950ed9..5993a2fecf 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 @@ -57,14 +57,16 @@ NOTE: When using multiple keyframe animations or transition properties on an ele ### Element removal order -There is some nuance to how `animate.leave` animations are run and when an animation will occur. `animate.leave` works if it is placed on the element that is being removed, and if `animate.leave` is placed on an element that is a _descendent_ of the element being removed, those child animations will happen _before_ the parent node is removed from the DOM. This ensures that you can confidently animate away child elements without the parent node disappearing prematurely. +There is some nuance to how `animate.leave` animations are run and when an animation will occur. `animate.leave` works if it is placed on the element that is being removed, and if `animate.leave` is placed on an element that is a _descendant_ of the element being removed _within the same component template_, those child `animate.leave` animations will happen _before_ the parent node is removed from the DOM. This ensures that you can confidently animate away child elements without the parent node disappearing prematurely. - - - + + + +IMPORTANT: Child animations fire only for elements within the same component template. If an element being removed contains child components, any `animate.leave` animations defined inside those child component templates will **not** run before the parent is removed. To animate a child component on removal, apply `animate.leave` to the child component's host element directly within the parent template instead, or programmatically handle triggering the animation in the child component and delaying the removal of the parent until that animation completes. + ## Event Bindings, Functions, and Third-party Libraries Both `animate.enter` and `animate.leave` support event binding syntax that allows for function calls. You can use this syntax to call a function in your component code or utilize third-party animation libraries, like [GSAP](https://gsap.com/), [anime.js](https://animejs.com/), or any other JavaScript animation library. 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 1012a124ce..0b260b113c 100644 --- a/adev-ja/src/content/guide/animations/enter-and-leave.md +++ b/adev-ja/src/content/guide/animations/enter-and-leave.md @@ -57,14 +57,16 @@ NOTE: 要素に複数のキーフレームアニメーションまたはtransiti ### 要素の削除順序 {#element-removal-order} -`animate.leave`アニメーションの実行方法とアニメーションが発生するタイミングには、いくつかの微妙な点があります。`animate.leave`は、削除される要素に配置されている場合に機能します。また、`animate.leave`が削除される要素の_子孫_要素に配置されている場合、それらの子アニメーションは親ノードがDOMから削除される_前に_実行されます。これにより、親ノードが早期に消えることなく、子要素を確実にアニメーションで退場させることができます。 +`animate.leave`アニメーションの実行方法とアニメーションが発生するタイミングには、いくつかの微妙な点があります。`animate.leave`は、削除される要素に配置されている場合に機能します。また、`animate.leave`が、削除される要素の_子孫_要素で、かつ_同じコンポーネントのテンプレート内_に配置されている場合、それらの子の`animate.leave`アニメーションは親ノードがDOMから削除される_前に_実行されます。これにより、親ノードが早期に消えることなく、子要素を確実にアニメーションで消すことができます。 - - - + + + +IMPORTANT: 子のアニメーションが発火するのは、同じコンポーネントのテンプレート内にある要素だけです。削除される要素が子コンポーネントを含む場合、それらの子コンポーネントのテンプレート内で定義された`animate.leave`アニメーションは、親が削除される前には実行され**ません**。子コンポーネントを削除時にアニメーションさせるには、親のテンプレート内で子コンポーネントのホスト要素に直接`animate.leave`を適用します。または、子コンポーネント内でアニメーションの開始をプログラムで処理し、そのアニメーションが完了するまで親の削除を遅らせます。 + ## イベントバインディング、関数、およびサードパーティライブラリ {#event-bindings-functions-and-third-party-libraries} `animate.enter`と`animate.leave`はどちらも、関数呼び出しを可能にするイベントバインディング構文をサポートしています。この構文を使用して、コンポーネントコード内の関数を呼び出したり、[GSAP](https://gsap.com/)、[anime.js](https://animejs.com/)などのサードパーティのアニメーションライブラリ、またはその他のJavaScriptアニメーションライブラリを利用したり可能です。 diff --git a/adev-ja/src/content/guide/animations/migration.en.md b/adev-ja/src/content/guide/animations/migration.en.md index 32a960290d..975683af6b 100644 --- a/adev-ja/src/content/guide/animations/migration.en.md +++ b/adev-ja/src/content/guide/animations/migration.en.md @@ -36,13 +36,13 @@ Adding the class `animated-class` to an element would trigger the animation on t The animations package allowed you to define various states using the [`state()`](api/animations/state) function within a component. Examples might be an `open` or `closed` state containing the styles for each respective state within the definition. For example: -#### With Animations Package +#### With Animations Package {#animating-state-and-styles-with-animations-package} This same behavior can be accomplished natively by using CSS classes, either with a keyframe animation or transition styling. -#### With Native CSS +#### With Native CSS {#animating-state-and-styles-with-native-css} @@ -66,7 +66,7 @@ Similarly, you can use `transition-duration`, `transition-delay`, and `transitio The animations package required specifying triggers using the `trigger()` function and nesting all of your states within it. With native CSS, this is unnecessary. Animations can be triggered by toggling CSS styles or classes. Once a class is present on an element, the animation will occur. Removing the class will revert the element back to whatever CSS is defined for that element. This results in significantly less code to do the same animation. Here's an example: -#### With Animations Package +#### With Animations Package {#triggering-an-animation-with-animations-package} @@ -74,7 +74,7 @@ The animations package required specifying triggers using the `trigger()` functi -#### With Native CSS +#### With Native CSS {#triggering-an-animation-with-native-css} @@ -94,7 +94,7 @@ These state matching patterns are not needed at all when animating with CSS dire The animations package offers the ability to animate things that have been historically difficult to animate, like animating a set height to `height: auto`. You can now do this with pure CSS as well. -#### With Animations Package +#### With Animations Package {#automatic-property-calculation-with-animations-package} @@ -104,7 +104,7 @@ The animations package offers the ability to animate things that have been histo You can use CSS Grid to animate to auto height. -#### With Native CSS +#### With Native CSS {#automatic-property-calculation-with-native-css} @@ -118,7 +118,7 @@ If you don't have to worry about supporting all browsers, you can also check out The animations package offered the previously mentioned pattern matching for entering and leaving but also included the shorthand aliases of `:enter` and `:leave`. -#### With Animations Package +#### With Animations Package {#enter-and-leave-with-animations-package} @@ -126,7 +126,7 @@ The animations package offered the previously mentioned pattern matching for ent -#### With Native CSS +#### With Native CSS {#enter-with-native-css} @@ -134,7 +134,7 @@ The animations package offered the previously mentioned pattern matching for ent -#### With Native CSS +#### With Native CSS {#leave-with-native-css} @@ -148,7 +148,7 @@ For more information on `animate.enter` and `animate.leave`, see the [Enter and Along with the aforementioned `:enter` and `:leave`, there's also `:increment` and `:decrement`. You can animate these also by adding and removing classes. Unlike the animation package built-in aliases, there is no automatic application of classes when the values go up or down. You can apply the appropriate classes programmatically. Here's an example: -#### With Animations Package +#### With Animations Package {#increment-and-decrement-with-animations-package} @@ -156,7 +156,7 @@ Along with the aforementioned `:enter` and `:leave`, there's also `:increment` a -#### With Native CSS +#### With Native CSS {#increment-and-decrement-with-native-css} @@ -168,6 +168,8 @@ Along with the aforementioned `:enter` and `:leave`, there's also `:increment` a Unlike the animations package, when multiple animations are specified within a given component, no animation has priority over another and nothing blocks any animation from firing. Any sequencing of animations would have to be handled by your definition of your CSS animation, using animation / transition delay, and / or using `animationend` or `transitionend` to handle adding the next css to be animated. +Child animations fire only within the same component template. In the `@angular/animations` package, parent animations could query and trigger animations in nested child components using `query()` and `animateChild()`. With `animate.leave` and native CSS animations, animations defined inside nested child component templates will not fire when a parent component removes an element or view. Only nested animations within the same Angular component template will execute. See the [Enter and Leave Animations guide](guide/animations#element-removal-order) for more information on this. + ### Disabling an animation or all animations With native CSS animations, if you'd like to disable the animations that you've specified, you have multiple options. @@ -219,7 +221,7 @@ To toggle classes for child nodes within a template, you can use class and style The `stagger()` function allowed you to delay the animation of each item in a list of items by a specified time to create a cascade effect. You can replicate this behavior in native CSS by utilizing `animation-delay` or `transition-delay`. Here is an example of what that CSS might look like. -#### With Animations Package +#### With Animations Package {#stagger-with-animations-package} @@ -227,7 +229,7 @@ The `stagger()` function allowed you to delay the animation of each item in a li -#### With Native CSS +#### With Native CSS {#stagger-with-native-css} @@ -253,7 +255,7 @@ In this example, the `rotate` and `fade-in` animations fire at the same time. Items reordering in a list works out of the box using the previously described techniques. No additional special work is required. Items in a `@for` loop will be removed and re-added properly, which will fire off animations using `@starting-styles` for entry animations. Alternatively, you can use `animate.enter` for this same behavior. Use `animate.leave` to animate elements as they are removed, as seen in the example above. -#### With Animations Package +#### With Animations Package {#reordering-list-with-animations-package} @@ -261,7 +263,7 @@ Items reordering in a list works out of the box using the previously described t -#### With Native CSS +#### With Native CSS {#reordering-list-with-native-css} diff --git a/adev-ja/src/content/guide/animations/migration.md b/adev-ja/src/content/guide/animations/migration.md index 73cfc0baea..f6b4b783fd 100644 --- a/adev-ja/src/content/guide/animations/migration.md +++ b/adev-ja/src/content/guide/animations/migration.md @@ -36,13 +36,13 @@ v20.2以降、`@angular/animations`パッケージは非推奨になり、同時 アニメーションパッケージでは、コンポーネント内で[`state()`](api/animations/state)関数を使ってさまざまな状態を定義できました。たとえば、定義の中にそれぞれの状態に対応するスタイルを含む`open`や`closed`といった状態です。例を示します。 -#### Animationsパッケージの場合 +#### Animationsパッケージの場合 {#animating-state-and-styles-with-animations-package} この動作は、キーフレームアニメーションまたはトランジションスタイルとCSSクラスを使うことで、ネイティブにも実現できます。 -#### ネイティブCSSの場合 +#### ネイティブCSSの場合 {#animating-state-and-styles-with-native-css} @@ -66,7 +66,7 @@ v20.2以降、`@angular/animations`パッケージは非推奨になり、同時 アニメーションパッケージでは、`trigger()`関数を使ってトリガーを指定し、その中にすべての状態をネストする必要がありました。ネイティブCSSでは、これは不要です。CSSのスタイルやクラスを切り替えるだけでアニメーションをトリガーできます。要素にクラスが存在するとアニメーションが実行され、クラスを削除すると、その要素に定義されているCSSへ戻ります。これにより、同じアニメーションをはるかに少ないコードで実現できます。例を示します。 -#### Animationsパッケージの場合 +#### Animationsパッケージの場合 {#triggering-an-animation-with-animations-package} @@ -74,7 +74,7 @@ v20.2以降、`@angular/animations`パッケージは非推奨になり、同時 -#### ネイティブCSSの場合 +#### ネイティブCSSの場合 {#triggering-an-animation-with-native-css} @@ -94,7 +94,7 @@ CSSで直接アニメーション化する場合、こうした状態マッチ アニメーションパッケージでは、固定した高さから`height: auto`へのアニメーションのように、従来は難しかったアニメーションを実現できました。これは現在では純粋なCSSでも可能です。 -#### Animationsパッケージの場合 +#### Animationsパッケージの場合 {#automatic-property-calculation-with-animations-package} @@ -104,7 +104,7 @@ CSSで直接アニメーション化する場合、こうした状態マッチ CSS Gridを使うと、height: autoへのアニメーションを実現できます。 -#### ネイティブCSSの場合 +#### ネイティブCSSの場合 {#automatic-property-calculation-with-native-css} @@ -118,7 +118,7 @@ CSS Gridを使うと、height: autoへのアニメーションを実現できま アニメーションパッケージでは、前述のenterとleaveのパターンマッチングに加えて、`:enter`と`:leave`というショートハンドエイリアスも提供していました。 -#### Animationsパッケージの場合 +#### Animationsパッケージの場合 {#enter-and-leave-with-animations-package} @@ -126,7 +126,7 @@ CSS Gridを使うと、height: autoへのアニメーションを実現できま -#### ネイティブCSSの場合 +#### ネイティブCSSの場合 {#enter-with-native-css} @@ -134,7 +134,7 @@ CSS Gridを使うと、height: autoへのアニメーションを実現できま -#### ネイティブCSSの場合 +#### ネイティブCSSの場合 {#leave-with-native-css} @@ -148,7 +148,7 @@ CSS Gridを使うと、height: autoへのアニメーションを実現できま 前述の`:enter`と`:leave`に加えて、`:increment`と`:decrement`もあります。これらもクラスを追加・削除することでアニメーションできます。アニメーションパッケージの組み込みエイリアスとは異なり、値が増減したときにクラスが自動で適用されるわけではありません。適切なクラスをプログラムから付与できます。例を示します。 -#### Animationsパッケージの場合 +#### Animationsパッケージの場合 {#increment-and-decrement-with-animations-package} @@ -156,7 +156,7 @@ CSS Gridを使うと、height: autoへのアニメーションを実現できま -#### ネイティブCSSの場合 +#### ネイティブCSSの場合 {#increment-and-decrement-with-native-css} @@ -168,6 +168,8 @@ CSS Gridを使うと、height: autoへのアニメーションを実現できま アニメーションパッケージとは異なり、あるコンポーネント内に複数のアニメーションを指定しても、どのアニメーションも他より優先されず、どのアニメーションの発火もブロックされません。アニメーションの順序付けは、animationやtransitionの遅延を使ったCSSアニメーション定義、あるいは次にアニメーションさせるCSSを追加するための`animationend`または`transitionend`によって処理する必要があります。 +Child animations fire only within the same component template. In the `@angular/animations` package, parent animations could query and trigger animations in nested child components using `query()` and `animateChild()`. With `animate.leave` and native CSS animations, animations defined inside nested child component templates will not fire when a parent component removes an element or view. Only nested animations within the same Angular component template will execute. See the [Enter and Leave Animations guide](guide/animations#element-removal-order) for more information on this. + ### アニメーションまたはすべてのアニメーションを無効にする {#disabling-an-animation-or-all-animations} ネイティブCSSアニメーションでは、指定したアニメーションを無効にしたい場合、複数の選択肢があります。 @@ -219,7 +221,7 @@ NOTE: これらのコールバックではバブリングの問題に注意し `stagger()`関数では、指定した時間だけリスト内の各項目のアニメーションを遅らせて、カスケード効果を作成できました。この挙動は、ネイティブCSSでも`animation-delay`または`transition-delay`を利用して再現できます。以下はそのCSSの例です。 -#### Animationsパッケージの場合 +#### Animationsパッケージの場合 {#stagger-with-animations-package} @@ -227,7 +229,7 @@ NOTE: これらのコールバックではバブリングの問題に注意し -#### ネイティブCSSの場合 +#### ネイティブCSSの場合 {#stagger-with-native-css} @@ -253,7 +255,7 @@ NOTE: これらのコールバックではバブリングの問題に注意し リスト項目の並び替えは、前述の手法を使うだけでそのまま機能します。特別な追加作業は必要ありません。`@for`ループ内の項目は適切に削除されて再追加されるため、enterアニメーションとして`@starting-styles`を使用したアニメーションが発火します。代わりに、同じ挙動を`animate.enter`で実現できます。上の例のように、要素が削除されるときは`animate.leave`を使ってアニメーションします。 -#### Animationsパッケージの場合 +#### Animationsパッケージの場合 {#reordering-list-with-animations-package} @@ -261,7 +263,7 @@ NOTE: これらのコールバックではバブリングの問題に注意し -#### ネイティブCSSの場合 +#### ネイティブCSSの場合 {#reordering-list-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 db2a70fa81..1fd7803649 100644 --- a/adev-ja/src/content/guide/animations/overview.en.md +++ b/adev-ja/src/content/guide/animations/overview.en.md @@ -256,7 +256,7 @@ Learn about more advanced features in Angular animations under the Animation sec ## Animations API summary The functional API provided by the `@angular/animations` module provides a domain-specific language \(DSL\) for creating and controlling animations in Angular applications. -See the [API reference](api#animations) for a complete listing and syntax details of the core functions and related data structures. +See the [API reference](api?package=angular_animations&status=8) for a complete listing and syntax details of the core functions and related data structures. | Function name | What it does | | :-------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | diff --git a/adev-ja/src/content/guide/animations/overview.md b/adev-ja/src/content/guide/animations/overview.md index 7e674c2003..d6736e09d9 100644 --- a/adev-ja/src/content/guide/animations/overview.md +++ b/adev-ja/src/content/guide/animations/overview.md @@ -256,7 +256,7 @@ HTMLテンプレートファイルでは、トリガー名を使って、定義 ## Animations APIの概要 {#animations-api-summary} `@angular/animations`モジュールが提供する関数型APIは、Angularアプリケーションでアニメーションを作成および制御するためのドメイン固有言語 \(DSL\) を提供します。 -コア関数と関連データ構造の完全な一覧と構文の詳細については、[APIリファレンス](api#animations)を参照してください。 +コア関数と関連データ構造の完全な一覧と構文の詳細については、[APIリファレンス](api?package=angular_animations&status=8)を参照してください。 | 関数名 | 役割 | | :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 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 7aa3fcab41..ab37f58402 100644 --- a/adev-ja/src/content/guide/animations/reusable-animations.en.md +++ b/adev-ja/src/content/guide/animations/reusable-animations.en.md @@ -18,7 +18,7 @@ HELPFUL: The `height`, `opacity`, `backgroundColor`, and `time` inputs are repla You can also export a part of an animation. For example, the following snippet exports the animation `trigger`. - + 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 c72f092647..954bba1071 100644 --- a/adev-ja/src/content/guide/animations/reusable-animations.md +++ b/adev-ja/src/content/guide/animations/reusable-animations.md @@ -18,7 +18,7 @@ HELPFUL: `height`、`opacity`、`backgroundColor`、`time`の入力値は実行 アニメーションの一部もエクスポートできます。 たとえば、次のスニペットではアニメーションの`trigger`をエクスポートしています。 - + ここから先は、再利用可能なアニメーション変数をコンポーネントクラスにインポートできます。 たとえば、次のコードスニペットでは`transitionAnimation`変数をインポートし、`useAnimation()`関数を通して使用しています。 diff --git a/adev-ja/src/content/guide/aria/toolbar.en.md b/adev-ja/src/content/guide/aria/toolbar.en.md index 95a1bb754d..53cc95aa84 100644 --- a/adev-ja/src/content/guide/aria/toolbar.en.md +++ b/adev-ja/src/content/guide/aria/toolbar.en.md @@ -55,7 +55,7 @@ Avoid toolbar when: Angular's toolbar provides a fully accessible toolbar implementation with: -- **Keyboard Navigation** - Navigate widgets with arrow keys, activate with Enter or Space +- **Keyboard Navigation** - Navigate widgets with arrow keys, Home, and End using roving tabindex, while controls retain native activation - **Screen Reader Support** - Built-in ARIA attributes for assistive technologies - **Widget Groups** - Organize related widgets like radio button groups or toggle button groups - **Flexible Orientation** - Horizontal or vertical layouts with automatic keyboard navigation @@ -127,25 +127,55 @@ Vertical toolbars stack controls top to bottom, useful for side panels or vertic ### Widget groups -Widget groups contain related controls that work together, like text alignment options or list formatting choices. Groups maintain their own internal state while participating in toolbar navigation. +Widget groups organize related controls that work together, such as text alignment options or formatting toggles. Groups maintain roving tabindex navigation while presenting the appropriate semantic structure to assistive technologies. -In the examples above, the alignment buttons are wrapped in `ngToolbarWidgetGroup` with `role="radiogroup"` to create a mutually exclusive selection group. +In the examples above, the alignment buttons are wrapped in `ngToolbarWidgetGroup` with `role="radiogroup"`. Selection is decoupled from the toolbar container, allowing you to manage state using Angular signals or custom directives: -The `multi` input controls whether multiple widgets within a group can be selected simultaneously: - -```html {highlight: [15]} - +```angular-html +
- - - + + +
- -
- - - + +
+ +
``` @@ -240,7 +270,7 @@ describe('MyToolbarComponent', () => { loader = TestbedHarnessEnvironment.loader(fixture); }); - it('should have widgets and allow selection', async () => { + it('should have widgets and update toggle state on click', async () => { // Load the toolbar harness const toolbar = await loader.getHarness(ToolbarHarness); @@ -251,7 +281,7 @@ describe('MyToolbarComponent', () => { // Click the first widget await widgets[0].click(); - // Verify selection state + // Verify pressed state updated via click handler expect(await widgets[0].isSelected()).toBe(true); }); }); diff --git a/adev-ja/src/content/guide/aria/toolbar.md b/adev-ja/src/content/guide/aria/toolbar.md index 875d259c91..be2d193149 100644 --- a/adev-ja/src/content/guide/aria/toolbar.md +++ b/adev-ja/src/content/guide/aria/toolbar.md @@ -55,7 +55,7 @@ Toolbarは、ユーザーが頻繁にアクセスする関連コントロール Angularのツールバーは、以下の機能を備えた完全にアクセシブルなツールバーの実装を提供します: -- **キーボードナビゲーション** - 矢印キーでウィジェットを移動し、EnterキーまたはSpaceキーでアクティブ化します +- **Keyboard Navigation** - Navigate widgets with arrow keys, Home, and End using roving tabindex, while controls retain native activation - **スクリーンリーダーのサポート** - 支援技術のための組み込みARIA属性 - **ウィジェットグループ** - ラジオボタングループやトグルボタングループのような関連ウィジェットを整理します - **柔軟な向き** - 自動キーボードナビゲーションを備えた水平または垂直レイアウト @@ -127,25 +127,55 @@ Angularのツールバーは、以下の機能を備えた完全にアクセシ ### ウィジェットグループ {#widget-groups} -ウィジェットグループには、テキストの配置オプションやリストの書式設定の選択肢など、連携して動作する関連コントロールが含まれています。グループは、ツールバーのナビゲーションに参加しながら、独自の内部状態を維持します。 +Widget groups organize related controls that work together, such as text alignment options or formatting toggles. Groups maintain roving tabindex navigation while presenting the appropriate semantic structure to assistive technologies. -上記の例では、配置ボタンは`ngToolbarWidgetGroup`でラップされ、`role="radiogroup"`が設定されており、相互に排他的な選択グループを作成しています。 +In the examples above, the alignment buttons are wrapped in `ngToolbarWidgetGroup` with `role="radiogroup"`. Selection is decoupled from the toolbar container, allowing you to manage state using Angular signals or custom directives: -`multi`入力は、グループ内の複数のウィジェットを同時に選択できるかどうかを制御します: - -```html {highlight: [15]} - +```angular-html +
- - - + + +
- -
- - - + +
+ +
``` @@ -240,7 +270,7 @@ describe('MyToolbarComponent', () => { loader = TestbedHarnessEnvironment.loader(fixture); }); - it('should have widgets and allow selection', async () => { + it('should have widgets and update toggle state on click', async () => { // Load the toolbar harness const toolbar = await loader.getHarness(ToolbarHarness); @@ -251,7 +281,7 @@ describe('MyToolbarComponent', () => { // Click the first widget await widgets[0].click(); - // Verify selection state + // Verify pressed state updated via click handler expect(await widgets[0].isSelected()).toBe(true); }); }); diff --git a/adev-ja/src/content/guide/components/advanced-configuration.en.md b/adev-ja/src/content/guide/components/advanced-configuration.en.md index 87a47d4ea5..f452e2a148 100644 --- a/adev-ja/src/content/guide/components/advanced-configuration.en.md +++ b/adev-ja/src/content/guide/components/advanced-configuration.en.md @@ -45,4 +45,4 @@ import {Component, CUSTOM_ELEMENTS_SCHEMA} from '@angular/core'; export class ComponentWithCustomElements { } ``` -Angular does not support any other schemas at this time. +Angular also provides `NO_ERRORS_SCHEMA`, which allows any element and any property. diff --git a/adev-ja/src/content/guide/components/advanced-configuration.md b/adev-ja/src/content/guide/components/advanced-configuration.md index fdf734bc2b..feed1ce4da 100644 --- a/adev-ja/src/content/guide/components/advanced-configuration.md +++ b/adev-ja/src/content/guide/components/advanced-configuration.md @@ -45,4 +45,4 @@ import {Component, CUSTOM_ELEMENTS_SCHEMA} from '@angular/core'; export class ComponentWithCustomElements { } ``` -Angularは、現時点で他のスキーマをサポートしていません。 +Angularは、任意の要素と任意のプロパティを許可する`NO_ERRORS_SCHEMA`も提供しています。 diff --git a/adev-ja/src/content/guide/components/host-elements.en.md b/adev-ja/src/content/guide/components/host-elements.en.md index e78c916f34..0493a09e3f 100644 --- a/adev-ja/src/content/guide/components/host-elements.en.md +++ b/adev-ja/src/content/guide/components/host-elements.en.md @@ -64,6 +64,11 @@ export class CustomSlider { NOTE: The global target names that can be used to prefix an event name are `document:`, `window:` and `body:`. +NOTE: Key names like `'(keydown.enter)'` are matched against `KeyboardEvent.key`, which depends on +the user's keyboard layout and input language. To match a physical key regardless of layout, use +the `code` modifier instead, e.g. `'(keydown.code.Enter)'`. See +[Using key modifiers](guide/templates/event-listeners#using-key-modifiers) for details. + ## The `@HostBinding` and `@HostListener` decorators You can alternatively bind to the host element by applying the `@HostBinding` and `@HostListener` @@ -72,9 +77,7 @@ decorator to class members. `@HostBinding` lets you bind host properties and attributes to properties and getters: ```ts -@Component({ - /* ... */ -}) +@Component({/* ... */}) export class CustomSlider { @HostBinding('attr.aria-valuenow') value: number = 0; diff --git a/adev-ja/src/content/guide/components/host-elements.md b/adev-ja/src/content/guide/components/host-elements.md index b78c77693d..875e2261c6 100644 --- a/adev-ja/src/content/guide/components/host-elements.md +++ b/adev-ja/src/content/guide/components/host-elements.md @@ -64,6 +64,11 @@ export class CustomSlider { NOTE: イベント名にプレフィックスとして使用できるグローバルターゲット名は `document:`、`window:`、`body:` です。 +NOTE: `'(keydown.enter)'`のようなキー名は`KeyboardEvent.key`と照合されます。これはユーザーのキーボードレイアウトや入力言語に依存します。 +レイアウトに関係なく物理キーに一致させるには、 +代わりに`code`修飾子を使用します。例: `'(keydown.code.Enter)'`。 +詳細は[キー修飾子の使用](guide/templates/event-listeners#using-key-modifiers)を参照してください。 + ## `@HostBinding`および`@HostListener`デコレーター {#the-hostbinding-and-hostlistener-decorators} クラスメンバーに`@HostBinding`および`@HostListener`デコレーターを適用することにより、 @@ -72,9 +77,7 @@ NOTE: イベント名にプレフィックスとして使用できるグロー `@HostBinding`を使用すると、ホストのプロパティと属性を、プロパティとゲッターにバインドできます。 ```ts -@Component({ - /* ... */ -}) +@Component({/* ... */}) export class CustomSlider { @HostBinding('attr.aria-valuenow') value: number = 0; diff --git a/adev-ja/src/content/guide/components/inputs.en.md b/adev-ja/src/content/guide/components/inputs.en.md index d8877449e3..67ab7ebd06 100644 --- a/adev-ja/src/content/guide/components/inputs.en.md +++ b/adev-ja/src/content/guide/components/inputs.en.md @@ -288,7 +288,7 @@ Binding to an input is the same in both signal-based and decorator-based inputs: The `@Input` decorator accepts a config object that lets you change the way that input works. -#### Required inputs +#### Required inputs {#required-inputs-decorator} You can specify the `required` option to enforce that a given input must always have a value. @@ -301,7 +301,7 @@ export class CustomSlider { If you try to use a component without specifying all of its required inputs, Angular reports an error at build-time. -#### Input transforms +#### Input transforms {#input-transforms-decorator} You can specify a `transform` function to change the value of an input when it's set by Angular. This transform function works identically to transform functions for signal-based inputs described above. @@ -319,7 +319,7 @@ function trimString(value: string | undefined) { } ``` -#### Input aliases +#### Input aliases {#input-aliases-decorator} You can specify the `alias` option to change the name of an input in templates. diff --git a/adev-ja/src/content/guide/components/inputs.md b/adev-ja/src/content/guide/components/inputs.md index 5e00e7f1d3..a103cfff9e 100644 --- a/adev-ja/src/content/guide/components/inputs.md +++ b/adev-ja/src/content/guide/components/inputs.md @@ -288,7 +288,7 @@ export class CustomSlider { `@Input`デコレーターは、入力の動作を変更できるconfigオブジェクトを受け取ります。 -#### 必須入力 {#required-inputs} +#### 必須入力 {#required-inputs-decorator} `required`オプションを指定して、特定の入力が常に値を持つ必要があることを強制できます。 @@ -301,7 +301,7 @@ export class CustomSlider { すべての必須入力を指定せずにコンポーネントを使用しようとすると、Angularはビルド時にエラーを報告します。 -#### 入力変換 {#input-transforms} +#### 入力変換 {#input-transforms-decorator} Angularによって入力が設定されるときにその値を変更する`transform`関数を指定できます。この変換関数は、上記で説明したシグナルベースの入力の変換関数と同様に機能します。 @@ -319,7 +319,7 @@ function trimString(value: string | undefined) { } ``` -#### 入力エイリアス {#input-aliases} +#### 入力エイリアス {#input-aliases-decorator} `alias`オプションを指定して、テンプレートでの入力の名前を変更できます。 diff --git a/adev-ja/src/content/guide/components/lifecycle.en.md b/adev-ja/src/content/guide/components/lifecycle.en.md index 419765338f..bb8c43abc5 100644 --- a/adev-ja/src/content/guide/components/lifecycle.en.md +++ b/adev-ja/src/content/guide/components/lifecycle.en.md @@ -37,7 +37,7 @@ process. - Change

Detection + Change
Detection ngOnInit Runs once after Angular has initialized all the component's inputs. @@ -111,9 +111,7 @@ has changed. You can optionally pass the current class or this as the first generic argument for stronger type checking. ```ts -@Component({ - /* ... */ -}) +@Component({/* ... */}) export class UserProfile { name = input(''); @@ -143,9 +141,7 @@ register a callback to be invoked upon the component's destruction by calling th of `DestroyRef`. ```ts -@Component({ - /* ... */ -}) +@Component({/* ... */}) export class UserProfile { constructor() { inject(DestroyRef).onDestroy(() => { @@ -306,9 +302,7 @@ Each interface has the same name as the corresponding method without the `ng` pr the interface for `ngOnInit` is `OnInit`. ```ts -@Component({ - /* ... */ -}) +@Component({/* ... */}) export class UserProfile implements OnInit { ngOnInit() { /* ... */ diff --git a/adev-ja/src/content/guide/components/lifecycle.md b/adev-ja/src/content/guide/components/lifecycle.md index 6d6af0bff2..6ef800c4e6 100644 --- a/adev-ja/src/content/guide/components/lifecycle.md +++ b/adev-ja/src/content/guide/components/lifecycle.md @@ -111,9 +111,7 @@ Angularアプリケーション全体に関連するライフサイクルフッ より強力な型チェックのために、オプションで現在のクラスまたはthisを最初のジェネリック引数として渡すことができます。 ```ts -@Component({ - /* ... */ -}) +@Component({/* ... */}) export class UserProfile { name = input(''); @@ -143,9 +141,7 @@ Angularは、コンポーネントがページに表示されなくなった場 `DestroyRef` の `onDestroy` メソッドを呼び出します。 ```ts -@Component({ - /* ... */ -}) +@Component({/* ... */}) export class UserProfile { constructor() { inject(DestroyRef).onDestroy(() => { @@ -306,9 +302,7 @@ Angularは、各ライフサイクルメソッド用のTypeScriptインターフ たとえば、`ngOnInit` のインターフェースは `OnInit` です。 ```ts -@Component({ - /* ... */ -}) +@Component({/* ... */}) export class UserProfile implements OnInit { ngOnInit() { /* ... */ diff --git a/adev-ja/src/content/guide/components/programmatic-rendering.en.md b/adev-ja/src/content/guide/components/programmatic-rendering.en.md index 39929912ee..1a2f5dd30d 100644 --- a/adev-ja/src/content/guide/components/programmatic-rendering.en.md +++ b/adev-ja/src/content/guide/components/programmatic-rendering.en.md @@ -20,24 +20,31 @@ chunks automatically and loaded only when necessary, based on the configured tri template. ```angular-ts +import {NgComponentOutlet} from '@angular/common'; + @Component({/*...*/}) -export class AdminBio { /* ... */ } +export class AdminBio { + /* ... */ +} @Component({/*...*/}) -export class StandardBio { /* ... */ } +export class StandardBio { + /* ... */ +} @Component({ - ..., + imports: [NgComponentOutlet], template: ` -

Profile for {{user.name}}

- ` +

Profile for {{ user().name }}

+ + `, }) export class CustomDialog { user = input.required(); - getBioComponent() { + bioComponent = computed(() => { return this.user().isAdmin ? AdminBio : StandardBio; - } + }); } ``` @@ -396,3 +403,18 @@ export class PopupService { } } ``` + +## Handling rendering errors + +When dynamically creating components using `ViewContainerRef.createComponent` or the standalone `createComponent` function, you can provide an `onError` callback in the options object to handle errors that occur during the rendering or change detection phases. This is the programmatic equivalent of using an `@error` block in templates. + +```ts +viewContainerRef.createComponent(DynamicComponent, { + onError: (err: Error, details: ErrorDetails) => { + console.error('Component rendering failed:', err); + // Render an alternative UI or log metrics + }, +}); +``` + +NOTE: The `onError` callback only catches errors that occur during the rendering or change detection phases. It does not catch errors that occur during component instantiation (for example, in the constructor). Angular throws construction errors synchronously when you call the API. diff --git a/adev-ja/src/content/guide/components/programmatic-rendering.md b/adev-ja/src/content/guide/components/programmatic-rendering.md index 48d196785e..bf80c45508 100644 --- a/adev-ja/src/content/guide/components/programmatic-rendering.md +++ b/adev-ja/src/content/guide/components/programmatic-rendering.md @@ -20,24 +20,31 @@ HELPFUL: 遅延読み込みのユースケース(たとえば、重いコンポ 構造ディレクティブです。 ```angular-ts +import {NgComponentOutlet} from '@angular/common'; + @Component({/*...*/}) -export class AdminBio { /* ... */ } +export class AdminBio { + /* ... */ +} @Component({/*...*/}) -export class StandardBio { /* ... */ } +export class StandardBio { + /* ... */ +} @Component({ - ..., + imports: [NgComponentOutlet], template: ` -

Profile for {{user.name}}

- ` +

Profile for {{ user().name }}

+ + `, }) export class CustomDialog { user = input.required(); - getBioComponent() { + bioComponent = computed(() => { return this.user().isAdmin ? AdminBio : StandardBio; - } + }); } ``` @@ -396,3 +403,18 @@ export class PopupService { } } ``` + +## Handling rendering errors + +When dynamically creating components using `ViewContainerRef.createComponent` or the standalone `createComponent` function, you can provide an `onError` callback in the options object to handle errors that occur during the rendering or change detection phases. This is the programmatic equivalent of using an `@error` block in templates. + +```ts +viewContainerRef.createComponent(DynamicComponent, { + onError: (err: Error, details: ErrorDetails) => { + console.error('Component rendering failed:', err); + // Render an alternative UI or log metrics + }, +}); +``` + +NOTE: The `onError` callback only catches errors that occur during the rendering or change detection phases. It does not catch errors that occur during component instantiation (for example, in the constructor). Angular throws construction errors synchronously when you call the API. diff --git a/adev-ja/src/content/guide/components/queries.en.md b/adev-ja/src/content/guide/components/queries.en.md index 8ce4e253ac..b0bc6e04a1 100644 --- a/adev-ja/src/content/guide/components/queries.en.md +++ b/adev-ja/src/content/guide/components/queries.en.md @@ -102,7 +102,7 @@ export class UserProfile {} If the query does not find a result, its value is `undefined`. This may occur if the target element is absent or hidden by `@if`. Angular keeps the result of `contentChild` up to date as your application state changes. -By default, content queries find only _direct_ children of the component and do not traverse into descendants. +By default, `contentChild` queries traverse into descendants, while `contentChildren` queries find only _direct_ children. See [Content descendants](#content-descendants). You can also query for multiple results with the `contentChildren` function. @@ -225,6 +225,30 @@ the `TemplateRef` associated with that element. Developers most commonly use `read` to retrieve `ElementRef` and `TemplateRef`. +You can also pass `Injector` to `read`. + +```angular-ts +@Component({ + selector: 'custom-table', + template: ` + + + + + + `, +}) +export class CustomTable { + columns = contentChild(TemplateRef); + innerInjector = viewChild('inner', {read: Injector}); +} +``` + +The above example retrieves the node injector of the `third-party-table` element, meaning the +injector as seen from that element's position in the tree. Passing it to `NgTemplateOutlet` through +`ngTemplateOutletInjector` lets directives in the projected template inject values that the +third-party component provides. + ### Content descendants By default, `contentChildren` queries find only _direct_ children of the component and do not traverse into descendants. diff --git a/adev-ja/src/content/guide/components/queries.md b/adev-ja/src/content/guide/components/queries.md index e1544875a6..e8742f4eac 100644 --- a/adev-ja/src/content/guide/components/queries.md +++ b/adev-ja/src/content/guide/components/queries.md @@ -102,7 +102,7 @@ export class UserProfile {} クエリが結果を見つけられない場合、その値は`undefined`になります。これは、ターゲット要素が存在しないか、`@if`によって非表示になっている場合に発生する可能性があります。Angularは、アプリケーションの状態が変化するにつれて`contentChild`の結果を最新の状態に保ちます。 -デフォルトでは、コンテンツクエリはコンポーネントの_直接_の子のみを見つけ、子孫にはトラバースしません。 +デフォルトでは、`contentChild`クエリは子孫にトラバースしますが、`contentChildren`クエリは_直接_の子のみを見つけます。[コンテンツの子孫](#content-descendants)を参照してください。 `contentChildren`関数を使用して、複数結果をクエリできます。 @@ -225,6 +225,30 @@ export class CustomExpando { 開発者は、`read`を使用して`ElementRef`と`TemplateRef`を取得することが最も一般的です。 +`read`には`Injector`も渡せます。 + +```angular-ts +@Component({ + selector: 'custom-table', + template: ` + + + + + + `, +}) +export class CustomTable { + columns = contentChild(TemplateRef); + innerInjector = viewChild('inner', {read: Injector}); +} +``` + +上記の例では、`third-party-table`要素のノードインジェクター、 +つまりその要素のツリー上の位置から見えるインジェクターを取得します。これを +`ngTemplateOutletInjector`経由で`NgTemplateOutlet`に渡すことで、投影されたテンプレート内の +ディレクティブが、サードパーティコンポーネントの提供する値を注入できるようになります。 + ### コンテンツの子孫 {#content-descendants} デフォルトでは、`contentChildren`クエリはコンポーネントの直接の子要素のみを検索し、子孫要素にはトラバースしません。 diff --git a/adev-ja/src/content/guide/components/styling.en.md b/adev-ja/src/content/guide/components/styling.en.md index 456f767b77..67a8cd6e30 100644 --- a/adev-ja/src/content/guide/components/styling.en.md +++ b/adev-ja/src/content/guide/components/styling.en.md @@ -142,3 +142,122 @@ reference CSS files. Additionally, your CSS may use [the `@import`at-rule](https://developer.mozilla.org/docs/Web/CSS/@import) to reference CSS files. Angular treats these references as _external_ styles. External styles are not affected by emulated view encapsulation. + +## Namespacing CSS custom properties + +Angular can add a prefix to the CSS custom properties (also called CSS variables) that your +component styles declare and read. Custom properties inherit down the DOM tree, so when something +outside your application defines a custom property such as `--primary-color` on an ancestor +element, your components read that value. This matters when your application shares a page with another +application or with markup you do not control. Angular does not namespace custom properties until +you ask it to, and an application that owns its page does not need namespacing. + +To scope the custom properties in your component styles to your application, add +[`provideCssVarNamespacing`](api/platform-browser/provideCssVarNamespacing) to your application's +providers. It uses the application's [`APP_ID`](api/core/APP_ID) as the namespace: + +```ts {header: "app.config.ts"} +import {APP_ID, ApplicationConfig} from '@angular/core'; +import {provideCssVarNamespacing} from '@angular/platform-browser'; + +export const appConfig: ApplicationConfig = { + providers: [{provide: APP_ID, useValue: 'my-app'}, provideCssVarNamespacing()], +}; +``` + +Angular prefixes the custom properties in your component styles with that namespace followed by an +underscore, so `--primary-color` becomes `--my-app_primary-color`. The prefix applies to +declarations, `var()` references, `@property` rules, and style bindings such as +`[style.--primary-color]`, including the style bindings a component declares in its `host` object. + +`APP_ID` is `ng` unless you set it, so give each application on the page its own `APP_ID`. +Otherwise, the applications share a prefix and collide again. To use a namespace that differs from +the application id, pass it to `provideCssVarNamespacing`. Angular appends the underscore itself: +`provideCssVarNamespacing('my-app_')` produces `--my-app__primary-color`. + +Angular namespaces the styles it compiles into a component: the `styles` and `styleUrl` of the +component, the styles you [write in a `