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 1537342506..6ee0d2dee2 100644
--- a/adev-ja/src/app/features/update/update.component.en.ts
+++ b/adev-ja/src/app/features/update/update.component.en.ts
@@ -71,6 +71,7 @@ export default class UpdateComponent {
protected afterRecommendations: Step[] = [];
protected readonly versions = [
+ {name: '21.0', number: 2100},
{name: '20.0', number: 2000},
{name: '19.0', number: 1900},
{name: '18.0', number: 1800},
@@ -108,8 +109,8 @@ export default class UpdateComponent {
{name: '2.1', number: 201},
{name: '2.0', number: 200},
];
- protected from = this.versions.find((version) => version.name === '19.0')!;
- protected to = this.versions.find((version) => version.name === '20.0')!;
+ protected from = this.versions.find((version) => version.name === '20.0')!;
+ protected to = this.versions.find((version) => version.name === '21.0')!;
protected futureVersion = 2100;
protected readonly steps: Step[] = RECOMMENDATIONS;
diff --git a/adev-ja/src/app/features/update/update.component.ts b/adev-ja/src/app/features/update/update.component.ts
index 4ff9e7ea94..6a1f38b7ad 100644
--- a/adev-ja/src/app/features/update/update.component.ts
+++ b/adev-ja/src/app/features/update/update.component.ts
@@ -71,6 +71,7 @@ export default class UpdateComponent {
protected afterRecommendations: Step[] = [];
protected readonly versions = [
+ {name: '21.0', number: 2100},
{name: '20.0', number: 2000},
{name: '19.0', number: 1900},
{name: '18.0', number: 1800},
@@ -108,8 +109,8 @@ export default class UpdateComponent {
{name: '2.1', number: 201},
{name: '2.0', number: 200},
];
- protected from = this.versions.find((version) => version.name === '19.0')!;
- protected to = this.versions.find((version) => version.name === '20.0')!;
+ protected from = this.versions.find((version) => version.name === '20.0')!;
+ protected to = this.versions.find((version) => version.name === '21.0')!;
protected futureVersion = 2100;
protected readonly steps: Step[] = RECOMMENDATIONS;
diff --git a/adev-ja/src/app/routing/sub-navigation-data.en.ts b/adev-ja/src/app/routing/sub-navigation-data.en.ts
index 12d4d84abc..e7813b6d56 100644
--- a/adev-ja/src/app/routing/sub-navigation-data.en.ts
+++ b/adev-ja/src/app/routing/sub-navigation-data.en.ts
@@ -14,6 +14,7 @@ import FIRST_APP_TUTORIAL_NAV_DATA from '../../../src/assets/tutorials/first-app
import LEARN_ANGULAR_TUTORIAL_NAV_DATA from '../../../src/assets/tutorials/learn-angular/routes.json';
import DEFERRABLE_VIEWS_TUTORIAL_NAV_DATA from '../../../src/assets/tutorials/deferrable-views/routes.json';
import SIGNALS_TUTORIAL_NAV_DATA from '../../../src/assets/tutorials/signals/routes.json';
+import SIGNAL_FORMS_TUTORIAL_NAV_DATA from '../../../src/assets/tutorials/signal-forms/routes.json';
import ERRORS_NAV_DATA from '../../../src/assets/content/reference/errors/routes.json';
import EXT_DIAGNOSTICS_NAV_DATA from '../../../src/assets/content/reference/extended-diagnostics/routes.json';
@@ -435,19 +436,31 @@ const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [
label: 'Overview',
path: 'guide/forms/signals/overview',
contentPath: 'guide/forms/signals/overview',
- status: 'new',
},
{
label: 'Form models',
path: 'guide/forms/signals/models',
contentPath: 'guide/forms/signals/models',
- status: 'new',
+ },
+ {
+ label: 'Field state management',
+ path: 'guide/forms/signals/field-state-management',
+ contentPath: 'guide/forms/signals/field-state-management',
+ },
+ {
+ label: 'Validation',
+ path: 'guide/forms/signals/validation',
+ contentPath: 'guide/forms/signals/validation',
+ },
+ {
+ label: 'Custom controls',
+ path: 'guide/forms/signals/custom-controls',
+ contentPath: 'guide/forms/signals/custom-controls',
},
{
label: 'Comparison with other form systems',
path: 'guide/forms/signals/comparison',
contentPath: 'guide/forms/signals/comparison',
- status: 'new',
},
],
},
@@ -592,6 +605,11 @@ const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [
path: 'guide/testing/utility-apis',
contentPath: 'guide/testing/utility-apis',
},
+ {
+ label: 'Zone.js Testing Utilities',
+ path: 'guide/testing/zone-js-testing-utilities',
+ contentPath: 'guide/testing/zone-js-testing-utilities',
+ },
{
label: 'Component harnesses overview',
path: 'guide/testing/component-harnesses-overview',
@@ -1201,6 +1219,7 @@ export const TUTORIALS_SUB_NAVIGATION_DATA: NavigationItem[] = [
LEARN_ANGULAR_TUTORIAL_NAV_DATA,
DEFERRABLE_VIEWS_TUTORIAL_NAV_DATA,
SIGNALS_TUTORIAL_NAV_DATA,
+ SIGNAL_FORMS_TUTORIAL_NAV_DATA,
{
path: DEFAULT_PAGES.TUTORIALS,
contentPath: 'tutorials/home',
diff --git a/adev-ja/src/app/routing/sub-navigation-data.ts b/adev-ja/src/app/routing/sub-navigation-data.ts
index 28c9dec49d..e13a0ce52a 100644
--- a/adev-ja/src/app/routing/sub-navigation-data.ts
+++ b/adev-ja/src/app/routing/sub-navigation-data.ts
@@ -14,6 +14,7 @@ import FIRST_APP_TUTORIAL_NAV_DATA from '../../../src/assets/tutorials/first-app
import LEARN_ANGULAR_TUTORIAL_NAV_DATA from '../../../src/assets/tutorials/learn-angular/routes.json';
import DEFERRABLE_VIEWS_TUTORIAL_NAV_DATA from '../../../src/assets/tutorials/deferrable-views/routes.json';
import SIGNALS_TUTORIAL_NAV_DATA from '../../../src/assets/tutorials/signals/routes.json';
+import SIGNAL_FORMS_TUTORIAL_NAV_DATA from '../../../src/assets/tutorials/signal-forms/routes.json';
import ERRORS_NAV_DATA from '../../../src/assets/content/reference/errors/routes.json';
import EXT_DIAGNOSTICS_NAV_DATA from '../../../src/assets/content/reference/extended-diagnostics/routes.json';
@@ -435,19 +436,31 @@ const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [
label: '概要',
path: 'guide/forms/signals/overview',
contentPath: 'guide/forms/signals/overview',
- status: 'new',
},
{
label: 'フォームモデル',
path: 'guide/forms/signals/models',
contentPath: 'guide/forms/signals/models',
- status: 'new',
+ },
+ {
+ label: 'フィールド状態管理',
+ path: 'guide/forms/signals/field-state-management',
+ contentPath: 'guide/forms/signals/field-state-management',
+ },
+ {
+ label: 'バリデーション',
+ path: 'guide/forms/signals/validation',
+ contentPath: 'guide/forms/signals/validation',
+ },
+ {
+ label: 'カスタムコントロール',
+ path: 'guide/forms/signals/custom-controls',
+ contentPath: 'guide/forms/signals/custom-controls',
},
{
label: '他のフォームシステムとの比較',
path: 'guide/forms/signals/comparison',
contentPath: 'guide/forms/signals/comparison',
- status: 'new',
},
],
},
@@ -592,6 +605,11 @@ const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [
path: 'guide/testing/utility-apis',
contentPath: 'guide/testing/utility-apis',
},
+ {
+ label: 'Zone.jsテストユーティリティ',
+ path: 'guide/testing/zone-js-testing-utilities',
+ contentPath: 'guide/testing/zone-js-testing-utilities',
+ },
{
label: 'コンポーネントハーネスの概要',
path: 'guide/testing/component-harnesses-overview',
@@ -1201,6 +1219,7 @@ export const TUTORIALS_SUB_NAVIGATION_DATA: NavigationItem[] = [
LEARN_ANGULAR_TUTORIAL_NAV_DATA,
DEFERRABLE_VIEWS_TUTORIAL_NAV_DATA,
SIGNALS_TUTORIAL_NAV_DATA,
+ SIGNAL_FORMS_TUTORIAL_NAV_DATA,
{
path: DEFAULT_PAGES.TUTORIALS,
contentPath: 'tutorials/home',
diff --git a/adev-ja/src/content/best-practices/style-guide.en.md b/adev-ja/src/content/best-practices/style-guide.en.md
index 11e02dedfd..5cffdd32a5 100644
--- a/adev-ja/src/content/best-practices/style-guide.en.md
+++ b/adev-ja/src/content/best-practices/style-guide.en.md
@@ -222,12 +222,15 @@ Prefer `class` and `style` bindings over using the [`NgClass`](/api/common/NgCla
```html
+
+
+
```
Both `class` and `style` bindings use a more straightforward syntax that aligns closely with
diff --git a/adev-ja/src/content/guide/aria/overview.en.md b/adev-ja/src/content/guide/aria/overview.en.md
index 9f7fe72d67..02838912d0 100644
--- a/adev-ja/src/content/guide/aria/overview.en.md
+++ b/adev-ja/src/content/guide/aria/overview.en.md
@@ -17,11 +17,31 @@ npm install @angular/aria
For example, let's take a toolbar menu. While it may appear to be a "simple" row of buttons tied with specific logic, keyboard navigation and screen readers add a lot of unexpected complexity to those unfamiliar with accessibility.
-```
-
-
-
-```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
In this one scenario, developers need to consider:
@@ -42,6 +62,7 @@ Angular Aria includes directives for common interactive patterns:
| [Grid](guide/aria/grid) | Two-dimensional data display with cell-by-cell keyboard navigation |
| [Listbox](guide/aria/listbox) | Single or multi-select option lists with keyboard navigation |
| [Menu](guide/aria/menu) | Dropdown menus with nested submenus and keyboard shortcuts |
+| [Menubar](guide/aria/menubar) | Horizontal navigation bar for persistent application menus. |
| [Multiselect](guide/aria/multiselect) | Multiple-selection dropdown pattern with compact display |
| [Select](guide/aria/select) | Single-selection dropdown pattern with keyboard navigation |
| [Tabs](guide/aria/tabs) | Tabbed interfaces with automatic or manual activation modes |
@@ -63,7 +84,7 @@ Angular Aria works well when you need accessible interactive components that are
Angular Aria might not fit every scenario:
- **Pre-styled components** - If you need components that look complete without custom styling, use Angular Material instead
-- **Simple forms** - Native HTML form controls like and provide built-in accessibility for straightforward use cases
+- **Simple forms** - Native HTML form controls like `` and ` ` provide built-in accessibility for straightforward use cases
- **Rapid prototyping** - When validating concepts quickly, pre-styled component libraries reduce initial development time
## Next steps
diff --git a/adev-ja/src/content/guide/components/lifecycle.en.md b/adev-ja/src/content/guide/components/lifecycle.en.md
index 2d84280612..47b6a9ea2c 100644
--- a/adev-ja/src/content/guide/components/lifecycle.en.md
+++ b/adev-ja/src/content/guide/components/lifecycle.en.md
@@ -108,6 +108,8 @@ mapping each component input name to a `SimpleChange` object. Each `SimpleChange
input's previous value, its current value, and a flag for whether this is the first time the input
has changed.
+You can optionally pass the current class or this as the first generic argument for stronger type checking.
+
```ts
@Component({
/* ... */
@@ -115,12 +117,11 @@ has changed.
export class UserProfile {
name = input('');
- ngOnChanges(changes: SimpleChanges) {
- for (const inputName in changes) {
- const inputValues = changes[inputName];
- console.log(`Previous ${inputName} == ${inputValues.previousValue}`);
- console.log(`Current ${inputName} == ${inputValues.currentValue}`);
- console.log(`Is first ${inputName} change == ${inputValues.firstChange}`);
+ ngOnChanges(changes: SimpleChanges) {
+ if (changes.name) {
+ console.log(`Previous: ${changes.name.previousValue}`);
+ console.log(`Current: ${changes.name.currentValue}`);
+ console.log(`Is first ${changes.name.firstChange}`);
}
}
}
diff --git a/adev-ja/src/content/guide/testing/services.en.md b/adev-ja/src/content/guide/testing/services.en.md
index 41570ea43c..dac0eacf35 100644
--- a/adev-ja/src/content/guide/testing/services.en.md
+++ b/adev-ja/src/content/guide/testing/services.en.md
@@ -1,5 +1,7 @@
# Testing services
+NOTE: While this guide is being updated for Vitest, some code examples currently use Karma/Jasmine syntax and APIs. We are actively working to provide Vitest equivalents where applicable.
+
To check that your services are working as you intend, you can write tests specifically for them.
Services are often the smoothest files to unit test.
diff --git a/adev-ja/src/content/guide/testing/utility-apis.en.md b/adev-ja/src/content/guide/testing/utility-apis.en.md
index 899c345926..38a72b333b 100644
--- a/adev-ja/src/content/guide/testing/utility-apis.en.md
+++ b/adev-ja/src/content/guide/testing/utility-apis.en.md
@@ -1,5 +1,7 @@
# Testing Utility APIs
+NOTE: While this guide is being updated for Vitest, some descriptions and examples of utility APIs are currently presented within the context of Karma/Jasmine. We are actively working to provide Vitest equivalents and updated guidance where applicable.
+
This page describes the most useful Angular testing features.
The Angular testing utilities include the `TestBed`, the `ComponentFixture`, and a handful of functions that control the test environment.
@@ -7,16 +9,13 @@ The [`TestBed`](#testbed-class-summary) and [`ComponentFixture`](#the-componentf
Here's a summary of the stand-alone functions, in order of likely utility:
-| Function | Details |
-| :--------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `waitForAsync` | Runs the body of a test \(`it`\) or setup \(`beforeEach`\) function within a special _async test zone_. See [waitForAsync](guide/testing/components-scenarios#waitForAsync). |
-| `fakeAsync` | Runs the body of a test \(`it`\) within a special _fakeAsync test zone_, enabling a linear control flow coding style. See [fakeAsync](guide/testing/components-scenarios#fake-async). |
-| `tick` | Simulates the passage of time and the completion of pending asynchronous activities by flushing both _timer_ and _micro-task_ queues within the _fakeAsync test zone_. The curious, dedicated reader might enjoy this lengthy blog post, ["_Tasks, microtasks, queues and schedules_"](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules). Accepts an optional argument that moves the virtual clock forward by the specified number of milliseconds, clearing asynchronous activities scheduled within that timeframe. See [tick](guide/testing/components-scenarios#tick). |
-| `inject` | Injects one or more services from the current `TestBed` injector into a test function. It cannot inject a service provided by the component itself. See discussion of the [debugElement.injector](guide/testing/components-scenarios#get-injected-services). |
-| `discardPeriodicTasks` | When a `fakeAsync()` test ends with pending timer event _tasks_ \(queued `setTimeOut` and `setInterval` callbacks\), the test fails with a clear error message. In general, a test should end with no queued tasks. When pending timer tasks are expected, call `discardPeriodicTasks` to flush the _task_ queue and avoid the error. |
-| `flushMicrotasks` | When a `fakeAsync()` test ends with pending _micro-tasks_ such as unresolved promises, the test fails with a clear error message. In general, a test should wait for micro-tasks to finish. When pending microtasks are expected, call `flushMicrotasks` to flush the _micro-task_ queue and avoid the error. |
-| `ComponentFixtureAutoDetect` | A provider token for a service that turns on [automatic change detection](guide/testing/components-scenarios#automatic-change-detection). |
-| `getTestBed` | Gets the current instance of the `TestBed`. Usually unnecessary because the static class methods of the `TestBed` class are typically sufficient. The `TestBed` instance exposes a few rarely used members that are not available as static methods. |
+| Function | Details |
+| :--------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `inject` | Injects one or more services from the current `TestBed` injector into a test function. It cannot inject a service provided by the component itself. See discussion of the [debugElement.injector](guide/testing/components-scenarios#get-injected-services). |
+| `ComponentFixtureAutoDetect` | A provider token for a service that turns on [automatic change detection](guide/testing/components-scenarios#automatic-change-detection). |
+| `getTestBed` | Gets the current instance of the `TestBed`. Usually unnecessary because the static class methods of the `TestBed` class are typically sufficient. The `TestBed` instance exposes a few rarely used members that are not available as static methods. |
+
+For handling complex asynchronous scenarios or testing legacy Zone.js-based applications, see the [Zone.js Testing Utilities](guide/testing/zone-js-testing-utilities) guide.
## `TestBed` class summary
diff --git a/adev-ja/src/content/introduction/essentials/signal-forms.en.md b/adev-ja/src/content/introduction/essentials/signal-forms.en.md
index 3bf1b4b5e3..16039c7391 100644
--- a/adev-ja/src/content/introduction/essentials/signal-forms.en.md
+++ b/adev-ja/src/content/introduction/essentials/signal-forms.en.md
@@ -8,7 +8,7 @@ This guide walks you through the core concepts to create forms with Signal Forms
## Creating your first form
-### 1. Create a form model
+### 1. Create a form model with `signal()`
Every form starts by creating a signal that holds your form's data model:
@@ -24,19 +24,19 @@ const loginModel = signal({
});
```
-### 2. Pass the form model to `form()`
+### 2. Pass the form model to `form()` to create a `FieldTree`
Then, you pass your form model into the `form()` function to create a **field tree** - an object structure that mirrors your model's shape, allowing you to access fields with dot notation:
```ts
-form(loginModel);
+const loginForm = form(loginModel);
// Access fields directly by property name
loginForm.email
loginForm.password
```
-### 3. Bind inputs with `[field]` directive
+### 3. Bind HTML inputs with `[field]` directive
Next, you bind your HTML inputs to the form using the `[field]` directive, which creates two-way binding between them:
@@ -45,19 +45,11 @@ Next, you bind your HTML inputs to the form using the `[field]` directive, which
```
-As a result, user changes (such as typing in the field) automatically updates the form, and any programmatic changes update the displayed value as well:
-
-```ts
-// Update the value programmatically
-loginForm.email().value.set('alice@wonderland.com');
-
-// The model signal is also updated
-console.log(loginModel().email); // 'alice@wonderland.com'
-```
+As a result, user changes (such as typing in the field) automatically updates the form.
NOTE: The `[field]` directive also syncs field state for attributes like `required`, `disabled`, and `readonly` when appropriate.
-### 4. Read form field values with `value()`
+### 4. Read field values with `value()`
You can access field state by calling the field as a function. This returns a `FieldState` object containing reactive signals for the field's value, validation status, and interaction state:
@@ -77,6 +69,22 @@ To read the field's current value, access the `value()` signal:
const currentEmail = loginForm.email().value();
```
+### 5. Update field values with `set()`
+
+You can programmatically update a field's value using the `value.set()` method. This updates both the field and the underlying model signal:
+
+```ts
+// Update the value programmatically
+loginForm.email().value.set('alice@wonderland.com');
+```
+
+As a result, both the field value and the model signal are updated automatically:
+
+```ts
+// The model signal is also updated
+console.log(loginModel().email); // 'alice@wonderland.com'
+```
+
Here's a complete example:
@@ -202,16 +210,17 @@ NOTE: Multiple select (``) is not supported by the `[field]` di
## Validation and state
-Signal Forms provides built-in validators that you can apply to your form fields. To add validation, pass a schema function as the second argument to `form()`. This function receives a **FieldPath** parameter that allows you to reference the fields in your form model:
+Signal Forms provides built-in validators that you can apply to your form fields. To add validation, pass a schema function as the second argument to `form()`. This function receives a **schema path** parameter that allows you to reference the fields in your form model:
```ts
-const loginForm = form(loginModel, (fieldPath) => {
- required(fieldPath.email);
- email(fieldPath.email);
+const loginForm = form(loginModel, (schemaPath) => {
+ debounce(schemaPath.email, 500);
+ required(schemaPath.email);
+ email(schemaPath.email);
});
```
-NOTE: FieldPath only mirrors the shape of your data and does not allow you to access value or any other state.
+NOTE: The schema path parameter provides paths to your fields for applying validation rules. To access field values and state, use the field tree (such as `loginForm.email()`).
Common validators include:
@@ -224,8 +233,8 @@ Common validators include:
You can also customize error messages by passing an options object as the second argument to the validator:
```ts
-required(p.email, { message: 'Email is required' });
-email(p.email, { message: 'Please enter a valid email address' });
+required(schemaPath.email, { message: 'Email is required' });
+email(schemaPath.email, { message: 'Please enter a valid email address' });
```
Each form field exposes its validation state through signals. For example, you can check `field().valid()` to see if validation passes, `field().touched()` to see if the user has interacted with it, and `field().errors()` to get the list of validation errors.
@@ -251,4 +260,4 @@ Every `field()` provides these state signals:
| `pending()` | Returns `true` if async validation is in progress |
| `errors()` | Returns an array of validation errors with `kind` and `message` properties |
-TIP: Show errors only after `field().touched()` is true to avoid displaying validation messages before the user has interacted with a field.
+TIP: Use the `debounce()` validation rule to delay error display until the user stops typing or leaves the field. This prevents showing errors while the user is still entering their input.
diff --git a/adev-ja/src/content/tutorials/home.en.md b/adev-ja/src/content/tutorials/home.en.md
index 2cdea3d03b..ffe118a8c6 100644
--- a/adev-ja/src/content/tutorials/home.en.md
+++ b/adev-ja/src/content/tutorials/home.en.md
@@ -18,4 +18,7 @@ Welcome to the Angular tutorials! These tutorials will guide you through the cor
via the Playground
+
+ via the Playground
+
diff --git a/origin b/origin
index 63a95c7b9e..0812ac3bec 160000
--- a/origin
+++ b/origin
@@ -1 +1 @@
-Subproject commit 63a95c7b9e6cc2dc5296331507ec028ca92ee2c4
+Subproject commit 0812ac3bec9b9f2fabba5a379e6626aa641a97c9